制作C ++解析器时的歧义解决方案

时间:2016-02-24 09:36:56

标签: c++ parsing lalr

我为C ++编写了一个LALR(1)解析器17。我发现 156 含糊不清,其中一些我可以按照标准解决它,但其他我不能解决。

例如: 当遇到小于时解析“ operator +< ...... ”时发生Shift-Reduce冲突:

我们可以将其解析为:

(1)

template-id - > operator-function-id ·< ......>

或:

(2)

unqualified-id - > operator-function-id · 其中(1)需要转移,但(2)需要减少。

但是,标准有:

在名称查找(3.4)之后发现名称是模板名称或者operator-function-id或literaloperator-id引用了一组重载函数,其中任何成员都是函数模板,如果这之后是<,<始终作为模板参数列表的分隔符,而不是小于运算符。解析模板参数列表时,第一个非嵌套的> 137将被视为结束分隔符,而不是大于运算符。

所以我们选择转移。

不幸的是,我找不到解决方案有很多含糊之处。在这里我列出了其中一些(其中一些可以明确做出选择,但我找不到证据):

  1. 标准中是否有一些部分表示“移位”是出现歧义时的默认选择?
  2. 声明符

    (1)当解析noptr-declarator并遇到left-paren时,我应该根据以下内容减少它:

    ptr-declarator - > noptr-declarator ·

    或改变左派以满足:

    声明者 - > noptr-declarator ·参数和限定符

    参数和限定符 - > · left-paren parameter-declaration-clause right-paren ......

    (2)当解析declarator-id并遇到左括号时,我应该根据以下内容减少它:

    noptr-declarator - > declarator-id · noptr-declarator - > noptr-declarator · \ left-bracket?constant-expression \ right-bracket?attribute-specifier-seq

    或移动左方以满足:

    noptr-declarator - > declarator-id·attribute-specifier-seq

    (attribute-specifier-seq是[[.......]])

2 个答案:

答案 0 :(得分:5)

跟进TonyD的评论:见Why can't C++ be parsed with a LR(1) parser?

在某些地方,你基本上必须保持解析产生的歧义,并通过名称解析来解决它,等效地,你必须将名称解析纠缠到解析过程中。在任何一种情况下,您都必须解释标准以确定如何解决歧义,是的,这是一项非常困难的任务。

然后你可以找出编译器真正做什么; GCC和MS都有很多标准的扩展和变体,无论是在语法和语义解释方面(这些都会产生在不同编译器下产生不同结果的程序)。最后,您可以找到系统头文件中的可憎之处;这些都是编译人员为了让他们的生活变得方便而添加的黑客攻击,如果有的话,他们的记录非常糟糕。

答案 1 :(得分:0)

C ++是Turing Complete to parse

非常相关的帖子here