我想标记一些二进制数据,其中某些部分的长度取决于前一个标记的值。你可以这样想:
<length><binary data>
假设 length 是两个字节的无符号整数,表示二进制数据的长度,以字节为单位。
如何与ANTLR 4实现此关联?
答案 0 :(得分:1)
您可能需要扩展ANTLR的输入流。截至目前,唯一的输入流ANTLRInputStream
和ANTLRFileStream
由char[]
备份,可能不符合您匹配任何类型二进制数据的要求。
为了使你所描述的词法分析器上下文敏感,你可以:
UNSIGNED
数字标记,一旦匹配,使用此值初始化实例变量(bytesToConsume
); bytesToConsume
,只要此bytesToConsume
大于0 就消耗字节/字符! bytesToConsume
初始化,您就不希望匹配UNSIGNED
令牌! !这些检查由semantic predicates {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 Main
java -jar antlr-4.0-complete.jar T.g4 javac -cp .;antlr-4.0-complete.jar *.java java -cp .;antlr-4.0-complete.jar Main
你会看到以下内容被打印到控制台(虽然我添加了缩进):
(parse
(block 03 aaa)
(block 0F bbbbbbbbbbbbbbb)
(block 01 c)
<EOF>)
使用ANTLR4的lexical modes也许可能更清洁。但是,我对v4很新,我不知道这是否可行,因为一旦消耗了一定量的字节/字符而不是BINARY模式中的清除结束,你想要回弹到默认的词法范围。