我猜你在用
this grammar
.
尽管该语法表明创建了正确的AST,但事实并非如此。它使用一些内联运算符从解析树中排除某些标记,但它从不为树创建任何根,从而导致一个完全扁平的解析树。因此,您无法以合理的方式获取所有全局变量。
你需要稍微调整一下语法:
options { ... }
在语法文件的顶部:
tokens
{
VARIABLE;
FUNCTION;
}
现在替换以下规则:
functionDeclaration
,
functionExpression
variableDeclaration
functionDeclaration
: 'function' LT* Identifier LT* formalParameterList LT* functionBody
-> ^(FUNCTION Identifier formalParameterList functionBody)
;
functionExpression
: 'function' LT* Identifier? LT* formalParameterList LT* functionBody
-> ^(FUNCTION Identifier? formalParameterList functionBody)
;
variableDeclaration
: Identifier LT* initialiser?
-> ^(VARIABLE Identifier initialiser?)
;
现在生成一个更合适的树。如果现在分析源代码:
var a = 1; function foo() { var b = 2; } var c = 3;
你现在所要做的就是在你的树根的子树上迭代,当你偶然发现一个
VARIABLE
令牌,你知道它是一个“全局”的,因为所有其他变量都将在
FUNCTION
下面是如何做到这一点:
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
public class Main {
public static void main(String[] args) throws Exception {
String source = "var a = 1; function foo() { var b = 2; } var c = 3;";
ANTLRStringStream in = new ANTLRStringStream(source);
JavaScriptLexer lexer = new JavaScriptLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
JavaScriptParser parser = new JavaScriptParser(tokens);
JavaScriptParser.program_return returnValue = parser.program();
CommonTree tree = (CommonTree)returnValue.getTree();
for(Object o : tree.getChildren()) {
CommonTree child = (CommonTree)o;
if(child.getType() == JavaScriptParser.VARIABLE) {
System.out.println("Found a global var: "+child.getChild(0));
}
}
}
}
产生以下输出:
Found a global var: a
Found a global var: c