Operator associativity using Scala Parsers

前端 未结 2 691
攒了一身酷
攒了一身酷 2021-01-16 08:07

So I\'ve been trying to write a calculator with Scala\'s parser, and it\'s been fun, except that I found that operator associativity is backwards, and that when I try to mak

2条回答
  •  滥情空心
    2021-01-16 08:33

    I'm interpreting your question as follows:

    If you write rules like def expression = number ~ "-" ~ expression and then evalute on each node of the syntax tree, then you find that in 3 - 5 - 4, the 5 - 4 is computed first, giving 1 as a result, and then 3 - 1 is computed giving 2 as a result.

    On the other hand, if you write rules like def expression = expression ~ "-" ~ number, the rules are left-recursive and overflow the stack.

    There are three solutions to this problem:

    1. Post-process the abstract syntax tree to convert it from a right-associative tree to a left-associative tree. If you're using actions on the grammar rules to do the computation immediately, this won't work for you.

    2. Define the rule as def expression = repsep(number, "-") and then when evaluating the computation, loop over the parsed numbers (which will appear in a flat list) in whichever direction provides you the associativity you need. You can't use this if more than one kind of operator will appear, since the operator will be thrown away.

    3. Define the rule as def expression = number ~ ( "-" ~ number) *. You'll have an initial number, plus a set of operator-number pairs in a flat list, to process in any direction you want (though left-to-right is probably easier here).

    4. Use PackratParsers as Daniel Sobral suggested. This is probably your best and simplest choice.

提交回复
热议问题