TinyPG неправильно анализирует эту грамматику, ошибку или плохую грамматику?

Мне нужно разобрать простой язык, который я не проектировал, поэтому я не могу изменить язык. Мне нужны результаты в C#, поэтому я использую TinyPG, потому что он очень прост в использовании и не требует внешних библиотек для запуска парсера.

Все шло довольно хорошо, пока я не столкнулся с этой конструкцией на языке. (Это упрощенная версия, но она показывает проблему):

EOF               -> @"^\s*$";
[Skip] WHITESPACE -> @"\s+";
LIST              -> "LIST";
END               -> "END";
IDENTIFIER        -> @"[a-zA-Z_][a-zA-Z0-9_]*";
Expr              -> LIST IDENTIFIER+ END;
Start             -> (Expr)+ EOF;

Результирующий синтаксический анализатор не может проанализировать это:

LIST foo BAR Baz END

потому что это жадно лекс IDENTIFIERвместо того, чтобы правильно как END ключевое слово.

Итак, вот мои вопросы:

  1. Является ли эта грамматика неоднозначной или неправильной для анализа LL(1)? Или это ошибка в TinyPG?

  2. Есть ли способ изменить грамматику так, чтобы TinyPG правильно проанализирует пример строки?

  3. Есть ли другие предложения для простого парсера, который выводит код в C# и не требует дополнительных библиотек? Я смотрел на LLLPG а также ANTLR4, но нашел их гораздо более хлопотным, чем TinyPG,

1 ответ

Вы можете быть тем же парнем, поскольку проблема выглядит идентично той, что я ответил на GitHub, но здесь она снова для людей, которые гуглили эту проблему.

Вот пример из проекта Simple-CIL-compiler. Идентификатор должен перехватывать отдельные слова, кроме перечисленных, что означает, что вы должны включить токен исключения в идентификатор

IDENTIFIER-> @"[a-zA-Z_][a-zA-Z0-9_]*(?<!(^)(end|else|do|while|for|true|false|return|to|incby|global|or|and|not|write|readnum|readstr|call))(?!\w)";

Надеюсь, это поможет.

(Ссылка на оригинальный пост)

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