Franck Pommereau

fixed heratic parsing error, minor changes

......@@ -69,7 +69,7 @@ tokens = (
'DOUBLE_MINUS',
'PLUS',
'MINUS',
'TIMES',
# 'TIMES',
'DIV',
'MODULO',
'DOUBLE_AMPERSAND',
......@@ -169,7 +169,7 @@ t_DOUBLE_PLUS = r'\+\+'
t_DOUBLE_MINUS = r'--'
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
# t_TIMES = r'\*'
t_DIV = r'/(?!\*)'
t_MODULO = r'%'
t_DOUBLE_AMPERSAND = r'&&'
......
......@@ -755,9 +755,7 @@ def p_empty(t):
pass
def p_error(t):
print("You've got a syntax error somewhere in your code.")
print("It could be around line %d." % t.lineno)
print("Good luck finding it.")
print("[%s:%s] syntax error" % (t.lineno, t.lexpos))
raise ParseError()
yacc.yacc(debug=1)
......
......@@ -2,6 +2,15 @@ import argparse, sys, os.path
import ply.yacc as yacc
from . import cparse, cvisitors, cx86
cttc = cx86
ARCH = {"x86" : cx86,
"ttc" : cttc}
ARCHDOC = """supported target architectures:
x86 Intel 80x86 assembly (in GNU Assemble format)
ttc The Tiny Computer assembly
"""
class CompileError (Exception) :
"Exception raised when there's been a compilation error."
......@@ -11,7 +20,8 @@ class Compiler (object) :
"""This object encapsulates the front-end for the compiler and
serves as a facade interface to the 'meat' of the compiler
underneath."""
def __init__ (self) :
def __init__ (self, arch) :
self.arch = arch
self.total_errors = 0
self.total_warnings = 0
def _parse (self) :
......@@ -31,12 +41,15 @@ class Compiler (object) :
self._compile_phase(cvisitors.SymtabVisitor())
self._compile_phase(cvisitors.TypeCheckVisitor())
self._compile_phase(cvisitors.FlowControlVisitor())
self._compile_phase(cx86.CodeGenVisitor(outfile))
self._compile_phase(self.arch.CodeGenVisitor(outfile))
if ast_file is not None:
self._compile_phase(cvisitors.ASTPrinterVisitor(ast_file))
def _print_stats (self) :
"Prints the total number of errors/warnings from compilation."
print("%d errors, %d warnings." % (self.total_errors, self.total_warnings))
if self.total_errors :
print("%d errors" % self.total_errors)
if self.total_warnings :
print("%s warnings" % self.total_warnings)
def compile (self, code, outfile, show_ast) :
"Compiles the given code string to the given file object."
self.code = code
......@@ -54,21 +67,32 @@ class Compiler (object) :
return 0
def main (args=None) :
parser = argparse.ArgumentParser(prog="cct")
parser = argparse.ArgumentParser(prog="cct",
epilog=ARCHDOC,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("-o", action="store", metavar="PATH",
type=argparse.FileType('w'), default=sys.stdout,
help="write output to PATH")
parser.add_argument("--ast", action="store_true", default=False,
help="dump AST for each C file")
parser.add_argument("--arch", action="store", choices=list(ARCH),
default="ttc",
help="output assembly for specified architecture (default 'ttc')")
parser.add_argument("-t", "--ttc", action="store_const", const="ttc",
dest="arch", help="output TTC assembly")
parser.add_argument("source", nargs="+", metavar="PATH",
help="C source files(s) to compile")
args = parser.parse_args(args)
for src in args.source :
print("Compiling %r" % src)
if args.ast :
ast_file = open(os.path.splitext(src)[0] + ".ast", "w")
ast_path = os.path.splitext(src)[0] + ".ast"
print("Dumping AST to %r" % ast_path)
ast_file = open(ast_path, "w")
else :
ast_file = None
retval = Compiler().compile(open(src).read(), args.o, ast_file)
code = "\n".join(open(src).readlines())
retval = Compiler(ARCH[args.arch]).compile(code, args.o, ast_file)
if ast_file is not None :
ast_file.close()
if retval != 0 :
......
This diff is collapsed. Click to expand it.