Использование ANTLR для идентификации объявлений глобальных переменных в файле JavaScript - PullRequest
1 голос
/ 27 сентября 2010

Я использовал предоставляемую ANTLR грамматику ECMAScript с целью определения глобальных переменных JavaScript.Создан AST, и теперь мне интересно, каков основанный способ фильтрации объявлений глобальных переменных.

Я заинтересован в поиске всех самых внешних токенов "variableDeclaration" в моем AST;фактический, как сделать, это ускользает от меня все же.Вот мой код установки:

String input = "var a, b; var c;";
CharStream cs = new ANTLRStringStream(input);

JavaScriptLexer lexer = new JavaScriptLexer(cs);

CommonTokenStream tokens = new CommonTokenStream();
tokens.setTokenSource(lexer);

JavaScriptParser parser = new JavaScriptParser(tokens);

program_return programReturn = parser.program();

Будучи новичком в ANTLR, кто-нибудь может предложить какие-нибудь указатели?

1 Ответ

3 голосов
/ 27 сентября 2010

Полагаю, вы используете эту грамматику .

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

генерируется следующее дерево:

alt text

Все, что вам теперь нужно сделать, это перебрать дочерние элементы корня вашего дерева, и когда вы наткнетесь на токен 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
...