1

JavaScript グローバル変数を識別する目的で、ANTLR が提供する ECMAScript 文法を使用してきました。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 を初めて使用する場合、だれでも指針を提供できますか?

4

1 に答える 1

3

この文法を使用していると思います。

その文法は適切な AST が作成されることを示唆していますが、そうではありません。いくつかのインライン演算子を使用して特定のトークンを解析ツリーから除外しますが、ツリーのルートを作成しないため、完全にフラットな解析ツリーになります。このことから、合理的な方法ですべてのグローバル変数を取得することはできません。

文法を少し調整する必要があります。

options { ... }文法ファイルの上部にある の下に次を追加します。

tokens
{
  VARIABLE;
  FUNCTION;
}

ここで、次のルールを置き換えます: functionDeclarationfunctionExpressionおよび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
于 2010-09-27T14:45:25.997 に答える