Parsing Lemon-LALR解析器的简单语法
这件事我已经坚持了一段时间了。我想分析一些简单的东西,如: 喜欢:word1 word2。。wordN讨厌:word1 word2。。沃顿 我用的是Lemon+Flex。目前我的语法是这样的:Parsing Lemon-LALR解析器的简单语法,parsing,parser-generator,lalr,lemon,Parsing,Parser Generator,Lalr,Lemon,这件事我已经坚持了一段时间了。我想分析一些简单的东西,如: 喜欢:word1 word2。。wordN讨厌:word1 word2。。沃顿 我用的是Lemon+Flex。目前我的语法是这样的: %left LIKES MOODS FROM HATES INFO. %syntax_error { std::cout << "Syntax error!" << std::endl; } final ::= likes_stmt. final ::= ha
%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;}
%left喜欢信息中的情绪。
%语法错误{
std::cout haves.push_back(A);}
列表::=likes\u stmt值(A)。{Data*Data=Data::getInstance();Data->likes.push_back(A);}
列表::=U stmt值(A)。{Data*Data=Data::getInstance();Data->haves.push_back(A);}
列表(A):=值(B)。{A=B;}
但这只适用于前两个单词。很明显我做错了什么,可能是在递归定义中?感谢您的提醒:)在我看来,您的喜好是以列表的形式定义的,而列表是以喜好的形式定义的。我很惊讶它对任何单词都有效。可能是因为我不懂LEMON语法(我当然一点也不懂这个列表),但语法BNF往往非常相似 我希望你的语法看起来更像:
final = likes_stmt ;
likes_stmt = LIKES list ;
likes_stmt = HATES list ;
list = value ;
list = list value ;
当然,这只会认出一个喜欢的短语,或者一个讨厌的短语,但不是同时或按你的问题的第2行暗示的顺序。 @ P> @ CurrFi火,IRA为你原来的问题提供了正确的答案,考虑投票。 让我来回答这个问题,您还需要将解析后的值分成两个列表。不要为解析这些列表创建不同的规则,因为这两种情况下列表的语法是相同的。您需要的是一个标志,指示在列表前面是否找到了喜欢或讨厌的内容。Lemon的
Parse
函数的第四个参数最适合这种需要。请参阅的“解析器接口”一节
下面更新了Ira的语法,用于设置和检查此类标志变量。请注意,规则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; }
谢谢你的回答。但恐怕我已经试过了。基本上,我试图做的是将字符串推到它们各自的位置(喜欢或讨厌)。在未来,我将有更多的保留标记,如信息、情绪等。它非常类似于谷歌的高级搜索语法。解析器生成器非常容易使用,并且在解析方面非常健壮。我建议你去掉语法中所有多余的语义动作,例如,把它简化成我写的东西,然后再试一次。如果可行,开始重新添加语义操作。通常的方法是首先解析,然后对树进行后处理,将信息收集到不同的类别中。这样,你就不会因为人工结果(“set_likes”等)而弄乱语法,而人工结果的唯一工作就是向“whileparsing”动作发送信号。在更复杂的语言中,这些信号大多只是制造悲伤,因为语法混乱,语法分析与工作纠缠不清。然而,如果这是OP需要做的所有事情,那么这个答案是好的。(谢谢你的投票!)