有一个更好的方法吗?
更好,我不知道。当然,还有另一种方式。你决定什么更好。
另一种选择是创建自定义 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;}
;
演示/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;
}
}
演示/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);
}
}
您可以通过打开 shell 并 cd-ing 到包含该目录的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;