我已经坚持了一段时间了。我想解析一些简单的东西:
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个单词。显然我做错了,可能是在递归定义中?任何抬头都表示赞赏:)
答案 0 :(得分:2)
在我看来,您的likes_stmt是按照列表定义的,而列表是根据喜欢来定义的。我很惊讶它对任何单词都有效。可能是我不理解LEMON语法(我肯定不会得到列表(A)位),但语法BNF往往非常相似。
我希望你的语法看起来更像:
final = likes_stmt ;
likes_stmt = LIKES list ;
likes_stmt = HATES list ;
list = value ;
list = list value ;
当然,这只能识别一个LIKES短语或一个HATES短语,但不能同时识别问题第2行所暗示的相同时间或顺序。
答案 1 :(得分:2)
@crozzfire,Ira为您的原始问题提供了正确答案,请考虑投票。
让我回答这个问题,你需要将解析后的值分成两个列表。不要为解析这些列表创建不同的规则,因为列表的语法对于两种情况都是相同的。你需要的是一个标志,表明在列表前面是否找到了LIKES或HATES。 Lemon Parse
函数的第四个参数最适合这种需求。请参阅Lemon documentation的“分析器界面”部分。
下面更新了Ira的语法,用于设置和检查这样的标志变量。请注意,需要在LIKES和HATES令牌之前放置规则set_likes_state
和set_hites_state
,以便在令牌减少时执行相关操作。
%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; }