0

Altlr バージョン 3.4 を使用しています。

最初の質問です。文法を参照してください。

request: 'C' DELIM source DELIM target
  { System.out.println("Hi"); }
  ;
source: ID ;
target: ID ;

DELIM: '|' ;
fragment ALPHA: 'a'..'z' | 'A'..'Z' ;
fragment NUM: '0'..'9' ;
ID: ALPHA (ALPHA | NUM)* ;

「ソース」と「ターゲット」を空にすることはできません。しかし、私のテストでは次のことが示されています。

  • 入力 "C|n1|n2" の場合: 通常の場合、問題ありません。
  • 入力 "C||n2" の場合: 構文エラー、および "Hi" は出力されません。期待される。Ok
  • 入力 "C|n1|" の場合 : 構文エラーですが、"Hi" が出力されます。良くない。

「リクエスト」トークンに到達した場合は、他のものを設定する必要があります。しかし、構文エラーの場合でも、コードは「リクエスト」トークンに到達します。なんで?

2 番目の質問: 固定長のトークン (たとえば、正確に 10 桁のトークン) のルールを指定するにはどうすればよいですか?

3 番目の質問は、エラー処理に関するものです。パーサーでemitErrorMessage()をオーバーライドしてエラーフラグを設定しましたが、レクサーで別のemitErrorMessage()を見つけました。パーサー オブジェクトとレクサー オブジェクトの間でエラー フラグを共有したくありません。レキサーでemitErrorMessage()をオーバーライドして何もせず、パーサーに完全に依存してエラーを報告することはできますか? または、別の言い方をすれば、エラーが発生した場合、パーサーはそれを確実にキャプチャしますか?

また、エラー フラグが 1 つのエラーに設定されている場合、パーサーは実際に回復して別のルールに一致させることができるので、前のエラーは誤警報でしょうか?

助けてくれてありがとう!

4

2 に答える 2

1
  • ..。
  • 入力「C|n1|」の場合 :構文エラーですが、「Hi」が出力されます。良くない。

「リクエスト」トークンに到達した場合は、他の設定を行う必要があります。しかし、上記から、構文エラーの場合でも、コードは「要求」トークンに到達します。なんで?

パーサーはこれから回復しようとするためです。パーサーが不一致のトークンから回復する(しようとする)ことを望まない場合は、次のような例外をスローするだけです。

grammar T;

// options...

@members {
  @Override
  public void emitErrorMessage(String message) {
    throw new RuntimeException(message);
  }
}

request
 : 'C' DELIM source DELIM target { System.out.println("Hi"); }
 ;

// more rules...

@membersの略であることに注意してください。これにより、パーサーで@parser::membersのみオーバーライドされ、レクサーではオーバーライドされません。emitErrorMessage(...)レクサーメンバーの場合は、を実行する必要があります@lexer::members

2番目の質問:固定長トークンのルール(たとえば、正確に10桁のトークン)を指定するにはどうすればよいですか?

参照:ANTR3は、トークンに受け入れられる文字数を設定します

3番目の質問はエラー処理についてです。..。

私の答えの最初の部分を参照してください:単にオーバーライドemitErrorMessage()して何もしません(デフォルトのアクションはに印刷することですstd.err)。

レクサーでemitErrorMessage()をオーバーライドして何もせず、パーサーに完全に依存してエラーを報告できますか?

パーサーとレクサーは異なるタイプまたはエラーを処理するため、レクサーの特定の問題を無視しても、パーサーが警告/エラーを生成しない場合があります。

于 2012-04-30T06:41:14.647 に答える
0

バート、あなたの助けは素晴らしいです。私もよく考えて、質問 1 の動作が正当であることを理解しました。コンパイラと同様に、パーサーは回復し、可能な限り多くのエラーを検出し続けます。

質問#2については、固定長を行う方法も見つけました。それが一般的な方法かどうかはわかりません:

例:exact3 '|' 正確な4;

// 方法 1:
exact3 : (d+=DIGIT)+ {$d!=null && $d.size()==3}? ;

// メソッド 2
exact4 : atmost4 {$atmost4.text.length()==4}? ;
atmost4:
@init {int n=1;}
: ({n<=4}?=>DIGIT {n++;})+
;

桁:'0'..'9';

質問 3 については、最初のエラーで失敗します。つまり、lexer と parser の両方で emitErrorMessage() をオーバーライドして、例外をスローします。emitErrorMessage(msg) を選択したのは、エラー メッセージが適切に準備されているためです。

共有してくれてありがとう!

于 2012-05-01T01:35:40.020 に答える