Как отключить встроенные правила?
Как я могу отключить все встроенные правила BNFC, как Ident
, Integer
или пробелы, используемые для разделения токенов?
Я нашел их бесполезными и раздражающими, поскольку они мешают анализаторам, которые я пытаюсь написать.
Я уже пытался переопределить их, но похоже, что лексер продолжает создавать правила для них. Я мог бы вручную удалить их из сгенерированных файлов, но я полностью против модификации машинно-сгенерированного кода.
Длинная версия о том, почему они раздражают.
Я только начинаю учиться использовать BNFC. Первое, что я попробовал, - это конвертировать мою предыдущую работу с Алекса в BNFC. В частности, я хочу сопоставлять только "хорошие" римские цифры. Я думал, что это будет довольно просто: римская цифра может рассматриваться как последовательность
<thousand-part> <hundred-part> <tens-part> <unit-part>
Там, где они не могут быть пустыми. Так что у числа есть непустой thousand-part
и может быть что угодно в остальном, или оно пустое thousand-part
и, таким образом, либо hundred-
или же tens-
или же 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
Или вообще цифра, которая имеет более одного *-part
не пусто, синтаксический анализатор выдает ошибку, потому что BNFC не может соответствовать MMI
с одним токеном и, таким образом, он использует встроенный Ident
правило Так как правило не отображается в грамматике, оно вызывает ошибку синтаксического анализа, хотя входная строка отлично подходит для определенной мной грамматики, это фальшивка Ident
Правило, которое в пути.
Примечание: я проверил, что если я разделяю разные части пробелами, я получаю правильный ввод, но позже я хочу поставить пробелы для разделения целых чисел, а не их токенов.
1 ответ
Согласно документации BNFC:
Эти типы жестко запрограммированы и не могут быть типами правил
Это означает, что: невозможно отключить встроенные правила без изменения сгенерированного кода. Единственный вариант - написать скрипт, который автоматически удаляет поддельные правила из сгенерированного файла и всегда использует Makefile
построить лексеры и парсер, чтобы не забывать этот шаг.
Похоже, что авторы сознательно решили уменьшить гибкость BNFC, навязывая свое определение того, что такое целочисленный литерал, как должен выглядеть идентификатор, как следует разделять токены и т. Д. Они могли бы предоставить правила по умолчанию, позволяющие отключить их с некоторыми вариант, но они решили, что если вы не согласны с их определениями, то вы не должны использовать их инструмент вообще.