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 54 92 ...

如何将每个映射tokens回 JAVA_SOURCE 中的位置?ANTLR 有柜台吗?

4

2 回答 2

2

默认情况下,ANTLR 产生CommonTokens。在此处阅读完整的 API:http ://www.antlr.org/api/Java/org/antlr/runtime/CommonToken.html

这是一个演示,用于打印有关 Java6 解析器遇到的标记的一些信息:

  • 将词法分析器和解析器规则合并到一个名为的文件中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

您将看到以下内容打印到您的控制台:

包装测试;

公共类测试{

  诠释 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
类型=公共,文本='公共',行=3,开始索引=15,charPositionInLine=0
type=CLASS, text='class', line=3, startIndex=22, charPositionInLine=7
type=IDENTIFIER, text='Test', line=3, startIndex=28, charPositionInLine=13
类型=LBRACE,文本='{',行=3,startIndex=33,charPositionInLine=18
类型=INT,文本='int',行=5,startIndex=38,charPositionInLine=2
type=IDENTIFIER, text='n', line=5, startIndex=42, charPositionInLine=6
type=EQ, text='=', line=5, startIndex=44, charPositionInLine=8
类型=INTLITERAL,文本='42',行=5,startIndex=46,charPositionInLine=10
type=SEMI, text=';', line=5, startIndex=48, charPositionInLine=12
类型=RBRACE,文本='}',行=6,开始索引=50,charPositionInLine=0

如果您正在寻找一种从解析器规则中获取令牌的方法,那么每个解析器规则在其ParserRuleReturnScopestart中都有一个and成员,可以将其强制转换为 CommonToken。stop

于 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 回答