Я думаю, вы используете this grammar.
Хотя эта грамматика предполагает создание собственного АСТ, это не так. Он использует некоторые встроенные операторы для исключения определенных токенов из дерева синтаксического анализа, но он никогда не создает корней для дерева, что приводит к полностью плоскому дереву синтаксического анализа. Из этого вы не можете получить все глобальные варны разумным способом.
Вам нужно настроить грамматику слегка:
Добавьте следующий под 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
+1 и ответил. Большое спасибо за всесторонний ответ. –
@ Кристофер, пожалуйста. –