Lemon LALR解析器的简单语法

3

我一直被这个问题困扰,想要解析的内容非常简单:

喜欢:单词1 单词2 ... 单词N 讨厌:单词1 单词2 ... 单词N

我正在使用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个回答

2
@crozzfire,Ira为您的原始问题提供了正确的答案,请考虑投票支持她。
让我回答一下您的问题,并满足您将解析值分成两个列表的额外要求。不要为这些列表的解析创建不同的规则,因为两种情况下列表的语法是相同的。您需要一个标志来指示在列表前面是否找到了LIKES或HATES。 Lemon的Parse函数的第4个参数最适合这种需求。请参见Lemon documentation中的“解析器接口”部分。
以下是更新后的Ira语法,用于设置和检查此类标志变量。请注意,规则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; }

1
通常这样做的方法是先解析,然后后处理树将信息收集到各种类别中。这样你就不会用人工产生的产物(“set_likes”等)来干扰语法,它们唯一的工作是向“while-parsing”操作发出信号。在更复杂的语言中,这些信号大多只会制造麻烦,因为它们使语法混乱且让解析和工作纠缠在一起。但是,如果这是 OP 需要做的 全部,那么这个答案就很好了。(感谢您的点赞!) - Ira Baxter

2

我看到你的likes_stmt是基于列表定义的,而列表又是基于likes定义的。我很惊讶它能在任何单词上运行。可能是因为我不理解LEMON语法(我确实不理解list(A)),但是语法BNF通常非常相似。

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

 final = likes_stmt ;

 likes_stmt = LIKES list ;
 likes_stmt = HATES list ;


  list = value ;
  list = list value ;

当然,这只能识别一个“喜欢”的短语或一个“讨厌”的短语,但不会同时识别两个或按照您问题中第二行所示的顺序识别两者。

谢谢你的回答。但我担心我已经尝试过了。基本上,我正在尝试将字符串推送到它们各自的位置(LIKES或HATES)。将来,我将有更多的保留标记,例如INFO,MOODS等。这非常类似于Google的高级搜索语法。 - crozzfire
解析器生成器非常易于使用,而且在解析方面非常强大。我建议你在语法中摆脱所有额外的语义动作内容,例如将其减少到基本上只有我所写的内容,并再次尝试。如果这样可以,请开始添加你的语义动作。 - Ira Baxter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接