2017-10-03 10 views
1

Je travaille sur un projet où je prends un fichier source C et injecte du code au début de chaque appel de fonction. Main charge le fichier et le transforme en chaîne.Comment enregistrer un fichier après l'avoir analysé avec ANTLR (en utilisant java)?

Main.java

  String inputFilename = args[0]; 
      byte[] bytes = Files.readAllBytes(Paths.get(inputFilename)); 
      String code = new String(bytes, StandardCharsets.UTF_8); 

      Translator translator = new Translator(code); 
      translator.translate(); 

La classe traducteur crée le ANTLRInputStream, CLexer, et CommonTokenStream. Ensuite, il marche l'arbre en utilisant la classe CodeListener.

Translator.java

public Translator(String code){ 
    ANTLRInputStream inputStream = new ANTLRInputStream(code); 
    CLexer lexer = new CLexer(inputStream); 
    tokens = new CommonTokenStream(lexer); 
    CParser parser = new CParser(tokens); 
    parseTree = parser.compilationUnit(); 
} 

void translate(){ 
    walker = new ParseTreeWalker(); 
    CodeListener listener = new CodeListener(tokens); 
    walker.walk(listener, parseTree); 
    parsedCode = listener.rewriter.getText(); 
    saveFile(); 
} 

void saveFile(){ 
    try (PrintStream out = new PrintStream(new FileOutputStream("filename.txt"))){ 
     out.print(parsedCode); 
    } catch (Exception e){ 
     e.printStackTrace(); 
    } 
} 

}

La classe CodeListener insère un commentaire, //hey look a function au début du corps de la fonction.

CodeListener.java

public TokenStreamRewriter rewriter; 
String parsedCode = ""; 
@Override 
public void enterFunctionDefinition(CParser.FunctionDefinitionContext ctx) { 

    String returnType = ctx.declarationSpecifiers().getText(); 
    String functionBody = ctx.compoundStatement().getText(); 
    rewriter.insertBefore(ctx.compoundStatement().getStart(), "//hey look a function "); 
} 

J'ai trouvé le flux modifié, mais est-il une manière que je peux obtenir le nouveau code modifié? Comment puis-je l'enregistrer dans un fichier tel que parsedcode.c, comme indiqué dans l'exemple ci-dessous?

code.c

int main(){ 
    foo(); 
    bar(); 
} 

void foo(){ 
    //does something 
} 

void bar(){ 
    //does something else 
} 

parsedcode.c

int main(){ 
    //hey look a function 
    foo(); 
    bar(); 
} 

void foo(){ 
    //hey look a function 
    //does something 
} 

void bar(){ 
    //hey look a function 
    //does something else 
} 

Répondre

1

Tu ne peux pas appeler toString() ou quel que soit le TokenStreamRewriter et enregistrer la chaîne?

+0

Oui, j'ai juste compris que pour travailler, j'ai besoin d'inclure des espaces blancs. J'ai changé la grammaire pour envoyer un canal 'WS: [\ t \ n \ r] -> channel (WHITESPACE);' avant que ce soit '' '' '' '' '' '' '' '' '' '' '' 'skip;' '@lexer :: members { public static final int WHITESPACE = 1; } 'Trouvé que dans le livre merci pour l'aide! – ryanmattscott