2017-03-09 43 views
2

我是新来的野牛,我试图做一个文法解析表达式。 我现在面临着一种转变/减少困惑,我无法解决。解决表达语法中的移位/减少冲突

语法如下:

%left "[" "(" 
%left "+" 

%% 

expression_list : expression_list "," expression 
       | expression 
       | /*empty*/ 
       ; 


expression : "(" expression ")" 
      | STRING_LITERAL  
      | INTEGER_LITERAL   
      | DOUBLE_LITERAL 
      | expression "(" expression_list ")" /*function call*/ 
      | expression "[" expression "]" /*index access*/ 
      | expression "+" expression   
      ; 

这是我的语法,但我面对的转变/减少与这两个规则"(" expression ")"expression "(" expression_list ")"冲突。 我该如何解决这个冲突?

编辑:我知道我可以使用优先级攀登来解决这个问题,但我不想这样做,因为这只是表达式语法的一小部分,而表达式语法的大小会使用优先级爬升爆炸。

+0

如果这是您的语法的整体,它没有转换 - 减少冲突。但是,我怀疑这是你的整个语法。 – rici

+0

哇我现在觉得真是愚蠢......我在另一条规则中发现了一个错字,这影响了这一条 – Exagon

+0

这就是为什么我们要求[mcve],这与“我的代码的几行”有很大不同。如果您制作[mcve],它通常会帮助您澄清问题,为您解决问题。 – rici

回答

2

语法中没有如所介绍的移位 - 缩减冲突,所以我想这只是完整语法的摘录。特别是,将有准确的移进/归约冲突中提到,如果真正的语法包括:

%start program 
%% 
program: %empty 
     | program expression 

在这种情况下,你会遇到歧义,因为给出的,例如,a(b),解析器无法分辨它是否是单个调用表达式或两个连续表达式,第一个是单个变量,第二个是括号表达式。为了避免这个问题,你需要有一些令牌来区分表达式(语句)。

还有其他一些问题:

expression_list : expression_list "," expression 
       | expression 
       | /*empty*/ 
       ; 

,允许表达式列表是,foo(如在f(,foo)),这很可能不期望的。更好的是

arguments: %empty 
     | expr_list 
expr_list: expr 
     | expr_list ',' expr 

而且优先级可能倒退。通常情况下,人们希望像调用和索引这样的后缀运算符比算术运算符更紧密地绑定,所以它们应该结束。否则a+b(7)(a+b)(7),这是非常规的。

+0

你是对的,我很抱歉 – Exagon