假设我有这个简单而无意义的语法:

propagate     :   what^ where*;
what          :   CHAR^;
where         :   NUMBER -> ^(PLUS NUMBER);

NUMBER        :   '0'..'9';
CHAR          :   'a'..'z';
PLUS          :   '+';

如果它解析像 a123456789 这样的字符串,它会生成一个 AST,如:

我要做的是将 what 解析的 token 传递给 where 并创建一个 AST(对于相同的输入),如:

我尝试了以下方式:
propagate       :   w=what^ where[$w.text]*;
what            :   CHAR^;
where[String s] :   NUMBER -> ^(PLUS CHAR[s] NUMBER);

NUMBER          :   '0'..'9';
CHAR            :   'a'..'z';
PLUS            :   '+';

如果 what 它是一个单一的标记它可以工作,但是如果它是一棵树呢?
这是正确的方法吗?

最佳答案

就是这样:

grammar T;

options {
  output=AST;
  ASTLabelType=CommonTree;
}

parse
 : propagate EOF!
 ;

propagate
 : what^ where[$what.tree]*
 ;

what
 : CHAR
 ;

where[CommonTree lhs]
 : NUMBER -> ^(PLUS {new CommonTree($lhs)} NUMBER)
 ;

NUMBER : '0'..'9';
CHAR   : 'a'..'z';
PLUS   : '+';

ANTLRWorks 的调试器可能不会显示正确的 AST:自己创建一个小的驱动程序类:

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

public class Main {
  public static void main(String[] args) throws Exception {
    TLexer lexer = new TLexer(new ANTLRStringStream("a123"));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    CommonTree tree = (CommonTree)parser.parse().getTree();
    DOTTreeGenerator gen = new DOTTreeGenerator();
    StringTemplate st = gen.toDOT(tree);
    System.out.println(st);
  }
}

要运行它,请执行以下操作:

java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main > ast.dot

这将产生一个表示以下 AST 的 DOT 文件:

关于parsing - 树构造 : propagate a subtree to child,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14244849/

10-16 10:14