Search code examples
javaantlr4translatefilewritercode-translation

How to save a file after parsing it with ANTLR (using java)?


I'm working on a project where I am taking a C source file and inject some code at the beginning of every function call. Main loads the file and turns it into a string.

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();

The translator class creates the ANTLRInputStream, CLexer, CParser and CommonTokenStream. Then it walks the tree using the CodeListener class.

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();
    }
}

}

The CodeListener Class inserts a comment, //hey look a function at the beginning of the function body.

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 ");
}

I found the modified stream, but is there a way I can get the newly modified code? How do I save it into a file such as parsedcode.c, as shown in the example below?

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
}

Solution

  • Can't you just call toString() or whatever on the TokenStreamRewriter and save the string?