如何禁用所有 BNFC 内置规则,例如Ident
,Integer
或用于分隔令牌的空格?
我发现它们无用且烦人,因为它们会干扰我正在尝试编写的解析器。
我已经尝试重新定义它们,但词法分析器似乎继续为它们生成规则。我可以从生成的文件中手动删除它们,但我完全反对修改机器生成的代码。
关于他们为什么烦人的长版本。
我刚刚开始学习如何使用 BNFC。我尝试的第一件事是将我以前的工作从 Alex 转换为 BNFC。特别是我想只匹配“好”的罗马数字。我认为这很简单:罗马数字可以看作是一个序列
<thousand-part> <hundred-part> <tens-part> <unit-part>
他们不可能都是空的。所以一个数字要么有一个非空的thousand-part
,并且可以是其余的任何东西,要么它有一个空的thousand-part
,因此要么hundred-
或tens-
要么unit-
part
必须是非空的。可以重复相同的事情直到单位的基本情况。
所以我想出了这个,这或多或少是我在 Alex 中所做的直接翻译:
N1. Numeral ::= TokThousands HundredNumber ;
N2. Numeral ::= HundredNumberNE ; --NE = Not Empty
N3. HundredNumber ::= ;
N4. HundredNumber ::= HundredNumberNE ;
N5. HundredNumberNE ::= TokHundreds TensNumber ;
N6. HundredNumberNE ::= TensNumberNE ;
N7. TensNumber ::= ;
N8. TensNumber ::= TensNumberNE ;
N9. TensNumberNE ::= TokTens UnitNumber ;
N10. TensNumberNE ::= UnitNumberNE ;
N11. UnitNumber ::= ;
N12. UnitNumber ::= UnitNumberNE ;
N13. UnitNumberNE ::= TokUnits ;
token TokThousands ({"MMM"} | {"MM"} | {"M"}) ; -- No x{m,n} in BNFC regexes?
token TokHundreds ({"CM"} | {"DCCC"} | {"DCC"} | {"DC"} | {"D"} | {"CD"} | {"CCC"} | {"CC"} | {"C"}) ;
token TokTens ({"IC"} | {"XC"} | {"LXXX"} | {"LXX"} | {"LX"} | {"LX"} | {"L"} | {"IL"} | {"XL"} | {"XXX"} | {"XX"} | {"X"}) ;
token TokUnits ({"IX"} | {"VIII"} | {"VII"} | {"VI"} | {"V"} | {"IV"} | {"III"} | {"II"} | {"I"}) ;
现在,问题是如果我尝试构建这个解析器,当给出如下输入时:
MMI
或者一般来说,如果一个数字有多个*-part
s 不为空,则解析器会给出错误,因为 BNFC 无法MMI
与单个令牌匹配,因此它使用内置Ident
规则。由于该规则未出现在语法中,因此会引发解析错误,尽管输入字符串在我定义的语法中完全没问题,但这是一个伪造 Ident
的规则。
注意:我验证了如果我用空格分隔不同的部分,我会得到正确的输入,但稍后我想用空格分隔整数,而不是它们的标记。