我想标记一些二进制数据,其中某些部分的长度取决于先前标记的值。你可以这样想:
<length><binary data>
假设长度是两个字节的无符号整数,表示二进制数据的长度(以字节为单位)。
如何使用 ANTLR 4 实现这种关联?
我想标记一些二进制数据,其中某些部分的长度取决于先前标记的值。你可以这样想:
<length><binary data>
假设长度是两个字节的无符号整数,表示二进制数据的长度(以字节为单位)。
如何使用 ANTLR 4 实现这种关联?
您可能需要扩展 ANTLR 的输入流。到目前为止,唯一的输入流ANTLRInputStream
和ANTLRFileStream
由 a 支持,char[]
这可能不适合您匹配任何类型的二进制数据的要求。
如您所述,要使词法分析器上下文敏感,您可以:
UNSIGNED
数字标记,一旦匹配,就bytesToConsume
用这个值初始化一个实例变量();bytesToConsume
设置好,只要bytesToConsume
大于 0 就消耗字节/字符!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 很陌生,我不知道这是否可能,因为一旦消耗了一定数量的字节/字符而不是二进制模式中的明确结束,您想弹回默认词法范围.