Expression parser & executor class
Version 2.1
Author: Alexandr Dubov (qwat) qwatos@gmail.com
Copyright (c) 2006-2012, Alexandr Dubov. All Rights Reserved.
Данный класс реализует простой парсер выражений, который поддерживает
строковые (в одинарных и обычных кавычках), численные, булевы (1/'') константы, ex: 'a', "a", 12, -1.2 ...
одномерные массивы-константы (элементы окружены квадратными скобками и разделены запятыми), ex: ['x', 1, 4]
вызовы определённых пользователем функций с одним (может указываться без скобок) или ex: f 2
несколькими (окружены круглыми скобками и разделены запятыми) аргументами, ex: f(2, 'm'), f() ...
причём элементы массивов и аргументы функций также могут быть любыми выражениями. ex: [1 + f(3)], f([1, 2]) ...
Поддерживаются подвыражения в круглых скобках, а также доступ к переменным, ex: 3 * (f 2 + 1)
имена и значения которых предоставлены пользователем в виде ассоциативного массива. ex: a + b <- array('a' => 1, 'b' => 2)
This class is about to be a simple expression parser, which supports as operands
string (surrounded by single or double quotes), numeric, boolean (1/'') constants, ex: 'a', "a", 12, -1.2 ...
1D-array constants (members surrounded by square brackets and divided by ','), ex: ['x', 1, 4]
user-defined function calls with single (can be placed w/o brackets) or ex: f 2
several (surrounded by brackets and divided by ',') arguments, ex: f(2, 'm'), f() ...
members of arrays and function arguments can be expressions itselves. ex: [1 + f(3)], f([1, 2]) ...
Also subexpressions in brackets supported, and variables with names and values being ex: 3 * (f 2 + 1)
supplied by user as associative array outside. ex: a + b <- array('a' => 1, 'b' => 2)
Поддерживаются след. операции (с синонимами)Such operations (with synonims) supported:
. - конкатенация строкstrings concat.
ageof - (unar) разница в сек. между текущим временем и заданнымdelta in secs between current time and given string value in date/time format
$ - (unar) разыменовывание переменной, имя которой задано строкойevaluate given by string value name of variable in runtime
$$ - (unar) вычисление выражения, заданного строкойevaluate given by string value expression in runtime
$$$ - (unar) :)
-> - связывание вызовов функций в цепь (см. ниже особенности)chaining functions calls (look specific below)
sizeof - (unar) кол-во элементов массиваsize of array
strlen - (unar) длина строкиlength of string
isarray - (unar) ? является ли операнд массивомindicate if value given is array
* / % + -
floor - (unar) целая частьinteger part of given value
in - ? является ли левый операнд элементом массиваindicate if value given at left is a member of array
not in - ? не является ли левый операнд элементом массиваindicate if value given at left is not a member of array
< > <= >=
like - ? является ли правый операнд подстрокой левого (case-insensitive)indicate if value given contains another value as substring (case-insensitive)
= (==, eq), != (ne), & (&&, and), | (||, or)
! (not) - (unar)
, - последовательность выражений, результатом является результат последнего из нихsequence of expressions, the last's result is the final
Пример использованияCommon use:
$template = '(1+(5-2)/2)." is number, ".(2 & 3 | sqrt 25 in [4, 5, 6])." is boolean"';
try {
qtexp_parser::reg_function('sqrt', function(array &$op, array &$out, array &$tree, array &$vars, $validate = false) {
if ($validate) // проверка типов аргументовvalidate arguments types
return;
else {
$out[0] = qtexp_parser::QTE_T_NUMBER; // тип результатаresult type
$out[1] = 0; // результатresult value
if (!empty($op['a'])) { // массив индексов аргументов в массиве параметров $tree['pars']array of arguments indexes in params array $tree['pars']
unset($member);
$member = &$tree['pars'][$op['a'][0]];
qtexp_parser::eval_par($member, $vars); // вычисляем значение аргументаexecute argument expression
$out[1] = sqrt($member[1]);
}
}
});
$tree = array();
qtexp_parser::prepare_expr($template, $tree);
$text = '';
$shift = 0;
qtexp_parser::execute_expr($tree, $vars, $text, $shift);
} catch (qtexpParserException $e) {
echo "$e\n";
}
Особенности:
1) внутреннее представление одномерных массивов (соот. и предоставляемых пользователем) таково: array(array(member1), array(member2), ...)
это связано с особенностями работы парсеров шаблонов, которые обычно используют двумерные массивы для итерации по ним
2) все строковые операторы используют "mb_" функции PHP
3) вызовы функций могут быть связаны оператором '->' в цепочку для облегчения читаемости кода, при этом операнд слева (может не быть
вызовом функции) вносится первым по счёту в список аргументов функции справа. ex: a->f(1)->g() эквивалентно g(f(a, 1))
Specific:
1) 1D-arrays internal (and in namespace from outside) representation is: array(array(member1), array(member2), ...)
this is done to be useful with templates parser, which commonly use 2D-arrays
2) all string operators use multibyte PHP-routines
3) functions calls can be chained with operator '->', the operand at left (can be not function call) will be inserted first
into the arguments list of function at right.