2011-07-20 48 views
3

自从现在我一直坚持这一点。我想分析简单的东西如:柠檬LALR解析器的简单语法

喜欢:字词1字词2 .. wordN HATES:字词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;} 

但是,这只适用于前2个单词。很明显,我做错了什么,可能是在递归定义?任何抬头赞赏:)

回答

2

@crozzfire,Ira为您的原始问题提供了正确答案,请考虑投票。

让我回答你的问题,附加要求是将解析值分成两个列表。不要为解析这些列表创建不同的规则,因为这两种情况下列表的语法是相同的。你需要的是一个标志,表明在列表前面是否有LIKS或HATES。柠檬Parse功能的第四个参数最适合这种需求。请参阅Lemon documentation的“解析器接口”部分。

下面更新艾拉的语法设置和检查这样的标志变量。请注意,规则set_likes_stateset_hites_state需要放置在LIKES和HATES标记之前,以减少令牌时执行相关操作。

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

通常,这样做的方式是首先解析,然后后处理该树以将信息收集到各种类别中。这样你就不会用人造产品(“set_likes”等)来破坏语法,而这些只是工作中的信号来表示“解析”动作。在更复杂的语言中,这些信号大多只会造成悲伤,因为混乱的语法和纠结与工作解析。但是,如果这是*所有* OP需要做的,那么这个答案是好的。 (感谢upvote!) –

2

它在我看来,你的likes_stmt是根据列表来定义的,列表是根据喜欢定义的。我很惊讶它对任何单词都有效。这可能是因为我不明白LEMON语法(我确定没有得到列表(A)),但是语法BNF往往非常相似。

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

final = likes_stmt ; 

likes_stmt = LIKES list ; 
likes_stmt = HATES list ; 


    list = value ; 
    list = list value ; 

这当然只认人喜欢短语或一个短语HATES,但两者不能同时间或者为了如线暗示2你的问题。

+0

感谢您的回答。但是我担心我已经尝试过了。基本上,我想要做的就是把琴弦推到他们各自的地方(LIKS或HATES)。将来,我会有更多的保留令牌,如INFO,MOODS等,它与Google的高级搜索语法非常相似。 – crozzfire

+0

解析器生成器非常易于使用,并且在解析时非常健壮。我建议你在你的语法中去掉所有额外的语义动作,例如,把它减少到与我写的相同,然后再试一次。如果可行,请开始添加语义操作。 –