Грамматика BNF + синтаксический анализатор Gold LALR, не в состоянии отличить специальный случай NewLine от пробела
- Я хочу рассматривать пробелы и символы новой строки как обычные пробелы.
- Я хочу отличать новые строки от других пробелов, кроме того, чтобы разрешить особый случай.
Первая попытка написать совместимую грамматику не удалась.
Вот грамматика:
! ------------------------------------------------- Sets
{WS} = {Whitespace} - {CR} - {LF}
{ID Head} = {Letter} + [_]
{ID Tail} = {Alphanumeric} + [_]
{String Chars} = {Printable} + {HT} - ["\]
! ------------------------------------------------- Terminals
! The following defines the Whitespace terminal using the {WS}
! set - which excludes the carriage return and line feed
! characters
Whitespace = {WS}+ | {CR}{LF} | {CR} | {LF}
!NewLine = {CR}{LF} | {CR} | {LF}
MyNewLine = {CR}{LF} | {CR} | {LF}
3 ответа
Они неоднозначны, потому что они оба содержат один и тот же набор {CR}{LF} | {CR} | {LF}
,
Учитывая вход {CR}{LF}
парсер не может сказать, с каким терминалом он должен совпадать.
Парсер, управляемый таблицами, не предназначен для непосредственной обработки "особых случаев". Если вы хотите игнорировать новые строки в одних контекстах, но приписывать им значение в других контекстах, вам придется обрабатывать это в ваших сокращениях (то есть разбивать новые строки по отдельности и отбрасывать их в ваших сокращениях), но это будет ужасно,
(Потенциально) лучшее решение состоит в том, чтобы использовать состояния токенизатора (возможно, контролируемые парсером), чтобы изменить, как вводятся символы новой строки. Трудно сказать без полного понимания вашей грамматики. Плюс, прошло несколько лет с тех пор, как я с этим связался.
Я думаю, что грамматика неоднозначна в том смысле, что и Whitespace, и MyNewLine соответствуют символам новой строки. Поскольку это приводит к шаткой работе по-своему, я предлагаю обнаруживать пробелы и новые строки по отдельности и решать, что делать с новой строкой в каждом конкретном случае.
Я не слишком опытен в этой области, но это то, что я помню из своего класса Theory Of Computation и класса Compiler Design.
Надеюсь, это поможет.
Поздний ответ.
К моему ужасу, я только недавно умер в последнее время;-).
Продолжайте использовать обычные линейные объявления грамматики
! ====================================================================
{Whitespace Ch} = {Whitespace} - {CR} - {LF}
Whitespace = {Whitespace Ch}+
Newline = {CR}{LF} | {CR} | {LF}
! ====================================================================
Различие между пробелами и символами новой строки уже учтено!
Рассмотрите возможность рассмотрения вашего особого случая при написании правил производства.
Для сложных случаев вам может даже потребоваться определить какой-нибудь виртуальный терминал (продвинутый метод).
Вы можете разработать свою грамматику и спросить, разместив ее снова.
Последнее редактирование: поделитесь, если вы уже обратились к проблеме. Благодарю.