如何禁用所有BNFC内置规则,例如Ident
,Integer
或用于分隔令牌的空格?
我发现他们无用和恼人的,因为它们干扰了我正在尝试编写的解析器。
我已经尝试重新定义它们,但似乎词法分析器继续为它们生成规则。我可以从生成的文件中手动删除它们,但我完全反对修改机器生成的代码。
为什么令人讨厌的长版本。
我刚开始学习如何使用BNFC。我尝试的第一件事是将我之前的作品从Alex转换为BNFC。特别是我想只匹配“好”的罗马数字。我觉得这很简单: 罗马数字可以看作像
这样的序列<thousand-part> <hundred-part> <tens-part> <unit-part>
他们不可能都是空的。因此,数字要么具有非空thousand-part
,要么可以是其他数字,或者它是空的thousand-part
,因此hundred-
或tens-
或{{1 } unit-
必须为非空。同样的事情可以迭代,直到单位的基本情况。
所以我想出了这个,这或多或少是对我在亚历克斯所做的直接翻译:
part
现在,问题在于,如果我尝试构建此解析器,则在提供类似的输入时
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
中不止一个的数字不为空,则解析器会出错,因为BNFC无法将*-part
与单个令牌匹配,因此它使用了内置MMI
规则。由于规则没有出现在语法中,因此它会引发一个解析错误,虽然输入字符串完全没有我定义的语法,但它是 bogus Ident
规则。
注意:我确认如果我用空格分隔不同的部分,我得到正确的输入,但后来我想把空格分开整数,而不是它们的标记。
答案 0 :(得分:0)
根据BNFC的documentation:
这些类型是硬编码的,不能是规则的值类型
这意味着:无需修改生成的代码就无法禁用内置规则。唯一的选择是编写一个脚本,自动从生成的文件中删除伪造的规则,并始终使用Makefile
来构建词法分析器和解析器,以避免忘记该步骤。
似乎作者故意决定降低BNFC 强加他们对整数文字的定义的灵活性,标识符应该是什么样的,标记应该如何分开等 他们可能提供了默认规则,允许使用某些选项禁用它们,但他们认为如果您不同意他们的定义,那么您根本不应该使用他们的工具。