我在下面的语法(摘录)
上得到减少/减少冲突 declaration : type list_of_id
list_of_id : ID
| list_of_id ',' ID
;
type : PATH
| SCAL
;
assignment : ID ":=" param
| ID ":=" expr
param : point relative_param
| ID relative_param
point : '(' expr ',' expr ')'
| '(' expr ':' expr ')'
relative_param : /* empty rule */
| "--" '+' param
| "--" CYCLE relative_param
| "--" param
expr : NB
| ID ``
| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| '(' expr ')'
我看到当输入为:foo:= bar时,有两种可能的派生:
我在语法中使用了两次ID,因为变量可以是path或scal类型。 如何在不使用glr-parser选项的情况下删除此冲突?
我试图将ID分成两个可能的ID:ID_PATH和ID_SCAL,并将产品param和expr更改为:
param : point relative_param
| ID_PATH relative_param
;
expr : NB
| ID_SCAL
| expr '+' expr
| expr '-' expr
| expr '/' expr
| '(' expr ')'
但在这种情况下,我如何区分词法分析器中的那两个(ID_SCAL和ID_PATH)?
答案 0 :(得分:0)
好吧,正如你已经诊断出来的那样,问题是你的语法含糊不清 - 它有两种不同的解析输入方式,如Foo := Bar
。所以你需要决定的第一件事是,它应该是什么?你怎么知道的?如果你(阅读代码的人)要用你试图解析的语言看到这个,你怎么知道Bar
是一个表达式还是一个没有relative_param的param?
如果它取决于先前对Bar
的一些声明,那么你需要解决这个问题。您需要在符号表中保留有关以前看到的声明的信息,然后在词法分析器中使用该符号表来查找它们被识别的标识符,以便确定词法分析器是否应该返回ID_PATH
或{{1} }。
如果它取决于先前的ID_SCAL
声明,那么你会做类似的事情,但你需要将语法改为更像:
Foo