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
),我希望有一个简单的方法来做到这一点,但也许深度克隆是唯一可能的方法。非常感谢。