Как отключить встроенные правила?

Как я могу отключить все встроенные правила 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, навязывая свое определение того, что такое целочисленный литерал, как должен выглядеть идентификатор, как следует разделять токены и т. Д. Они могли бы предоставить правила по умолчанию, позволяющие отключить их с некоторыми вариант, но они решили, что если вы не согласны с их определениями, то вы не должны использовать их инструмент вообще.

Другие вопросы по тегам