柠檬LALR解析器的简单语法



我已经被这个困扰了一段时间了。我想解析一些简单的东西,如:

喜欢:word1 word2 ..单词1单词2…wordN

我正在使用柠檬+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;}

但这只适用于前两个单词。显然我做错了什么,可能是在递归定义中?任何提示都很感谢:)

@crozzfire, Ira为你最初的问题提供了正确的答案,请考虑投票。

让我来回答您将解析值分离到两个列表中的附加要求。不要为这些列表的解析创建不同的规则,因为这两种情况下列表的语法是相同的。你需要的是一个标志,以表明是否喜欢或讨厌被发现在前面的列表。Lemon的Parse函数的第4个参数最适合这种需求。参见Lemon文档中的"解析器接口"一节。

下面是更新的Ira设置和检查标记变量的语法。请注意,规则set_likes_stateset_hites_state需要放在like和hate令牌之前,以便在令牌减少时执行相关操作。

    %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; }

在我看来,您的likees_stmt是根据列表定义的,而列表是根据喜欢定义的。我很惊讶它对任何单词都有效。这可能是我不理解LEMON的语法(我肯定不明白列表(A)位),但语法bnf往往非常相似。

我希望你的语法看起来更像:

 final = likes_stmt ;
 likes_stmt = LIKES list ;
 likes_stmt = HATES list ;

  list = value ;
  list = list value ;

当然,这只会识别一个喜欢的短语,或一个讨厌的短语,但不会同时或按照你的问题的第二行所暗示的顺序。

相关内容

  • 没有找到相关文章

最新更新