разбор сложного логического выражения в pyparsing в стиле двоичного дерева

Я пытаюсь разобрать сложное логическое выражение, подобное приведенному ниже;

x > 7 AND x < 8 OR x = 4

и получить проанализированную строку в виде двоичного дерева. Для приведенного выше выражения ожидаемое проанализированное выражение должно выглядеть следующим образом:

[['x', '>', 7], 'AND', [['x', '<', 8], 'OR', ['x', '=', 4]]]

Логический оператор «ИЛИ» имеет более высокий приоритет, чем оператор «И». Скобки могут переопределить приоритет по умолчанию. Чтобы быть более общим, проанализированное выражение должно выглядеть так;

<left_expr> <logical_operator> <right_expr>

Другим примером может быть

input_string = x > 7 AND x < 8 AND x = 4
parsed_expr  = [[['x', '>', 7], 'AND', ['x', ',', 8]], 'AND', ['x', '=', 4]]

До сих пор я придумал это простое решение, которое, к сожалению, не может генерировать анализируемое выражение в виде двоичного дерева. operatorPrecedence, похоже, не помогает мне здесь, где последовательно используется тот же логический оператор, что и в предыдущем примере.

import pyparsing as pp
complex_expr = pp.Forward()
operator = pp.Regex(">=|<=|!=|>|<|=").setName("operator")
logical = (pp.Keyword("AND") | pp.Keyword("OR")).setName("logical")
vars = pp.Word(pp.alphas, pp.alphanums + "_") | pp.Regex(r"[+-]?\d+(:?\.\d*)?(:?[eE][+-]?\d+)?")
condition = (vars + operator + vars)
clause = pp.Group(condition ^ (pp.Suppress("(") + complex_expr + pp.Suppress(")") ))

expr = pp.operatorPrecedence(clause,[
                            ("OR", 2, pp.opAssoc.LEFT, ),
                            ("AND", 2, pp.opAssoc.LEFT, ),])

complex_expr << expr
print complex_expr.parseString("x > 7 AND x < 8 AND x = 4")

Приветствуются любые предложения или рекомендации.

BNFдля выражения (без скобок) может быть

<expr>       -> <expr> | <expr> <logical> <expr>
<expr>       -> <opnd> <relational> <opnd>
<opnd>       -> <variable> | <numeric>
<relational> -> <'>'> | <'='> | <'>='> | <'<='> | <'!='>
19
задан consumer 22 June 2012 в 05:22
поделиться