Операторы ветвления
Операторы этого типа позволяют принимать решение о выполнении тех или иных действий в зависимости от ситуации.В Parser существует два оператора ветвлений: if, проверяющий условие и выполняющий одну из указанных веток, и switch, выполняющий поиск необходимой ветки, соответствующей заданной строке или значению заданного выражения.
А что это вообще такое?
Чтение строки
$console:lineТакая конструкция считывает строку с консоли.
Чтение
$cookie:имя_cookieВозвращает значение cookie с указанным именем.
Класс console[3.1.2]
Класс предназначен для создания простых интерактивных служб, работающих в текстовом построчном режиме.Работать такие службы могут в паре со стандартной UNIX программой inetd.
Например, можно на Parser реализовать news-сервер (NNTP).
Добавьте такую строку в ваш /etc/inetd.conf и перезапустите inetd:
nntp stream tcp nowait учетная_запись /путь/к/parser3 /путь/к/parser3 /путь/к/nntp.p
В скрипте nntp.p опишите ваш NNTP сервер.
Что даст возможность людям его использовать - nntp://ваш_сервер.
Класс cookie
Класс предназначен для работы с HTTP cookies.Кодировки
Уверены, наличие разных кодировок доставляет вам такое же удовольствие, как и нам.В Parser встроена возможность прозрачного перекодирования документов из кодировки, используемой на сервере в кодировку посетителя и обратно.
Parser перекодирует
| · | данные форм; |
| · | строки при преобразовании вида uri; |
| · | текстовый результат обработки страницы. |
Кодировку, используемую вами в документах на сервере, вы задаете в поле $request:charset.
Кодировку, желаемую вами в результате - в $response:charset.
Сделать это необходимо в одном из auto методов.
Рекомендуем задавать кодировку результата в HTTP заголовке content-type, чтобы программа просмотра страниц знала о ней, и пользователю вашего сервера не нужно было переключать ее вручную.
$response:content-type[
$.value[text/html]
$.charset[$response:charset]
]
Кодировку текста отправляемых вами писем можно задать отличной от кодировке результата, см. ^mail:send[…].
При работе с базами данных необходимо задать кодировку, в которой общаться с SQL-сервером, см. Формат строки подключения.
Список допустимых кодировок определяется в Конфигурационном файле.
По умолчанию везде используется кодировка UTF-8.
Примечание: имя кодировки нечувствительно к регистру. [3.1]
Создаст на две недели cookie
$cookie:login_name[$.value[guest]
$.expires(14)
]
Создаст на две недели cookie с именем login_name и запишет в него значение guest.
записанные значения доступны для чтения
$cookie:my_cookieСчитывается и выдается значение cookie с именем my_cookie.
Примечание: записанные значения доступны для чтения сразу.
в него значение Петя. Созданный
$cookie:user[Петя]Создаст cookie с именем user и запишет в него значение Петя. Созданный cookie будет храниться на диске пользователя 90 дней.
Примечание: записанное значение сразу доступно для чтения.
$cookie:имя[
$.value[значение]
$.expires(число дней)
]
$cookie:имя[
$.value[значение]
$.expires[session]
]
$cookie:имя[
$.value[значение]
$.domain[имя домена]
]
$cookie:имя[
$.value[значение]
$.path[подраздел]
]
Сохраняет в cookie с указанным именем.
Необязательные модификаторы:
$.expires(число дней) - задает число дней (может быть дробным, 1.5=полтора дня), на которое сохраняется cookie;
$.expires[session] - создает сеансовый cookie (cookie не будет сохранятся, а уничтожится с закрытием окна браузера);
$.expires[$date] - задает дату и время, до которой будет храниться cookie, здесь $date - переменная типа date;
$.domain[имя домена] - задает cookie в домен с указанным именем;
$.path[подраздел] - задает cookie только на определенный подраздел сайта.
Сборка Parser из исходных кодов
Загрузите из CVS исходные коды Parser3 и необходимых дополнительных модулей. Для этого выполните следующую команду:cvs -d :pserver:anonymous@cvs.parser.ru:/parser3project login
Пароль пустой.
cvs -d :pserver:anonymous@cvs.parser.ru:/parser3project get -r имя_ветки имя_модуля
Имя_ветки - если не указывать -r, вы получите текущую разрабатываемую версию.
Для получения стабильной версии, забирайте ветку «release_3_X_XXXX».
Имя модуля:
Имя основного модуля: parser3.
Модуль с SQL драйверами: sql.
Сейчас в нем доступны каталоги:
sql/mysql
sql/pgsql
sql/oracle
sql/odbc
Для компиляции под UNIX…
…варианта Parser в виде модуля Apache 1.3 необходимо сначала в каталоге с исходными кодами Apache исполнить команду
./configure
и только после этого собирать Parser.
Для компиляции под Win32…
…необходим каталог:
win32/tools
…SQL драйверов необходимы каталоги:
win32/sql/mysql
win32/sql/pgsql
win32/sql/oracle
…варианта Parser, работающего с XML, в файле parser3/src/include/pa_config_fixed.h необходима директива
#define XML
…варианта Parser, принимающего письма по электронной почте, в файле parser3/src/include/pa_config_fixed.h необходима директива
#define WITH_MAILRECEIVE
Пользователи UNIX/Cygwin, инструкции по компиляции и установке читайте в файлах INSTALL каждого модуля.
Для компиляции под Win32 используйте Microsoft Visual Studio (6.0 или новее), используйте файлы .dsw каждого модуля. Распаковывайте все модули в каталог parser3project, находящийся в корне (важно!) диска.
Запись строки
$console:line[текст]Такая конструкция выводит строку на консоль.
Запись
$cookie:имя[значение]Сохраняет в cookie с указанным именем указанное значение на 90 дней.
А что это вообще такое?
Calendar. Создание календаря на заданную неделю месяца
^date:calendar[rus|eng](год;месяц;день)Метод формирует таблицу с календарем на одну неделю заданного месяца года. Для определения недели используется параметр день. Параметр rus|eng также как и в предыдущем методе определяет формат календаря. С параметром rus дни недели начинаются с понедельника, c eng - с воскресенья.
Calendar. Создание календаря на заданный месяц
^date:calendar[rus|eng](год;месяц)Метод формирует таблицу с календарем на заданный месяц года. Параметр rus|eng определяет формат календаря. С параметром rus дни недели начинаются с понедельника, c eng - с воскресенья.
Create. Дата или время в стандартном для СУБД формате
^date::create[год]^date::create[год-месяц]
^date::create[год-месяц-день]
^date::create[год-месяц-деньчасов]
^date::create[год-месяц-день часов:минут]
^date::create[год-месяц-день часов:минут:секунд]
^date::create[год-месяц-день часов:минут:секунд.миллисекунд] [3.1.3]
^date::create[часов:минут]
^date::create[часов:минут:секунд]
Создает объект класса date, содержащий значение произвольной даты и/или времени с точностью до секунды. Обязательными частями строки-параметра являются значение года или часа и минуты. месяц, день, часов, минут, секунд, миллисекунд являются необязательными, если не заданы, подставляются первый день, нулевые час, минута, секунда или текущий день.
Замечание: значение миллисекунд игнорируется.
Удобно использовать этот конструктор для работы с датами, полученными их базы данных, ведь из запроса вы получите значения полей с датой, временем или и датой и временем в виде строк.
Create. Относительная дата
^date::create(количествосуток после EPOCH)Конструктор с одним параметром предназначен для задания относительных значений дат. Имея объект класса date, можно сформировать новый объект того же класса с датой, смещенной относительно исходной.
Create. Произвольная дата
^date::create(year;month)^date::create(year;month;day)
^date::create(year;month;day;hour;minute;second)
Создает объект класса date, содержащий значение произвольной даты с точностью до секунды. Обязательными параметрами конструктора являются значения года и месяца. Параметры конструктора day,hour, minute, second являются необязательными, если не заданы, подставляются первый день, нулевые час, минута, секунда.
DOM. nodeType
DOM-элементы бывают разных типов, тип элемента хранится в integer поле nodeType.В классе xdoc имеются следующие константы, удобные для проверки значения этого поля:
$xdoc:ELEMENT_NODE= 1
$xdoc:ATTRIBUTE_NODE = 2
$xdoc:TEXT_NODE = 3
$xdoc:CDATA_SECTION_NODE = 4
$xdoc:ENTITY_REFERENCE_NODE = 5
$xdoc:ENTITY_NODE = 6
$xdoc:PROCESSING_INSTRUCTION_NODE = 7
$xdoc:COMMENT_NODE = 8
$xdoc:DOCUMENT_NODE = 9
$xdoc:DOCUMENT_TYPE_NODE = 10
$xdoc:DOCUMENT_FRAGMENT_NODE = 11
$xdoc:NOTATION_NODE = 12
Класс date
Класс date предназначен для работы с датами. Возможные варианты использования - календари, всевозможные проверки, основывающиеся на датах и т.п.Диапазон возможных значений - от 01.01.1970 до 01.01.2038 года.
Не забывайте, что в нашем календарном времени есть разрывы и нахлесты: во многих странах принято так-называемое «летнее» время, когда весной часы переводят вперед, а осенью назад.
Скажем, в Москве не бывает времени «02:00, 31 марта 2002», а время «02:00, 27 октября 2002» бывает дважды.
Числовое значение объекта класса date равно числу суток с EPOCH (01.01.1970 00:00:00, UTC) до даты, заданной в объекте. Этим значением полезно пользоваться для вычисления относительной даты, например:
# проверка "обновлен ли файл позже, чем неделю назад?"
^if($last_update > $now-7){
новый
}{
старый
}
Число суток может быть дробным, скажем, полтора дня = 1.5.
Обычно класс оперирует локальными датой и временем, однако можно узнать значение хранимой им даты/времени в произвольном часовом поясе, см. ^date.roll[TZ;…].
Для общения между компьютерами, работающими в разных часовых поясах, удобно обмениваться значениями даты/времени, не зависящими от пояса - здесь очень удобен UNIX формат, представляющий собой число секунд, прошедших с EPOCH.
Unix формат можно использовать в JavaScript и ряде других языков сценариев, работающих в браузере.
Parser полностью поддерживает работу с UNIX форматом дат.
Now. Текущая дата
^date::now[]^date::now(смещениев днях)
Конструктор создает объект класса date, содержащий значение текущей даты с точностью до секунды, используя системное время сервера. Если указано, то плюс смещение в днях.
Используется локальное время той машины, где работает Parser (локальное время сервера). Для того, чтобы узнать время в другом часовом поясе, используйте ^date.roll[TZ;…].
Определение методов и пользовательских операторов
@имя[параметры]тело
@имя[параметры][локальные переменные]
тело
Метод, это блок кода, имеющий имя, принимающий параметры, и возвращающий результат. Имена параметров метода перечисляются через точку с запятой. Метод также может иметь локальные переменные, которые необходимо объявить в заголовке метода, после объявления параметров, имена разделяются точкой с запятой.
Локальные переменные видны в пределах оператора или метода, и изнутри вызываемых ими операторов и методов, см. ниже $caller.
При описании метода можно пользоваться не только параметрами или локальными переменными, а также любыми другими именами, при этом вы будете работать с полями класса, или полями объекта, в зависимости от того, как был вызван определенный вами метод, статически, или динамически.
В Parser вы можете расширить базовый набор операторов, операторами в Parser считаются методы класса MAIN.
Определение пользовательского класса и операторов
Файл в таком формате определяет пользовательский класс:@CLASS
имя_класса
#необязательно
@USE
файл_с_родительским классом
# необязательно
@BASE
имя_родительского_класса
# так рекомендуется называть метод-конструктор класса
@create[параметры]
# далее следуют определения методов класса
@method1[параметры]
…
Модуль можно подключить (см. «Подключение модулей») к произвольному файлу - там появится возможность использования определенного здесь класса.
Если не указать @CLASS, файл определит ряд дополнительных операторов.
Если определен метод…
@auto[]
…он будет выполнен автоматически при загрузке класса как статический метод (так называемый статический конструктор). Используется для инициализации статических полей (переменных) класса.
Примечание: результат работы метода игнорируется - никуда не попадает.
У метода auto может быть объявлен параметр:
@auto[filespec]
В этом параметре Parser передаст полное имя файла, содержащего метод.
В Parser создаваемые классы наследуют методы классов, от которых были унаследованы. Унаследованные методы можно переопределить.
В том случае, когда в качестве родительского класса выступает другой пользовательский класс, необходимо подключить модуль, в котором он находится, а также объявить класс базовым (@BASE).
Для того, чтобы пользоваться методами и полями родительских классов, необходимо использовать следующие конструкции:
^класс:метод[параметры] - вызов метода родительского класса (примечание: хотя такой синтаксис вызова метода и похож на синтаксис вызова статического метода, фактически, в случае динамического метода, происходит динамический вызов метода родительского класса), для обращения к своему ближайшему родительскому классу (базовому классу) можно использовать конструкции ^BASE::конструктор[параметры] и ^BASE:метод[параметры].
Поля объектов класса date
Через поля объектов класса date могут быть получены следующие величины:$date.monthмесяц
$date.year год
$date.day день
$date.hour часы
$date.minute минуты
$date.second секунды
$date.weekday день недели (0 - воскресенье, 1 - понедельник, …)
$date.yearday день года (0 - 1-ое января, 1 - 2-ое января, …)
$date.daylightsaving 1 - летнее время, 0 - стандартное время
$date.TZ часовой пояс; [3.1.1]
содержит значение, если эта дата была получена ^date.roll[TZ;…]
и временем, которую сразу помещаем
$date_now[^date::now[]]^connect[строка подключения]{
^void:sql{insert into access_log
(access_date)
values
('^date_now.sql-string[]')
}
}
Получаем строку вида '2001-11-30 13:09:56' с текущей датой и временем, которую сразу помещаем в колонку таблицы СУБД. Без использования данного метода пришлось бы выполнять необходимое форматирование вручную. Обратите внимание, данный метод не формирует кавычки, их требуется задавать вручную.
^if($node.nodeType
^if($node.nodeType == $xnode:ELEMENT_NODE){<$node.tagName>
}
с календарем на ту неделю
$week_of_month[^date:calendar[rus](2001;11;30)]В результате в переменную $week_of_month будет помещена таблица с календарем на ту неделю ноября 2001 года, которая содержит 30-е число. Формат таблицы следующий:
|
year |
month |
day |
weekday |
|
2001 |
11 |
26 |
01 |
|
2001 |
11 |
27 |
02 |
|
2001 |
11 |
28 |
03 |
|
2001 |
11 |
29 |
04 |
|
2001 |
11 |
30 |
05 |
|
2001 |
12 |
01 |
06 |
|
2001 |
12 |
02 |
07 |
$president_on_tv_at[^date::create(2001;12;31;23;55)]
В результате выполнения данного кода, создается объект класса date, значения полей которого соответствуют времени появления президента на телевизионном экране в комнате с веб-сервером.
$now[^date::now[]]
$date_after_week[^date::create($now+7)]
В примере получается дата, на неделю большая текущей.
Параметр конструктора не обязательно должен быть целым числом.
$date_after_three_hours[^date::create($now+3/24)]
# считаем новыми статьи за последние 3 дня
$new_after[^date::now(-3)]
$articles[^table::sql{select id, title, last_update from articles where …}]
^articles.menu{
$last_update[^date::create[$articles.last_update]]
$articles.title
^if($last_update > $new_after){новая}
}
Внимание пользователям Oracle: чтобы получать дату и время в удобном формате, в строке соединения с сервером укажите формат даты и времени, рекомендованный в Приложении 3.
$date_now[^date::now[]]
$date_now.year
$date_now.month
$date_now.day
$date_now.hour
$date_now.minute
$date_now.second
$date_now.weekday
В результате выполнения данного кода, создается объект класса date, содержащий значение текущей даты, а на экран будет выведено значение:
год
месяц
день
час
минута
секунда
день недели
$date_now[^date::now[]]
$date_now.month
В результате выполнения данного кода, создается объект класса date, содержащий значение текущей даты, а на экран будет выведен номер текущего месяца.
$date_now[^date::now[]]
^connect[строка подключения]{
^void:sql{insert into access_log
(access_date)
values
('^date_now.sql-string[]')
}
}
Получаем строку вида '2001-11-30 13:09:56' с текущей датой и временем, которую сразу помещаем в колонку таблицы СУБД. Без использования данного метода пришлось бы выполнять необходимое форматирование вручную. Обратите внимание, данный метод не формирует кавычки, их требуется задавать вручную.
^if($node.nodeType == $xnode:ELEMENT_NODE){
<$node.tagName>
}
В результате выполнения данного кода,
$president_on_tv_at[^date::create(2001;12;31;23;55)]В результате выполнения данного кода, создается объект класса date, значения полей которого соответствуют времени появления президента на телевизионном экране в комнате с веб-сервером.
В примере получается дата, на
$now[^date::now[]]$date_after_week[^date::create($now+7)]
В примере получается дата, на неделю большая текущей.
Параметр конструктора не обязательно должен быть целым числом.
$date_after_three_hours[^date::create($now+3/24)]
Внимание пользователям Oracle: чтобы получать
# считаем новыми статьи за последние 3 дня$new_after[^date::now(-3)]
$articles[^table::sql{select id, title, last_update from articles where …}]
^articles.menu{
$last_update[^date::create[$articles.last_update]]
$articles.title
^if($last_update > $new_after){новая}
}
Внимание пользователям Oracle: чтобы получать дату и время в удобном формате, в строке соединения с сервером укажите формат даты и времени, рекомендованный в Приложении 3.
В результате выполнения данного кода,
$date_now[^date::now[]]$date_now.year
$date_now.month
$date_now.day
$date_now.hour
$date_now.minute
$date_now.second
$date_now.weekday
В результате выполнения данного кода, создается объект класса date, содержащий значение текущей даты, а на экран будет выведено значение:
год
месяц
день
час
минута
секунда
день недели
В результате выполнения данного кода,
$date_now[^date::now[]]$date_now.month
В результате выполнения данного кода, создается объект класса date, содержащий значение текущей даты, а на экран будет выведен номер текущего месяца.
Пример сдвига часового пояса
@main[]$now[^date::now[]]
^show[]
^show[Москва;MSK-3MSD]
^show[Амстердам;MET-1DST]
^show[Лондон;GMT0BST]
^show[Нью-Йорк;EST5EDT]
^show[Чикаго;CST6CDT]
^show[Денвер;MST7MDT]
^show[Лос-Анжелес;PST8PDT]
@show[town;TZ]
^if(def $town){
$town
^now.roll[TZ;$TZ]
}{
Локальное время сервера
}
$now.year/$now.month/$now.day, $now.hour ч. $now.minute мин.
Пример сдвига месяца
$today[^date::now[]]^today.roll[month](-1)
$today.month
В данном примере мы присваиваем переменной $today значение текущей даты и затем уменьшаем номер текущего месяца на единицу. В результате мы получаем номер предыдущего месяца.
Работа с переменными в динамических методах
Поиск значения переменной происходит в:| · | в списке локальных переменных; |
| · | в текущем объекте и его классе; |
| · | в родительских объектах и их классах. |
Запись значения переменной производится в уже имеющуюся переменную (см. область поиска выше), если таковая имеется. В противном случае создается новая переменная (поле) в текущем объекте.
Примечание: старайтесь всячески избегать использования полей класса не из методов класса, кроме простейших случаев! По-возможности, общайтесь с объектом только через его методы.
Работа с переменными в статических методах
Поиск значения переменной происходит в:| · | в списке локальных переменных; |
| · | в текущем классе или его родителях. |
Запись значения переменной производится в уже имеющуюся переменную (см. область поиска выше), если таковая имеется. В противном случае создается новая переменная (поле) в текущем классе.
Roll. Сдвиг даты
^date.roll[year](смещение)^date.roll[month](смещение)
^date.roll[day](смещение)
^date.roll[TZ][Новыйчасовой пояс] [3.1.1]
С помощью этого метода можно увеличивать/уменьшать значения полей year, month, day объектов класса date.
Также можно узнать дату/время, соответствующие хранящимся в объекте класса date в другом часовой поясе, задав системное имя нового часового пояса. Список имен см. в документации на вашу операционную систему, ключевые слова: «Переменная окружения TZ».
Системная переменная: caller
Все методы и операторы имеют локальную переменную caller, которая хранит «контекст вызова» метода или оператора.Через нее можно:
| · | узнать, кто вызвал вызвавший описываемый метод или оператор, обратившись к $caller.self;
|
| · | считать - $caller.считать, или записать - $caller.записать[значение] переменную, как будто вы находитесь в том месте, откуда вызвали описываемый метод или оператор. |
Например вам нужен оператор, похожий на системный for, но чем-то отличающийся от него. Вы можете написать его сами, воспользовавшись возможностью менять локальную переменную с именем, переданным вам, в контексте вызова вашего оператора.
@steppedfor[name;from;to;step;code]
$caller.$name($from)
^while($caller.$name<=$to){
$code
^caller.$name.inc($step)
}
Теперь такой вызов…
@somewhere[][i]
^steppedfor[i](1;10;2){$i }
…напечатает «1 3 5 7 9 », обратите внимание, что изменяется локальная переменная метода somewhere.
Примечание: возможность узнать контекст вызова удобна для задания контекста компиляции кода (см. «process. Компиляция и исполнение строки».
Системная переменная: result
Все методы и операторы имеют локальную переменную result. Если ей присвоить какое-то значение, то именно оно будет результатом выполнения метода. Значение переменной result можно считывать и использовать в вычислениях.Пример:
@main[]
$a(2)
$b(3)
$summa[^sum[$a;$b]]
$summa
@sum[a;b]
^eval($a+$b)
$result[Ничегоне скажу!]
Здесь клиенту будет выдана строка Ничего не скажу!, а не результат сложения двух чисел.
Важно: операторы, это методы класса MAIN, но в отличие от методов других классов, их можно вызвать из любого класса просто по имени, т.е. можно писать ^include[…], вместо громоздкого ^MAIN:include[…].
Системная переменная: self
Все методы и операторы имеют локальную переменную self, она хранит ссылку на текущий объект, в статических методах хранит то же, что и $CLASS.Пример:
@main[]
$a[Статическое поле ^$a класса MAIN]
^test[Параметр метода]
@test[a]
^$a - $a
^$self.a - $self.a
Выведет:
$a - Параметр метода
$self.a - Статическое поле $a класса MAIN
Системное поле класса: CLASS
$имя_класса:CLASS - хранит ссылку на класс объекта.Это удобно при задании контекста компиляции кода (см. «process. Компиляция и исполнение строки».
По этой ссылке также доступны статические поля класса, пример:
@main[]
^method[$cookie:CLASS]
@method[storage]
$storage.field
Этот код напечатает значение $cookie:field.
Sql-string. Преобразование даты
^date.sql-string[]Метод преобразует дату к виду ГГГГ-ММ-ДДЧЧ:ММ:СС, который принят для хранения дат в СУБД. Использование данного метода позволяет вносить в базы данных значения дат без дополнительных преобразований.
Unix-timestamp. Дата и время в UNIX формате[3.1.2]
^date::unix-timestamp(дата_время_в_UNIX_формате)Конструктор создает объект класса date, содержащий значение, соответствующее переданному числовому значению в UNIX формате (см. также краткое описание).
Unix-timestamp. Преобразование
^date.unix-timestamp[]Преобразует дату и время к значению в UNIX формате (см. краткое описание).
А что это вообще такое?
Класс env
Класс предназначен для получения значения переменных окружения. Со списком стандартных переменных окружения можно ознакомиться по адресу http://www.w3c.org/cgi. Веб-сервер Apache задает значения ряда дополнительных переменных.Литералы в выражениях
Если строка содержит пробелы, то в выражении ее нужно заключать в кавычки или апострофы.Пример:
^if($name eq Вася)
Здесь Вася - строка, которая не содержит пробелов, поэтому ее можно не заключать в кавычки или апострофы.
^if($name eq "Вася Пупкин")
Здесь строка содержит пробелы, поэтому заключена в кавычки.
Обработка ошибок
Человек несовершенен. Вы должны быть готовы к тому, что вместо ожидаемого, на экране вашего компьютера появится сообщение об ошибке. Избежать этого, к сожалению, почти невозможно. На начальном этапе сообщения об ошибках будут довольно частыми. Основной причиной ошибок сначала, вероятнее всего, будут непарные скобки (помните, мы говорили о текстовых редакторах, помогающих их контролировать?) и ошибки в записи конструкций Parser.Если в ходе работы возникла ошибка, обычно обработка страницы прекращается, происходит откат (rollback) по всем активным на момент ошибки SQL-соединениям, и, вместо того вывода, который должен был попасть пользователю, вызывается метод unhandled_exception, ему передается информация об ошибке и стек вызовов, приведших к ошибке, и выдаются результаты его работы. Также ошибка записывается в журнал ошибок веб-сервера.
Однако часто желательно перехватить возникшую ошибку, и сделать нечто полезное вместо ошибочного кода.
Допустим, вы хотите проверить на правильность XML код, полученный из ненадежного источника. Здесь прерывание обработки страницы вам совершенно ни к чему, наоборот - вы ожидаете ошибку определенного типа и хотите ее обработать.
Parser с радостью идет навстречу, и дает вам в руки мощный инструмент: оператор try.
При сложной обработке данных часто выясняется, что имеет место ошибка в методе, вызванном из другого, а тот, в свою очередь, из третьего. Как в такой ситуации просто сообщить и обработать ошибку?
Используйте оператор throw, чтобы сообщить об ошибке, и обработайте ошибку на верхнем уровне - и вам не придется проверять ее на всех уровнях вложенности вызовов методов.
Также во многих ситуациях сам Parser или его системные классы сообщают о ошибках, см. «Системные ошибки».
Операторы в выражениях и их приоритеты
Операторы в таблице перечислены в порядке убывания приоритета:|
Оператор |
Значение | |
|
высший приоритет | ||
|
() |
Группировка частей выражения | |
|
! |
Логическая операция NOT | |
|
~ |
Побитовая инверсия (NOT) | |
|
- |
Одиночный минус | |
|
* |
Умножение | |
|
/ |
Деление |
Внимание, |
|
\ |
Целочисленное деление |
деление на ноль |
|
% |
Остаток от деления |
дает ошибку number.zerodivision. |
|
+ |
Сложение | |
|
- |
Вычитание | |
|
<< |
Побитовый сдвиг влево | |
|
>> |
Побитовый сдвиг вправо | |
|
& |
Побитовая операция AND | |
|
| |
Побитовая операция OR | |
|
!| |
Побитовая операция XOR | |
|
is |
Проверка типа | |
|
def |
Определен ли объект? | |
|
in |
Находится ли текущий документ в каталоге? | |
|
-f |
Существует ли файл? | |
|
–d |
Существует ли каталог? | |
|
== |
Равно | |
|
!= |
Неравно | |
|
eq |
Строки равны | |
|
ne |
Строки не равны | |
|
< |
Меньше | |
|
> |
Больше | |
|
<= |
Меньше или равно | |
|
>= |
Больше или равно | |
|
lt |
Строка меньше | |
|
gt |
Строка больше | |
|
le |
Строка меньше или равна | |
|
ge |
Строка больше или равна | |
|
&& |
Логическая операция AND |
второй операнд не вычисляется, если первый - ложь |
|
|| |
Логическая операция OR |
второй операнд не вычисляется, если первый - истина |
|
!|| |
Логическая операция XOR | |
|
низший приоритет |
Получение значения поля запроса
$env:HTTP_ПОЛЕ_ЗАПРОСАТакая конструкция возвращает значение поля запроса, передаваемое браузером веб-серверу (по HTTP протоколу).
Поля запроса имеют имена
^if(^env:HTTP_USER_AGENT.pos[MSIE]>=0){Пользователь, вероятно, использует MicroSoft Internet Explorer
}
Поля запроса имеют имена в верхнем регистре и начинающиеся с HTTP_, и знаки '-' в них заменены на '_'.
Подробности в документации на ваш веб-сервер.
$env:REMOTE_ADDR
Возвратит IP-адрес машины, с которой был запрошен документ.
с которой был запрошен
$env:REMOTE_ADDRВозвратит IP-адрес машины, с которой был запрошен документ.
Статические поля. Получение значения переменной окружения
$env:переменная_окруженияВозвращает значение указанной переменной окружения.
@Unhandled_exception. Вывод необработанных ошибок
Если ошибка так и не была обработана ни одним обработчиком (см. оператор try), Parser вызывает метод unhandled_exception, ему передается информация об ошибке и стек вызовов, приведших к ошибке, и выдаются результаты его работы. Также ошибка записывается в журнал ошибок веб-сервера.Хороший тон, это оформить сообщение об ошибке в общем дизайне вашего сайта.
А также проверить, и не показывать технические подробности вашим посетителям.
Рекомендуем поместить этот метод в Конфигурационный файл сайта.
А что это вообще такое?
Basename. Имя файла без пути
^file:basename[filespec]Из полного пути к файлу (filespec) получает имя файла с расширением имени, но без пути.
Cgi и exec. Исполнение программы
^file::cgi[имяфайла]^file::cgi[имя файла;env_hash]
^file::cgi[имя файла;env_hash;аргументы]
^file::exec[имя файла]
^file::exec[имя файла;env_hash]
^file::exec[имя файла;env_hash;аргументы]
Конструктор cgi создает объект класса file, содержащий результат исполнения программы в соответствии со стандартом CGI.
Внимание: перез запуском программы Parser изменяет текущий каталог на каталог с программой.
Заголовки, которые выдаст CGI-скрипт, конструктор поместит в поля класса file в ВЕРХНЕМ регистре. Например, если некий скрипт script.pl, среди прочего, выдает в заголовке строку field:value, то после работы конструктора
$f[^file::cgi[script.pl]],
обратившись к $f.FIELD, получим значение value.
Конструктор exec аналогичен file::cgi, но не отделяет HTTP-заголовки от текста, возвращаемого скриптом.
Имя файла - имя файла с путем.
Объект, созданный этими конструкторами, имеет дополнительные поля:
status - информация о статусе завершении программы (обычно 0 - программа завершилась успешно, не 0 - с ошибкой)
stderr - результат считывания стандартного потока ошибок
Пример:
$cgi_file[^file::cgi[new.cgi]]
$cgi_file.text
Выведет на экран результаты работы скрипта new.cgi.
Необязательные параметры конструкторов ^file::cgi и ^file::exec:
env_hash - хеш, в котором могут задаваться
| · | дополнительные переменные окружения, которые впоследствии будут доступны внутри исполняемого скрипта, |
| · | а также переменная stdin, содержащая текст, передаваемый исполняемому скрипту в стандартном потоке ввода. |
Внимание: при обработке HTTP POST запроса, при помощи конструкции $.stdin[$request:body] вы можете передать в стандартный поток ввода скрипта полученные вами POST-данные. [3.0.8, раньше они передавались по-умолчанию]
Content-type. MIME-тип файла
$файл.content-typeПоле может содержать MIME-тип файла. При выполнении CGI-скрипта (см. file::cgi) MIME-тип может задаваться CGI-скриптом, полем заголовка ответа «content-type». При загрузке (см. file::load) или получении информации о файле (см. file::stat) MIME-тип определяется по таблице $MAIN:MIME-TYPES (см. «Конфигурационный метод»), если в таблице расширение имени файла найдено не будет, будет использован тип «application/octet-stream».
Delete. Удаление файла с диска
^file:delete[путь]Удаляет указанный файл.
Путь - путь к файлу
Если после удаления в каталоге больше ничего не осталось, каталог тоже удаляется(если это возможно).
Dirname. Путь к файлу
^file:dirname[filespec]Из пути к файлу или каталогу (filespec) получает только путь.
Fields. Все поля формы
$form:fieldsТакая конструкция возвращает хеш со всеми полями формы или параметрами, переданными через URL. Имена ключей хеша те же, что и у полей формы, значениями ключей являются значения полей формы.
Find. Поиск файла на диске
^file:find[файл]^file:find[файл]{код,если файл не найден}
Метод возвращает строку (объект класса string), содержащую имя файла с путем от корня веб пространства, если он существует по указанному пути, либо в каталогах более высокого уровня. В противном случае выполняется заданный код, если он указан.
Fullpath. Полное имя файла от корня веб-пространства
^file:fullpath[имя файла]Из имени файла получает полное имя файла от корня веб-пространства. См. также «Приложение 1. Пути к файлам и каталогам».
Пример: в странице /document.html вы создаете ссылку на картинку, но настоящий адрес запрошенного документа может быть иным, скажем, при применении модуля mod_rewrite веб-сервера Apache, если поставить относительную ссылку на картинку, она не будет отображена браузером, поскольку браузер относительные пути разбирает относительно к текущему запрашиваемому документу, и ничего не знает про то, что на веб-сервере использован mod_rewrite.
Поэтому удобно заменить относительное имя на полное:
$image[^image::measure[^file:fullpath[image.gif]]]
^image.html[]
Такая конструкция…

…создаст код, содержащий абсолютный путь.
Imap. Получение координат нажатия в ISMAP
$form:imapЕсли пользователь нажал на картинку с атрибутом ISMAP, такая конструкция возвращает хеш с полями x и y, в которых доступны координаты нажатия.
Justext. Расширение имени файла
^file:justext[filespec]Из полного пути к файлу (filespec) получает расширение имени файла без точки.
Justname. Имя файла без расширения
^file:justname[filespec]Из полного пути к файлу (filespec) получает имя файла без пути и расширения имени.
Класс file
Класс file предназначен для работы с файлами. Объекты класса могут быть созданы различными способами:| 1. | методом POST через поле формы . |
|
|
| 2. | одним из конструкторов класса file. |
При передачи файлов клиентам (например, методом mail:send или через поле response:body) необходимо задавать HTTP-заголовок content-type. В Parser для определения типа файла по расширению его имени существует таблица MIME-TYPES, определенная в Конфигурационном методе (см. главу Настройка). По ней, в зависимости от расширения файла, Parser автоматически определяет нужный тип данных для передачи в строке content-type. Если тип данных не удается определить по таблице, используется тип application/octet-stream.
Для проверки существования файлов и каталогов есть специальные операторы.
Класс form
Класс form предназначен для работы с полями форм. Класс имеет статические поля, доступные только для чтения.Для проверки заполнения формы и редактирования имеющихся записей из базы данных удобно использовать такой подход:
^if($edit){
# запись из базы
$record[^table::sql{… where id=…}]
}{
# новая запись, ошибка при заполнении, необходимо вывести
# поля формы
$record[$form:fields]
}
List. Получение оглавления каталога
^file:list[путь]^file:list[путь;фильтр]
Формирует таблицу (объект класса table) с одним столбцом name, содержащим файлы и каталоги по указанному пути, имена которых удовлетворяют шаблону, если он задан.
фильтр - регулярное выражение (см. метод match класса string) для обобщения типа запрашиваемых файлов. Без указания фильтра будут выведены все найдены по заданному пути файлы
Load. Загрузка файла с диска или HTTP-сервера
^file::load[формат;имя файла]^file::load[формат;имя файла;опции загрузки]
^file::load[формат;имя файла;новоеимя файла]
^file::load[формат;имя файла;новое имя файла;опции загрузки]
Загружает файл с диска или HTTP-сервера.
Формат - формат представления загружаемого файла. Может быть text(текстовый) или binary(двоичный). Различие между этими типами в разных символах переноса строк. Для PC эти символы 0D 0A. При использовании формата text при загрузке 0D отбросится за ненадобностью, при записи методом save добавится.
имя файла - имя файла с путем или URL файла на HTTP-сервере.
Необходимо иметь ввиду, что если в конструкторе задан параметр новое имя файла, его значение будет присвоено полю name. Этим параметром удобно пользоваться при использовании метода mail:send для передачи файла под нужным именем.
опции загрузки - см. «Работа с HTTP-серверами».
Если файл был загружен с HTTP-сервера, поля заголовков HTTP-ответа в верхнем регистре доступны как поля объекта класса file.
Также доступно поле tables, это хеш, ключами которого являются поля заголовки HTTP-ответа в верхнем регистре, а значениями таблицы с единственным столбцом value, содержащими все значения одноименных полей HTTP-ответа. [3.1.1]
Lock. Эксклюзивное выполнение кода
^file:lock[имяфайла-блокировки]{код}Код не выполняется одновременно, для обеспечения эксклюзивности используется файл-блокировки.
Move. Перемещение или переименование файла
^file:move[старое имя файла;новое имя файла]Метод переименовывает или перемещает файл и каталог (для платформы Win32 объекты нельзя перемещать через границу диска). Новый каталог создается с правами 775. Каталог старого файла удаляется, если после выполнения метода он остается пустым.
Внимание: необходимо крайне осторожно относиться к возможности записи в веб-пространстве, поскольку возможностью что-нибудь куда-нибудь записать нередко пользуются современные геростраты.
Name. Имя файла
$файл.nameПоле содержит имя файла. Объект класса file имеет поле name, если пользователь закачал файл через поле формы. Также в конструкторе file::load может быть указано альтернативное имя файла.
Поля HTTP-ответа
Если файл был загружен с HTTP-сервера, поля заголовков HTTP-ответа доступны доступны, как поля объекта класса file:$файл.ПОЛЕ_HTTP_ОТВЕТА (ЗАГЛАВНЫМИ БУКВАМИ)
Например: $файл.SERVER.
Если один заголовок повторяется в ответе несколько раз, все его значения доступны в поле tables [3.0.8, пока нет в 3.1.0]:
$.tables[
$.HTTP-ЗАГОЛОВОК[таблица значений, единственный столбец value]
]
Пример:
$f[^file::load[binary;http://www.parser.ru]]
^f.tables.foreach[key;value]{
$key=^value.menu{$value.value}[|]
}
Получение значения поля формы
$form:поле_формыТакая конструкция возвращает значение поля формы. Возвращаемый объект может принадлежать либо классу file, если поле формы имеет тип file, либо классу string. Дальнейшая работа с объектом возможна только методами, определенными для соответствующих классов.
Поле без имени считается имеющим имя nameless.
Координаты нажатия пользователем на картинку с атрибутом ISMAP доступны через $form:imap.
^file:basename
^file:basename[/a/some.tar.gz]…выдаст…
some.tar.gz
^file:delete[story.txt]
#имя файла
^file:dirname[/a/some.tar.gz]
#имя каталога…
^file:dirname[/a/b/]
Оба вызова выдадут:
/a
^file:justext[/a/some.tar.gz]
…выдаст…
gz
^file:justname[/a/some.tar.gz]
…выдаст…
some.tar
$list[^file:list[/;\.zip^$]]
^list.menu{
$list.name
}
Выведет имена всех архивных файлов с расширением имени .zip, находящихся в корневом каталоге веб-сервера.
^file:lock[/counter.lock]{
$file[^file::load[text;/counter.txt]]
$string[^eval($file.text+1)]
^string.save[/counter.txt]
}
Количество посещений: $string
В отсутствие блокировки, два одновременных обращения к странице могли вызвать увеличение счетчика… на 1, а не на 2:
| · | пришел первый; |
| · | пришел второй; |
| · | считал первый, значение счетчика 0; |
| · | считал второй, значение счетчика 0; |
| · | увеличил первый, значение счетчика 1; |
| · | увеличил второй, значение счетчика 1; |
| · | записал первый, значение счетчика 1; |
| · | записал второй поверх только что записанного первым, значение счетчика 1, а не 2. |
Внимание: всегда думайте об одновременно приходящих запросах. При работе с базами данных обычно есть встроенные в SQL-сервер средства для их корректной обработки.
^file:move[/path/file1;/file1]
Переместит файл file1 в корень веб-пространства.
^archive.save[text;/arch/archive.txt]
Пример сохранит объект класса file в текстовом формате под именем archive.txt в каталог /arch/.
$name[image.gif]
$file[^file::load[$name]]
^connect[строка соединения]{
^void:sql{insert into images (name, bytes) values ('$name', '^file.sql-string[]')}
}
$f[^file::stat[some.zip]]
Размер в байтах: $f.size
Год создания: $f.cdate.year
$new_after[^date::now(-3)]
Статус: ^if($f.mdate >= $new_after){новый;старый}
^form:fields.foreach[field;value]{
$field - $value
}[
]
Пример выведет на экран все поля формы и соответствующие значения.
Предположим, что URI страницы www.mysite.ru/testing/index.html?name=dvoechnik&mark=2. Тогда пример выдаст следующее:
name - dvoechnik
mark - 2
Выберите, чем вы увлекаетесь в свободное время:
$hobby[$form:tables.hobby]
^if($hobby){
Ваши хобби:
^hobby.menu{
$hobby.field
}[
]
}{
Ничего не выбрано
}
Пример выведет на экран выбранные варианты или напишет, что ничего не выбрано.
^file:delete
^file:delete[story.txt]Оба вызова
#имя файла^file:dirname[/a/some.tar.gz]
#имя каталога…
^file:dirname[/a/b/]
Оба вызова выдадут:
/a
^file:justext
^file:justext[/a/some.tar.gz]…выдаст…
gz
^file:justname
^file:justname[/a/some.tar.gz]…выдаст…
some.tar
Выведет имена всех архивных файлов
$list[^file:list[/;\.zip^$]]^list.menu{
$list.name
}
Выведет имена всех архивных файлов с расширением имени .zip, находящихся в корневом каталоге веб-сервера.
В отсутствие блокировки, два одновременных
^file:lock[/counter.lock]{$file[^file::load[text;/counter.txt]]
$string[^eval($file.text+1)]
^string.save[/counter.txt]
}
Количество посещений: $string
В отсутствие блокировки, два одновременных обращения к странице могли вызвать увеличение счетчика… на 1, а не на 2:
| · | пришел первый; |
| · | пришел второй; |
| · | считал первый, значение счетчика 0; |
| · | считал второй, значение счетчика 0; |
| · | увеличил первый, значение счетчика 1; |
| · | увеличил второй, значение счетчика 1; |
| · | записал первый, значение счетчика 1; |
| · | записал второй поверх только что записанного первым, значение счетчика 1, а не 2. |
Внимание: всегда думайте об одновременно приходящих запросах. При работе с базами данных обычно есть встроенные в SQL-сервер средства для их корректной обработки.
Переместит файл file1
^file:move[/path/file1;/file1]Переместит файл file1 в корень веб-пространства.
Пример сохранит объект класса file
^archive.save[text;/arch/archive.txt]Пример сохранит объект класса file в текстовом формате под именем archive.txt в каталог /arch/.
$name[image.gif]
$name[image.gif]$file[^file::load[$name]]
^connect[строка соединения]{
^void:sql{insert into images (name, bytes) values ('$name', '^file.sql-string[]')}
}
$f[^file::stat[some.zip]]
$f[^file::stat[some.zip]]Размер в байтах: $f.size
Год создания: $f.cdate.year
$new_after[^date::now(-3)]
Статус: ^if($f.mdate >= $new_after){новый;старый}
Пример выведет на экран все
^form:fields.foreach[field;value]{$field - $value
}[
]
Пример выведет на экран все поля формы и соответствующие значения.
Предположим, что URI страницы www.mysite.ru/testing/index.html?name=dvoechnik&mark=2. Тогда пример выдаст следующее:
name - dvoechnik
mark - 2
Пример выведет на экран выбранные
Выберите, чем вы увлекаетесь в свободное время:$hobby[$form:tables.hobby]
^if($hobby){
Ваши хобби:
^hobby.menu{
$hobby.field
}[
]
}{
Ничего не выбрано
}
Пример выведет на экран выбранные варианты или напишет, что ничего не выбрано.
Пример без указания пути

Допустим, этот код расположен в документе /news/sport/index.html, здесь ищется файл header.gif в каталоге /news/sport/, разработанный специально для раздела спортивных новостей. Если он не найден, и не существует /news/sport/header.gif, то используется стандартный заголовочный рисунок новостного раздела.
безымянное поле
Внутри show.html строка 123 доступна как $form:nameless.
обычное поле
^if(def $form:photo){
^form:photo.save[binary;/upload/photos/beauty.gif]
}
^if(def $form:user){
Пользователь: $form:user
}
Сохранит картинку, выбранную пользователем в поле формы и присланную на сервер, в заданном файле.
Пример передачи нескольких аргументов
Кроме того, вызываемой программе можно передать ряд аргументов, перечислив их через точку с запятой после хеша переменных окружения:^file::exec[script.pl;;длина;ширина]
Внимание: настоятельно рекомендуется хранить запускаемые скрипты вне веб-пространства, поскольку запуск скрипта с произвольными параметрами может привести к неожиданным результатам.
Пример с указанием пути

Здесь ищется файл header.gif в каталоге /i/раздел/подраздел/. Если он не найден, он будет последовательно искаться в каталогах
| · | /i/раздел/ |
| · | /i/ |
| · | /
|
Пример внешнего скрипта
^file::exec[script.pl;$.CGI_INFORMATION[этогомне не хватало]]Внутри скрипта script.pl можно воспользоваться переданной информацией:
print "Дополнительная информация: $ENV{CGI_INFORMATION}\n";
Пример загрузки файла с диска
$f[^file::load[binary;article.txt]]Файл с именем $f.name имеет размер $f.size и содержит текст:
$f.text
Выведет размер, имя и текст файла.
Пример загрузки файла с HTTP-сервера
$file[^file::load[text;http://parser.ru/]]Программное обеспечение сервера: $file.SERVER
$file.text
Qtail. Получение остатка строки запроса
$form:qtailВозвращает часть $request:query после второго ?.
Save. Сохранение файла на диске
^файл.save[формат;имя файла]Метод сохраняет объект в файл в заданном формате под указанным именем.
Формат - формат сохранения файла (text или binary)
Имя файла - имя файла и путь, по которому он будет сохранен
Size. Размер файла
$файл.sizeПоле содержит размер файла в байтах.
Sql-string. Сохранение файла на SQL-сервере[3.1.2]
^file.sql-string[]Выдает строку, которую можно использовать в SQL-запросе. Позволяет сохранить файл в базе данных.
Внимание: на данный момент реализована поддержка только MySQL-сервера.
Sql. Загрузка файла из SQL-сервера[3.1.2]
^file::sql{запрос}^file::sql[имя файла]{запрос}
Загружает файл из SQL-сервера. Результатом выполнения запроса должна быть одна запись. Считается, что ее
| · | первая колонка содержит данные файла; |
| · | вторая колонка содержит имя файла; |
| · | третья колонка содержит content-type файла (если не указан, он будет определен по таблице $MIME-TYPES). |
Имя файла может быть также задано параметром.
Имя файла и его content-type будет переданы посетителю при $response:download.
Stat. Получение информации о файле
^file::stat[имяфайла]Объект, созданный этим конструктором, имеет дополнительные поля (объекты класса date):
$файл.size - размер файла в байтах;
$файл.cdate - дата создания;
$файл.mdate - дата изменения;
$файл.adate - дата последнего обращения к файлу.
имя файла - имя файла с путем.
Tables. Получение множества значений поля
$form:tablesТакая конструкция возвращает хеш со всеми полями формы или параметрами, переданными через URL. Имена ключей хеша те же, что и у полей формы, значениями же являются таблицы, см. ниже.
$form:tables.поле_формы
Если поле формы имеет хотя бы одно значение, такая конструкция возвращает таблицу (объект класса table) с одним столбцом field, содержащим все значения поля. Используется для получения множества значений поля.
Внимание: не забудьте проверить наличие таблицы перед тем, как начать ею оперировать.
Text. Текст файла
$файл.textПоле содержит текст файла. Использование этого поля позволяет выводить на странице содержимое текстовых файлов или результатов работы file::cgi и file::exec.
А что это вообще такое?
Add. Сложение хешей
^хеш.add[хеш-слагаемое]Добавляет к хешу другой хеш-слагаемое, при этом одноименные ключи хеша перезаписываются.
Чтение
$hashfile.ключВозвращает строку, ассоциированную с ключом, если эта ассоциация не устарела.
Clear. Удаление всего содержимого
^hashfile.clear[]Удаляет все ассоциации.
_Count. Количество ключей хеша
^хеш._count[]Возвращает количество ключей хеша.
Create. Создание пустого и копирование хеша
^hash::create[]^hash::create[существующий хеш или хешфайл]
Если параметр не задан, будет создан пустой хеш.
Если указан существующий хеш или хешфайл, конструктор создает его копию.
Пустой хеш, создаваемый конструктором без параметров, нужен в ситуации, когда необходимо динамически наполнить хеш данными, например:
$dyn[^hash::create[]]
^for[i](1;10){
$dyn.$i[$value]
}
Перед выполнением for мы определили, что именно наполняем.
Если предполагается интенсивная работа по изменению содержимого хеша, но необходимо сохранить, скажем, значения по умолчанию, например:
$pets[
$.pet[Собака]
$.food[Косточка]
$.good[Ошейник]
]
$pets_copy[^hash::create[$pets]]
Delete. Удаление файлов данных с диска
^hashfile.delete[]Удаляет с диска файлы, в которых хранятся данные хеш файла.
Delete. Удаление пары ключ/значение
^hashfile.delete[ключ]Метод удаляет из файла пару ключ/значение.
Delete. Удаление пары ключ/значение
^хеш.delete[ключ]Метод удаляет из хеша пару ключ/значение.
Foreach. Перебор ключей хеша
^хеш.foreach[ключ;значение]{тело}^хеш.foreach[ключ;значение]{тело}[разделитель]
^хеш.foreach[ключ;значение]{тело}{разделитель}
Метод аналогичен методу menu класса table. Перебирает все ключи хеша и соответствующие им значения (порядок перебора не определен).
ключ - имя переменной, которая возвращает имена ключей
значение - имя переменной, которая возвращает соответствующие значения ключей
тело - код, исполняемый для каждой пары ключ-значение хеша
разделитель - код, который выполняется перед каждым непустым не первым телом
Foreach. Перебор ключей хеша
^hashfile.foreach[ключ;значение]{тело}^hashfile.foreach[ключ;значение]{тело}[разделитель]
^hashfile.foreach[ключ;значение]{тело}{разделитель}
Перебирает все ключи хеша и соответствующие им значения (порядок перебора не определен). Метод аналогичен foreach класса hash.
Hash. Преобразование к обычному hash
^hashfile.hash[]Преобразует hashfile в обычный хеш.
Хеш (ассоциативный массив)
Хеш, или ассоциативный массив - позволяет хранить ассоциации между строковыми ключами и произвольными значениями. Создание хеша происходит автоматически при таком присваивании переменной значения или вызове метода:$имя[
$.ключ1[значение]
$.ключ2[значение]
. . .
$.ключN[значение]
]
или
^метод[
$.ключ1[значение]
$.ключ2[значение]
. . .
$.ключN[значение]
]
Также можно создать пустой копию другого хеша, см. «Класс hash, create. Создание пустого и копирование хеша».
Получение значений ключей хеша:
$имя.ключ
Хеш позволяет создавать многомерные структуры, например, hash of hash, где значениями ключей хеша выступают другие хеши.
$имя[
$.ключ1_уровня1[$.ключ1_уровня2[значение]]
. . .
$.ключN_уровня1[$.ключN_уровня2[значение]]
]
Intersection. Пересечение хешей
^хеш_a.intersection[хеш_b]Метод выполняет пересечение двух хешей. Возвращает хеш, содержащий ключи, принадлежащие как хешу a, так и b. Результат необходимо присваивать новому хешу.
Intersects. Определение наличия пересечения хешей
^хеш_a.intersects[хеш_b]Метод определяет наличие пересечения (одинаковых ключей) двух хешей. Возвращает булевое значение "истина", если пересечение есть, или "ложь" в противном случае.
Использование хеша вместо таблицы
$хеш.fields - сам хеш.Для большей взаимозаменяемости таблиц и хешей поле fields хранит ссылку на сам хеш. См. table.fields.
Как работать с документацией
Данное руководство состоит из трех частей.В первой, учебной части рассматриваются практические задачи, решаемые с помощью Parser. На примере создания учебного сайта показаны базовые возможности языка и основные конструкции. Для создания кода можно пользоваться любым текстовым редактором. Желательно, чтобы в нем был предусмотрен контроль над парностью скобок с параллельной подсветкой, поскольку при увеличении объема кода и его усложнении становится сложно следить за тем, к чему относится та или иная скобка, и эта возможность существенно облегчит ваш труд. Также поможет в работе и выделение цветом конструкций языка. Читать и редактировать код станет намного проще.
Учебная часть построена в виде уроков, в начале которых предлагается рабочий код, который можно просто скопировать в нужные файлы. Далее подробно разбирается весь пример с объяснением логики его работы. В конце каждого урока тезисно перечислены все основные моменты, а также даны рекомендации, на что надо обратить особое внимание. Внимательное изучение представленных уроков обеспечит вас необходимым запасом знаний для последующей самостоятельной работы над проектами на Parser.
Во второй части представлен справочник по синтаксису языка и подробно рассмотрены правила описания различных конструкций.
Третья часть представляет собой справочник операторов и базовых классов языка с описанием методов и краткими примерами их использования.
В приложениях к документации рассмотрены вопросы установки и конфигурирования Parser.
_Keys. Список ключей хеша
^хеш._keys[]^хеш._keys[имя столбца] [3.1.2]
Метод возвращает таблицу (объект класса table), содержащую единственный столбец, где перечислены все ключи хеша (порядок перечисления не определен).
Имя столбца - «key» или переданное имя.
Класс hash
Класс предназначен для работы с хешами - ассоциативными массивами. Хеш считается определенным (def), если он не пустой. Числовым значением хеша является число ключей (значение, возвращаемое методом ^хеш._count[]).Класс hashfile [3.1.2]
Класс предназначен для работы с хешами, хранящимися на диске. В отличие от класса hash объекты данного класса считаются всегда определенным (def) и не имеют числового значения.Если класс hash хранит свои данные в оперативной памяти, hashfile хранит их на диске, причем можно отдельно задавать время хранения каждой пары ключ-значение.
Замечание: в настоящий момент для хранения одного hashfile используются два файла: .dir и .pag.
Чтение и запись данных происходит очень быстро - идет работа только с необходимыми фрагментами файлов данных.
На простых задачах hashfile работает значительно быстрее баз данных.
Замечание: в один момент времени с файл может изменяться только одним скриптом, остальные ждут окончания его работы.
Конструкторы
Обычно хеши создаются не конструкторами, а так, как описано в разделе "Конструкции языка Parser".Open. Открытие или создание
^hashfile::open[имя файла]Открывает имеющийся на диске файл или создает новый.
Для хранения данных в настоящий момент используются два файла, с суффиксами .dir и .pag.
Поля
В качестве поля хеша выступает ключ, по имени которого можно получить значение:$my_hash.key
Такая запись возвратит значение, поставленное в соответствие ключу. Если происходит обращение к несуществующему ключу, будет возвращено значение ключа _default, если он задан в хеше.
Для большей взаимозаменяемости таблиц и хешей поле fields хранит ссылку на сам хеш, см. «Использование хеша вместо таблицы».
В выражениях числовое значение хеша
$man[$.name[Вася]
$.age[22]
$.sex[m]
]
^man._count[]
Вернет: 3.
В выражениях числовое значение хеша равно количеству ключей:
^if($man > 2){больше}
Будет создан файл
$man[$.name[Вася]
$.age[22]
$.sex[m]
]
$tab_keys[^man._keys[]]
^tab_keys.save[keys.txt]
Будет создан файл keys.txt с такой таблицей:
key
sex
age
name
Новое содержание хеша
$man[$.name[Вася]
$.age[22]
$.sex[m]
]
$woman[
$.name[Маша]
$.age[20]
$.weight[50]
]
^man.add[$woman]
Новое содержание хеша $man:
$man[
$.name[Маша]
$.age[20]
$.sex[m]
]
с ним значение из хеша
^man.delete[name]Удалит ключ name и связанное с ним значение из хеша man.
желательно некоторую информацию получить от
Допустим, желательно некоторую информацию получить от посетителя на одной странице сайта, и иметь возможность отобразить ее - на другой странице сайта. Причем необходимо, чтобы посетитель не мог ее ни увидеть ни подделать.Можно поместить информацию в hashfile, ассоциировав ее со случайной строкой - идентификатором «сеанса общения с посетителем». Идентификатор сеанса общения можно поместить в cookie, данные теперь хранятся на сервере, не видны посетителю и не могут быть им подделаны.
# создаем/открываем файл с информацией
$sessions[^hashfile::open[/sessions]]
^if(!def $cookie:sid){
$cookie:sid[^math:uuid[]]
}
# после этого…
$information_string[произвольное значение]
# …так запоминаем произвольную $information_string под ключом sid на 2 дня
$sid[$cookie:sid]
$sessions.$sid[$.value[$information_string] $.expires(2)]
# …а так можем считать сохраненное ранее значение
# если с момента сохранения прошло меньше 2х дней
$sid[$cookie:sid]
$information_string[$sessions.$sid]
Выведет на
$man[$.name[Вася]
$.age[22]
$.sex[m]
]
^man.foreach[key;value]{
$key=$value
}[
]
Выведет на экран:
sex=m
age=22
name=Вася
Получится хеш
$man[$.name[Вася]
$.age[22]
$.sex[m]
]
$woman[
$.name[Маша]
$.age[20]
$.weight[50]
]
$int_hash[^man.intersection[$woman]]
Получится хеш $int_hash:
$int_hash[
$.name[Вася]
$.age[22]
]
^if
^if(^man.intersects[$woman]){Пересечение есть
}{
Не пересекаются
}
man останется только один ключ
$man[$.name[Вася]
$.age[22]
$.sex[m]
]
$woman[
$.name[Маша]
$.age[20]
]
^man.sub[$woman]
В результате в хеше $ man останется только один ключ $man.sex со значением m.
Получится хеш
$man[$.name[Вася]
$.age[22]
$.sex[m]
]
$woman[
$.name[Маша]
$.age[20]
$.weight[50]
]
$union_hash[^man.union[$woman]]
Получится хеш $union_hash:
$union_hash[
$.name[Вася]
$.age[22]
$.sex[m]
$.weight[50]
]
hash of bool[3.1.2]
В БД содержится таблица participants:participant
Константин
Александр
Выполнение кода…
^connect[строка подключения]{
$participants[^hash::sql{select participant from participants}]
}
…даст хеш такой структуры…
$participants[
$.Константин(1)
$.Александр(1)
]
…из которого можно эффективно извлекать информацию, например, так:
$person[Иван]
$person ^if($participants.$person){участвует}{не участвует} в мероприятии
hash of hash
В БД содержится таблица hash_table:pet food aggressive
cat milk very
dog bone never
Выполнение кода…
^connect[строка подключения]{
$hash_of_hash[^hash::sql{select
pet, food, aggressive
from
hash_table
}]
}
…даст хеш такой структуры…
$hash_of_hash[
$.cat[
$.food[milk]
$.aggressive[very]
]
$.dog[
$.food[bone]
$.aggressive[never]
]
]
…из которого можно эффективно извлекать информацию, например, так:
$animal[cat]
$animal любит $hash_of_hash.$animal.food
Sql. Создание хеша на основе выборки из базы данных
^hash::sql{запрос}^hash::sql{запрос}[$.limit(n) $.offset(o) $.distinct(d)]
Конструктор создает хеш, в котором имена ключей совпадают со значениями первого столбца выборки. Имена столбцов формируют ключи хеша, а значения столбцов - соответствующие этим ключам значения. Если столбцов больше одного, получается структура hash of hash.
Если же запрос возвращает только один столбец, формируется хеш, где значения столбца формируют ключи хеша, и им ставится в соответствие логическое значение истина. [3.1.2]
Дополнительные параметры конструктора:
$.limit(n) - получить только n записей
$.offset(o) - отбросить первые o записей выборки
$.distinct(1/0) - 1=отбирать записи с уникальным ключом, 0=считать наличие дубликата ошибкой
По-умолчанию, наличие в ключевом столбце одинаковых значений считается ошибкой, если вам необходимо именно отобрать из результата записи с уникальным ключом, задайте опцию $.distinct(1).
Примечание: имейте в виду, что так между клиентом и сервером передаются лишние данные, и, скорее всего, запрос можно изменить, чтобы необходимая уникальность ключа обеспечивалась SQL-сервером. Если вам необходимы данные и в виде таблицы и в виде хеша, подумайте над использованием table::sql в паре с table.hash.
Sub. Вычитание хешей
^хеш.sub[хеш-вычитаемое]Метод вычитает из хеша другой хеш-вычитаемое, удаляя ключи, общие для обоих хешей.
Union. Объединение хешей
^хеш_a.union[хеш_b]Метод выполняет объединение двух хешей. Возвращает хеш, содержащий все ключи хеша a и те из b, которых нет в a. Результат необходимо присваивать новому хешу.
Запись
$hashfile.ключ[строка]Сохраняет на диск ассоциацию между ключом и строкой.
$hashfile.ключ[
$.value[строка]
$.expires(число дней)
]
$hashfile:ключ[
$.value[строка]
$.expires[дата]
]
Такая запись позволяет указать дату устаревания ассоциации. Можно указать число дней или конкретную дату.
Необязательные модификаторы:
$.expires(число дней) - задает число дней (может быть дробным, 1.5=полтора дня), на которое сохраняется пара ключ/строка, 0 дней=навсегда;
$.expires[$date] - задает дату и время, до которой будет храниться ассоциация, здесь $date - переменная типа date.
А что это вообще такое?
Arc. Рисование дуги
^картинка.arc(centerx;center y;width;height;start in degrees;end in degrees;color)Метод рисует дугу с заданными параметрами. Дуга представляет собой часть эллипса (как частный случай окружности) и задается координатами центра X и Y, шириной, высотой, а также начальным и конечным углом, задаваемым в градусах.
Bar. Рисование закрашенных прямоугольников
^картинка.bar(x0;y0;x1;y1;цветпрямоугольника)Метод рисует на изображении закрашенный заданным цветом прямоугольник по заданным координатам.
Circle. Рисование неокрашенной окружности
^картинка.circle(centerx;center y;радиус;цвет линии)Метод рисует окружность заданного радиуса линией заданного цвета относительно центра с координатами X и Y.
Copy. Копирование фрагментов изображений
^картинка.copy[исходное_изображение](x1;y1;ширина1;высота1;x2;y2)^картинка.copy[исходное_изображение](x1;y1;ширина1;высота1;x2;y2;ширина2;высота2;приближение цвета)Метод копирует фрагмент одного изображения в другое изображение. Это очень удобно использовать в задачах, подобных расставлению значков на карте. В качестве параметров методу передаются:
| 1. | Исходное изображение
|
| 2. | координаты (X1;Y1) верхнего левого угла копируемого фрагмента |
| 3. | ширина и высота копируемого фрагмента |
| 4. | координаты (X2;Y2) по которым будет вставлен копируемый фрагмент |
| 5. | в качестве необязательных параметров могут быть заданы новая ширина и высота вставляемого фрагмента (в этом случае происходит масштабирование), а также величина, характеризующая точность передачи цвета. Чем она меньше, тем точнее цветопередача, но количество передаваемых цветом уменьшается и наоборот (по умолчанию равна 150) |
Create. Создание объекта с заданными размерами
^image::create(размерX; размер Y)^image::create(размер X; размер Y; цвет фона)
Создает объект класса image размером X на Y. В качестве необязательного параметра можно задать произвольный цвет фона. Если этот параметр пропущен, созданное изображение будет иметь белый цвет фона.
Fill. Закрашивание одноцветной области изображения
^картинка.fill(x;y;цвет)Метод используется для закрашивания областей изображения, окрашенных в одинаковый цвет, новым цветом. Область закрашивания определяется относительно точки с координатами X и Y.
Font. Загрузка файла шрифта для
^картинка.font[набор_букв;имя_файла_шрифта.gif](ширина_пробела)^картинка.font[набор_букв;имя_файла_шрифта.gif](ширина_пробела;ширина_символа)
Помимо методов для рисования, Parser также предусматривает возможность нанесения надписей на рисунки. Для реализации этой возможности требуется наличие специальных файлов с изображением шрифтов. Можно либо использовать готовые файлы шрифтов, либо самостоятельно создавать собственные с нужным набором символов.
После загрузки такого файла с помощью метода font набору букв, заданных в параметрах метода, ставятся в соответствие фрагменты изображения из файла. Данный файл должен быть в формате GIF с прозрачным фоном и содержать изображение необходимого набора символов в следующем виде:
Пример файла digits.gif с изображением цифр:
0
1
2
3
4
5
6
7
8
9
Высота каждого символа определяется как отношение высоты рисунка к количеству букв в наборе.
Методу передаются следующие параметры:
Набор букв - перечень символов, входящих в файл шрифта
Имя и путь к файлу шрифта
Ширина символа пробела (в пикселах)
Ширина символа - необязательный параметр
По умолчанию, при загрузке файла шрифта автоматически измеряется ширина всех его символов и при выводе текста используется пропорциональный (proportional) шрифт. Если задать ширину символа, то шрифт будет моноширинным.
Все символы следует располагать непосредственно у левого края изображения.
Format. Вывод числа в заданном формате
^имя.format[форматнаястрока]Метод выводит значение переменной в заданном формате (см. Форматные строки).
Gif. Кодирование объектов класса image в формат GIF
^картинка.gif[]^картинка.gif[имя файла] [3.1.2]
Используется для кодирования созданных Parser объектов класса image в формат GIF.
Имя файла будет передано посетителю при $response:download.
Внимание: в результате использования этого метода создается новый объект класса file, а не image!
Кроме того, необходимо учитывать тот факт, что цвета выделяются из палитры, и, когда палитра заканчивается, начинается подбор ближайших цветов. В случае создания сложных изображений, особенно с предварительно загруженным фоном, следует иметь в виду последовательность захвата цветов.
Html. Вывод изображения
^картинка.html[]^картинка.html[хеш]
Создает следующий HTML-тег:
В качестве параметра методу может быть передан хеш, содержащий дополнительные атрибуты изображения, например alt и border, задающие надпись, появляющуюся при наведении курсора и ширину рамки.
Замечание: атрибуты изображения можно переопределять.
Inc, dec, mul, div, mod. Простые операции над числами
^имя.inc(число)
^имя.dec(число)
Int, double. Преобразование объектов к числам
или
или
Преобразуют значение переменной $имя к целому или вещественному числу соответственно, и возвращает это число. При преобразовании вещественного числа к целому производится округление.
Можно задать значение по умолчанию, которое будет получено, если преобразование невозможно. Значение по умолчанию можно использовать при обработке данных, получаемых интерактивно от пользователей. Это позволит избежать появления текстовых значений в математических выражениях при вводе некорректных данных, например, строки вместо ожидаемого числа.
Внимание: пустая строка и строка состоящая только из "white spaces" (символы пробела, табуляция, перевода строки) считается нулем.
Класс image
Класс для работы с графическими изображениями. Объекты класса image бывают двух типов. К первому относятся объекты, созданные на основе существующих изображений в поддерживаемых форматах. Ко второму - объекты, формируемые самим Parser.Из JPEG файлов можно получить EXIF информацию (http://www.exif.org).
Для представления цветов используется схема RGB, в которой каждый оттенок цвета представлен тремя составляющими компонентами (R-красный, G-зеленый, B-синий). Каждая составляющая может принимать значение от 0x00 до 0xFF (0 - 255 в десятичной системе). Итоговый цвет представляет собой целое число вида 0xRRGGBB, где под каждую составляющую компоненту отведено два разряда в указанной последовательности. Формула для вычисления цвета следующая:
(R*0x100+G)*0x100+B
Так, для белого цвета, у которого все компоненты имеют максимальное значение - FF, данная формула при подстановке дает:
(0xFF*0x100+0xFF)*0x100+0xFF = 0xFFFFFF
Классы int, double
Объектами классов int и double являются целые и вещественные числа, как заданные пользователем, так и полученные в результате вычислений или преобразований. Числа, относящиеся к классу double, имеют представление в формате с плавающей точкой. Диапазон значений зависит от платформы, но, как правило:|
для int |
от -2147483648 |
до 2147483647 |
|
для double |
от 1.7E-308 |
до 1.7E+308 |
Length. Получение длины надписи в пикселах
^картинка.length[текстнадписи]Метод вычисляет полную длину надписи в пикселах.
Line. Рисование линии на изображении
^картинка.line(x0;y0;x1;y1;цвет)Метод рисует на изображении линию из точки с координатами (х0:y0) в точку (x1:y1) заданного цвета.
Load. Создание объекта на основе
^image::load[имя_файла.gif]Создает объект класса image на основе готового фона. Это дает возможность использовать готовые изображения в формате GIF в качестве подложки для рисования, что может использоваться для создания графиков, графических счетчиков и т.п.
Measure. Создание объекта на основе
^image::measure[файл]^image::measure[имяфайла]
Создает объект класса image, измеряя размеры существующего графического файла или объекта класса file в поддерживаемом формате (сейчас поддерживаются GIF, JPEG и PNG).
Из JPEG файлов также считывается EXIF информация (http://www.exif.org), если она там записана. Большинство современных цифровых фотоаппаратов при записи JPEG файла записывают в него также информацию о снимке, параметрах экспозиции и другую информацию в формате EXIF.
Сама картинка не считывается, основное назначение метода - последующий вызов для созданного объекта метода html.
Параметры:
Файл - объект класса file
Имя файла - имя файла с путем
Примечание: поддерживается EXIF 1.0, считываются теги из IFD0 и SubIFD.
Методы рисования
Данные методы используются только для объектов класса image, созданных с помощью конструкторов create и load. С их помощью можно рисовать линии и различные геометрические фигуры на изображениях и закрашивать области изображений различными цветами. Это дает возможность создавать динамически изменяемые картинки для графиков, графических счетчиков и т.п.Отсчет координат для графических объектов ведется с верхнего левого угла, точка с координатами (0:0).
Описание формата файла, описывающего кодировку
Данные в формате tab-delimited со следующими столбцами:char - символ, или его код, заданный в десятичной или шестнадцатеричной форме
(0xHH) в той кодировке, которую определяет этот файл.
white-space, digit, hex-digit, letter, word - набор флажков, задающих класс этого символа. Пустое содержимое означает непринадлежность символа к этому классу, непустое [например, 'x'] - принадлежность.
Подробнее о символьных классах см. описание регулярных выражений в литературе.
lowercase - если символ имеет пару в нижнем регистре, то символ или код парного символа. Скажем, у буквы 'W' есть парная 'w'. Используется в регулярных выражениях для поиска, нечувствительного к регистру символов, а также в методах lower и upper класса string.
unicode1 - основной Unicode код символа. Если совпадает с кодом символа, то можно не указывать. Скажем, у буквы 'W' он совпадает, а у буквы 'Я' - нет.
unicode2 - дополнительный Unicode символа, если имеется.
Pixel. Работа с точками изображения
^картинка.pixel(x;y)Выдает цвет указанной точки изображения. Если координаты попадают за пределы изображения, выдает -1.
^картинка.pixel(x;y;цвет)
Задает цвет указанной точки.
Поля
| $картинка.src |
Polybar. Рисование окрашенных
^картинка.polybar(цветмногоугольника)[таблица с координатами узлов]Метод рисует многоугольник заданного цвета по координатам узлов, задаваемым в таблице. Последний узел автоматически соединяется с первым.
Polygon. Рисование неокрашенных
^картинка.polygon(цветлинии)[таблица с координатами узлов]Метод рисует линией заданного цвета многоугольник по координатам узлов, задаваемым в таблице. Последний узел автоматически соединяется с первым.
Polyline. Рисование ломаных линий по координатам узлов
^картинка.polyline(цвет)[таблицас координатами точек]Метод рисует линию по координатам узлов, задаваемым в таблице. Он используется для создания ломаных линий.
В браузере будет выведен черный
$square[^image::create(100;100;0x000000)]^square.arc(50;50;40;40;0;90;0xFFFFFF)
$response:body[^square.gif[]]
В браузере будет выведен черный квадрат с дугой в четверть (от 0 до 90 градусов) окружности радиусом 40 пикселов.
В браузере будет выведен черный
$square[^image::create(100;100;0x000000)]^square.bar(5;40;95;60;0xFFFFFF)
$response:body[^square.gif[]]
В браузере будет выведен черный квадрат размером 100 на 100 пикселов, внутри которого находится белый прямоугольник 90 x 20 пикселов, нарисованный по заданным координатам.
В браузере будет выведен черный
$square[^image::create(100;100;0x000000)]^square.circle(50;50;10;0xFFFFFF)
$response:body[^square.gif[]]
В браузере будет выведен черный квадрат с окружностью радиусом в десять пикселов, нарисованной линией белого цвета с центром в точке (50;50).
В данном примере мы создаем
$mygif[^image::load[test.gif]]$resample_width($mygif.width*2)
$resample_height($mygif.height*2)
$mygif_new[^image::create($resample_width;$resample_height)]
^mygif_new.copy[$mygif](0;0;20;30;0;0;$mygif_new.width;$mygif_new.height)
$response:body[^mygif_new.gif[]]
В данном примере мы создаем два объекта класса image. Первый создан на основе существующего GIF файла. Второй - вдвое больший по размеру, чем первый, создается самим Parser, после чего в него мы копируем фрагмент первого размером 20х30 и «растягиваем» этот фрагмент на всю ширину и высоту второго рисунка. Последняя строчка кода выводит увеличенный фрагмент на экран. Данный подход можно применять только для изображений, которые не требуется выводить с хорошим качеством.
Будет создан объект square класса
$square[^image::create(100;100;0x000000)]Будет создан объект square класса image размером 100х100 c черным цветом фона.
в этом файле. Если снимок
$photo[^image::measure[photo.jpg]]Имя файла: $photo.src
Ширина изображения в пикселах: $photo.width
Высота изображения в пикселах: $photo.height
$date_time_original[$photo.exif.DateTimeOriginal]
^if(def $date_time_original){
Снимок сделан ^date_time_original.sql-string[]
}
Будет выведено имя файла, а также ширина и высота изображения, хранящегося в этом файле. Если снимок был сделан цифровым фотоаппаратом, вероятно, будет выведена дата и время съемки.
В браузере будет выведен квадрат
$square[^image::create(100;100;0x000000)]^square.line(0;0;100;100;0xFFFFFF)
^square.fill(10;0;0xFFFF00)
$response:body[^square.gif[]]
В браузере будет выведен квадрат размером 100 на 100 пикселов, перечеркнутый по диагонали белой линией. Нижняя половина квадрата черная, а верхняя закрашена желтым цветом.
В данном случае будет загружен
$square[^image::create(100;100;0x00FF00)]^square.font[0123456789;digits.gif](0)
В данном случае будет загружен файл, содержащий изображения цифр от 0 до 9, и набору цифр от 0 до 9 будет поставлено в соответствие их графическое изображение. После того, как определен шрифт для нанесения надписи, можно использовать метод text для нанесения надписей.
В браузере будет выведен черный
$square[^image::create(100;100;0x000000)]$response:body[^square.gif[]]
В браузере будет выведен черный квадрат размером 100 на 100 пикселов.
В браузере будет выведена картинка
$photo[^image::measure[myphoto.jpg]]^photo.html[
$.border[0]
$.alt[Это я в молодости…]
]
В браузере будет выведена картинка из переменной $photo. При наведении курсора будет появляться надпись: это я в молодости…
В результате будет вычислена длина
$square[^image::create(100;100;0x00FF00)]^square.font[0123456789;digits.gif](0)
^square.length[128500]
В результате будет вычислена длина надписи «128500» в пикселах с учетом пробелов.
В браузере будет выведен черный
$square[^image::create(100;100;0x000000)]^square.line(0;0;100;100;0xFFFFFF)
$response:body[^square.gif[]]
В браузере будет выведен черный квадрат размером 100 на 100 пикселов перечеркнутый по диагонали белой линией.
Будет создан объект класса image
$background[^image::load[counter_background.gif]]Будет создан объект класса image на основе готового изображения в формате GIF. Этот объект может впоследствии использоваться для подложки в методах рисования.
В браузере будет выведен равнобедренный
$rectangle_coordinates[^table::create{x y0 0
50 100
100 0
}]
$square[^image::create(100;100;0x000000)]
^square.polybar(0x00FF00)[$rectangle_coordinates]
$response:body[^square.gif[]]
В браузере будет выведен равнобедренный треугольник зеленого цвета на черном фоне. В таблице заданы координаты вершин треугольника.
В браузере будет выведен равнобедренный
$rectangle_coordinates[^table::create{x y0 0
50 100
100 0
}]
$square[^image::create(100;100;0x000000)]
^square.polygon(0x00FF00)[$rectangle_coordinates]
$response:body[^square.gif[]]
В браузере будет выведен равнобедренный треугольник, нарисованный линией зеленого цвета на черном фоне. В таблице заданы координаты вершин треугольника.
В браузере будет выведена буква
$table_with_coordinates[^table::create{x y10 0
10 100
20 100
20 50
50 50
50 40
20 40
20 10
60 10
65 15
65 0
10 0
}]
$square[^image::create(100;100;0xFFFFFF)]
$square.line-style[*** ]
$square.line-width(2)
^square.polyline(0xFF00FF)[$table_with_coordinates]
$file_withgif[^square.gif[]]
^file_withgif.save[binary;letter_F.gif]
$letter_F[^image::load[letter_F.gif]]
^letter_F.html[]
В браузере будет выведена буква F, нарисованная пунктирной линией на белом фоне. В рабочем каталоге будет создан файл letter.gif. В этом примере используются объекты класса image двух различных типов. В таблице задаются координаты точек ломанной линии. Затем на созданном с помощью конструктора create фоне рисуется линия по указанным координатам узлов. Созданный объект класса image кодируется в формат GIF. Полученный в результате этого объект класса file сохраняется на диск. Затем создается новый объект класса image на основе сохраненного файла. Этот объект выводится на экран браузера методом html.
В браузере будет выведен черный
$square[^image::create(100;100;0x000000)]^square.rectangle(5;40;95;60;0xFFFFFF)
$response:body[^square.gif[]]
В браузере будет выведен черный квадрат размером 100 на 100 пикселов, внутри которого находится прямоугольник 90 x 20 пикселов, нарисованный линией белого цвета по заданным координатам.
В браузере будет выведен черный
$paint_nodes[^table::create{x y10 20
90 20
90 80
10 80
}]
$square[^image::create(100;100;0x000000)]
^square.line(0;0;100;100;0xFFFFFF)
^square.line(100;0;0;100;0xFFFFFF)
^square.replace(0x000000;0xFF00FF)[$paint_nodes]
$response:body[^square.gif[]]
В браузере будет выведен черный квадрат, перечеркнутый по диагонали белыми линиями, со вписаным в него розовым прямоугольником. Поскольку в методе replace задана замена на розовый цвет только для черного цвета, белые линии не перекрасились.
В браузере будет выведен черный
$square[^image::create(100;100;0x000000)]^square.sector(50;50;40;40;0;90;0xFFFFFF)
$response:body[^square.gif[]]
В браузере будет выведен черный квадрат с сектором в четверть (от 0 до 90 градусов) окружности радиусом 40 пикселов. Сектор нарисован линией белого цвета.
Для методов рисования будет использоваться
$картинка.line-style[*** ]$картинка.line-width(2)
Для методов рисования будет использоваться пунктирная линия вида:
*** *** *** *** ***
толщиной в два пиксела.
В браузере будет выведен зеленый
$square[^image::create(100;100;0x00FF00)]^square.font[0123456789;digits.gif](0)
^square.text(5;5)[128500]
$response:body[^square.gif[]]
В браузере будет выведен зеленый квадрат с надписью «128500» левая верхняя точка которой находится в точке с координатами (5;5).
и эквивалентен записи
$var(5)^var.inc(7)
^var.dec(3)
^var.div(4)
^var.mul(2)
$var
Пример возвратит 4.5 и эквивалентен записи $var((5+7-3)/4*2).
Вернет количество записей
^connect[строка подключения]{^int:sql{select count(*) from news}
}
Вернет количество записей в таблице news.
Пример работы с EXIF информацией
$image[^image::measure[jpg/DSC00003.JPG]]$exif[$image.exif]
^if($exif){
Производитель фотоаппарата, модель: $exif.Make $exif.Model
Время съемки: ^exif.DateTimeOriginal.sql-string[]
Выдержка: $exif.ExposureTime секунды
Диафрагма: F$exif.FNumber
Использовалась вспышка: ^if(def $exif.Flash){^if($exif.Flash){да;нет};неизвестно}
}{
нет EXIF информации
}
Пример создания тега IMG с указанием размеров изображения
$photo[^image::measure[photo.png]]^photo.html[]
Будет создан объект photo класса image, на основе готового графического изображения в формате PNG, и выдан тег IMG, ссылающийся на данный файл, с указанием width и height.
^var.format
$var(15.67678678)^var.format[%.2f]
Возвратит: 15.68
$var(0x123)
^var.format[0x%04X]
Возвратит: 0x0123
Выведет число 1024, поскольку объект
$str[Штука]^str.int(1024)
Выведет число 1024, поскольку объект str нельзя преобразовать к классу int.
$double(1.5)
^double.int[]
Выведет число 2, поскольку произведено автоматическое округление.
Rectangle. Рисование незакрашенный прямоугольников
^картинка.rectangle(x0;y0;x1;y1;цветлинии)Метод рисует на изображении незакрашенный прямоугольник по заданным координатам с заданным цветом линии.
Replace. Замена цвета в области, заданной таблицей координат
^картинка.replace(старыйцвет;новый цвет)[таблица с координатами точек]Метод используется для замены одного цвета другим в области изображения, заданной с помощью таблицы координат.
Sector. Рисование сектора
^картинка.sector(centerx;center y;width;height;start in degrees;end in degrees;color)Метод рисует сектор с заданными параметрами линией заданного цвета. Параметры метода аналогичны методу arc.
Sql. Получение числа из базы данных
^int:sql{запрос}^int:sql{запрос}[$.limit(1) $.offset(o) $.default{код}]
^double:sql{запрос}
^double:sql{запрос}[$.limit(1) $.offset(o) $.default{код}]
Возвращает число, полученное в результате SQL-запроса к серверу баз данных. Запрос должен возвращать значение из одного столбца одной строки.
|
Запрос |
- запрос к базе данных, написанный на языке SQL |
|
$.offset(o) |
- отбросить первые o записей выборки |
|
$.default{код} |
- если результат SQL-запроса не число, то метод возвратит результат выполнения кода |
Text. Нанесение надписей на изображение
^картинка.text(x;y)[текстнадписи]Метод выводит заданную надпись по указанным координатам (X;Y), используя файл шрифта, предварительно загруженный методом font
Тип и ширина линий
$картинка.line-style[типлинии]$картинка.line-width(толщина линии)
Перед вызовом любых методов рисования можно задавать тип и толщину используемых линий.
Тип линии задается строкой, где пробелы означают отсутствие точек в линии, а любые другие символы - наличие.
Установка и настройка Parser
Parser3 доступен в нескольких вариантах:| · | CGI скрипт (и интепретатор), |
| · | модуль к веб-серверу Apache 1.3, |
| · | ISAPI расширение веб-сервера Microsoft Internet Information Server 4.0 или новее. |
Дополнительно можно установить драйверы для различных SQL-серверов (сейчас доступны для MySQL, PgSQL, Oracle, ODBC).
Описание каталогов и файлов :
parser3[.exe] - CGI скрипт (и интерпретатор)
ApacheModuleParser3.dll - модуль к веб-серверу Apache 1.3
parser3isapi.dll - ISAPI расширение веб-сервера IIS 4.0 или новее
auto.p.dist - пример Конфигурационного файла
parser3.charsets/ - каталог с файлами таблиц кодировок:
|
koi8-r.cfg |
- Cyrillic [KOI8-R] |
|
windows-1250.cfg |
- Central european[windows-1250] |
|
windows-1251.cfg |
- Cyrillic[windows-1251] |
|
windows-1257.cfg |
- Baltic[windows-1257] |
Доступны скомпилированные версии Parser и его SQL-драйверов под ряд платформ (см. http://parser.ru/download/).
Внимание: в целях безопасности они скомпилированы так, что могут читать и исполнять только файлы, принадлежащие тому же пользователю/группе пользователей, от имени которых работает сам Parser.
Как подключаются конфигурационные файлы?
Для CGI скрипта (parser3[.exe]):
конфигурационный файл считывается из файла, заданного переменной окружения CGI_PARSER_CONFIG,
Если переменная не задана, ищется в том же каталоге, где расположен сам CGI скрипт.
Для модуля к Apache путь к конфигурационному файлу задается директивой:
#can be in .htaccess
ParserConfig полный_путь
Для ISAPI расширения (parser3isapi.dll):
конфигурационный файл auto.p ищется в том же каталоге, где расположен сам файл.
Установка Parser на веб-сервер Apache 1.3, модуль сервера
Для установки Parser необходимо внести изменения в основной конфигурационный файл веб-сервера, или, если у вас нет к нему доступа, необходима возможность использовать .htaccess файлы.По-умолчанию, в установке Apache возможность использования .htaccess отключена.
Если она вам необходима, разрешите их использовать (по крайней мере, задавать FileInfo). Для чего в основном конфигурационном файле веб-сервера (обычно httpd.conf) в секцию вашего
<Directory /путь/к/вашему/веб/пространству>
AllowOverride FileInfo
Parser3 самостоятельно выполняет необходимые перекодирования, так что для Русского Apache добавьте в основной конфигурационный файл веб-сервера (обычно httpd.conf) строку:
CharsetDisable On
запрещающую использование возможностей перекодирования Русского Apache для вашего сервера.
Если возможности изменить основной конфигурационный файл веб-сервера у вас нет, добавьте эту строку в .htaccess файл.
Под UNIX:
Необходимо собрать Parser из исходных кодов, задав ключ --with-apache13 у скрипта configure, при make на экране появится инструкция по дальнейшей сборке Apache из его исходных кодов.
Внимание: на некоторых системах стандартный make не работает с make-файлами Parser3, воспользуйтесь GNU вариантом: gmake.
Под Win32:
Поместите файлы с исполняемым кодом модуля Parser (в текущей версии, ApacheModuleParser3.dll) в произвольный каталог.
Если вы используете версию Parser с поддержкой XML, в каталог, указанный в переменной окружения PATH (например, C:\WinNT), распакуйте XML библиотеки.
Добавьте в файл httpd.conf после имеющихся строк LoadModule:
# динамическая загрузка модуля
LoadModule parser3_module x:\path\to\ApacheModuleParser3.dll
Внимание: если необходимо, поместите сопутствующие .dll файлы в тот же каталог.
А после имеющихся строк AddModule (если не имеются, не добавляйте):
# добавление модуля к списку активных модулей
AddModule mod_parser3.c
Внимание: до 3.1.1 версии Parser: AddModule mod_parser3.C (на конце .C большая)
Добавьте в файл .htaccess вашего сайта (или в httpd.conf в секцию
# назначение обработчиком .html страниц
AddHandler parser3-handler html
# задание Конфигурационного файла
ParserConfig x:\path\to\parser3\config\auto.p
# запрет на доступ к .p файлам, в основном, к auto.p
<Files ~ "\.p$">
Order allow,deny
Deny from all
Установка Parser на веб-сервер Apache, CGI скрипт
Для установки Parser необходимо внести изменения в основной конфигурационный файл веб-сервера, или, если у вас нет к нему доступа, необходима возможность использовать .htaccess файлы.По-умолчанию, в установке Apache возможность использования .htaccess отключена.
Если она вам необходима, разрешите их использовать (по крайней мере, задавать FileInfo). Для чего в основном конфигурационном файле веб-сервера (обычно httpd.conf) в секцию
<Directory /путь/к/вашему/веб/пространству>
AllowOverride FileInfo
Parser3 самостоятельно выполняет необходимые перекодирования, так что для Русского Apache добавьте в основной конфигурационный файл веб-сервера (обычно httpd.conf) строку:
CharsetDisable On
запрещающую использование возможностей перекодирования Русского Apache для вашего сервера.
Если возможности изменить основной конфигурационный файл веб-сервера у вас нет, добавьте эту строку в .htaccess файл.
Поместите файл с исполняемым кодом Parser (в текущей версии, parser3) в каталог для CGI-скриптов.
Под Win32: если вы используете версию Parser с поддержкой XML, в этот же каталог распакуйте XML библиотеки.
Добавьте в файл .htaccess вашего сайта (или в httpd.conf в секцию
# назначение обработчиком .html страниц
AddHandler parser3-handler html
Action parser3-handler /cgi-bin/parser3
# запрет на доступ к .p файлам, в основном, к auto.p
<Files ~ "\.p$">
Order allow,deny
Deny from all
Если вас не устраивает расположение конфигурационного файла по умолчанию (см. Установка и настройка Parser), вы можете задать его явно:
# задание переменной окружения с путем к auto.p
SetEnv CGI_PARSER_CONFIG /путь/к/файлу/auto.p
Замечание: для этого необходим модуль mod_env, который по умолчанию установлен.
Об ошибках Parser делает записи в журнал ошибок parser3.log, который, по умолчанию, расположен в том же каталоге, где и CGI-скрипт Parser. Если у Parser нет возможности сделать запись в данный файл, об ошибке будет сообщено в стандартный поток ошибок, и запись об ошибке попадет в журнал ошибок веб-сервера. Если вас не устраивает расположение журнала ошибок parser3.log, вы можете задать его явно:
# задание переменной окружения с путем к parser3.log
SetEnv CGI_PARSER_LOG /путь/к/файлу/parser3.log
Замечание: для этого необходим модуль mod_env, который по умолчанию установлен.
Установка Parser на веб-сервер IIS 5.0 или новее
Поместите файлы с исполняемым кодом модуля Parser (в текущей версии, parser3isapi.dll) в произвольный каталог.Если вы используете версию Parser с поддержкой XML, в каталог, указанный в переменной окружения PATH (например, C:\WinNT), распакуйте XML библиотеки.
После чего назначьте Parser обработчиком .html страниц:
| 1. | Запустите Management Console, нажмите на правую кнопку мыши на названии вашего веб-сервера и выберите Properties. |
| 2. | Перейдите на вкладку Home directory и в разделе Application settings нажмите на кнопку Configuration… |
| 3. | В появившемся окне нажмите на кнопку Add. |
| 4. | В поле Executable введите полный путь к файлу parser3.exe или parser3isapi.dll. |
| 5. | В поле Extension введите строку .html. |
| 6. | Включите опцию Check that file exists. |
| 7. | Нажмите на кнопку OK. |
А что это вообще такое?
Класс junction
Класс предназначен для хранения кода и контекста его выполнения.При обращении к переменным, хранящим в себе junction, Parser выполняет код в сохраненном контексте.
Значение типа junction появляется в переменной…
…при присваивании ей кода:
$junction{Код,присваиваемый переменной: ^do_something[]}
…при передачи кода параметром:
@somewhere[]
^method{Код, передаваемый параметром: ^do_something_else[]}
…
@method[parameter]
#здесь в $parameter придет junction
…при обращении к имени метода класса:
$action[$user:edit]
#$action[$user:delete]
^action[параметр]
Здесь $action хранит ссылку на метод и его класс, вызов action теперь аналогичен вызову ^edit[параметр].
…при обращении к имени метода объекта:
$action[$person.show_info]
^action[full]
Здесь $action хранит ссылку на метод и его объект, вызов action теперь аналогичен вызову ^person.show_info[параметры].
junction выражений и кода
@possible_reminder[age;have_passport]^myif($age>=16 && !$have_passport){
Тебе уже $age лет, пора сходить в милицию.
}
@myif[condition;action][age]
$age(11)
^if($condition){
$action
}
Напоминание: параметр с выражением, это код, вычисляющий выражение, он выполняется - вычисляется выражение - при каждом обращении к параметру внутри вызова.
Здесь оператору myif передан код, печатающий, среди прочего, $age. Выполнение проверки и кода оператор производит в сохраненном (внутри $condition и $action) контексте, поэтому наличие в myif локальной переменной age и ее значение никак не влияет на то, что будет проверено и что напечатано.
Пример проверки наличия метода
^if($some_method is junction){^some_method[параметр]
}{
нет метода
}
Метод some_method, будет вызван только, если определен.
А что это вообще такое?
Что делать дальше: на этом создание
Удачи!Что надо запомнить: Parser использует
Синтаксис работы с объектами:|
$переменная[значение] |
- задаем значение |
|
$переменная |
- получаем значение |
|
$переменная [^имя_класса::конструктор[параметры]] |
- создаем объекта класса имя_класса и присваиваем его переменной |
|
$переменная.имя_поля |
- получаем поле самого объекта, хранящегося в переменной |
|
^переменная.метод[] |
- вызываем действие (метод класса, к которому принадлежит объект, хранящийся в переменной) |
Что надо запомнить:
| · | наряду с методами объектов, создаваемых с помощью конструкторов класса, существуют статические методы. Вы можете непосредственно обращаться к этим методам без предварительного использования конструктора для создания объекта |
| · | в циклах for можно обращаться к счетчику как к переменной по имени и получать его текущее значение |
Поскольку код становится все объемнее, неплохо бы начать снабжать его комментариями, чтобы потом было легче разбираться. В Parser комментариями считается любая строка, начинающаяся со знака #. До сих пор мы не пользовались этим, но в дальнейшем нам пригодится комментирование кода. Следующая строка - пример комментария:
# весь этот текст Parser проигнорирует - это комментарий !!!!
Обязательно комментируйте свой код! В идеале он должен быть самодокументирующимся, а человек, читающий его, должен сразу же понимать о чем идет речь, что из чего следует и т.д. Если этого не сделать, то спустя какое-то время вспомнить что делает та или иная функция станет очень сложно даже вам самим, не говоря уже про остальных. Помните об этом!
Что узнали:
| · | механизм взаимодействия Parser с СУБД MySQL |
| · | как осуществлять различные SQL-запросы к БД (статический метод sql класса void и конструктор sql класса table) |
| · | оператор untaint |
Что узнали:
| · | класс MAIN
|
| · | создание пользовательского класса |
| · | как передавать параметры методам |
Что узнали:
| · | класс xdoc
|
| · | как загружать XML, делать XSLT преобразования, выводить объекты класса xdoc в виде HTML |
Что узнали:
| · | файл auto.p может содержаться не только в корневом каталоге сайта, но и в любом другом, при этом функции, в нем определенные, явно доступны только внутри этого каталога |
| · | переменная-хеш - это массив, нужный для построения ассоциативной связи одних объектов с другими. В нашем случае объектами выступали строки |
| · | статический метод calendar создает таблицу с календарем на текущий месяц |
| · | цикл for позволяет последовательно выполнить определенные действия заданное количество раз |
Циклы
Цикл - процесс многократного выполнения некоторой последовательности действий.В Parser существует два оператора циклов: for, в котором количество повторов тела цикла ограничивается заданными значениями счетчика, и while, где количество повторов зависит от выполнения условия. Для того, чтобы избежать зацикливания, в Parser встроен механизм обнаружения бесконечных циклов. Бесконечным считается цикл, тело которого выполняется более 10000 раз.
в Parser принадлежит конкретному классу,
Любой объект в Parser принадлежит конкретному классу, характеризуется полями и методами именно этого класса. Чтобы он появился, его нужно создать. Делает это конструктор данного класса. Разберитесь с этой терминологией, это основа.Отвлеклись? Продолжим. Переменной $sections мы присвоили вот что:
^table::load[sections.cfg]
Буквально это означает следующее: мы создали объект класса table при помощи конструктора load. Общее правило для создания объекта записывается так:
^имя_класса::конструктор[параметры_конструктора]
Подробности в разделе «Передача параметров».
В качестве параметра конструктору мы передали имя файла с таблицей и путь к нему.
Теперь переменная $sections содержит таблицу с разделами нашего сайта. Parser считает ее объектом класса table и точно знает, какие действия с ней можно выполнить. Пока нам понадобится только один метод этого класса - menu, который последовательно перебирает все строки таблицы. Также нам потребуются значения из полей самой таблицы. Синтаксис вызова методов объекта:
^объект.метод_класса[параметры]
Получение значений полей объекта (мы ведь имеем дело с вполне определенной таблицей с заданными нами же полями):
$объект.имя_поля
Знания, полученные выше, теперь позволяют без труда разобраться в последней части нашего кода:
Мы формируем HTML-таблицу, в каждый столбец которой помещаем значения, содержащиеся в полях нашей таблицы $sections: uri - адрес и name - имя. При помощи метода menu мы автоматически перебираем все строки таблицы. Таким образом, даже если у нас будет несколько десятков разделов, ни один из них не будет потерян или пропущен. Мы можем свободно добавлять разделы, удалять их и даже менять местами. Изменения вносятся только в файл sections.cfg. Логика работы не нарушится. Все просто и красиво.
Давайте подведем итоги первого урока.
Меню навигации
Давайте начнем с самого начала. Итак, вы хотите сделать сайт (узел, сервер). Первым делом, необходимо уяснить, каким образом на сайте будет упорядочена та или иная информация. Сколько будет категорий, подразделов т.д. Все эти вопросы возникают на первом этапе - "Организация сайта".А какой должна быть навигация сайта? Требований к хорошей навигации много. Она должна быть понятна, легко узнаваема, единообразна, удобна в использовании, быстро загружаться, давать четкое понятие о текущем местоположении. При этом на сайте не должно возникать 404-й ошибки, т.е. все ссылки должны работать. Если у вас есть опыт создания сайтов, то вам, скорее всего, приходилось сталкиваться с проблемой создания грамотной навигации.
Не правда ли, хочется иметь какое-то решение, которое всегда будет под рукой и позволит автоматизировать весь этот процесс? Что-то такое, что даст возможность единственный раз написать код и потом, в одном месте, дописывать столько разделов, сколько нужно?
Создание меню, которое ориентирует пользователя на сайте, не дает ему заблудиться - вот задача, с которой нам хочется начать повествование о Parser. Почему именно это? Прежде всего потому, что большое количество тегов:
трудно контролировать. А если вам понадобится добавить еще один раздел? Придется в каждую страницу вносить изменения, а человеку свойственно делать ошибки. При этом отнюдь не исключено, что после такой «модернизации» ваш ресурс в ответ на запросы пользователей сообщит о том что «данная страница не найдена». Вот где проблема, которую с помощью Parser можно решить очень легко.
Решение следующее. Мы создаем некую функцию на Parser, которая будет генерировать нужный нам фрагмент HTML-кода. В терминологии Parser функции называются методами. В тех местах, где этот код понадобится, будем просто давать указание «Вставить меню навигации» и сразу же будет создана страница, содержащая меню. Для этого сделаем несколько простых шагов:
1. Всю информацию о наших ссылках будем хранить в одном файле, что позволит впоследствии вносить необходимые изменения только в нем. В корневом каталоге будущего сайта создаем файл sections.cfg, в который помещаем следующую информацию:
|
section_id |
name |
uri |
|
1 |
Главная |
/ |
|
2 |
Новости |
/news/ |
|
3 |
Контакты |
/contacts/ |
|
4 |
Цены |
/price/ |
|
5 |
Ваше мнение |
/gbook/ |
Здесь используется так называемый формат tab-delimited. Столбцы разделяются знаком табуляции, а строки - переводом каретки. При копировании этой таблицы в текстовый редактор данное форматирование будет создано автоматически, но если вы будете создавать таблицу вручную, необходимо это учитывать. Для таблиц ВСЕГДА применяется формат tab-delimited.
2. В том же каталоге, где и sections.cfg, создаем файл auto.p
В нем мы будем хранить все те кирпичики, из которых впоследствии Parser соберет наш сайт. AUTO означает, что все эти кирпичики будут всегда доступны для Parser в нужный момент, а расширение ".p", как вы, наверное, догадались, это… правильно! Он самый!
3. В файл auto.p вставим следующий код:
@navigation[]
$sections[^table::load[sections.cfg]]
Данные из этого файла и будут служить основой для нашего навигационного меню.
Вот и все, подготовительные работы закончены. Теперь открываем код страницы, где все это должно появиться (например, index.html), и говорим: «Вставить меню навигации». На Parser это называется «вызов метода» и пишется так:
^navigation[]
Осталось только открыть в браузере файл, в который мы вставили вызов метода и посмотреть на готовое меню навигации. Теперь в любом месте на любой странице мы можем написать заветное ^navigation[], и Parser вставит туда наше меню. Страница будет сформирована «на лету». Что хотели, то и получили.
Если у вас дела обстоят именно так, то поздравляем - вы вступили в мир динамических сайтов. Очень скоро вы также запросто будете использовать базы данных для формирования страниц и делать многое другое.
Однако не будем радоваться раньше времени. Давайте разберемся, что же мы сделали, чтобы добиться такого результата. Взгляните на код в auto.p. Если кажется, что все непонятно, не надо бежать прочь. Уверяем, через несколько минут все встанет на свои места. Итак, посмотрим на первую строчку:
@navigation[]
Она аналогична строке ^navigation[], которую мы вставили в текст страницы для создания меню. Различие только в первом символе: ^ и @. Однако логический смысл этого выражения совершенно иной - здесь мы определяем метод, который вызовем позже. Символ @ (собака) в первой колонке строки в Parser означает, что мы хотим описать некоторый блок, которым воспользуемся в дальнейшем. Следующее слово определяет имя нашего метода: navigation. Это только наше решение, как ее назвать. Вполне допустимы имена: а_ну_ка_вставь_меню_быстро. Но читаться такая программа будет хуже, впрочем, кому как понятнее, можете назвать и так.
Жизненно необходимо давать простые, понятные имена. Они должны точно соответствовать тому, что именуемый объект будет хранить и делать. Сохраните нервы и время себе и всем тем, кому придется разбираться в ваших текстах, отнеситесь, пожалуйста, к именам внимательно. Имена могут быть русские или латинские, главное соблюдать единообразие: или все по-русски, или по-английски.
Идем дальше.
$sections[^table::load[sections.cfg]]
Это ключевая строка нашего кода. Она достаточно большая, поэтому давайте разберем ее по частям.
Строка начинается символом $ (рубль) и следующим сразу за ним именем sections. Так в Parser обозначаются переменные. Это надо запомнить. Все просто: видим в тексте $var - имеем дело с переменной var. Переменная может содержать любые данные: числа, строки, таблицы, файлы, рисунки и даже часть кода. Присвоение переменной $parser_home_url значения www.parser3.ru на Parser выглядит так: $parser_home_url[www.parser3.ru]. После этого мы можем обратиться к переменной по имени, т.е. написать $parser_home_url и получить значение www.parser3.ru.
Еще раз тоже самое:
|
$var[…] |
- присваиваем |
|
$var |
- получаем |
В нашем случае переменная $sections будет хранить таблицу из файла sections.cfg.
Любую таблицу Parser рассматривает как самостоятельный объект, с которым он умеет производить только вполне определенные действия, например, добавить или удалить из нее строку. Поскольку переменная может хранить любые данные, необходимо указать, что присвоенное нами переменной значение является именно таблицей.
Лирическое отступление.
Пример из жизни. Всю автомобильную технику можно грубо разделить на несколько классов: легковые автомашины, грузовики, трактора и гусеничная техника. Любой автомобиль является объектом одного из этих классов. Вы легко можете определить, к какому классу относится автомобиль, поскольку их всех объединяют общие характеристики, такие как вес, масса перевозимого груза и т.д. Любой автомобиль может совершать действия: двигаться, стоять или ломаться. Каждый из автомобилей обладает своими собственными свойствами. И самое главное, автомобиль не может появиться сам собой, его нужно создать. Когда конструктор придумывает новую модель автомобиля, он точно знает, автомобиль какого класса он создает, какими свойствами будет наделено его творение и что оно сможет делать. Также и в Parser: каждый объект относится к определенному классу, объект класса создается конструктором этого класса и наделен характеристиками (полями) и методами (действиями), общими для всех подобных объектов.
Меню навигации и структура страниц
Предыдущий урок мы закончили тем, что определили недостатки в реализации меню. Давайте займемся их устранением. Наше меню выводит лишнюю ссылку на текущую страницу, что нисколько не украшает будущий сайт. Чтобы этого избежать, необходимо проверить, не является ли раздел, на который мы выводим ссылку, текущим. Иными словами, нам нужно сравнить URI раздела, на который собираемся ставить ссылку, с текущим URI. В случае если они совпадают, ссылку на раздел ставить не надо. Дополнительно для удобства пользователей мы изменим в меню навигации цвет столбца текущего раздела.Открываем файл auto.p и меняем его содержимое на:
@navigation[]
$sections[^table::load[/sections.cfg]]
^sections.menu{
^navigation_cell[]
}
$cell_width[^eval(100\$sections)%]
^if($sections.uri eq $request:uri){
}{
}
Что изменилось? На первый взгляд не так уж и много, но функциональность нашего модуля существенно возросла. Мы описали еще один метод - navigation_cell, который вызывается из метода navigation. В нем появилась новая структура:
^if(условие){код если условие "истина"}{код если условие "ложь"}
Что она делает, понять не сложно. В круглых скобках задается условие, в зависимости от того, какое значение возвращает условие, "ложь" или "истина", можно получить разный результат. Также, если в условии записано выражение, значение которого равно нулю, то результат - "ложь", иначе - "истина". Мы используем оператор if для того, чтобы в одном случае поставить ссылку на раздел, а другом нет. Осталось только разобраться с условием. Будем сравнивать на равенство две текстовых строки, в одной из которых - значение URI раздела из таблицы sections, в другой - текущий URI ($request:uri возвращает строку, содержащую URI текущей страницы). Тут возникает вопрос о том, какие же строки равны между собой? Несомненно, только те, которые полностью совпадают и по длине, и по символьному содержанию.
Для сравнения двух строк в Parser предусмотрены следующие операторы:
eq - строки равны (equal): parser eq parser
ne - строки не равны (not equal): parser ne parser3
lt - первая строка меньше второй (less than): parser lt parser3
gt - первая строка больше второй (greater than): parser3 gt parser
le - первая строка меньше или равна второй (less or equal)
ge - первая строка больше или равна второй (greater or equal)
С условием разобрались: если $sections.uri и $request:uri совпадают, ссылку не ставим (а заодно красим столбец в другой цвет - подумаем о наших пользователях, так им будет удобнее), если нет - ставим.
Идем дальше. Меню из первого урока выводило столбцы разной ширины. Ничего страшного, но некрасиво. Проблема решается очень просто: всю ширину меню (100%) делим на количество разделов, которое равно количеству строк в таблице sections. Для этого воспользуемся оператором ^eval() и тем, что можно использовать объекты класса table в математических выражениях. При этом их числовое значение равно числу записей в таблице. Обратите внимание также на то, что мы пользуемся целочисленным делением, используя обратный слеш вместо прямого.
На ^eval() остановимся чуть подробнее. Он позволяет получить результат математического выражения без введения дополнительных переменных, иными словами, хотим что-то посчитать - пишем:
^eval(выражение)[формат]
Использование [формат] дает возможность вывода результата выражения в том виде, который нужен. Форматная строка [%d] отбрасывает дробную часть, [%.2f] дает два знака после запятой, а [%04d] отводит 4 знака под целую часть, дополняя недостающие символы нулями слева. Форматированный вывод нужен, когда необходимо представить число в определенном виде (скажем, 12.44 $ смотрится куда лучше 12.44373434501 $).
Вот, собственно, и все, что касается меню. Теперь оно функционально и готово к использованию.
Наш первый кирпичик для будущего сайта готов. Теперь займемся структурой страниц. Давайте разобьем их на следующие блоки: header - верхняя часть страницы, body - основной информационный блок, включающий также наше меню и footer - нижняя часть страницы. Многие сайты имеют похожую структуру.
Footer будет для всех страниц одинаковым, header - для всех страниц одинаковый по стилю, но с разными текстовыми строками - заголовками страницы, а body будет разный у всех страниц, сохраняя только общую структуру (предположим, два вертикальных информационных блока, соотносящихся по ширине как 3:7). К body отнесем и наше меню.
Каждая из страниц будет иметь следующую структуру:
|
header | |
|
navigation body_additional (30%) |
body_main (70%) |
|
footer |
С footer все очень просто - в auto.p добавляем код:
@footer[]
$now[^date::now[]]
1997-$now.year