110 lines
3.8 KiB
Java
110 lines
3.8 KiB
Java
|
package main;
|
||
|
|
||
|
import org.antlr.v4.runtime.CharStream;
|
||
|
import org.antlr.v4.runtime.CharStreams;
|
||
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||
|
import parser.CminusLexer;
|
||
|
import parser.CminusParser;
|
||
|
import submit.ASTVisitor;
|
||
|
import org.antlr.v4.runtime.Parser;
|
||
|
import submit.RegisterAllocator;
|
||
|
import submit.SymbolTable;
|
||
|
import submit.ast.Node;
|
||
|
|
||
|
import java.io.File;
|
||
|
import java.io.FileWriter;
|
||
|
import java.io.IOException;
|
||
|
import java.util.Properties;
|
||
|
import java.util.logging.Handler;
|
||
|
import java.util.logging.Level;
|
||
|
import java.util.logging.Logger;
|
||
|
|
||
|
public class Main {
|
||
|
private static Logger LOGGER;
|
||
|
|
||
|
/**
|
||
|
* @param args the command line arguments
|
||
|
* @throws java.io.IOException
|
||
|
*/
|
||
|
public static void main(String[] args) throws IOException {
|
||
|
// Logging setup
|
||
|
Level level = Level.INFO;
|
||
|
|
||
|
// TODO Enable trace-level code as needed. When true, LOGGER.fine() statements
|
||
|
// will be visible.
|
||
|
final boolean trace = true;
|
||
|
if (trace) {
|
||
|
level = Level.ALL;
|
||
|
}
|
||
|
|
||
|
Properties props = System.getProperties();
|
||
|
props.setProperty("java.util.logging.SimpleFormatter.format", "%5$s%6$s%n");
|
||
|
Logger.getLogger("").setLevel(level);
|
||
|
for (Handler handler : Logger.getLogger("").getHandlers()) {
|
||
|
handler.setLevel(level);
|
||
|
}
|
||
|
LOGGER = Logger.getLogger(Parser.class.getName());
|
||
|
|
||
|
if (args.length < 1) {
|
||
|
throw new RuntimeException("Be sure to add your test C- file as a command-line parameter.");
|
||
|
}
|
||
|
final String filename = args[0];
|
||
|
|
||
|
LOGGER.info("");
|
||
|
LOGGER.info("Parsing " + filename + "\n");
|
||
|
LOGGER.info("");
|
||
|
final CharStream charStream = CharStreams.fromFileName(filename);
|
||
|
CminusLexer lexer = new CminusLexer(charStream);
|
||
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||
|
CminusParser parser = new CminusParser(tokens);
|
||
|
parser.setBuildParseTree(true);
|
||
|
CminusParser.ProgramContext programCtx = parser.program();
|
||
|
|
||
|
LOGGER.info("");
|
||
|
LOGGER.info("Building abstract syntax tree");
|
||
|
LOGGER.info("");
|
||
|
ASTVisitor v = new ASTVisitor(LOGGER);
|
||
|
Node ast = v.visitProgram(programCtx);
|
||
|
SymbolTable symbolTable = v.getSymbolTable();
|
||
|
|
||
|
LOGGER.info("");
|
||
|
LOGGER.info("MIPS code:");
|
||
|
LOGGER.info("");
|
||
|
StringBuilder code = new StringBuilder();
|
||
|
StringBuilder data = new StringBuilder();
|
||
|
RegisterAllocator regAllocator = new RegisterAllocator();
|
||
|
try {
|
||
|
ast.toMIPS(code, data, symbolTable, regAllocator);
|
||
|
} finally {
|
||
|
StringBuilder mips = new StringBuilder();
|
||
|
mips.append("# All program code is placed after the\n" +
|
||
|
"# .text assembler directive\n" +
|
||
|
".text\n" +
|
||
|
"\n" +
|
||
|
"# Declare main as a global function\n" +
|
||
|
".globl\tmain\n\nj main\n");
|
||
|
mips.append(code.toString());
|
||
|
mips.append("\n# All memory structures are placed after the\n" +
|
||
|
"# .data assembler directive\n" +
|
||
|
".data\n" +
|
||
|
"\n");
|
||
|
mips.append(data.toString());
|
||
|
|
||
|
// Write MIPS code to stdout
|
||
|
LOGGER.info(mips.toString());
|
||
|
|
||
|
// Write MIPS code to output file for easy loading into MARS
|
||
|
final String fn = filename.substring(0, filename.length() - 1) + "asm";
|
||
|
try {
|
||
|
FileWriter myWriter = new FileWriter(fn);
|
||
|
myWriter.write(mips.toString());
|
||
|
myWriter.close();
|
||
|
} catch (IOException e) {
|
||
|
LOGGER.severe("Error writing to file " + fn + "\n");
|
||
|
e.printStackTrace();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|