3

目前我用它来解析算术表达式:

expr  : '(' expr ')' 
      | number op expr 
      | variable op expr 
      | number
      | variable
      | <error>

它适用于简单的表达式,但不能处理嵌套的括号表达式。任何想法如何扩展/修改它以便它可以处理嵌套表达式。

例如这有效:

5 + 12
33 - $var
13 + 2 * $v
( 44 + 98 )

但这不起作用:

( 44 + 98 ) / 2
( 44 + 98 ) / ( 5 + $var2 )
( 11 + 5 ) * ( 3 + ( $v * 2 ) )
4

2 回答 2

4

你的优先链有问题。1 + (2 + 3)可以解析为number op expr,expr右边是'(' expr ')', 但(1 + 2) + 3不能, 因为expr不能出现在op. 当然你不能直接添加它,因为左递归是被禁止的。您需要做的是将其分解为:

expr: term '+' expr
    | term '-' expr
    | term

term: factor '*' term
      | factor '/' term
      | factor

factor: '(' expr ')'
    | number
    | variable
    | <error>

是的,括号一直在链的末尾,这可能看起来很奇怪,但它说的是带括号的表达式可以出现在因子可以出现的任何地方,并且会在它冒泡之前被评估。现在很容易看出,由于所有内容都引用factor,因此带括号的表达式可以出现在它需要的任何地方。

于 2016-02-14T21:26:32.520 回答
3

添加规则以使用中缀运算符将括号表达式与另一个表达式组合:

| '(' expr ')' op expr

顺便说一句,原始语法不受嵌套表达式的影响,而是以括号中的术语开头的中缀表达式。

一般来说,用户 hobbs 的解决方案是处理具有不同偏好的中缀运算符的表达式的标准方法。它还有一个额外的好处,即正确的子表达式求值顺序由适当的语法处理,不需要由额外的代码处理。

仅当您不需要成熟的表达式评估器时才使用我的解决方案(您肯定会发现您需要一个......)。

于 2016-02-14T21:28:56.353 回答