这是我的 BNFC 格式语法的简化版本:
-- programs -------------------------------------
entrypoints Program ;
Prog. Program ::= [ Def ] ;
terminator Def "" ;
-- definitions ----------------------------------
DVar. Def ::= VarDecl ;
DFun. Def ::= FunDef;
-- functions definitions ------------------------
DFunAll. FunDef ::= FunType Id "(" [ Arg ] ")" FunBody;
DFunBody. FunBody ::= "{" RetStmt "}" ;
-- function statements --------------------------
StmtRetVoid. RetStmt ::= "return" ";" ;
-- variable declarations ------------------------
DVarSimple. VarDecl ::= Type Id ";" ;
DVarList. VarDecl ::= Type Id "," [Id] ";" ;
-- arguments ------------------------------------
ArgDecl. Arg ::= Type Id ;
separator Arg "," ;
-- types -----------------------------------------
TInt. Type ::= "int" ;
TFunRetT. FunType ::= Type ;
TFunRetV. FunType ::= "void" ;
-- identifiers ------------------------------------
position token Id (letter (letter | digit | '_')*) ;
separator Id "," ;
对于此语法happy,生成 1 个未使用的规则和 1 个移位/减少冲突警告。我在这里面临的问题是我无法正确解析函数返回类型。闻起来超级简单,但我被卡住了。
更具体地说,我int foo(int x) {return;}在void foo(int x) {return;}解析成功时得到解析错误。因此,这三个规则似乎无法按预期协同工作:
DFunAll. FunDef ::= FunType Id "(" [ Arg ] ")" FunBody;
TInt. Type ::= "int" ;
TFunRetT. FunType ::= Type ;
如果我将FunDef规则更改为FunDef ::= Type Id "(" [ Arg ] ")" FunBody;解析顺利,但我想保留Type和FunType区分,以免成为void常规的Type.