Простая грамматика для парсера Lemon LALR - PullRequest
3 голосов
/ 20 июля 2011

Я застрял с этим с некоторых пор.Я хочу разобрать что-то простое, например:

LIKES: word1 word2 .. wordN HATES: word1 word2 .. wordN

Я использую Lemon + Flex.На данный момент моя грамматика выглядит примерно так:

%left LIKES MOODS FROM HATES INFO.

%syntax_error {  
  std::cout << "Syntax error!" << std::endl;  
}   

final ::= likes_stmt.
final ::= hates_stmt.

likes_stmt ::= LIKES list(A). { Data *data=Data::getInstance();data->likes.push_back(A);}
hates_stmt ::= HATES list(A). { Data *data=Data::getInstance();data->hates.push_back(A);}

list ::= likes_stmt VALUE(A).   { Data *data=Data::getInstance();data->likes.push_back(A);}
list ::= hates_stmt VALUE(A).   { Data *data=Data::getInstance();data->hates.push_back(A); }

list(A) ::= VALUE(B).           {A=B;}

Но это работает только для первых 2 слов.Очевидно, я делаю что-то не так, возможно, в рекурсивном определении?Любая голова приветствуется:)

Ответы [ 2 ]

2 голосов
/ 10 августа 2012

@ crozzfire, Ира предоставила правильный ответ на ваш первоначальный вопрос, подумайте над тем, чтобы проголосовать за него.

Позвольте мне ответить на ваш вопрос с дополнительным требованием разделить проанализированные значения на два списка.Не создавайте разные правила для разбора этих списков, так как грамматика списка одинакова для обоих случаев.Вам нужен флаг, чтобы указать, были ли LIKES или HATES найдены перед списком.Четвёртый параметр функции Lemon Parse подходит для этого лучше всего.См. Раздел «Интерфейс синтаксического анализатора» Документация Lemon .

Ниже приведена обновленная грамматика Иры, которая устанавливает и проверяет такую ​​переменную флага.Обратите внимание, что правила set_likes_state и set_hites_state должны быть размещены непосредственно перед токенами LIKES и HATES, чтобы выполнялось соответствующее действие при уменьшении токенов.

    %extra_argument {unsigned* state}

    final ::= likes_stmt.
    final ::= hates_stmt.

    likes_stmt ::= set_likes_state LIKES list(A).
    hates_stmt ::= set_hites_state HATES list(A).

    list ::= list VALUE(A).   { if (*state == 0) {/*add A to list1*/} else {/*add A to list2*/}; }
    list ::= VALUE(A).        { if (*state == 0) {/*add A to list1*/} else {/*add A to list2*/}; }

    set_likes_state ::= .     { *state = 0; }
    set_hites_state ::= .     { *state = 1; }
2 голосов
/ 21 июля 2011

Мне кажется, что ваш likes_stmt определен в терминах списка, а список определен в терминах лайков. Я удивлен, что это работает для любых слов вообще. Возможно, я не понимаю синтаксис LEMON (я точно не получаю бит списка (A)), но грамматики BNF, как правило, очень похожи.

Я ожидаю, что ваша грамматика будет выглядеть примерно так:

 final = likes_stmt ;

 likes_stmt = LIKES list ;
 likes_stmt = HATES list ;


  list = value ;
  list = list value ;

Конечно, это будет распознавать только одну фразу LIKES или одну фразу HATES, но не то и то же время или в порядке, как это подразумевается в строке 2 вашего вопроса.

...