我已经被这个困扰了一段时间了。我想解析一些简单的东西,如:
喜欢: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_state
和set_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 ;
当然,这只会识别一个喜欢的短语,或一个讨厌的短语,但不会同时或按照你的问题的第二行所暗示的顺序。