解析头后面跟着未知长度的二进制数据块



在一个数据流中有两个数据包。每个报头后面都有一些长度未知的二进制数据,直到找到另一个报头或达到EOF。数据如下:HDR12HDR345HDR是头标记12345为二进制数据。

这是我现在的错误语法:

grammar TEST;
parse   :   STREAM EOF;
STREAM  :   PACKET*;
PACKET  :   HEADER DATA;
HEADER  :   'HDR';
DATA    :   .*;

可以识别第一个报头令牌,但是数据令牌太长,它会消耗下一个报头和数据。

经过三天的寻找,我没有找到任何解决方案,这两个匹配,"二进制数据"one_answers"未知长度"方面。但是我仍然认为这一定是一些常见的解析场景。ANTLR并不像第一眼看上去那么简单:(

感谢您的帮助和建议。

如果没有任何东西直接放在.*之后,ANTLR将尽可能多地消耗(直到EOF)。所以规则是:

DATA : .*;

应该更改( .*之后必须有)。

而且,每个词法分析器规则至少应该匹配一个字符。但是您的STREAM规则可能会匹配空字符串,导致词法分析器创建无限数量的空字符串令牌。

最后,ANTLR用于解析文本输入,而不是二进制数据。在ANTLR邮件列表中查看这个问题,或者在列表中搜索更多信息。

编辑

除了在.*后面放置一些东西之外,您还可以在词法分析器中执行一些"手动"查找。一个小演示如何告诉ANTLR继续使用字符,直到词法分析器"看到"前面的内容(在您的示例中是"HDR"):

grammar T;
@parser::members {
  public static void main(String[] args) throws Exception {
    String input = "HDR1 foo HDR2 bar nn baz HDR3HDR4 the end...";
    TLexer lexer = new TLexer(new ANTLRStringStream(input));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    parser.parse();
  }
}
@lexer::members {
  private boolean hdrAhead() {
    return input.LA(1) == 'H' && 
           input.LA(2) == 'D' && 
           input.LA(3) == 'R';
  }
}
parse  : stream EOF;
stream : packet*; // parser rules _can_ match nothing
packet : HEADER DATA? {System.out.println("parsed :: " + $text.replaceAll("\s+", ""));};
HEADER : 'HDR' '0'..'9'+;
DATA   : ({!hdrAhead()}?=> .)+;

如果你运行上面的演示:

java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar TParser

(在Windows上,最后一个命令是:java -cp .;antlr-3.3.jar TParser)

将以下内容打印到控制台:

parsed :: HDR1foo
parsed :: HDR2barbaz
parsed :: HDR3
parsed :: HDR4theend...

表示输入字符串:

HDR1 foo HDR2 bar 
baz HDR3HDR4 the end...

相关内容

  • 没有找到相关文章

最新更新