【问题标题】:Simple Grammar for Lemon LALR ParserLemon LALR 解析器的简单语法
【发布时间】:2011-07-20 19:35:03
【问题描述】:

我已经被这个问题困扰了一段时间了。我想解析一些简单的东西:

喜欢:word1 word2 .. wordN 讨厌: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 个单词。显然我做错了什么,可能在递归定义中?任何提醒表示赞赏:)

【问题讨论】:

    标签: parsing parser-generator lalr lemon


    【解决方案1】:

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

    让我回答您的问题,即将解析的值分成两个列表的附加要求。不要为解析这些列表创建不同的规则,因为两种情况下列表的语法是相同的。您需要的是一个标志来指示是否在列表前面找到了 LIKES 或 HATES。 Lemon 的Parse 函数的第四个参数最适合这种需求。请参阅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; }
    

    【讨论】:

    • 通常这样做的方式是先解析,然后对树进行后处理以将信息收集到各种类别中。这样,您就不会使用人工产生(“set_likes”等)来破坏语法,而人工产生的唯一工作就是向“解析时”动作发出信号。在更复杂的语言中,这些信号大多只会造成悲伤,因为语法混乱,解析工作也很纠结。但是,如果这是 all OP 需要做的,那么这个答案很好。 (感谢您的支持!)
    【解决方案2】:

    在我看来,您的 likes_stmt 是根据列表定义的,而列表是根据喜欢定义的。我很惊讶它适用于任何单词。可能是我不懂 LEMON 语法(我肯定没听懂 list(A) 位),但 BNF 的语法往往非常相似。

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

     final = likes_stmt ;
    
     likes_stmt = LIKES list ;
     likes_stmt = HATES list ;
    
    
      list = value ;
      list = list value ;
    

    当然,这只会识别一个 LIKES 短语或一个 HATES 短语,但不能同时识别两个短语或问题第 2 行暗示的顺序。

    【讨论】:

    • 感谢您的回答。但恐怕我已经尝试过了。基本上,我要做的是将字符串推到各自的位置(喜欢或讨厌)。未来,我会保留更多的标记,例如 INFO 、 MOODS 等。它非常类似于 Google 的高级搜索语法。
    • 解析器生成器非常易于使用,并且在解析方面非常健壮。我建议你去掉语法中所有额外的语义动作内容,例如,将其简化为几乎我所写的内容,然后再试一次。如果可行,请开始添加您的语义操作。
    猜你喜欢
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 2017-09-07
    • 2012-08-23
    • 2020-08-21
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    相关资源
    最近更新 更多