3

一段时间以来,我一直坚持这一点。我想解析一些简单的东西:

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

4

2 回答 2

2

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

让我用您将解析值分成两个列表的附加要求来回答这个问题。不要为解析这些列表创建不同的规则,因为两种情况下列表的语法是相同的。您需要的是一个标志来指示是否在列表前面找到了 LIKES 或 HATES。LemonParse函数的第 4 个参数最适合这种需求。请参阅Lemon 文档的“解析器接口”部分。

下面是更新的 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; }
于 2012-08-10T08:24:23.377 回答
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 行所暗示的顺序。

于 2011-07-20T22:48:53.590 回答