diff --git a/compiler/compilation.py b/compiler/compilation.py index 832e7e8..1a8b7fd 100644 --- a/compiler/compilation.py +++ b/compiler/compilation.py @@ -62,11 +62,8 @@ class CompilationEngine: self.close('classVarDec') self.advance() - """ Writes a single line(with \n) on the XML, taking into account the indentation """ def write(self, klass, subklass = None): - print(self.type()) - print(klass) assert(klass == self.type()) if (klass == Token.SYMBOL): assert(subklass == self.s()) @@ -94,7 +91,7 @@ class CompilationEngine: self.write(T) self.advance() - def CompuleSubroutine(self): + def CompileSubroutine(self): self.open('subroutineDec') self.write() pass diff --git a/compiler/engine.py b/compiler/engine.py index 24feb6b..e089e4b 100644 --- a/compiler/engine.py +++ b/compiler/engine.py @@ -1,4 +1,6 @@ from tokenizer import JackTokenizer +from keywords import * +from grammar import CLASS """ New Compilation Engine @@ -8,3 +10,6 @@ class Engine: self.i = 0 self.jt = JackTokenizer(input_file, False) self.file = open(input_file + ".xml", 'w') + + def xml_file(self, input_file): + return input_file + ".xml" diff --git a/compiler/grammar.py b/compiler/grammar.py index 4b06791..cf40029 100644 --- a/compiler/grammar.py +++ b/compiler/grammar.py @@ -1,67 +1,5 @@ from keywords import Keyword -class Element: - def __init__(name, grammar, terminal = False): - self.name = name - self.grammar = grammar - self.terminal = terminal - -CLASS = Element('class', [ - # class className { - Keyword.CLASS, - Keyword.IDENTIFIER, - Keyword.BRACE_OPEN, - # class Variable Declarations (one or more) = list - CLASSVARDEC, - # subroutine declarations (one or more) = list - SUBROUTINEDEC, - # } - Keyword.BRACE_CLOSE -]) - -CLASSVARDEC = Element('classVarDec', [ - # static|field type (, name)* ; - Keyword.STATIC | Keyword.FIELD, - TYPE, - [Keyword.COMMA, Keyword.IDENTIFIER], - Keyword.SEMICOLON -]) - -# Parameter List = -# ( -# (type varName) (, type varName)* -# )? -# we use tuples for zero OR one of a sequence -PARAMETER_LIST = Element('parameterList', ( - TYPE, - Keyword.IDENTIFIER, - [Keyword.COMMA, TYPE, Keyword.IDENTIFIER] -)) - -TYPE = Element('type', Keyword.INT | Keyword.CHAR | Keyword.BOOLEAN | Keyword.IDENTIFIER, True) - -SUBROUTINE_BODY = Element('subroutineBody', [ - # One or more variable declarations - # `var type varName (, varName)* ;` - [VARDEC], - STATEMENTS -]) - -SUBROUTINEDEC = Element('subroutineDec', [ - # (constructor | function | method) (void | type) subRoutineName '(' parameterList ')' - # subroutineBody - Keyword.CONSTRUCTOR | Keyword.FUNCTION | Keyword.METHOD, - Keyword.VOID | TYPE, - Keyword.IDENTIFIER, - Keyword.PARAN_OPEN, - PARAMETER_LIST, - Keyword.PARAN_CLOSE, - # Subroutine Body { - Keyword.BRACE_OPEN, - SUBROUTINE_BODY, - Keyword.BRACE_CLOSE, -]) - """ The grammar is defined by the following constructs: @@ -79,10 +17,29 @@ This is basically an attempt to translate Figure 10.5 from the book into a Python structure. """ +class Element: + def __init__(self, name, grammar, terminal = False): + self.name = name + self.grammar = grammar + self.terminal = terminal +TYPES = Element('type', Keyword.INT | Keyword.CHAR | Keyword.BOOLEAN | Keyword.IDENTIFIER, True) + +CLASSVARDEC = Element('classVarDec', [ + # static|field type (, name)* ; + Keyword.STATIC | Keyword.FIELD, + TYPES, + [Keyword.COMMA, Keyword.IDENTIFIER], + Keyword.SEMICOLON +]) + +VARDEC = Element('varDec', [Keyword.VAR, TYPES, Keyword.IDENTIFIER, + [Keyword.COMMA, Keyword.IDENTIFIER], + Keyword.SEMICOLON +]) UNARY_OP = Element('unaryOp', Keyword.NOT | Keyword.MINUS, True) -CONSTANT = Element('KeywordConstant', Keyword.TRUE | Keyword.FALSE, Keyword.NULL, Keyword.THIS, True) +CONSTANT = Element('KeywordConstant', Keyword.TRUE | Keyword.FALSE|Keyword.NULL|Keyword.THIS, True) TERM = Element('term', Keyword.INTEGERCONSTANT | Keyword.STRINGCONSTANT | Keyword.TRUE | Keyword.FALSE | Keyword.IDENTIFIER) @@ -114,6 +71,7 @@ STATEMENT = Element('statement', { Keyword.BRACE_OPEN, lambda: STATEMENTS, Keyword.BRACE_CLOSE, + # This is the tricky one ( Keyword.ELSE, Keyword.BRACE_OPEN, lambda:STATEMENT, Keyword.BRACE_CLOSE) ], (Keyword.WHILE): [ @@ -129,3 +87,52 @@ STATEMENT = Element('statement', { }) STATEMENTS = Element('statements', [STATEMENT]) + +SUBROUTINE_BODY = Element('subroutineBody', [ + # One or more variable declarations + # `var type varName (, varName)* ;` + [VARDEC], + STATEMENTS +]) + +""" Pseudo-element to help define subroutine declarations """ +RETURN_TYPES= Keyword.INT | Keyword.CHAR|Keyword.BOOLEAN|Keyword.IDENTIFIER|Keyword.VOID + +# Parameter List = +# ( +# (type varName) (, type varName)* +# )? +# we use tuples for zero OR one of a sequence +PARAMETER_LIST = Element('parameterList', ( + TYPES, + Keyword.IDENTIFIER, + [Keyword.COMMA, TYPES, Keyword.IDENTIFIER] +)) + +SUBROUTINEDEC = Element('subroutineDec', [ + # (constructor | function | method) (void | type) subRoutineName '(' parameterList ')' + # subroutineBody + Keyword.CONSTRUCTOR | Keyword.FUNCTION | Keyword.METHOD, + RETURN_TYPES, + Keyword.IDENTIFIER, + Keyword.PARAN_OPEN, + PARAMETER_LIST, + Keyword.PARAN_CLOSE, + # Subroutine Body { + Keyword.BRACE_OPEN, + SUBROUTINE_BODY, + Keyword.BRACE_CLOSE, +]) + +CLASS = Element('class', [ + # class className { + Keyword.CLASS, + Keyword.IDENTIFIER, + Keyword.BRACE_OPEN, + # class Variable Declarations (one or more) = list + CLASSVARDEC, + # subroutine declarations (one or more) = list + SUBROUTINEDEC, + # } + Keyword.BRACE_CLOSE +]) diff --git a/compiler/keywords.py b/compiler/keywords.py index 5260b14..94f12ac 100644 --- a/compiler/keywords.py +++ b/compiler/keywords.py @@ -46,3 +46,32 @@ class Keyword(Flag): IDENTIFIER = auto() INTEGERCONSTANT = auto() STRINGCONSTANT = auto() + +class Symbol(Flag): + # Symbols Start here + BRACE_OPEN = Keyword.BRACE_OPEN + BRACE_CLOSE = Keyword.BRACE_CLOSE + PARAN_OPEN = Keyword.PARAN_OPEN + PARAN_CLOSE = Keyword.PARAN_CLOSE + SQUARE_OPEN = Keyword.SQUARE_OPEN + SQUARE_CLOSE = Keyword.SQUARE_CLOSE + DOT = Keyword.DOT + SEMICOLON = Keyword.SEMICOLON + PLUS = Keyword.PLUS + MINUS = Keyword.MINUS + MUL = Keyword.MUL + DIV = Keyword.DIV + AND = Keyword.AND + OR = Keyword.OR + LT = Keyword.LT + GT = Keyword.GT + EQ = Keyword.EQ + NOT = Keyword.NOT + COMMA = Keyword.COMMA + +class Token(Flag): + KEYWORD = auto() + SYMBOL = auto() + IDENTIFIER = Keyword.IDENTIFIER + INTEGERCONSTANT = Keyword.INTEGERCONSTANT + STRINGCONSTANT = Keyword.STRINGCONSTANT