113 lines
3.1 KiB
Python
113 lines
3.1 KiB
Python
import sys
|
|
import os
|
|
import subprocess
|
|
|
|
from antlr4 import FileStream, CommonTokenStream # Token
|
|
from antlr4.error.ErrorListener import ConsoleErrorListener # ErrorListener
|
|
|
|
try:
|
|
from parser.MPLexer import MPLexer as Lexer
|
|
from parser.MPParser import MPParser as Parser
|
|
from astgen.ASTGeneration import ASTGeneration
|
|
from checker.StaticCheck import StaticChecker
|
|
from codegen.CodeGenerator import CodeGenerator
|
|
except ModuleNotFoundError:
|
|
print('Generate ANTLR4 first')
|
|
print('python genANTLR4.py')
|
|
exit(1)
|
|
|
|
|
|
ANTLR_JAR = os.environ.get('ANTLR_LIB')
|
|
JASMIN_JAR = './external/jasmin.jar'
|
|
|
|
if ANTLR_JAR is None:
|
|
# fall back, not recommended
|
|
ANTLR_JAR = './external/antrl4.jar'
|
|
|
|
|
|
class SyntaxException(Exception):
|
|
def __init__(self, msg):
|
|
self.message = msg
|
|
|
|
|
|
class NewErrorListener(ConsoleErrorListener):
|
|
INSTANCE = None
|
|
|
|
def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e):
|
|
raise SyntaxException(
|
|
"Error on line " +
|
|
str(line) +
|
|
" col " +
|
|
str(column) +
|
|
": " +
|
|
offendingSymbol.text)
|
|
|
|
|
|
def compile(inputfile):
|
|
lexer = Lexer(FileStream(inputfile))
|
|
tokens = CommonTokenStream(lexer)
|
|
try:
|
|
# listener = TestParser.createErrorListener()
|
|
listener = NewErrorListener().INSTANCE
|
|
parser = Parser(tokens)
|
|
parser.removeErrorListeners()
|
|
parser.addErrorListener(listener)
|
|
tree = parser.program()
|
|
except SyntaxException as f:
|
|
msg = f.message.split(':')[0].split(' ')
|
|
line = int(msg[3])
|
|
col = int(msg[5])
|
|
error_line = open(inputfile).read()
|
|
error_line = error_line.split('\n')[line - 1]
|
|
print(error_line)
|
|
print('~' * (col) + '^')
|
|
print(f.message)
|
|
raise f
|
|
asttree = ASTGeneration().visit(tree)
|
|
|
|
checker = StaticChecker(asttree)
|
|
checker.check()
|
|
|
|
path = os.path.dirname(inputfile)
|
|
filename = os.path.basename(inputfile).split('.')[0]
|
|
codeGen = CodeGenerator()
|
|
codeGen.gen(asttree, path, filename)
|
|
|
|
subprocess.call(
|
|
# "java -jar " + JASMIN_JAR + " " + path + "/MPClass.j",
|
|
"java -jar {} {}/{}.j -d {}".format(JASMIN_JAR, path, filename, path),
|
|
shell=True,
|
|
stderr=subprocess.STDOUT
|
|
)
|
|
|
|
with open('{}/io.class'.format(path), 'wb') as iofile:
|
|
iofile.write(open('libs/io.class', 'rb').read())
|
|
|
|
subprocess.call(
|
|
# 'jar cvfm {}/{}.jar {}/manifest.mf {} {}.class'.format(
|
|
'jar cvfe {0}.jar {0} io.class {0}.class'.format(
|
|
filename
|
|
),
|
|
cwd=path,
|
|
shell=True,
|
|
stderr=subprocess.STDOUT
|
|
)
|
|
|
|
os.remove('{}/{}.j'.format(path, filename))
|
|
os.remove('{}/{}.class'.format(path, filename))
|
|
os.remove('{}/io.class'.format(path))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
argv = sys.argv
|
|
if len(argv) != 2:
|
|
exit(1)
|
|
|
|
try:
|
|
print("Compiling {}".format(os.path.relpath(argv[1])))
|
|
compile(argv[1])
|
|
except BaseException as e:
|
|
print(e)
|
|
exit(1)
|
|
print("Compiled successfully")
|