5

如何强制通过 GLR 方法解决 shift\reduce 冲突?
假设我希望解析器自己解决右移位运算符和模板参数的两个右尖括号之间的冲突。我让词法分析器将 2 个连续的“>”符号作为单独的标记传递,而不将它们合并为一个“>>”标记。然后我把这些规则放到语法中:

operator_name:  
     "operator" ">"  
   | "operator" ">" ">"  
;  

我希望这是一个转变\减少冲突。如果我有具有左关联性的“>”的令牌声明,这不会是冲突。所以我必须删除令牌优先级\关联性声明,但这会导致许多其他冲突,我不想通过为每个冲突规则指定上下文优先级来手动解决这些冲突。那么,有没有办法在声明令牌的同时强制 shift\reduce 冲突?

4

2 回答 2

2

我相信在 operator_name 的规则上使用上下文相关的优先级会起作用。

更新后的标准指定的 C++ 语法实际上修改了语法以接受 >> 标记作为关闭两个打开的模板声明。我建议遵循它以获得标准行为。例如,您必须注意“x >> y”不会被解析为“x >> y”,并且您还必须确保“foo<bar<2 >> 1>>”无效,而“foo< bar<(2 >> 1)>>" 有效。

于 2012-02-01T17:05:20.693 回答
1

我在 Yacc(类似于 Bison)工作,有类似的场景。

有时,标准语法被称为“由语法指导的解析”。

这种情况有时被称为“语义指导的解析”。

例子:

...
// shift operator example
if ((x >> 2) == 0)
...
// consecutive template closing tag example
List<String, List<String>> MyList =
...

让我们记住,我们的大脑就像编译器一样工作。人脑可以编译这个,但以前的语法不能。嗯。让我们看看人类的大脑是如何编译这段代码的。

如您所知,连续的“>”和“>”标记之前的“x”表示表达式或左值。头脑认为“两个连续的大于符号,在一个表达式之后,应该成为一个单一的移位运算符标记”。

对于“字符串”标记:“两个连续的大于符号,在类型标识符之后,应该成为两个连续的模板结束标记标记”。

我认为这种情况不能通过通常的运算符优先级、移位或减少,或者只是语法来处理,而是使用(“hacking”)解析器本身提供的一些函数。

我在您的示例语法规则中没有看到错误。“操作员”符号避免混淆您提到的两种情况。应该关注的部分是使用移位运算符的语法,以及使用连续的模板结束标记。

operator_expr_example:  
  lvalue "<<"  lvalue |  
  lvalue ">>"  lvalue |
  lvalue "&&"  lvalue |
;  

template_params:  
  identifier |
  template_declaration_example |
  array_declaration |
  other_type_declaration 
;  

template_declaration_example:  
  identifier "<"  template_params ">"
;  

干杯。

于 2012-02-01T17:18:33.030 回答