bison解析C语法一定要用GLR算法吗?

Is GLR algorithm a must when bison parsing C grammar?

我正在尝试 flex/bison 学习 C 语法。

我发现 bison 无法解析此 bison 语法:https://www.lysator.liu.se/c/ANSI-C-grammar-y.html,因为 LALR 算法无法递归处理多个表达式。

GLR算法是C文法的必修课吗?

该语法没有任何问题,除了:

  • 它代表了一个很旧的C版本
  • 它需要一个能够以某种方式区分 IDENTIFIERTYPE_NAME
  • 的词法分析器
  • 它甚至不尝试处理预处理器阶段

此外,由于上述维基百科页面 link 中描述的 "dangling else" ambiguity. However, that conflict can be ignored because bison's conflict resolution algorithm produces the correct result in this case. (You can suppress the warning either with an %expect directive or by including a precedence declaration which favours shifting else over reducing if. Or you can eliminate the ambiguity in the grammar using the technique,它有一个 shift/reduce 冲突。 (注意:我不是在谈论维基百科页面上的复制和粘贴代码。对于 C 语言,您需要考虑所有以 if 语句终止的复合语句的情况。)

此外,LR解析器不是递归的,它不存在可以描述为"process recursively multiple expressions"失败的问题。 (递归下降解析器可能会遇到这个问题,尽管解决这个问题很容易。)

所以您可能遇到的任何问题(如果您的问题涉及具体问题)与您的问题中描述的内容无关。

在我上面列出的问题中,最麻烦的是转换运算符的语法歧义。 cast 运算符实际上并没有歧义;显然,C 编译器设法正确编译此类表达式。但是区分两个可能的解析,例如 (x)-y*z 需要知道 x 是命名类型还是变量。

在 C 中,所有的名称都是词法范围的,所以肯定可以在编译时解析 x。但是该决议不是上下文无关的。由于 GLR 也是一种解析上下文无关语法的技术,因此使用 GLR 解析器不会直接帮助您。从理论上讲,GLR 解析器可以生成 "parse forests" 而不是解析树,这可能是有用的;也就是说,GLR 解析器的输出可能有效地包含所有可能的正确解析,从而可以通过为每个范围构建符号 table 来解决歧义,然后通过检查有效的名称绑定在替代解析之间进行选择每个站点。 (这是有效的,因为类型别名声明——"typedefs"——没有歧义,所以所有潜在的解析都将具有相同的别名声明。)

不过,通常的解决方案是使用确定性解析器解析程序文本,在解析期间维护一个符号 table,并让词法分析器访问该符号 table,以便它可以区分 IDENTIFIERTYPE_NAME,正如您 link 的语法所期望的那样。这种技术被礼貌地称为 "lexical feedback",尽管它也经常被称为 "the lexer hack".