ANTLR Как получить переписанный исходный код?(используя TokenRewriteStream) - PullRequest
2 голосов
/ 21 декабря 2011

Я пытаюсь создать простой переводчик, переводящий что-то вроде:

aaa | bbb | ccc

до

1 : aaa
2 : bbb
c : ccc

Вот грамматика test01.g:

grammar test01;

options {
    output=AST; 
}

@members{
  int N;
}

test 
@init{
  N = 0;
}:
  id ('|' id)* -> id (BR id)*;

id   : {N++;} ID  -> {new CommonTree(new CommonToken(ID, Integer.toString(N) + " : "  + $ID.text))};
ID   : ('a'..'z')+;
BR   : '\n';
WS   : ' '{$channel=HIDDEN;};

Источник перевода FooTest.java:

import org.antlr.runtime.*;

class FooTest {
  public static void main(String[] args) throws Exception {    
    String text = "aaa | bbb | ccc";        
    System.out.println("parsing: "+text);        
    ANTLRStringStream in = new ANTLRStringStream(text);
    test01Lexer lexer = new test01Lexer(in);
    CommonTokenStream tokens = new TokenRewriteStream(lexer);
    test01Parser parser = new test01Parser(tokens);
    parser.test();
    System.out.println("Result: "+tokens.toString());    
  }
}

Когда я запускаю его, я ожидаю получить что-то вроде:

parsing: aaa | bbb | ccc
Result:
 1 : aaa
 2 : bbb 
 3 : ccc

Но я получаю:

  parsing: aaa | bbb | ccc
  Result:  aaa | bbb | ccc

Текст кажется неизменным.

Как получить модифицированный источник?

1 Ответ

1 голос
/ 21 декабря 2011

Вы просто печатаете список токенов flat , выполняя:

CommonTokenStream tokens = new TokenRewriteStream(lexer);
// ...
System.out.println("Result: "+tokens.toString());  

Если вы настраиваете свой класс FooTest на:

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;

class FooTest {
  public static void main(String[] args) throws Exception {    
    String text = "aaa | bbb | ccc";        
    System.out.println("parsing: "+text);        
    ANTLRStringStream in = new ANTLRStringStream(text);
    test01Lexer lexer = new test01Lexer(in);
    CommonTokenStream tokens = new TokenRewriteStream(lexer);
    test01Parser parser = new test01Parser(tokens);
    CommonTree root = (CommonTree)parser.test().getTree();
    for(int i = 0; i < root.getChildCount(); i++) {
      CommonTree child = (CommonTree)root.getChild(i);
      System.out.println("root.children[" + i + "] = " + child);
    }
  }
}

на консоль выводится следующее:

parsing: aaa | bbb | ccc
root.children[0] = 1 : aaa
root.children[1] = BR
root.children[2] = 2 : bbb
root.children[3] = BR
root.children[4] = 3 : ccc

И обратите внимание, что вам не нужно помещать глобальную переменную в ваш класс анализатора.Правила также обрабатывают переменные (локальные для них).Это предпочтительно:

grammar test01;

options {
    output=AST; 
}

test:
  id ('|' id)* -> id (BR id)*;

id
@init{
  int N = 0;
}
  : {N++;} ID  -> {new CommonTree(new CommonToken(ID, Integer.toString(N) + " : "  + $ID.text))}
  ;

// other rules
...