2011-07-20 4 views
3

私はこれまでしばらくの間これに固執してきました。レモンLALRパーサーのためのシンプルな文法

が好き:として私はシンプルなものを解析したい単語1ワード2 ... wordNは嫌い:単語1 WORD2 .. wordN

私はレモン+フレックスを使用しています。現時点で私の文法は次のようになっています:

%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はあなたの元の質問に対して正解を出したので、投票してください。

2つのリストに解析された値を区切るための追加要件があります。両方のケースでリストの文法が同じであるため、これらのリストの解析に異なるルールを作成しないでください。必要なのは、LIKEまたはHATESがリストの前にあるかどうかを示すフラグです。レモンの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; } 
+0

通常、これを行う方法は最初に解析し、ツリーを後処理してさまざまなカテゴリに情報を収集します。そうすれば、人工的な制作物( "set_likes"など)で文法を混乱させることはありません。その仕事は、 "while-parsing"アクションに信号を送ることだけです。より複雑な言語では、これらのシグナルはほとんど文法を混乱させ、構文解析を仕事と混同するため、悲しみを生み出します。しかし、これが*すべて* OPが行う必要がある場合、この答えは問題ありません。 (upvoteありがとう!) –

2

あなたのlikes_stmtはリストの観点から定義されており、リストは好きな点で定義されています。私はそれがどんな言葉でもうまくいくのに驚いています。私はLEMON構文(私はリスト(A)ビットを得ていない)を理解していない可能性がありますが、文法BNFはかなり似ている傾向があります。

私はあなたの文法はもっとように見えることを期待したい。もちろん

final = likes_stmt ; 

likes_stmt = LIKES list ; 
likes_stmt = HATES list ; 


    list = value ; 
    list = list value ; 

ラインによって示唆されるように、同じ時間や順序で両方これが唯一の1フレーズを好き認識することになる、または1つのフレーズを嫌いではなく、あなたの質問2。

+0

ご回答ありがとうございます。しかし、私はすでにそれを試みたのではないかと心配しています。基本的に、私がしようとしているのは、文字列をそれぞれの場所(LIKESまたはHATES)にプッシュすることです。今後は、INFOやMOODSなどの予約トークンを増やす予定です。Googleの高度な検索構文とよく似ています。 – crozzfire

+0

パーサージェネレーターは使い方が簡単で、解析にかなり堅牢です。私はあなたの文法に余分なセマンティックアクションをすべて削除することをお勧めします。例えば、これを私が書いたものだけに減らして、もう一度試してみてください。それが機能する場合は、セマンティックアクションを追加し直してください。 –

関連する問題