【问题标题】:Using ANTLR to identify global variable declarations in a JavaScript file使用 ANTLR 识别 JavaScript 文件中的全局变量声明
【发布时间】:2010-09-27 22:45:45
【问题描述】:

我一直在使用 ANTLR 提供的 ECMAScript 语法,目的是识别 JavaScript 全局变量。生成了一个 AST,我现在想知道过滤掉全局变量声明的基本方法是什么。

我有兴趣在我的 AST 中查找所有最外层的“variableDeclaration”标记;但是,实际的操作方法却让我望而却步。到目前为止,这是我的设置代码:

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 新手,谁能提供任何指点?

【问题讨论】:

    标签: java javascript antlr antlr3


    【解决方案1】:

    我猜你正在使用this grammar

    虽然该语法表明创建了正确的 AST,但事实并非如此。它使用一些内联运算符从解析树中排除某些标记,但它从不为树创建任何根,从而产生一个完全平坦的解析树。由此,您无法以合理的方式获取所有全局变量。

    你需要稍微调整一下语法:

    在语法文件顶部的options { ... }下添加以下内容:

    tokens
    {
      VARIABLE;
      FUNCTION;
    }
    

    现在将以下规则替换为:functionDeclarationfunctionExpressionvariableDeclaration

    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
    

    【讨论】:

      猜你喜欢
      • 2013-09-29
      • 2011-06-19
      • 2019-11-28
      • 1970-01-01
      • 2011-06-30
      • 2020-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多