2017-03-01 18 views
0

1つのパス(ファイル全体)で解析するときにうまくいく文法があります。ANTLR4 parsing subrules

ここで、解析をコンポーネントに分割したいと考えています。そして、パーサーをサブルールで実行します。私は、私は、次のルールに表示されますサブルールを解析する他の人を想定して問題に遭遇した:上記のルールは、すべてが正常に動作するためにEOF解析し、トップレベルの開始規則から解析され

thing : LABEL? THING THINGDATA thingClause? 
      //{System.out.println("G4 Lexer/parser thing encountered");} 
     ; 
... 
thingClause : ',' ID (',' ID)? 
      ; 

。 (EOFには解析されない)サブ規則として解析されると、 "、"文字またはEOF文字のいずれかを見ることを期待しているので、節がなければパーザは動揺する。

ライン8:0ミスマッチ入力「%」期待{「」}

IはEOFを解析する際にトップレベルルールが探しているため、%は正しく、別の 『事』コンポーネントに解析されます。

toprule : thing+ 
      | endOfThingsTokens 
      ; 

endOfThingsTokensはEOFの前に発生します。このため、トップレベルのルールが機能する理由が考えられます。

サブルールを解析するには、ANTLR4パーサーが%トークンを受け入れたり無視したりして、 "OK we have thingClauseが表示されていません"と言い、トークンストリームをリセットして次のオブジェクトを別のオブジェクトパーサのインスタンス

この特定のケースでは、私は現在レクサー文法でスキップしているパーサーに改行を渡すためにレクサーを変更できます。これは、現在不要なトークンストリーム内の改行を受け入れるために、他にもたくさんの変更が必要になります。

本質的に、ルールに「レコードの終わり」トークンを持たせるためには何らかの方法が必要です。しかし、私は意味論的述語規則でこれを解決する方法があるのか​​疑問に思っていました。

何かのように:

thing : { if comma before %}? LABEL? THING THINGDATA thingClause? 
      | LABEL? THING THINGDATA 
      ; 
    ... 

    thingClause : ',' ID (',' ID)? 
      ; 

上記述語の擬似コードは、オプションthingClauseを隠すでしょうか?特定の「終わり」のトークン(つまり改行)を探すことなく、パーサが1つの「もの」を解析した後にパーサが停止するようには満足できない場合。

私がこれを解決すれば、私は答えを投稿します。

答えて

1

パーサーは、トークンストリームで(効果的に)先読みして、現在のルールが満たされるかどうかを判断します。対応するトークンが消費されます。ルックアヘッドトークンが使用されていない場合、パーサーはこれらのルックアヘッドトークンと追加のルックアヘッドトークンを消費する別のルールを探します。

要素が一致しない場合、パーサで消費されないトークンが発生します。したがって、あなたが見ているエラー。

パーサールックアヘッドはデータに依存します。ルールの要素の評価が、現在のルールが消費する可能性のあるトークンよりも多くのトークンをパーサに容易に読み取ることができることを意味します。

述語が役立つ可能性がありますが、決定的な問題にはなりません。つまり、たとえパーサーがプレディクトされていないaltと一致したとしても、そのaltによって消費されるよりも多くのトークンをパーサに読み込んでいる可能性があります。

この非決定論を避ける唯一の方法は、サブルールの境界でトークンストリームに<EOF>トークンを事前に注入することです。

+0

ありがとうございました。私は、EOFを事前注入するための一般的な方法を作成する方法について考えてきました。私はTokenReWriterを見てきましたが、それは私が見てきた例が元のトークンストリームを解析した後に呼び出されるので、それをどのように使いたいのかは分かりません。しかし、私が望むかもしれない場所でEOFトークンを注入するカスタムトークンストリームを作成するのに十分なロープがあるようです。 –

+0

申し訳ありませんが、あなたを奨励するつもりはありませんでした。理論的には可能ですが、それはひどく非実用的なアプローチです。はるかに優れた選択肢は、簡単で標準的なAntlr実装を使用できないように問題を特定して解決することです。 – GRosenberg

+0

@RossYoungbloodもちろん、このサブルールとマッチしたい場合は、最後にEOF( 'thing'ルールを呼び出します)を持つ' thingStandalone'ルールを作成することができます。 –