Próbuję parsować złożone wyrażenie logiczne, takie jak poniższe;parsowanie złożonego wyrażenia logicznego w pyparsing w drzewie binarnym
x > 7 AND x < 8 OR x = 4
i pobierz przeanalizowany ciąg znaków jako drzewo binarne. Na powyższym wyrażeniu oczekiwany analizowany wyrażenie powinno wyglądać
[['x', '>', 7], 'AND', [['x', '<', 8], 'OR', ['x', '=', 4]]]
„OR” operator logiczny ma wyższy priorytet niż „i” operatora. Nawias może zastąpić domyślny priorytet. Aby być bardziej ogólnym, analizowane wyrażenie powinno wyglądać;
<left_expr> <logical_operator> <right_expr>
Innym przykładem może być
input_string = x > 7 AND x < 8 AND x = 4
parsed_expr = [[['x', '>', 7], 'AND', ['x', ',', 8]], 'AND', ['x', '=', 4]]
Dotychczas wymyśliłem tego prostego rozwiązania, które niestety nie mogą generować przeanalizowanych wyraz w binarnym drzewie mody. operatorPrecedence nie wydaje mi się, że pomogło mi tutaj, gdy jest taki sam operator logiczny, jak w poprzednim przykładzie.
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")
Wszelkie sugestie lub wskazówki są mile widziane.
BNF
dla wyrażenia (bez nawiasów) może być
<expr> -> <expr> | <expr> <logical> <expr>
<expr> -> <opnd> <relational> <opnd>
<opnd> -> <variable> | <numeric>
<relational> -> <'>'> | <'='> | <'>='> | <'<='> | <'!='>
Kod jest nieco trudne do naśladowania, można zakładać gramatykę w BNF? – georg
właśnie dodałem BNF ... nie jestem pewien czy jest jednoznaczny czy nie. – consumer