Estoy tratando de analizar expresiones lógicas complejas como la siguiente;analizando una expresión lógica compleja en pyparsing en una forma de árbol binario
x > 7 AND x < 8 OR x = 4
y obtenga la cadena analizada como un árbol binario. Para la expresión anterior analizado la expresión esperada debe ser similar
[['x', '>', 7], 'AND', [['x', '<', 8], 'OR', ['x', '=', 4]]]
'O' operador lógico tiene mayor precedencia que la 'Y' operador. El paréntesis puede anular la precedencia predeterminada. Para ser más general, la expresión analizada debería ser similar;
<left_expr> <logical_operator> <right_expr>
Otro ejemplo sería
input_string = x > 7 AND x < 8 AND x = 4
parsed_expr = [[['x', '>', 7], 'AND', ['x', ',', 8]], 'AND', ['x', '=', 4]]
Hasta el momento se me ocurrió con esta sencilla solución, que por desgracia no puede generar la expresión analizada en forma de árbol binario. operatorPrecedence no parece haberme ayudado aquí donde hay el mismo operador lógico consecutivamente que en el ejemplo anterior.
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")
Cualquier sugerencia u orientación es muy apreciada.
BNF
para la expresión (sin paréntesis) podría ser
<expr> -> <expr> | <expr> <logical> <expr>
<expr> -> <opnd> <relational> <opnd>
<opnd> -> <variable> | <numeric>
<relational> -> <'>'> | <'='> | <'>='> | <'<='> | <'!='>
Su código es un poco difícil de seguir, ¿podría enviar la gramática en BNF? – georg
acaba de agregar el BNF ... no estoy seguro de si es inequívoco o no. – consumer