powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Грамматика. BNF
6 сообщений из 6, страница 1 из 1
Грамматика. BNF
    #34915636
Серж
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть следующий кусочек грамматики:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
{String Ch  1 }      = {Printable National} - ["]
{String Ch  2 }      = {Printable National} - ['']
{Id Ch Standard}   = {Alphanumeric} + [_]
{Id Ch Extended}   = {Printable National} - ['['] - [']']

StringLiteral   = '"'{String Ch  1 }*'"' | ''{String Ch  2 }*''
IntegerLiteral  = {Digit}+
RealLiteral     = {Digit}+'.'{Digit}+

Id             = ({Letter}{Id Ch Standard}* | '['{Id Ch Extended}+']' | StringLiteral)

Идентификатор (Id) может быть простым, т.е. начинаться с буквы и не содержать пробелов, национальных символов и т.д., либо может обрамляться
1 квадратными скобками
2 кавычками двойными "
3 одинарными '
и тогда может содержать в себе все что угодно.

Т.е. варианты 2 и 3 -- это строка, StringLiteral.

Так как я записал, грамматика компилируется без ошибок. Когда выполняю тест, то если использовать квадратные скобки, то все хорошо. Если идентификатор записать, как строку, т.е. в кавычках, то парсер выдает ошибку "Токен StringLiteral найден, ожидался Id".

Как правильно грамматику записать для такого случая?

P.S. Пользуюсь Gold Parser
...
Рейтинг: 0 / 0
Грамматика. BNF
    #34915734
teras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Серж wrote:
> Есть следующий кусочек грамматики:
>
> {String Ch *1*} = {Printable National} - ["]
> {String Ch *2*} = {Printable National} - ['']
> {Id Ch Standard} = {Alphanumeric} + [_]
> {Id Ch Extended} = {Printable National} - ['['] - [']']
>
> StringLiteral = '"'{String Ch *1*}*'"' | ''{String Ch *2*}*''
> IntegerLiteral = {Digit}+
> RealLiteral = {Digit}+'.'{Digit}+
>
> Id = ({Letter}{Id Ch Standard}* | '['{Id Ch Extended}+']' | StringLiteral)
>
>
> Идентификатор (Id) может быть простым, т.е. начинаться с буквы и не
> содержать пробелов, национальных символов и т.д., либо может обрамляться
> 1 квадратными скобками
> 2 кавычками двойными "
> 3 одинарными '
> и тогда может содержать в себе все что угодно.
>
> Т.е. варианты 2 и 3 -- это строка, StringLiteral.
>
> Так как я записал, грамматика компилируется без ошибок. Когда выполняю
> тест, то если использовать квадратные скобки, то все хорошо. Если
> идентификатор записать, как строку, т.е. в кавычках, то парсер выдает
> ошибку "Токен StringLiteral найден, ожидался Id".
>

GOLD-ом не пользуюсь. Поэтому из общих соображений, опыта с lex/yacc b и
того, но в грамматике видимо присутствует конфликт между StringLiteral и Id.
Конфликт возникает либо на уровне лексического анализа (если Id
считается терминалом): определение Id через StringLiteral, в этом случае
StringLiteral и Id неразличимы, и парсер отдает приоритет первому
(например, так делает lex. Причем молча). Либо на уровне синтаксического
анализа (если Id - нетерминал): тогда в выражениях будет возникать
конфликт между действиями одинакового типа (перенос-перенос,
свертка-свертка). Yacc в этих случаях ругается, но парсер генерит,
так-же отдавая приоритет первому правилу.

> Как правильно грамматику записать для такого случая?
>

Это зависит от того как используются StringLiteral и Id в грамматике. Из
общих соображений и того, что присутствуют правила вида (даже косвенно,
с учетом LR(0) ситуаций)

Primary = StringLiteral | Id ;

Id можно разбить на два независимых терминала, и трансформировать
StringLiteral в Id на уровне правила обработки. Или использовать
предикаты, если поддерживаются в GOLD. Или внести предикат на уровень
лексического анализа.

Подобная проблема возникает, например, при использовании LALR(1) в
языках типа в C/C++ - конфликт между типом и идентификатором.
Разрешается обычно на уровне лексического анализатора, скажем в lex:

[_a-zA-Z][_a-zA-Z0-9]* { return is_type_name(yytext) ? TYPE_NAME :
IDENT; }
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Грамматика. BNF
    #34915870
Серж
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо. Понятно, но смутно :) Ид и СтрингЛитерал оба терминалы. И действительно получаются неразличимы.

teras, а с lemon'ом не работал?
...
Рейтинг: 0 / 0
Грамматика. BNF
    #34915971
teras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Серж wrote:
> Спасибо. Понятно, но смутно :) Ид и СтрингЛитерал оба терминалы. И
> действительно получаются неразличимы.

Вот смотри, рассмотрим такой пример: идентификатор
([a-zA-Z_][a-zA-Z_0-9]*) и ключевое слово (например, while) в типичном
языке. Очевидно, что ключевое слово так-же является идентификатором. То
есть грамматика содержащий два этих правила в принципе неоднозначна.

Другими словами следующий две грамматики lex, читающие со входа "while"
вернут разный результат:

========
while return WHILE;
[a-zA-Z_][a-zA-Z_0-9]* return IDENT;
========
[a-zA-Z_][a-zA-Z_0-9]* return IDENT;
while return WHILE;
========

Во второй грамматике правило для WHILE не сработает никогда. Поэтому, и
применяются правила разрешения конфликтов по принципу более раннего
объявления. Кстати, flex об этом предупреждает. А вот, скажем, lex - нет.

>
> teras, а с lemon'ом не работал?
Приходилось немного. А что?
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Грамматика. BNF
    #34915984
Серж
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Теперь понятнее.

У меня есть файлик grammar.y для lemon'а, но посмотрев в него и почитав справку на сайте автора я так и не понял как его использовать.

А вообще мне надо представить выражение в каком-либо структурированном виде (дерево, например), чтобы можно было про нему пройти.
...
Рейтинг: 0 / 0
Грамматика. BNF
    #34916173
teras
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Серж wrote:
> Теперь понятнее.
>
> У меня есть файлик grammar.y для lemon'а, но посмотрев в него и почитав
> справку на сайте автора я так и не понял как его использовать.

А что именно непонятно? lemon поддерживает только синтаксический анализ.
Лексический анализатор к нему нужно писать отдельно. То есть делаешь
функцию, читающую файл и разбирающую поток на отдельные лексемы - те
самые while, if, ident, number, string, и т.д (или можно каким-нибудь
flex). Затем, компилируешь грамматику lemon. Он делает функцию,
воспринимающую на входе лексемы (и значения), и производящую
синтаксический анализ, в соответствии с грамматикой. Достигнув конца
потока эта функция вызывается в последний раз с лексемой 0 (ноль).

>
> А вообще мне надо представить выражение в каком-либо структурированном
> виде (дерево, например), чтобы можно было про нему пройти.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Грамматика. BNF
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]