Hi! In Instaparse, how do I specify operator precedence... I tried ordered choice, but it doesn't do what I want. Simple example:
(def tp (insta/parser "
s = expression
<expression> = binop / integer
integer = #'[0-9]+'
<binop> = times / plus
times = expression <'*'> expression
plus = expression <'+'> expression"
:auto-whitespace whitespace))
parser> (tp "5 + 3 * 7")
[:s [:times [:plus [:integer "5"] [:integer "3"]] [:integer "7"]]]
I have seen solutions that distinguish between add-expression and mul-expression, but that doesn't scale very well for more operatorsOrdered choice only works when considering parses available at a given position, not when ranking this parse here over another parse over there.
So in your example, your binop / integer
was making it try 5 + 3
before 5
ah, so I can fix it by making expression unordered? Or what's the best way?
I don't think ordered choice is the best tool for "order of operations"... I'll send you another example in a sec
Thanks!
@mrchance check out the arithmetic expr parser in https://github.com/engelberg/instaparse#transforming-the-tree
Thanks, I'll check it out
notice how no ordered choice is necessary, because the grammar is structured so that the order of operations follows naturally
hm, ok, but my impression is that would get unwieldy when there is more operators. I'll give it a try though, I don't have that many π
perhaps. not sure.
Hereβs a potentially more elegant way of expressing it (not sure if this actually works):
expr = add-sub
add-sub = mul-div (('+' | '-') mul-div)*
mul-div = term (('*' | '/') term)*
term = number | <'('> add-sub <')'>
hmm, wouldn't this disallow top level multiplication terms?
I am already wishing I had given my own language a lisp syntax π
@mrchance no, it would end up as [:expr [:add-sub [:mul-div "1" "*" "2"]]]
right π It worked, btw. For the Moment it's still quite manageable too. Thanks for the fast replies!