一部の長さが前のトークンの値に依存するバイナリ データをトークン化したいと考えています。次のように考えることができます。
<length><binary data>
長さは、バイナリ データの長さをバイト単位で示す 2 バイトの符号なし整数であるとします。
この相関関係を ANTLR 4 で実装するにはどうすればよいですか?
一部の長さが前のトークンの値に依存するバイナリ データをトークン化したいと考えています。次のように考えることができます。
<length><binary data>
長さは、バイナリ データの長さをバイト単位で示す 2 バイトの符号なし整数であるとします。
この相関関係を ANTLR 4 で実装するにはどうすればよいですか?
ANTLR の入力ストリームを拡張する必要がある場合があります。現時点では、入力ストリーム と のみANTLRInputStream
がANTLRFileStream
によってバックアップされてchar[]
います。これは、あらゆる種類のバイナリ データに一致するという要件に合わない可能性があります。
説明したようにレクサーをコンテキストに依存させるには、次のことができます。
UNSIGNED
数値トークンに一致し、これが一致したら、インスタンス変数 ( )bytesToConsume
をこの値で初期化します。bytesToConsume
限り、バイト/文字を消費します!bytesToConsume
bytesToConsume
に一致させたくありません!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 モードで明確に終了するのではなく、一定量のバイト/文字が消費されたら、デフォルトのレキシカル スコープに戻りたいからです。 .