简体   繁体   English

带有非分组括号的 pyparsing 中缀表示法

[英]pyparsing infix notation with non-grouping parentheses

I'm working on a billing application where users can enter arbitrary mathematical expressions.我正在开发一个计费应用程序,用户可以在其中输入任意数学表达式。 For example, a line item might be defined as (a + b) * c .例如,订单项可能定义为(a + b) * c

pyparsing handles the order of operations well enough in this case:在这种情况下,pyparsing 可以很好地处理操作顺序:

import pyparsing as pp

operand = pp.Word(pp.alphanums)
boolean_operator = pp.one_of(['||', '&&'])
comparison_operator = pp.one_of(['<', '<=', '>', '>=', '==', '!='])

infix_pattern = pp.infix_notation(
    operand,
    [
        ('^', 2, pp.OpAssoc.LEFT),
        ('*', 2, pp.OpAssoc.LEFT),
        ('/', 2, pp.OpAssoc.LEFT),
        ('+', 2, pp.OpAssoc.LEFT),
        ('-', 2, pp.OpAssoc.LEFT),
        (comparison_operator, 2, pp.OpAssoc.LEFT),
        (boolean_operator, 2, pp.OpAssoc.LEFT),
    ]
)

print(infix_pattern.parse_string('(a + b) * c'))
# [[['a', '+', 'b'], '*', 'c']]

Users can also enter a handful of well-known functions, including the calling parentheses and arguments. For example, if a line item is defined as a(b) == c(d) , pyparsing gets confused:用户还可以输入一些众所周知的函数,包括调用括号和 arguments。例如,如果一个订单项定义为a(b) == c(d) ,pyparsing 会感到困惑:

print(infix_pattern.parse_string('a(b) == c(d)'))
# ['a']

What I would like to see in this case is ['a(b)', '==', 'c(d)'] .在这种情况下,我希望看到的是['a(b)', '==', 'c(d)'] What do I need to do differently in order to keep the first example working as-is and get the desired behavior from the second example?为了使第一个示例按原样工作并从第二个示例中获得所需的行为,我需要做些什么不同的事情?

Okay I think I got it:好的,我想我明白了:

import pyparsing as pp

operand = pp.Word(pp.alphanums) + pp.Opt(pp.Literal('(') + ... + pp.Literal(')'))
boolean_operator = pp.one_of(['||', '&&'])
comparison_operator = pp.one_of(['<', '<=', '>', '>=', '==', '!='])

infix_pattern = pp.infix_notation(
    operand,
    [
        ('^', 2, pp.OpAssoc.LEFT),
        (pp.one_of(['*', '/']), 2, pp.OpAssoc.LEFT),
        (pp.one_of(['+', '-']), 2, pp.OpAssoc.LEFT),
        (comparison_operator, 2, pp.OpAssoc.LEFT),
        (boolean_operator, 2, pp.OpAssoc.LEFT),
    ]
)

print(infix_pattern.parse_string('(a + b) * c'))
# [[['a', '+', 'b'], '*', 'c']]

print(infix_pattern.parse_string('a(b) == c(d)'))
# [['a', '(', 'b', ')', '==', 'c', '(', 'd', ')']]

I could combine the a(b) and c(d) with pp.Combine or something but this is fine.我可以将a(b)c(d)pp.Combine或其他东西结合起来,但这很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM