1

Java Grammar for ANTLRを使用すると、Javaコードを読み取って、トークンを順番に出力できました。

    String filePath = JAVA_SOURCE;
    String input = readFileAsString(filePath);
    //ANTLRStringStream in = new ANTLRStringStream(input);
    InputStream inputStream = new FileInputStream(filePath);
    ANTLRInputStream in = new ANTLRInputStream(inputStream);
    Java6Lex lexer = new Java6Lex(in);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    while(true) {
        int val = tokens.LA(1);
        tokens.consume();

        if (val == -1) {
            break;
        }
        System.out.printf("%d ", val);
    }

59 54 38 54 81 61 92 59 54 38 54 96 61 92 59 54 38 54 81 54 92 90 5492..。

tokensそれぞれをJAVA_SOURCEの位置にマップするにはどうすればよいですか?ANTLRにはカウンターか何かがありますか?

4

2 に答える 2

2

デフォルトでは、ANTLR はCommonTokens を生成します。ここで完全な API を読んでください: http://www.antlr.org/api/Java/org/antlr/runtime/CommonToken.html

以下は、Java6 パーサーが検出したトークンに関する情報を出力するデモです。

  • lexer と parser ルールを という単一のファイルにマージしますJava6.g(もちろん、文法に「Java6」という名前を付けます!)
  • ファイルantlr-3.3-complete.jarを同じフォルダーにコピーしますJava6.g

Java6.gファイルに次をコピーして貼り付けます。

grammar Java6;

// options ...

@parser::members{
  public static void main(String[] args) throws Exception {
    String source = "package test;\n\npublic class Test {\n\n  int n = 42;\n}\n";
    Java6Lexer lexer = new Java6Lexer(new ANTLRStringStream(source));
    Java6Parser parser = new Java6Parser(new CommonTokenStream(lexer));
    System.out.println(source);
    parser.dumpTokens();
  }
}

dumpTokens
  :  (
       t=. {
         CommonToken ct = (CommonToken)t;
         System.out.printf("type=\%s, text='\%s', line=\%d, startIndex=\%d, charPositionInLine=\%d\n", 
                            tokenNames[ct.getType()], 
                            ct.getText(), 
                            ct.getLine(), 
                            ct.getStartIndex(), 
                            ct.getCharPositionInLine());
       }
     )* 
     EOF
  ;

// the rest of the grammar rules are not changed

Java6 ファイルを実行します。

java -cp antlr-3.3-complete.jar org.antlr.Tool Java6.g
javac -cp antlr-3.3-complete.jar *.java
java -cp .:antlr-3.3-complete.jar Java6Parser

コンソールに次のように表示されます。

パッケージテスト;

パブリック クラス テスト {

  int n = 42;
}

type=PACKAGE、text='package'、line=1、startIndex=0、charPositionInLine=0
type=IDENTIFIER、text='test'、line=1、startIndex=8、charPositionInLine=8
type=SEMI、text=';'、line=1、startIndex=12、charPositionInLine=12
type=PUBLIC、text='public'、line=3、startIndex=15、charPositionInLine=0
type=CLASS、text='class'、line=3、startIndex=22、charPositionInLine=7
type=IDENTIFIER、text='Test'、line=3、startIndex=28、charPositionInLine=13
type=LBRACE、text='{'、line=3、startIndex=33、charPositionInLine=18
type=INT、text='int'、line=5、startIndex=38、charPositionInLine=2
type=IDENTIFIER、text='n'、line=5、startIndex=42、charPositionInLine=6
type=EQ、text='='、line=5、startIndex=44、charPositionInLine=8
type=INTLITERAL、text='42'、line=5、startIndex=46、charPositionInLine=10
type=SEMI、text=';'、line=5、startIndex=48、charPositionInLine=12
type=RBRACE、text='}'、line=6、startIndex=50、charPositionInLine=0

また、パーサー ルールからトークンを取得する方法を探している場合は、すべてのパーサー ルールの ParserRuleReturnScope に、 CommonTokenにキャストできるstartandstopメンバーがあります。

于 2013-01-18T18:26:25.803 に答える
0

Token オブジェクトには行番号が含まれているため、Token のリストを取得すると問題が解決します。このサイトで説明されているように、do {} while ループがない場合、tokens.getTokens() は [] を返します。

    do
    {
        tokens.consume();
    } while (tokens.LA(1) != -1);

    List<Token> tokenList = tokens.getTokens();
    for (Token token : tokenList)
    {   
        int type = token.getType();
        bigList.add(type);
        int line = token.getLine();
        System.out.printf("LINE %d - TOKEN %d\n", line, type);
    }

36 行目にこのコード「System.out.println(z);」がある場合、結果は次のようになります。

LINE 36 - TOKEN 54 - IDENTIFIER
LINE 36 - TOKEN 31 - DOT
LINE 36 - TOKEN 54 - IDENTIFIER
LINE 36 - TOKEN 31 - DOT
LINE 36 - TOKEN 54 - IDENTIFIER
LINE 36 - TOKEN 70 - LPAREN
LINE 36 - TOKEN 54 - IDENTIFIER
LINE 36 - TOKEN 91 - RPAREN
LINE 36 - TOKEN 92 - SEMI

追加した

列の位置を取得するには、「token.getCharPositionInLine()」を使用できます。

于 2013-01-18T04:00:26.580 に答える