【问题标题】:Arithmetic expression grammar in prefix notation (Java Cup)前缀符号中的算术表达式语法(Java Cup)
【发布时间】:2013-09-04 10:46:07
【问题描述】:

我正在用前缀符号编写算术表达式的语法。但是,在解析负数或减法时我遇到了问题。语法示例是这样的:

precedence right +, -;
precedence right *, /;
precedence right uminus;

E ::= + E E
   |  - E E
   |  * E E
   |  / E E
   |  ( E )
   |  - E %prec uminus
   |  id
   |  digit
   ;

但是如果我的输入是- 5 4,它会将5 减少为E,然后减少- E(负数),然后解析器在4 处给我一个语法错误。正确的应该是5E,下一个4E,然后- E EE。如何使用关联性解决这个问题?还是我需要重写我的语法?

【问题讨论】:

    标签: parsing arithmetic-expressions compiler-construction cup


    【解决方案1】:

    (从评论中提拔)

    您的语法确实模棱两可,优先声明对您没有一点帮助。

    将输入视为由N - 标记组成的输入,然后是M 1 标记。

    - - - - - - - ... - 1 1 1 ... 1
    

    为了使它成为一个表达式,- 标记中的M-1 必须是二进制的,而其余的 N-(M-1) 必须是一元的,但是无法分辨哪个是哪个(除非它们都是二进制) .

    即使你武断地说第一个N-(M-1) -s 是一元的,在你读取整个输入之前你也无法知道N-(M-1) 的值是什么,这意味着你不能用有限前瞻。

    但前缀符号的全部意义在于避免使用括号。像上面这样的任意声明使得无法表示替代解释,因此某些表达式不可能用前缀表示法表示。这完全是错误的。

    这是一个简单的案例:

    - 5 - - - 4 3 1
    

    要么是

    5 - (- (4 - (3 - 1)))
    5 - ((- (4 - 3)) - 1)
    5 - (((- 4) - 3) - 1)
    

    在前缀表示法中,您需要声明每个运算符的“arity”,无论是隐式(每个运算符都有已知数量的参数),还是显式使用从 Prolog 借来的这样的表示法:

    -/2 5 -/2 -/2 -/1 4 3 1
    

    或者,您可以使用强制括号分隔参数,如 Lisp/Scheme "s-exprs":

    (- 5 (- (- (- 4) 3) 1))
    

    【讨论】:

    • @System.exit 它也适用于“后缀”表示法,也称为逆波兰表示法 (RPN)。虽然我不确定你在问什么。
    • 我正在为前缀中的算术表达式的语法寻求可能的解决方案(如果存在),它可以接受负数/变量。实际上,我已经为“按顺序”表示法做了一个模棱两可的语法并且它有效,但我正面临这个带有前缀表示法的问题(负数)。
    • @System.exit:in-fix 表示法具有额外的句法线索,可让您判断运算符是一元还是二元。此外,它有括号。对于前缀表示法,如果没有这些功能,您需要用其元数标记运算符或标记操作数,以便您知道哪一个是最后一个。或一些类似的变体。
    • 我会更深入地检查它。谢谢@rici。我将添加一些语义规则来实现这一点。
    【解决方案2】:

    首先,删除所有优先声明。前缀语法中不需要它们。事实上,这应该足以解决任何解析器生成器中的问题。顺便说一句,您使用的是哪一个?

    Cup 具有有限的前瞻。正如@rici 指出的那样,在这种情况下无法解决歧义。您可以做的是限制语法,因此只能使用一个连续的一元 -

        B ::= E
           |  - E
           ;
        E ::= + B B
           |  - B B
           |  * B B
           |  / B B
           |  ( B )
           |  id
           |  digit
           ;
    

    请多看几遍,因为我已经很生疏了。

    【讨论】:

    • 我正在使用 Cup,实际上我确实需要优先级,因为语法不明确。如果我不声明优先级,CUP 会显示 shift/reduce 错误。
    • @System.exit:恐怕优先级不会帮助您解决歧义。考虑输入由N- 标记组成的输入,然后是M1 标记。为了使它成为一个表达式,- 标记中的M-1 必须是二进制的,而其余的 N-(M-1) 必须是一元的,但是没有办法分辨哪个是哪个(除非它们都是二进制的)。即使您随意说第一个 N-(M-1) - 是一元的,在您读取整个输入之前,您也无法判断 N-(M-1) 的值是什么,这意味着您无法使用有限前瞻进行解析.
    • @rici 你的评论应该是一个答案
    猜你喜欢
    • 2012-04-10
    • 1970-01-01
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-15
    • 1970-01-01
    相关资源
    最近更新 更多