antlr - 如何将一个 token 的长度取决于另一个 token 的值?

标签 antlr binary-data antlr4

我想标记一些二进制数据,其中某些部分的长度取决于前一个标记的值。你可以这样想:

<length><binary data>

假设长度是两个字节的无符号整数,表示以字节为单位的二进制数据的长度。

如何使用 ANTLR 4 实现这种相关性?

最佳答案

您可能需要扩展 ANTLR 的输入流。截至目前,唯一的输入流, ANTLRInputStream ANTLRFileStream , 由 char[] 支持这可能不适合您匹配任何类型的二进制数据的要求。

要按照您的描述使词法分析器上下文敏感,您可以:

  • 匹配一个 UNSIGNED数字标记,一旦匹配,用这个值初始化一个实例变量( bytesToConsume );
  • 一旦这个 bytesToConsume已设置,只要此 bytesToConsume 消耗字节/字符大于0!
  • 当然,只要bytesToConsume已经初始化,不想匹配UNSIGNED token !

  • !这些检查由 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

    Windows

    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

    And you'll see the following being printed to the console (I added indentation though):

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

    编辑

    也许可以通过使用 ANTLR4 的 lexical modes 来做一些更清洁的事情。 .但是,我对 v4 还是很陌生,我不知道这是否可行,因为一旦消耗了一定数量的字节/字符,您就想回到默认词法范围,而不是在 BINARY 模式中明确结束.

    关于antlr - 如何将一个 token 的长度取决于另一个 token 的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15348045/

    相关文章:

    c++ - Antlr4 C++ 访客 API

    antlr - 匹配可选元素序列中的至少一个元素(ANTLR)

    c# - 将二进制读取函数从 C# 转换为 C

    antlr4 - 对于 +、-、/、* 等的正确优先级评估,正确的语法应该是什么

    antlr4 - getType 在 antlr4 中做了什么?

    c# - 如何转换 AS400 ADO.Net 连接字符串中的 CCSID 65535 个字符

    java - antlr如何以任意顺序定义可选部分

    java - ANTLR: "missing attribute access on rule scope"问题

    antlr - 在 antlr 中插入符号前缀而不是后缀

    c++ - BMP 阅读器无法正常工作