--- parser3/operators.ru.txt 2003/11/06 10:25:49 1.130
+++ parser3/operators.ru.txt 2006/12/07 18:35:31 1.186
@@ -50,11 +50,14 @@ Xне сделано, видимо, не будет сделано
%left '-' '+'
%left '*' '/' '%' '\\'
%left NEG /* negation: unary - */
+ !литералы
+ true
+ false
!^if(условие){когда да}{когда нет}
!^switch[значение]{^case[вариант1[;вариант2...]]{действие}^case[DEFAULT]{действие по умолчанию}}
- !^while(условие){тело}
+ !^while(условие){тело}[[разделитель]|{разделитель который выполняется перед непустым очередным не первым телом}]
!^for[i](0;4){тело}[[разделитель]|{разделитель который выполняется перед непустым очередным не первым телом}]
!^use[модуль]
!^try{
@@ -86,25 +89,33 @@ Xне сделано, видимо, не будет сделано
удобно сделать после выставления 401 ошибки
^return[результат] + - отваливает из выполнения метода,
выдавая нестандартный результат
- ^break[] + - обрывает цикл
- ^continue[] + - обрывает итерацию цикла
- !^untaint[[as-is|file-spec|http-header|mail-header|uri|table|sql|js|xml|html|optimized-html]]{код}
+ !^break[] + - обрывает цикл
+ !^continue[] + - обрывает итерацию цикла
+ !^untaint[[as-is|file-spec|http-header|mail-header|uri|sql|js|xml|html|optimized-html]]{код}
default as-is
!^taint[[lang]][код]
default "just tainted, language unknown"
- !^process[[$caller.CLASS|$object|$КЛАСС:CLASS]]{строка, которая будет process-ed, как код}[во что переименовать @main]
+ !^process[[$caller.CLASS|$object|$КЛАСС:CLASS]]{строка, которая будет process-ed, как код}[
+ $.main[во что переименовать @main]
+ $.file[имя файла из которого, якобы, данный текст]
+ $.lineno(номер строки в файле, откуда данный текст. можно отрицательный)
+ ]
!^process..[путь][во что переименовать @main]
по умолчанию, методы компилируются в $self [в случае оператора, $self=$MAIN:CLASS]
!^connect[protocol://строка соединения]]{код с ^sql[...]-ями}
!mysql://user:pass@{host[:port]|[/unix/socket]}/database?
+ ClientCharset=parser-charset << charset in which parser thinks client works
charset=cp1251_koi8&
timeout=3&
compress=1&
- named_pipe=1
+ named_pipe=1&
+ autocommit=1
+ autocommit если выставить в 0, будет делать commit/rollback
!pgsql://user:pass@{host[:port]|[local]}/database?
- client_encoding=win,[to-find-out]&
- datestyle=ISO,SQL,Postgres,European,NonEuropean=US,German,DEFAULT=ISO
+ client_encoding=win,[to-find-out]
+ &datestyle=ISO,SQL,Postgres,European,NonEuropean=US,German,DEFAULT=ISO
+ &ClientCharset=parser-charset << charset in which parser thinks client works
!oracle://user:pass@service?
NLS_LANG=RUSSIAN_AMERICA.CL8MSWIN1251&
@@ -117,8 +128,10 @@ Xне сделано, видимо, не будет сделано
NLS_ISO_CURRENCY ISO currency symbol
NLS_SORT sort sequence
ORA_ENCRYPT_LOGIN=TRUE
+ ClientCharset=parser-charset << charset in which parser thinks client works
- !odbc://DSN=dsn^;UID=user^;PWD=password
+ !odbc://DSN=dsn^;UID=user^;PWD=password^;ClientCharset=parser-charset
+ ClientCharset << charset in which parser thinks client works
для работы connect нужно, чтобы заранее(рекомендуется в системном parser3)
была определена таблица
@@ -149,10 +162,11 @@ odbc c:\drives\y\parser3project\odbc\
ставить такой префикс перед открывающим апострофом, впритык, везде без проблелов
/**имя_поля**/'literal'
!^rem{}
- !^cache[файл](секунд){код}
+ !^cache[файл](секунд){код}[{catch код}]
!относительное задание времени
!скэшировать строку, которая получается при выполнении кода на 'секунд' секунд
!если 0секунд, значит не кэшировать, а старый такой стереть
+ !в catch коде $exception.handled[cache] ^rem{флаг, что exception обработан}
!^cache[файл][expires date]{код}
!абсолютное задание времени
X^cache[файл] удалить файл [не ругает, если его нет] // такое было, больше не будет, делать ^cache(0)
@@ -160,9 +174,11 @@ odbc c:\drives\y\parser3project\odbc\
!^cache[expires date]
!сигнализирует вышестоящему ^cache "уменьши до стольких-то 'секунд'/'expires'"
!в пределе: ^cache(0) отменить кэширование
+ !^cache[] выдаёт текущую expires date
X^cache[read]
сигнализирует вышестоящему ^cache "взять скэшированное насильно, игнорируя expires",
выдаёт bool "получилось/нет"
+ !^sleep(seconds)
Xесть глобальный флажок в свойствах/командной строке "не оптимизировать"
@@ -200,6 +216,7 @@ odbc c:\drives\y\parser3project\odbc\
!$имя whitespace или ${имя}неважно подстановка значения
!^имя параметры вызов
!$имя.CLASS класс значения
+ !$имя.CLASS_NAME имя класса
!$имя[$.key[] () {}] конструктор элемента переменной-хэша $имя.key
!^method[$.key[] () {}] конструктор элемента параметра-хеша $parameter.key
$CLASS.имя обращение к переменной класса
@@ -231,11 +248,18 @@ odbc c:\drives\y\parser3project\odbc\
0
!^имя.pos[...]
-1
+ !^void.left(n)
+ ничего не выдаёт
+ !^void.right(n)
+ ничего не выдаёт
+ !^void.mid(p[;n])
+ ничего не выдаёт
!^имя.int[] (default)
0 или default
!^имя.double[] (default)
0 или default
- !^void:sql{запрос без результата}
+ !^void:sql{запрос без результата}{$.bind[см. table::sql]}
+
!int,double
!^имя.int[] целочисленное значение
@@ -246,7 +270,7 @@ odbc c:\drives\y\parser3project\odbc\
!^имя.div(на сколько /)
!^имя.mod(на сколько %)
!^имя.format[формат]
- !^int/double:sql{query}[[$.limit(2) $.offset(4) $.default{0}]]
+ !^int/double:sql{query}[[$.limit(2) $.offset(4) $.default{0} $.bind[см. table::sql]]]
запрос, результат которого должен быть один столбец/одна строка
!string
@@ -258,7 +282,7 @@ odbc c:\drives\y\parser3project\odbc\
пример:
^if(def $form:name) не пуста?
^if($user.isAlive) истина? [автопреобразование к числу, не ноль?]
- !^string::sql{query}[[$.limit(1) $.offset(4) $.default{n/a}]]
+ !^string::sql{query}[[$.limit(1) $.offset(4) $.default{n/a} $.bind[см. table::sql]]]
результат запроса должен быть один столбец/одна строка
!^имя.int[] .int(default) целочисленное значение строки.
если ломается преобразование, берётся default
@@ -297,6 +321,11 @@ odbc c:\drives\y\parser3project\odbc\
!^строка.normalize[] выдает другую строку, в которой фрагменты на одном языке объединены
полезно делать перед сложными match операциями, если вы знаете, что входная строка
состоит из большого числа фрагментов
+ !^string.trim[start|both|end[;chars]] выкидывает charset из начала/конца/и начала и конца
+ default 'chars' -- whitespace chars
+ !^string.append[string]
+ !^string.base64[] encode
+ !^string:base64[encoded] decode
!table
в выражении
@@ -311,7 +340,11 @@ odbc c:\drives\y\parser3project\odbc\
!пустые строки, и строки в первой колонке содержащие '#', игнорируются
!$.separator[^#09]
!$.encloser["] по-умолчанию, нет.
- !^table::sql{query}[[$.limit(2) $.offset(4) todo:$.default{ ^table::create[...] }]]
+ !^table::sql{query}[[$.limit(2) $.offset(4) $.bind[hash] todo:$.default{ ^table::create[...] }]]
+ bind привязывает переменные в запросе к их значениям
+ пока реализован только для oracle
+ в запросе надо написать ":имя"
+ в параметре bind передать hash, из которого возьмётся(или куда запишется) значение
!^таблица.save[[nameless|append;]путь[;опции, см. load]]
!$таблица.поле
!$таблица.fields из named таблицы выдаёт текущую запись как Hash
@@ -367,11 +400,33 @@ odbc c:\drives\y\parser3project\odbc\
!^hash::sql{запрос}[[$.distinct(1) $.limit(2) $.offset(4) todo:$.default{$.field[]...}]]
получается hash(ключи=значения первая колонка ответа)
of hash(ключи=названия остальных колонкок ответа)
- !^hash._keys[]+ таблица из одного столбца $key
+ !^hash._keys[[название колонки с ключами]]+ таблица из одного столбца $key или как передадут
!^hash._count[]
!^foreach[key;value]{тело}[[разделитель]|{разделитель который выполняется перед непустым очередным не первым телом}]
!^delete[ключ] удалить ключ
+!hashfile
+ !^hashfile::open[filename]
+ !^hashfile.clear[] забыть всё
+ !.ключ[значение] положить значение
+ !.ключ[$.value[значение] $.expires ЗНАЧЕНИЕ}
+ положить значение до expires
+ значение поля expires может быть date, или число дней(0дней=на вечно)
+ !.ключ достать
+ !^delete[ключ] удалить ключ
+ !^delete[] удалить файлы, содержащие данные
+ !^hash[]
+ преобразовать в обычный hash
+ попутно стирает устаревшие пары
+ !^foreach[key|value]{тело}[[разделитель]|{разделитель который выполняется перед непустым очередным не первым телом}]
+
+ пример:
+ $sessions[^hashfile::open[/db/sessions]]
+
+ $sid[^math:uuid[]]
+ $sessions.$sid[$.value[$uid] $.expires(1)]
+ $uid[$sessions.$sid]
+
!form
[берётся первый элемент из одноимённых из GET, потом первый из POST]
!$form:поле = string/file
@@ -384,13 +439,16 @@ odbc c:\drives\y\parser3project\odbc\
!env
!$env:переменная
+ !$env:PARSER было то же самое, что показывается при запуске parser.cgi
!cookie
!$cookie:имя считать старое или свежезаданное
!$cookie:имя[значение] на 90 дней
- !$cookie:имя[$.value[значение] $.expires ЗНАЧЕНИЕ ]
+ !$cookie:имя[$.value[значение] $.expires ЗНАЧЕНИЕ $.secure(true)]
!значение поля expires может быть 'session', date, или число дней(0дней=session)
! если дата, она будет преобразована к формату "Sun, 25-Aug-2002 12:03:45 GMT"
+ ! можно устанавливать bool свойства, например $.secure(true), $.httponly(true)
+
!request
!$request:query
@@ -416,6 +474,7 @@ odbc c:\drives\y\parser3project\odbc\
! $attribute[zzz] field: abc; {attribute=zzz}<<часть
!значение поля или атрибута может быть string или date
! если дата, она будет преобразована к формату "Sun, 25-Aug-2002 12:03:45 GMT"
+ !$response:headers накопленные поля
!$response:body[DATA] замещает стандартный ответ
!$response:download[DATA] замещает стандартный ответ,
выставляет флаг, заставляющий browser предложить download
@@ -430,24 +489,6 @@ odbc c:\drives\y\parser3project\odbc\
ПРЕДУПРЕЖДЕНИЕ: класс form получает свои поля после обработки всех auto класса MAIN
поэтому необходимо задать $request/response:charset в одном из них. не после.
-hashfile
- !^hashfile::open[filename]
- ^hashfile.clear[] забыть всё
- !.ключ[значение] положить значение
- .ключ[$.value[значение] $.expires(секунд)} положить значение на expires секунд
- !.ключ достать
- !^delete[ключ] удалить ключ
- !^hash[]
- преобразовать в обычный hash
- ^foreach[key|value]{тело}[[разделитель]|{разделитель который выполняется перед непустым очередным не первым телом}]
-
- пример:
- $uids[^hashfile::assign[/db/uids]]
-
- $random[23847387taduigh345XGHWElxjgdjg]
- $uids.$random[$.value[$uid] $.expires(60*30)]
- $uid[$persistent.logins.$random]
-
!mail
!$mail.received=MESSAGE:
.from
@@ -524,7 +565,7 @@ hashfile
!это старый формат, поддерживается для обратной совместимости
!если имя части начинается со слова text, то это текстовый блок.
!если имя части начинается со слова attach, то это вложение, формат задания::
- !$attach[$.format[!uue|Xbase64] $.value[DATA] $.file-name[user-file-name]]
+ !$attach[$.format[!uue|!base64] $.value[DATA] $.file-name[user-file-name]]
!важно: при multipart не указывать content-type
^mail:send[
# по-умолчанию, совпадает с source encoding.
@@ -617,6 +658,8 @@ hashfile
определяющее прожорливость выделялки цветов из палитры [default=150]
меньше - точнее приближает цвета, но они быстро кончаются
больше - неточно приближает цвет, но бОльшей части хватит
+ !^картинка.pixel(x;y)[(color)]
+ узнать или задать цвет пиксела
!file
!$файл_из_post.name
@@ -627,6 +670,7 @@ hashfile
!^file:find[имя файла][{когда не нашли}]
!^file:list[путь[;шаблон]] = table с колонкой name
!^file::load[text|binary;!big.zip[;!domain_press_release_2001_03_01.zip][;опции]]
+ !^file::create[text;имя;^untaint[xml]{data}]
!$файл_который_был_loaded.size
!^file::stat[имя файла]
!$файл_который_был_stated.size !.adate !.mdate !.cdate
@@ -641,6 +685,8 @@ hashfile
можно переименовывать и двигать каталоги[win32: но не через границу дисков]
каталоги для dest создаются с правами 775
каталог старого файла стирается, если после move он остаётся пуст
+ !^file:copy[имя файла;имя копии файла]
+ можно копировать только файлы
!^file:lock[имя файла]{код}
файл при необходимости создаётся
блокируется
@@ -653,7 +699,27 @@ hashfile
!^file:justname[/a/some.tar.gz]=some.tar
!^file:justext[/a/some.tar.gz]=gz
!/some/page.html: ^file:fullpath[a.gif] => /some/a.gif
-
+ !^file.sql-string[] внутри ^connect даст правильно escaped строку, которую можно в запрос отдать
+ X^file::sql[[имя_файла_для_download]]{}
+ !^file::sql{}[[
+ $.name[имя_файла_для_download]
+ $.content-type[пользовательский content-type]
+ ]]
+ результат запроса должен быть "одна строка".
+ колонки:
+ первая колонка - данные
+ если есть вторая - это имя файла
+ если есть третья - это content-type
+ !^file.base64[] encode
+ !^file::base64[encoded string] decode
+ !^file:crc32[имя файла]
+ вычисляет crc32 файла с указанным именем
+ !^file.crc32[]
+ вычисляет crc32 объекта
+ !^file.md5[]
+ !^file:md5[имя файла]
+ выдает digest файла, длиной 16 байт в виде строки,
+ где байты digest выданы в hex виде, впритык, в нижнем регистре
!math
!$math:PI
@@ -682,6 +748,8 @@ hashfile
если нет тела salt, оно создаётся случайным
$1$ вызывает MD5 алгоритм функции OS 'crypt', если поддерживается [заведомо нет на solaris].
другие salt читайте документацию по функции OS 'crypt'.
+ !^math:crc32[string]
+ вычисляет crc32 строки
!date
!время типа time можно использовать в выражениях, подставляет
@@ -708,11 +776,13 @@ hashfile
!^date.sql-string[] %Y-%m-%d %H:%M:%S
where published='$дата.sql-string[]'
!^date:calendar[rus|eng;год;месяц] выдаёт неименованную таблицу
- столбцы: 0..6, week, weekyear
+ столбцы: 0..6, week, year
!^date:calendar[rus|eng;год;месяц;день] выдаёт именнованную таблицу
столбцы: year, month, day, weekday
xdoc(xnode)
+ !$xdoc.search-namespaces hash, where keys=prefixes, values=urls
+
DOM1 attributes:
!readonly attribute DocumentType doctype
Xreadonly attribute DOMImplementation implementation
@@ -771,10 +841,17 @@ xdoc(xnode)
выдаёт media-type при подстановке $response:body[сюда]
+ !если на документ ссылаются так:
+ parser://method/param/to/that/method
+ то в качестве документа используется ^MAIN:method[/param/to/that/method]
+ [примечание: в параметр всегда приходит лидирующая /, даже, если параметров вообще не было]
+
!xnode
DOM1 attributes:
!$node.nodeName
!$node.nodeValue
+ !read
+ !write
!$node.nodeType = int
ELEMENT_NODE = 1
ATTRIBUTE_NODE = 2
@@ -913,11 +990,6 @@ xdoc(xnode)
file time
file time
file time
- !$status:charset hash
- !cache table
- file
- file
- file
!$status:rusage hash
!utime user time used
@@ -944,8 +1016,22 @@ xdoc(xnode)
Return the total number of bytes [EVER(c)PAF] allocated in this process.
Never decreases.
+ !$status:pid process id
+ !$status:tid thread id
-!DATA::=string | file
+console
+ $console:timeout
+ !$console:line
+ read/write строку
+
+DATA::=string | file | hash
+
+!hash вида
+[
+ $.file[имя файла на диске]
+ $.name[имя файла для пользователя]
+ $.mdate[date]
+]
!MAIN
это класс, загружаемый на автомате из parser3.conf,
@@ -977,18 +1063,28 @@ xdoc(xnode)
операторов/методов, приведших к ошибке.
!при загрузке файла (file::load, table::load, xdoc::load) можно указать такое имя файла:
- !http://domain/document?params
+ !http://domain/document[?params<> создает http.status ошибку,
!это можно отключить, передав
!$.any-status(1)
!$.charset[кодировка удалённых докуметов по-умолчанию] << если сервер вернёт content-type:charset=ОНА_ПЕРЕБИВАЕТ
+ !$.user[пользователь]
+ !$.password[пароль]
!file::load в дополнительные поля записывает
!ПОЛЕ:значение (имена полей ответа заглавными буквами)
!tables << хеш их ПОЛЕ->table с единственным столбцом "value".
@@ -1024,5 +1120,12 @@ xdoc(xnode)
!нужно выключить русский apache: CharsetDisable on
-!если в MAIN будет определён флаг $ORIGINS(1) то вместо обычного вывода страницы будет
+Xесли в MAIN будет определён флаг $ORIGINS(1) то вместо обычного вывода страницы будет
выдан список фрагментов результата с указанием их происхождения
+
+!если описание метода содержит локальную переменную result в явном виде
+ (есть и неявная переменная)
+ то код вывода строковых литералов не попадает в конечный байт-код,
+ а непробельные символы считаются синтаксической ошибкой
+ для вывода чего бы то ни было надо пользоваться этой переменной
+