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.
pyparsing handles the order of operations well enough in this case:
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:
print(infix_pattern.parse_string('a(b) == c(d)'))
# ['a']
What I would like to see in this case is ['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:
I could combine the
a(b)andc(d)withpp.Combineor something but this is fine.