【问题标题】:Reduce/Reduce conflict when introducing pointers in my grammar在我的语法中引入指针时减少/减少冲突
【发布时间】:2013-01-06 05:21:04
【问题描述】:

我正在开发一个小型编译器,以便更好地了解创建自己的语言的困难。现在我正处于向我的语法添加指针功能的阶段,但是这样做我遇到了减少/减少冲突。

这是我的语法的简化版本,可由bnfc 编译。我使用happy 解析器生成器,程序告诉我存在reduce/reduce 冲突。

entrypoints Stmt ;

-- Statements
-------------
SDecl. Stmt ::= Type Ident; -- ex: "int my_var;"
SExpr. Stmt ::= Expr;       -- ex: "printInt(123); "

-- Types
-------------
TInt.      Type ::= "int" ;
TPointer.  Type ::= Type "*" ;
TAlias.    Type ::= Ident ; -- This is how I implement typedefs

-- Expressions
--------------
EMult.     Expr1 ::= Expr1 "*" Expr2 ;
ELitInt.   Expr2 ::= Integer ;
EVariable. Expr2 ::= Ident ;

-- and the standard corecions
_.         Expr  ::= Expr1 ;
_.         Expr1 ::= Expr2 ;

我正处于语法如何工作的学习阶段。但我想我知道会发生什么。考虑这两个程序

main(){
  int a;
  int b;
  a * b;
}

typedef int my_type;
main(){
  my_type * my_type_pointer_variable;
}

typedefmain(){} 部分与我的语法无关,但它们提供了一些上下文)

在第一个程序中,我希望它将a "*" b 解析为Stmt ==(SExpr)==> Expr ==(EMult)==> Expr * Expr ==(..)==> Ident "*" Ident,即基本上使用SExpr 规则开始步进。

同时我希望my_type * my_type_pointer_variable 使用规则进行扩展。 Stmt ==(SDecl)==> Type Ident ==(TPointer)==> Type "*" Ident ==(TAlias)==> Ident "*" Ident.

但语法阶段不知道标识符最初是类型别名还是变量。


(1) 我怎样才能摆脱减少/减少冲突和 (2) 我是唯一一个有这个问题的人吗?有没有明显的解决方案,c语法是如何解决这个问题的?

到目前为止,我已经成功地通过使用“&”或其他符号而不是“*”来更改我的语言的语法,但这是非常不可取的。此外,我无法从各种公共 c 语法中理解并试图了解为什么他们没有这个问题,但我没有运气。

最后,我如何自己解决此类问题?我从happys 中了解到的更详细的输出是冲突是如何发生的,聪明是解决这些冲突的唯一方法吗?恐怕我会在介绍EIndir. Expr = '*' Expr;时遇到更多问题

【问题讨论】:

    标签: grammar bnf happy reduce-reduce-conflict


    【解决方案1】:

    在 C 解析器中处理此问题的常用方法通常称为 "the lexer feedback hack"。从某种意义上说,它根本不在语法中处理它,因此它是一种“黑客”;相反,当词法分析器识别出一个标识符时,它将该标识符分类为类型名或非类型名,并为每种情况返回一个不同的标记(通常为类型名的标识符指定“TypeIdent”,而对于任何其他)。词法分析器通过查看符号表的当前状态来进行选择,因此它会看到在解析中当前点之前发生的所有 typedef,但看不到当前点之后的 typedef。这就是为什么 C 要求您在每个编译单元中第一次使用 typedef 之前声明它们。

    【讨论】:

    • 多么有趣啊!有没有办法在不编写不需要内存的词法分析器的情况下做到这一点?或者真的没有编程语言具有类似 c 的语法(使用 * 进行乘法 指针声明)并允许将类型别名声明(typedefs)放在代码中的任何位置?跨度>
    • 现在标记为正确。我刚刚意识到 lexer hack 是一个实际术语,甚至在维基百科上都有解释。我编辑了答案以清楚地反映这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多