Полагаю, вы используете эту грамматику .
Хотя эта грамматика предполагает создание правильного 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