Expression parser & executor class

Version 2.1

Author: Alexandr Dubov (qwat) qwatos@gmail.com
Copyright (c) 2006-2012, Alexandr Dubov. All Rights Reserved.


DownloaD ver. 2.1

DownloaD ver. 2.0 (без поддержки функцийwithout user-defined functions support)
ENGLISH TEXT
РУССКИЙ ТЕКСТ


Данный класс реализует простой парсер выражений, который поддерживает
строковые (в одинарных и обычных кавычках), численные, булевы (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.