Parsing Lemon-LALR解析器的简单语法

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

这件事我已经坚持了一段时间了。我想分析一些简单的东西,如:

喜欢: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 ::= 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需要做的所有事情,那么这个答案是好的。(谢谢你的投票!)