我正在尝试创建我的第一个ANTLR3树语法,但我一直遇到同样的问题。解析器的输出是:
$ echo 'foo, bar' | ./run.sh
foo bar
TreeGrammar.g: node from line 0:0 required (...)+ loop did not match anything at input 'EOF'
Exception in thread "main" java.lang.NullPointerException
at Driver.main(Driver.java:29)
输出清楚地表明stage-1解析器产生正确的令牌('foo'和'bar')。不知何故,阶段2的树解析器拒绝解析阶段1的结果。由于代码是非常基本的,它一定是我的一些简单而愚蠢的疏忽;-)
下面是我的简单测试代码:Grammar.g:
grammar Grammar;
options {
output = AST;
}
statement: word (','! word)* EOF!;
word: ID;
ID: ('a'..'z'|'A'..'Z')+;
WS: (' ' | 't' | 'n' | 'r')+ { $channel = HIDDEN; } ;
TreeGrammar.g:
tree grammar TreeGrammar;
options {
tokenVocab = Grammar;
ASTLabelType = CommonTree;
output = template;
}
statement: word+;
word: ID;
Driver.java:
import java.io.*;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
public class Driver {
public static void main(String[] args) throws Exception {
FileReader groupFileR = new FileReader("Template.stg" );
StringTemplateGroup templates = new StringTemplateGroup(groupFileR);
groupFileR.close();
ANTLRInputStream input = new ANTLRInputStream(System.in);
GrammarLexer lexer = new GrammarLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
GrammarParser parser = new GrammarParser(tokens);
GrammarParser.statement_return result = parser.statement();
CommonTree t = (CommonTree)result.getTree();
System.out.println(t.toStringTree());
CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
nodes.setTokenStream(tokens);
TreeGrammar walker = new TreeGrammar(nodes);
walker.setTemplateLib(templates);
walker.statement();
TreeGrammar.statement_return r2 = walker.statement();
StringTemplate output = (StringTemplate) r2.getTemplate();
System.out.println(output.toString());
}
}
假设你的Stringtemplate组是正确形成的,你的问题很可能是你遍历 AST两次:
walker.statement();
TreeGrammar.statement_return r2 = walker.statement();
。,你调用walker.statement()
两次。这是(第一个)错误告诉你的:
TreeGrammar.g: node from line 0:0 required (...)+ loop did not match anything at input 'EOF'
您使用walker.statement()
消耗一次输入,导致节点流处于结束(EOF),然后您再次调用walker.statement()
,它期望再次行走word+
,但只剩下EOF
。