我正在尝试为类 C 语言编写 LBNF/BNFC 语法。在 C 语言中,有许多可能的修饰符,您可能会或可能不会在声明前写入(如inline、const等volatile)。
我正在尝试编写语法以重用代码并使生成的 Haskell AST 易于使用。类型的语法可能如下所示:
rule TypeName ::= "bool" | "int" | "double" | "void" | Id ;
Type. Type ::= TypeQualifier TypeName;
ConstModifier. TypeModifier ::= "const" ;
VolatileModifier. TypeModifier ::= "volatile" ;
NoModifier. TypeModifier ::= ;
对于函数声明,它可能如下所示:
Fun. Fun ::= FunModifier Type Id "(" [Param] ")" ";" ;
InlineModifier. FunModifier ::= "inline" ;
NoFunModifier. FunModifier ::= ;
问题是由于这些可选前缀,我得到了大量的移位/减少,有时甚至减少/减少冲突。避免这些冲突的替代语法可能如下所示:
NotInlinedFun. Fun ::= Type Id "(" [Param] ")" ";" ;
InlinedFun. Fun ::= "inline" Type Id "(" [Param] ")" ";" ;
或者
NotInlinedFun. Fun ::= FunRest
InlinedFun. Fun ::= "inline" FunRest;
FunRest. FunRest ::= Type Id "(" [Param] ")" ";" ;
这导致了这样的 Haskell AST:
data Fun = AFun FunRest | BFun FunRest | CFun FunRest
data FunRest = FunRest Type Id [Param]
而不是更吸引人
data Fun = Fun Modifier Type Id [Param]
data Modifier = A | B | C
您可以看到这如何迅速导致规则组合爆炸或使用不愉快的 Haskell AST。
我怎样才能最好地避免这些冲突?