BNFC简单生产规则的解析问题

时间:2019-04-11 10:32:19

标签: grammar bnfc

这是我的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;,则解析过程很顺利,但是我想区分TypeFunType以便不让void为常规的Type

1 个答案:

答案 0 :(得分:0)

  

我想区分TypeFunType以便不像常规Type那样具有空位。

但是您要让解析器在有足够信息做出决定之前先确定intType还是FunType。由于无法确定是否应用生产FunType ::= Type,因此它选择移动Id(因为移位/减少冲突的默认解决方案是移位)。这使得不可能使用FunType ::= Type生产,这会触发未使用的规则警告。

唯一的简单解决方案是完全放弃FunType,但要付出一些重复:

DFunAllT.        FunDef ::= Type Id "(" [ Arg ] ")" FunBody;
DFunAllV.        FunDef ::= "void" Id "(" [ Arg ] ")" FunBody;

如果重复困扰您,您可以离开因素:

DFunTI.   FunTypeId ::= Type Id;
DFunVI.   FunTypeId ::= "void" Id;
DFunAll.  FunDef ::= FunTypeId "(" [ Arg ] ")" FunBody;

第一个可能更适合您的AST。