在antlr中,有没有办法在AST模式下获取CommonTree的解析文本?

Wei*_*Wei 5 java antlr

一个简单的例子:

(grammar):

stat: ID '=' expr NEWLINE -> ^('=' ID expr)

expr: atom '+' atom -> ^(+ atom atom)

atom: INT | ID

...

(input text): a = 3 + 5
Run Code Online (Sandbox Code Playgroud)

相应的'3 + 5'的CommonTree包含一个'+'标记和两个子标记(3,5).

此时,恢复解析为此树('3 + 5')的原始输入文本的最佳方法是什么?

我已经获得了CommonTree对象中单个标记的文本,位置和行号,因此从理论上讲,可以确保只丢弃空格标记并使用此信息将它们拼凑在一起,但它看起来容易出错.

有一个更好的方法吗?

Bar*_*ers 3

有一个更好的方法吗?

更好,我不知道。当然还有另一种方法。你决定什么更好。

另一种选择是创建自定义 AST 节点类(以及相应的节点适配器),并在解析期间将匹配的文本添加到此 AST 节点。这里的技巧是不使用skip(),它会丢弃词法分析器中的令牌,而是将其放在通道上HIDDEN。这实际上是相同的,但是,这些(隐藏)标记匹配的文本在解析器中仍然可用。

一个快速演示:将所有这 3 个文件放在名为 的目录中demo

演示/TG

grammar T;

options {
  output=AST;
  ASTLabelType=XTree;
}

@parser::header {
  package demo;
  import demo.*;
}

@lexer::header {
  package demo;
  import demo.*;
}

parse
 : expr EOF -> expr
 ;

expr
@after{$expr.tree.matched = $expr.text;}
 : Int '+' Int ';' -> ^('+' Int Int)
 ;

Int
 : '0'..'9'+
 ;

Space
 : ' ' {$channel=HIDDEN;}
 ;
Run Code Online (Sandbox Code Playgroud)

演示/XTree.java

package demo;

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;

public class XTree extends CommonTree {

  protected String matched;

  public XTree(Token t) {
    super(t);
    matched = null;
  }
}
Run Code Online (Sandbox Code Playgroud)

演示/Main.java

package demo;

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;

public class Main {

  public static void main(String[] args) throws Exception {
    String source = "12    +  42 ;";
    TLexer lexer = new TLexer(new ANTLRStringStream(source));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    parser.setTreeAdaptor(new CommonTreeAdaptor(){
      @Override
      public Object create(Token t) {
        return new XTree(t);
      }
    }); 
    XTree root = (XTree)parser.parse().getTree();
    System.out.println("tree    : " + root.toStringTree());
    System.out.println("matched : " + root.matched);    
  }
}
Run Code Online (Sandbox Code Playgroud)

您可以通过打开 shell 并 cd 到包含该demo目录的目录并执行以下命令来运行此演示:

java -cp demo/antlr-3.3.jar org.antlr.Tool demo/Tg
javac -cp 演示/antlr-3.3.jar 演示/*.java
java -cp .:demo/antlr-3.3.jar demo.Main

这将产生以下输出:

树:(+ 12 42)
匹配:12 + 42;