我正在开发一个小型编译器,以便更好地了解创建自己的语言的困难。现在我正处于向我的语法添加指针功能的阶段,但是这样做我遇到了减少/减少冲突。
这是我的语法的简化版本,可由bnfc
. 我使用happy
解析器生成器,这就是程序告诉我存在减少/减少冲突。
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;
}
(typedef
和main(){}
部分不相关,在我的语法中。但它们给出了一些上下文)
在第一个程序中,我希望它解析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 语法中理解,并试图了解为什么他们没有这个问题,但我在这方面没有运气。
最后,我如何自己解决这些问题?我从happy
更详细的输出中了解到冲突是如何发生的,聪明是解决这些冲突的唯一方法吗?恐怕我会偶然发现更多问题,例如在介绍时EIndir. Expr = '*' Expr;