我正在研究一个小型编译器,以便更好地理解创建自己的语言的困难。现在我处于为我的语法添加指针功能的阶段,但我通过这样做了减少/减少冲突。在我的语法中引入指针时减少/减少冲突
这是我的语法的简化版本,可由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;
非常有趣!有没有办法做到这一点,而不用编写自己的不需要有内存的词法分析器?或者是否真的没有类似c语法的编程语言(使用'*'乘法*和*指针声明),并允许将类型别名声明(typedefs)放在代码中的任何位置? – Tarrasch
现在标记为正确。我刚刚意识到,词法分析黑客是一个实际的术语,甚至在维基百科上进行了解释。我编辑了答案,清楚地反映了这一点。 – Tarrasch