Parsing 树构造:将子树传播到子树
假设我有一个简单而无意义的语法:Parsing 树构造:将子树传播到子树,parsing,antlr,antlr3,abstract-syntax-tree,Parsing,Antlr,Antlr3,Abstract Syntax Tree,假设我有一个简单而无意义的语法: propagate : what^ where*; what : CHAR^; where : NUMBER -> ^(PLUS NUMBER); NUMBER : '0'..'9'; CHAR : 'a'..'z'; PLUS : '+'; 如果它解析一个字符串,如a123456789,它将生成一个类似AST的: 我要做的是将What
propagate : what^ where*;
what : CHAR^;
where : NUMBER -> ^(PLUS NUMBER);
NUMBER : '0'..'9';
CHAR : 'a'..'z';
PLUS : '+';
如果它解析一个字符串,如a123456789
,它将生成一个类似AST的:
我要做的是将What
解析的令牌传递到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.*;
导入org.antlr.runtime.tree.*;
导入org.antlr.stringtemplate.*;
公共班机{
公共静态void main(字符串[]args)引发异常{
TLexer lexer=新的TLexer(新的AntlStringStream(“a123”);
TParser parser=newtparser(newcommontokenstream(lexer));
CommonTree=(CommonTree)parser.parse().getTree();
DOTTreeGenerator gen=新的DOTTreeGenerator();
StringTemplate st=gen.toDOT(树);
系统输出打印LN(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
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的点文件:
如果
a
是一棵树(有子树),它似乎只传播树的根(只有a
没有子树),你能检查它吗?也许这取决于CommonTree
的构造函数?@SalvatoreD.,嗯,这不是你问的吗?你的例子和我的演示也一样。也许可以编辑您的问题并重新表述,或者添加更多示例。我的问题是,如果我想传播整个树及其子节点,而不是单个节点,该怎么办。您的演示和我的代码只传播一个令牌或树的根。如果在您的演示中a
有两个名为b
和c
的子级,我会选择一个ast:^(加上^(abc)1)^(加上^(abc)2).
@SalvatoreD.,啊,好的。然后,您需要自己做一些额外的工作,因为在ANTLRv3中没有深度复制功能。另请参见此问答:不要使用{newcommontree($lhs)}
执行类似{deepCopy($lhs)}
的操作,其中deepCopy(CommonTree)
是@parser::members{…}
部分中的一个方法(当然,该部分返回CommonTree
),我希望有一个简单的方法来做到这一点,但也许深度克隆是唯一可能的方法。非常感谢。