我不明白的是如何在这棵树的顶部获得“idList”节点(事实上也是语法之一)。如何使用重写和那些运算符重现这棵树?
你不能单独使用^
和。!
这些运算符仅对现有令牌进行操作,而您想创建额外的令牌(并使这些令牌成为子树的根)。您可以使用重写规则并定义一些虚构的标记来做到这一点。
快速演示:
grammar test;
options {
output=AST;
ASTLabelType=CommonTree;
}
tokens {
IdList;
Id;
}
@parser::members {
private static void walk(CommonTree tree, int indent) {
if(tree == null) return;
for(int i = 0; i < indent; i++, System.out.print(" "));
System.out.println(tree.getText());
for(int i = 0; i < tree.getChildCount(); i++) {
walk((CommonTree)tree.getChild(i), indent + 1);
}
}
public static void main(String[] args) throws Exception {
testLexer lexer = new testLexer(new ANTLRStringStream("abc abc123"));
testParser parser = new testParser(new CommonTokenStream(lexer));
walk((CommonTree)parser.program().getTree(), 0);
}
}
program : idList EOF -> idList;
idList : id* -> ^(IdList id*);
id : ID -> ^(Id ID);
ID : LETTER (LETTER | DIGIT)*;
SPACE : ' ' {skip();};
fragment LETTER : 'a' .. 'z' | 'A' .. 'Z';
fragment DIGIT : '0' .. '9';
如果您运行上面的演示,您将看到以下内容被打印到控制台:
IdList
Id
abc
Id
abc123
如您所见,虚构的标记也必须以大写字母开头,就像词法分析器规则一样。如果您想赋予虚构的标记与text
它们所代表的解析器规则相同,请改为执行以下操作:
idList : id* -> ^(IdList["idList"] id*);
id : ID -> ^(Id["id"] ID);
这将打印:
idList
id
abc
id
abc123