4

一部の長さが前のトークンの値に依存するバイナリ データをトークン化したいと考えています。次のように考えることができます。

<length><binary data>

長さは、バイナリ データの長さをバイト単位で示す 2 バイトの符号なし整数であるとします。

この相関関係を ANTLR 4 で実装するにはどうすればよいですか?

4

1 に答える 1

1

ANTLR の入力ストリームを拡張する必要がある場合があります。現時点では、入力ストリーム と のみANTLRInputStreamANTLRFileStreamによってバックアップされてchar[]います。これは、あらゆる種類のバイナリ データに一致するという要件に合わない可能性があります。

説明したようにレクサーをコンテキストに依存させるには、次のことができます。

  • UNSIGNED数値トークンに一致し、これが一致したら、インスタンス変数 ( )bytesToConsumeをこの値で初期化します。
  • これが設定されると、これが 0 より大きいbytesToConsume限り、バイト/文字を消費します!bytesToConsume
  • もちろん、 が初期化されるとすぐに、 tokenbytesToConsumeに一致させたくありません!UNSIGNED

! これらのチェックはセマンティック述語 {boolean-expression}?によって実行されます。

デモ:

grammar T;

@lexer::members {

  private int bytesToConsume = -1;         

  boolean binary() {
    if(bytesToConsume < 0) {
      return false;
    }
    bytesToConsume--;
    return true;
  }
}

parse
 : block* EOF
 ;

block
 : UNSIGNED BINARY
 ;

UNSIGNED 
 : {!binary()}? 
   [0-9a-fA-F] [0-9a-fA-F] {bytesToConsume = Integer.parseInt(getText(), 16);}
 ;

BINARY
 : ({binary()}? . )+
 ;

ドライバー クラス:

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

public class Main {

  public static void main(String[] args) throws Exception {
    TLexer lexer = new TLexer(new ANTLRInputStream("03aaa0Fbbbbbbbbbbbbbbb01c"));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    ParseTree tree = parser.parse();
    System.out.println(tree.toStringTree(parser));
  }
}

次のようにしてテストします。

*ニックス

java -jar antlr-4.0-complete.jar T.g4
javac -cp .:antlr-4.0-complete.jar *.java
java -cp .:antlr-4.0-complete.jar メイン

ウィンドウズ

java -jar antlr-4.0-complete.jar T.g4
javac -cp .;antlr-4.0-complete.jar *.java
java -cp .;antlr-4.0-complete.jar メイン

そして、コンソールに次のように表示されます (ただし、インデントを追加しました)。

(parse 
  (block 03 aaa) 
  (block 0F bbbbbbbbbbbbbbb) 
  (block 01 c) 
  <EOF>)

編集

おそらく、ANTLR4 の字句モードを利用することで、よりクリーンなことが可能になるでしょう。ただし、私は v4 にまったく慣れていないため、これが可能かどうかはわかりません。BINARY モードで明確に終了するのではなく、一定量のバイト/文字が消費されたら、デフォルトのレキシカル スコープに戻りたいからです。 .

于 2013-03-11T21:55:58.677 に答える