def CompileDoStatement(self, out): 'compile doStatement' self.__print_nonterm_tag(out, 'doStatement') # <doStatement> self.__validate(out, Token(JackTokenizer.KEYWORD,'do',1,1), True) self.CompileSubroutineCall(out) self.__validate(out, Token(JackTokenizer.SYMBOL,';',1,1), True) self.__print_nonterm_tag(out, 'doStatement', True) # </doStatement>
def CompileTerm(self, out): 'compile term' self.__print_nonterm_tag(out, 'term') # <term> token = self.__tokenizer.peek() if token.typ in (JackTokenizer.INTEGER, JackTokenizer.STRING) \ or token.value in KEYWORDCONST: _ = self.__tokenizer.next() self.__print_term_tag(out, token) # intConst | strConst | keywordConstant elif token.value == '(': _ = self.__tokenizer.next() self.__print_term_tag(out, token) # ( self.CompileExpression(out) self.__validate(out, Token(JackTokenizer.SYMBOL,')',1,1), True) elif token.value in UNARYOP: _ = self.__tokenizer.next() self.__print_term_tag(out, token) # unaryOp self.CompileTerm(out) else: token2 = self.__tokenizer.peek(1) if token2.value in ('(', '.'): self.CompileSubroutineCall(out) else: self.__validate(out, varName_token) # varName token = self.__tokenizer.peek() if token.value == '[': _ = self.__tokenizer.next() self.__print_term_tag(out, token) # [ self.CompileExpression(out) self.__validate(out, Token(JackTokenizer.SYMBOL,']',1,1), True) self.__print_nonterm_tag(out, 'term', True) # </term>
def CompileSubroutineBody(self, out): 'compile subroutineBody' self.__print_nonterm_tag(out, 'subroutineBody') # <subroutineBody> self.__validate(out, Token(JackTokenizer.SYMBOL,'{',1,1), True) self.CompileVarDec(out) self.CompileStatements(out) self.__validate(out, Token(JackTokenizer.SYMBOL,'}',1,1), True) self.__print_nonterm_tag(out, 'subroutineBody', True) # </subroutineBody>
def CompileReturnStatement(self, out): 'compile returnStatement' self.__print_nonterm_tag(out, 'returnStatement') # <returnStatement> self.__validate(out, Token(JackTokenizer.KEYWORD,'return',1,1), True) token = self.__tokenizer.peek() if token.value != ';': self.CompileExpression(out) self.__validate(out, Token(JackTokenizer.SYMBOL,';',1,1), True) self.__print_nonterm_tag(out, 'returnStatement', True) # </returnStatement>
def compileClass(self, out): 'compile class' self.__print_nonterm_tag(out, 'class') # <class> self.__validate(out, Token(JackTokenizer.KEYWORD,'class',1,1), True) self.__validate(out, varName_token) self.__validate(out, Token(JackTokenizer.SYMBOL,'{',1,1), True) self.CompileClassVarDec(out) self.CompileSubroutineDec(out) self.__validate(out, Token(JackTokenizer.SYMBOL,'}',1,1), True) self.__print_nonterm_tag(out, 'class', True) # </class>
def CompileWhileStatement(self, out): 'compile whileStatement' self.__print_nonterm_tag(out, 'whileStatement') # <whileStatement> self.__validate(out, Token(JackTokenizer.KEYWORD,'while',1,1), True) self.__validate(out, Token(JackTokenizer.SYMBOL,'(',1,1), True) self.CompileExpression(out) self.__validate(out, Token(JackTokenizer.SYMBOL,')',1,1), True) self.__validate(out, Token(JackTokenizer.SYMBOL,'{',1,1), True) self.CompileStatements(out) self.__validate(out, Token(JackTokenizer.SYMBOL,'}',1,1), True) self.__print_nonterm_tag(out, 'whileStatement', True) # </whileStatement>
def CompileLetStatement(self, out): 'compile letStatement' self.__print_nonterm_tag(out, 'letStatement') # <letStatement> self.__validate(out, Token(JackTokenizer.KEYWORD,'let',1,1), True) self.__validate(out, varName_token) token = self.__tokenizer.peek() if token.value == '[': _ = self.__tokenizer.next() self.__print_term_tag(out, token) # [ self.CompileExpression(out) self.__validate(out, Token(JackTokenizer.SYMBOL,']',1,1), True) self.__validate(out, Token(JackTokenizer.SYMBOL,'=',1,1), True) self.CompileExpression(out) self.__validate(out, Token(JackTokenizer.SYMBOL,';',1,1), True) self.__print_nonterm_tag(out, 'letStatement', True) # </letStatement>
def CompileSubroutineCall(self, out): 'compile subroutineCall' self.__validate(out, varName_token) # varName token = self.__tokenizer.peek() if token.value == '.': _ = self.__tokenizer.next() self.__print_term_tag(out, token) # '.' self.__validate(out, varName_token) # varName self.__validate(out, Token(JackTokenizer.SYMBOL,'(',1,1), True) token = self.__tokenizer.peek() if token.value != ')': self.CompileExpressionList(out) else: self.__print_nonterm_tag(out, 'expressionList') # <expressionList> self.__print_nonterm_tag(out, 'expressionList', True) # </expressionList> self.__validate(out, Token(JackTokenizer.SYMBOL,')',1,1), True)
def _read_tokens(filename, start, end): with open(filename, 'r') as file: content = file.readlines() lines = content[start:end] tokens = [] for line in lines: tokens.append(Token.load_xml(line.strip())) return tokens
def CompileSubroutineDec(self, out): 'compile subroutineDec' token = self.__tokenizer.peek() while token.value in SUBROUTINETYPE: self.__print_nonterm_tag(out, 'subroutineDec') # <subroutineDec> _ = self.__tokenizer.next() self.__print_term_tag(out, token) # 'constructor' | 'function' | 'method' token = self.__tokenizer.next() if token.value != 'void' and not self.__is_type(token): self.__error_msg(token, 'void|'+ '|'.join(TYPE_) +'|className') self.__print_term_tag(out, token) # 'void' | type self.__validate(out, varName_token) self.__validate(out, Token(JackTokenizer.SYMBOL,'(',1,1), True) self.CompileParameterList(out) self.__validate(out, Token(JackTokenizer.SYMBOL,')',1,1), True) self.CompileSubroutineBody(out) self.__print_nonterm_tag(out, 'subroutineDec', True) # </subroutineDec> token = self.__tokenizer.peek()
def CompileClassVarDec(self, out): 'compile classVarDec' token = self.__tokenizer.peek() while token.value in CLASSVARTYPE: self.__print_nonterm_tag(out, 'classVarDec') # <classVarDec> _ = self.__tokenizer.next() self.__print_term_tag(out, token) # 'static' | 'field' self.CompileType(out) self.__validate(out, varName_token) token = self.__tokenizer.peek() while token.value == ',': _ = self.__tokenizer.next() self.__print_term_tag(out, token) # , self.__validate(out, varName_token) token = self.__tokenizer.peek() self.__validate(out, Token(JackTokenizer.SYMBOL,';',1,1), True) self.__print_nonterm_tag(out, 'classVarDec', True) # </classVarDec> token = self.__tokenizer.peek()
def CompileVarDec(self, out): 'compile varDec' token = self.__tokenizer.peek() while token.value == 'var': self.__print_nonterm_tag(out, 'varDec') # <varDec> _ = self.__tokenizer.next() self.__print_term_tag(out, token) # 'var' self.CompileType(out) self.__validate(out, varName_token) token = self.__tokenizer.peek() while token.value == ',': _ = self.__tokenizer.next() self.__print_term_tag(out, token) # , self.__validate(out, varName_token) token = self.__tokenizer.peek() self.__validate(out, Token(JackTokenizer.SYMBOL,';',1,1), True) self.__print_nonterm_tag(out, 'varDec', True) # </varDec> token = self.__tokenizer.peek()
def test_classVarDec(self): tokens = [ Token(TOKEN_KEYWORD, 'field'), Token(TOKEN_KEYWORD, 'int'), Token(TOKEN_IDENTIFIER, 'x'), Token(TOKEN_SYMBOL, ','), Token(TOKEN_IDENTIFIER, 'y'), Token(TOKEN_SYMBOL, ';') ] compiler = CompilationEngine(None) compiler.tokens = tokens self.assertTrue(compiler.isClassVarDec(0, len(tokens) - 1)) node = compiler.compileClassVarDec(0, len(tokens) - 1) self.assertEqual(len(node.children), 6)
def CompileIfStatement(self, out): 'compile ifStatement' self.__print_nonterm_tag(out, 'ifStatement') # <ifStatement> self.__validate(out, Token(JackTokenizer.KEYWORD,'if',1,1), True) self.__validate(out, Token(JackTokenizer.SYMBOL,'(',1,1), True) self.CompileExpression(out) self.__validate(out, Token(JackTokenizer.SYMBOL,')',1,1), True) self.__validate(out, Token(JackTokenizer.SYMBOL,'{',1,1), True) self.CompileStatements(out) self.__validate(out, Token(JackTokenizer.SYMBOL,'}',1,1), True) token = self.__tokenizer.peek() if token.value == 'else': _ = self.__tokenizer.next() self.__print_term_tag(out, token) # 'else' self.__validate(out, Token(JackTokenizer.SYMBOL,'{',1,1), True) self.CompileStatements(out) self.__validate(out, Token(JackTokenizer.SYMBOL,'}',1,1), True) self.__print_nonterm_tag(out, 'ifStatement', True) # </ifStatement>
**omitted ''' import collections from xml.sax.saxutils import escape from JackTokenizer import JackTokenizer, Token TABSIZE = 2 CLASSVARTYPE = ('static', 'field') TYPE_ = ('int', 'char', 'boolean') SUBROUTINETYPE = ('constructor', 'function', 'method') STATEMENT = ('let', 'if', 'while', 'do', 'return') OPERATOR = ('+', '-', '*', '/', '&', '|', '<', '>', '=') KEYWORDCONST = ('true', 'false', 'null', 'this') UNARYOP = ('-', '~') varName_token = Token(JackTokenizer.IDENTIFIER,'varName',1,1) class CompilationEngine(object): '''write tokens into file, only check the basic flow''' def __init__(self): self.__tokenizer = None self.__indent = 0 def compile(self, tokenizer, outfile): 'complie the source file' self.__tokenizer = tokenizer self.compileClass(outfile) def compileClass(self, out): 'compile class'
def test_load_xml(self): string = '<integerConstant>30</integerConstant>' token = Token.load_xml(string) self.assertEqual(token.to_xml(), string)