def __init__(self, filepath):
     jt = JackTokenizer(filepath)
     ce = CompilationEngine(filepath, jt.tokens)
     self.vmwriter = VMWriter(filepath)
     self.symbol_table = SymbolTable()
     self.class_name = None
     self.generateClass(ce.root)
Exemple #2
0
    def __init__(self, parserInput, parserOutput, daSymbolTable):

        self.tTp = []  #tokens to parse array aka tTp
        self.tTpcopy = []  #copy to help remove stuff
        self.tokenCounter = 0
        self.indent = 0

        # open the input.xml file made by the tokenizer (full of tokens ready to parse)
        with open(parserInput) as f:
            for line in f:
                self.tTpcopy.append(line)
        self.tTp = self.tTpcopy[1:-1]  # remove unwanted stuff from copy

        self.output1 = open(parserOutput + '.xml', 'w')
        #output to write to
        self.theVMWriter = VMWriter(parserOutput)

        self.currentTokenArr = self.tTp[self.tokenCounter].split(' ')
        self.currentToken = self.tTp[self.tokenCounter]  # first token
        self.className = ''
        self.subroutineVoid = False
        self.iflabel = 0
        self.whilelabel = 0
        self.constructor = False
        self.functionType = ''
        self.subroutineName = ''

        # get symbol table and everything started
        self.theSymbolTable = daSymbolTable
        self.theSymbolTable.classStart()
        self.compileClass()  # start compiling

        self.output1.close()  # close the file when done
    def compile_class(self) -> None:
        """
        compiles a class
        :return: None
        """

        # create VMWriter for current class
        self.VMWriter = VMWriter(self.file_name)

        # was class
        self.tokenizer.advance()
        # now name

        # current class name :
        self.current_class_name = self.tokenizer.get_current_token()[1]

        # was name
        self.tokenizer.advance()
        # now {

        # was {
        self.tokenizer.advance()
        # now class body

        while self.tokenizer.has_more_tokens():
            current_token = self.tokenizer.get_current_token()
            token_string = current_token[1]
            if CompilationEngine.is_class_field(token_string):
                self.compile_class_var_declaration()
            elif CompilationEngine.is_subroutine(token_string):
                self.compile_subroutine()

        # insert last  "}" of end of class
        current_token = self.tokenizer.get_current_token()[1]
        self.tokenizer.advance()
Exemple #4
0
 def __init__(self, file_path):
     self._tokenizer = JackTokenizer(file_path)
     self._vm_writer = VMWriter(file_path.replace(".jack", "Compiled.vm"))
     self._symbol_table = SymbolTable()
     self.class_name = ""
     self.label_value = 1
     self.compile_class()
Exemple #5
0
    def loadFile(self, filepath):
        self.tokenizer = JackTokenizer(filepath)
        self._generateTree()
        self._initializeClassDetails(self.treeRoot)

        outputFilePath = filepath[:-5] + ".vm"
        self.writer = VMWriter(outputFilePath)
 def __init__(self, tokenizer, output_file):
     self.tokenizer = tokenizer
     self.output_file = output_file
     self.class_symbol_table = SymbolTable()
     self.subroutine_symbol_table = SymbolTable()
     self.vm_writer = VMWriter(output_file)
     self.label_counter = LabelCounter(labels=self.TOKENS_THAT_NEED_LABELS)
     self.class_name = None
 def __init__(self, inputFile, outputFile):
     self.tokenizer = JackTokenizer(inputFile)
     self.vmWriter = VMWriter(outputFile)
     self.symbolTable = SymbolTable()
     self.classname = ""
     self.CompileClass()
     self.whilecounter = 0
     self.ifcounter = 0
 def __init__(self, input_file):
     self.st=SymbolTable()
     self.vmW = VMWriter()
     self.tknz = JackTokenizer(input_file)
     self._vm_string = ''
     self.tknz.advance()
     self.Op=[]
     self.Function=[]
Exemple #9
0
 def __init__(self, tokenizer, output_vm_file, output_xml_file=None):
     self.tokenizer = tokenizer
     self.vmr = VMWriter(output_vm_file)
     self.output_xml_file = output_xml_file
     self.indent = ""
     self.symbol_table = SymbolTable()
     self.current_class = None
     self.void_subr = set()
     self.label_counter = 0
    def __init__(self, input: JackTokenizer, output_file_path):
        self.tokenizer = input
        self.vmwriter = VMWriter(output_file_path)
        self.symbol_table = SymbolTable()

        self.label_index = 0
        self.curr_token = ''
        self.curr_token_type = ''
        self.depth = 0
 def __init__(self, _tokens, _in_path, _out_file):
     self.tokens = iter(_tokens)
     self.file_name = str(split(_in_path)[1].split('.')[0])
     self.out_file = _out_file
     self.writer = VMWriter(_out_file)
     self.sym_table = SymbolTable()
     self.class_name = ''
     self.curr_subroutine_name = ''
     self.curr_cond_index = 0
Exemple #12
0
 def __init__(self, inpath, outpath):
     self.tokenizer = Tokenizer(inpath)
     self.symboltable = SymbolTable()
     self.vmwriter = VMWriter(outpath)
     self._class_name = None
     if self.tokenizer.has_more_tokens():
         self.compile_class()
     self.vmwriter.close()
     print("{0} completed.".format(outpath))
Exemple #13
0
 def __init__(self, tokens_with_tokenType, out_vm_file):
     self.tokens_with_tokenType = tokens_with_tokenType
     self.symbol_table = SymbolTable()
     self.vm_writer = VMWriter(out_vm_file)
     self.class_name = out_vm_file.stem
     self.construct_op_dict()
     self.construct_segment_dict()
     self.while_label_index = 0
     self.if_else_label_index = 0
Exemple #14
0
 def __init__(self, tokenizer, outputFile, vmFile):
     from SymbolTable import SymbolTable
     from VMWriter import VMWriter
     self.tokenizer = tokenizer
     self.outputFile = outputFile
     self.symbolTable = SymbolTable()
     self.vmWriter = VMWriter(vmFile)
     self.labelNum = 0
     print(outputFile)
 def __init__(self, tokens, fp_out):
     self.tokens = tokens
     self.num = 0  #current node in tree
     self.total = len(tokens)
     self.crnt_elem = self.tokens[0]
     self.symbols = SymbolTable()#create symbol table(s)
     #possibly should call compileclass from outside
     self.VM = VMWriter(fp_out)
     self.labels = {} #to create unique labels
Exemple #16
0
 def __init__(self, filepath):
     self._tokenizer = JackTokenizer(filepath) 
     self._writer = VMWriter(filepath)
     self._classVariables = SymbolTable()
     self._subroutineVariables = SymbolTable()
     self._currentToken = None
     self._preserveCurrentToken = False
     self._className = ''
     self._currentCompilingFunction = {'kind': '', 'name': ''}
     self._numberConditionalsStatementsCurrentFunction = 0
 def __init__ (self, path):
     super().__init__(path)
     self.xml = str()
     self.advance()
     self.st = SymbolTable()
     self.vm = VMWriter(self.path[:-5]+'.vm')
     self.className = str()
     self.labelCounter = 0
     self.currentFunctionName = str()
     self.currentSubroutineType = str()
Exemple #18
0
 def __init__(self, tokenizer, out_file_name):
     '''
     Constructor
     '''
     self._tokenizer = tokenizer
     self._vm_writer = VMWriter(out_file_name)
     self._class_name = None
     self._symbol_table = SymbolTable()
     self._counter = 0
     self._subroutine_name = None
Exemple #19
0
 def __init__(self, tokenizer, output):
     """
     c'tor
     :param tokenizer: tokenizer object
     :param output: output file/stream
     """
     self.tokenizer = tokenizer
     self.vmWriter = VMWriter(output)
     self.symbols = SymbolTable()
     self.className = None
     self.labelC = 0
Exemple #20
0
 def __init__(self, tokenizer: JackTokenizer, jack_file):
     self.tokenizer = tokenizer
     self.class_name = ''
     log_file_name = jack_file.name.replace('.jack', '_engine.xml')
     self.log_file = open(log_file_name, 'w')
     log_file_name = jack_file.name.replace('.jack', '.vm')
     self.output_file = open(log_file_name, 'w')
     self.symbol_table = SymbolTable()
     self.vm_writer = VMWriter(self.output_file)
     self.while_label_index = 0
     self.if_label_index = 0
 def __init__(self, filename: str, token_list: list):
     self.token_index = 0
     self.identation_level = 0
     self.tokens = token_list
     self.output_file_name = filename
     self.symbol_table = SymbolTable()
     self.VMWriter = VMWriter(filename.replace(".jack", ".vm"))
     self.is_identifier_used = False
     self.current_if_labels = 0
     self.current_while_labels = 0
     pass
    def __init__(self, filename):

        self.tokenizer = JackTokenizer(filename)
        self.types = ['int', 'char', 'boolean']
        self.operators = ['+', '-', '*', '/', '&', '|', '<', '>', '=']
        self.keywordsConstant = ['true', 'false', 'null', 'this']
        self.fileName = splitext(filename)[0]
        self.symbolTable = SymbolTable()
        self.vm = VMWriter(splitext(filename)[0])
        self.whileLabelNum = 0
        self.ifLabelNum = 0
Exemple #23
0
 def __init__(self, in_address):
     self.tokenizer = Tokenizer(in_address)
     self.symbol_table = SymbolTable()
     self.vm_writer = VMWriter(in_address.replace(".jack", ".vm"))
     self.curr_token = self.tokenizer.get_current_token()
     self.out_address = in_address.replace(".jack", ".xml")
     self.output = ""
     self.indent = 0
     self.label_count = -1
     self.class_name = ""
     self.compile_class()
def make_file(filename):
    tokenizer = JackTokenizer()
    tokenizer.read_file(filename)
    tokenizer.divide_into_tokens()
    file_to_write = filename[:-5] + "." + "vm"
    writer = VMWriter(file_to_write)
    parser = CompilationEngine(tokenizer, writer)
    parser.void_subroutines()
    parser.methods_()
    parser.compile_class()
    writer.close()
 def __init__(self, input_path, output_path):
     self.class_name = ''
     self.subroutine_name = ''
     self.if_counter = -1
     self.while_counter = -1
     self.subroutine_num_arg = 0
     self.tkx = JackTokenizer(input_path)
     self.class_table = symbolTable()
     self.subroutine_table = symbolTable()
     self.vm_writer = VMWriter(output_path)
     self.compile_class(output_path)
 def __init__(self, input_stream, output_stream):
     """
     Creates a new compilation engine with the
     given input and output. The next routine
     called must be compileClass().
     """
     self.__prefix = ""
     self.__tokenizer = JackTokenizer(input_stream)
     self.__writer = VMWriter(output_stream)
     self.__symbol_table = SymbolTable()
     self.__label_counter = 0
     self.__class_name = None
 def __init__(self, inFile):
     self.t = Tokenizer(inFile)
     self.symTable = SymbolTable()
     self.vmName = inFile.rstrip('.jack') + '.vm'
     self.vm = VMWriter(self.vmName)
     self.className = ''
     self.types = ['int', 'char', 'boolean', 'void']
     self.stmnt = ['do', 'let', 'if', 'while', 'return']
     self.subroutType = ''
     self.whileIndex = 0
     self.ifIndex = 0
     self.fieldNum = 0
 def __init__(self, inputFile, outputFile, outputFile2):
     # Syntax tokenizer modules
     self.inF = open(inputFile, 'r')
     self.opF = open(outputFile, 'w')
     self.Jt = []
     self.JtIndex = 1
     # Compilation module
     self.vmWr = VMWriter(outputFile2)
     self.symTab = SymbolTable()
     # parse the result of the tokenizer into a list
     for line in self.inF:
         self.Jt.append(line)
     self.compileProgram()
Exemple #29
0
 def __init__(self, source):
     self.if_counter = 0
     self.while_counter = 0
     self.tokenizer = Tokenizer(source)
     self.tokenizer.has_more_tokens()
     self.tokenizer.advance()
     self.symbols = SymbolTable()
     self.writer = VMWriter(source)
     self.arithmetic_op = {}
     self.init_op()
     self.root = Element(CLASS)
     self.class_name = ""
     self.compile_class(self.root)
     self.writer.close()
Exemple #30
0
    def compileFiles(self):
        """Compile each file in the given directory using all modules and generate code."""
        verbose = self.parse_arg(sys.argv)

        for filename in self.filenames:
            vm_writer = VMWriter(filename)
            tokenizer = Tokenizer(filename)
            symbol_table = SymbolTable()
            tokenizer.tokenize()
            engine = CompilationEngine(tokens=tokenizer,
                                       vm_writer=vm_writer,
                                       symbol_table=symbol_table,
                                       verbose=verbose)
            engine.compileClass()
            vm_writer.close()
Exemple #31
0
 def __init__(self, tokenizer, out_file_name):
     """
     Constructor
     """
     self._tokenizer = tokenizer
     self._vm_writer = VMWriter(out_file_name)
     self._class_name = None
     self._symbol_table = SymbolTable()
     self._counter = 0
     self._subroutine_name = None
 def __init__(self, inFile, outFile):
     """Creates a new compilation engine with the given input and output.
     The next routine called must be compileClass()"""
     self.tokenizer = JackTokenizer(inFile)
     self.targetFile = open(outFile, 'w')
     self.getNext()
     self.classTable = None
     self.className = ''
     self.writer = VMWriter(outFile)
     self.labelWhile = 1
     self.labelIf = 1
 def __init__(self, input_file, output_file):
     self.jack_tokenizer = JackTokenizer(input_file)
     self.symbol_table = SymbolTable()
     self.writer = VMWriter(output_file)
     self.class_name = ""
     self.subroutine_name = ""
     self.return_type = ""
     self.label_counter_if = 0
     self.label_counter_while = 0
     self.num_args_called_function = 0
     self.is_unary = False
     self.dic_arithmetic = {"+" : "add" , "-" : "sub", "*" : "call Math.multiply 2",
                            "/" : "call Math.divide 2", "&" : "and", "|" : "or", "<" : "lt", ">" : "gt", "=" : "eq"}
class CompilationEngine(object):
	def __init__(self, src, output):
		self.tokenizer = JackTokenizer(src)
		self.writer = VMWriter(output)
		self.symbolTable = SymbolTable()
		self.labelIndex = 0

	def _acceptNextToken(self, token):
		if self.tokenizer.hasMoreToken():
			self.tokenizer.advance()
			typ = self.tokenizer.tokenType()
			tok = self.tokenizer.tokenValue()
			if type(token) != list:
				token = [token]
			if typ in token or tok in token:
				return tok
		raise SyntaxError('Parse Error')

	def _tryNextToken(self, token):
		if self.tokenizer.hasMoreToken():
			typ, tok = self.tokenizer.next()
			if type(token) != list:
				token = [token]
			if typ in token or tok in token:
				return True
		return False

	def compileClass(self):
		#'class' className '{' classVarDec* subroutineDec* '}'
		self._acceptNextToken('class')
		self.classname = self._acceptNextToken('identifier')
		self._acceptNextToken('{')

		while self._tryNextToken(['static', 'field']):
			self.compileClassVarDec()
		while self._tryNextToken(['constructor', 'function', 'method']):
			self.compileSubroutine()
		self._acceptNextToken('}')

		self.writer.close()

	def compileClassVarDec(self):
		#('static'|'field') type varName (','varName)* ';'
		kind = self._acceptNextToken(['static', 'field'])
		type = self._acceptNextToken(['int', 'char', 'boolean', 'identifier'])
		self.symbolTable.define(self._acceptNextToken('identifier'), type, kind)

		while self._tryNextToken(','):
			self._acceptNextToken(',')
			self.symbolTable.define(self._acceptNextToken('identifier'), type, kind)
		self._acceptNextToken(';')

	def compileSubroutine(self):
		#('constructor'|'function'|'method')
		#('void'|type)subroutineName'('parameterList')'
		#subroutineBody
		self.labelIndex = 0

		self.symbolTable.startSubroutine()
		subroutine = self._acceptNextToken(['constructor', 'function', 'method'])
		self._acceptNextToken(['void', 'int', 'char', 'boolean', 'identifier'])
		functionname = self._acceptNextToken('identifier')

		if subroutine == 'method':
			self.symbolTable.define('this', self.classname, 'argument')

		self._acceptNextToken('(')
		self.compileParameterList()
		self._acceptNextToken(')')
		self._acceptNextToken('{')

		argc = 0
		while self._tryNextToken('var'):
			argc += self.compileVarDec()
		self.writer.writeFunction(self.classname + '.' + functionname, argc)

		if subroutine == 'constructor':
			self.writer.writePush('constant', self.symbolTable.varCount('field'))
			self.writer.writeCall('Memory.alloc', 1)
			self.writer.writePop('pointer', 0)
		elif subroutine == 'method':
			self.writer.writePush('argument', 0)
			self.writer.writePop('pointer', 0)
		while self._tryNextToken(STATEMENT):
			self.compileStatements()
		self._acceptNextToken('}')

	def compileParameterList(self):
		#((type varName)(','type varName)*)?
		if self._tryNextToken(TYPE):
			type = self._acceptNextToken(TYPE)
			self.symbolTable.define(self._acceptNextToken('identifier'), type, 'argument')
			while self._tryNextToken(','):
				self._acceptNextToken(',')
				type = self._acceptNextToken(TYPE)
				self.symbolTable.define(self._acceptNextToken('identifier'), type, 'argument')

	def compileVarDec(self):
		#'var' type varName (',' varName)*';'
		argc = 1
		self._acceptNextToken('var')
		type = self._acceptNextToken(TYPE)
		self.symbolTable.define(self._acceptNextToken('identifier'), type, 'local')

		while self._tryNextToken(','):
			self._acceptNextToken(',')
			argc += 1
			self.symbolTable.define(self._acceptNextToken('identifier'), type, 'local')
		self._acceptNextToken(';')
		return argc

	def compileStatements(self):
		#statement*
		#letStatement|ifStatement|whileStatement|doStatement|returnStatement
		while self._tryNextToken(STATEMENT):
			if self._tryNextToken('let'):
				self.compileLet()
			elif self._tryNextToken('if'):
				self.compileIf()
			elif self._tryNextToken('while'):
				self.compileWhile()
			elif self._tryNextToken('do'):
				self.compileDo()
			elif self._tryNextToken('return'):
				self.compileReturn()

	def compileDo(self):
		#'do' subroutineCall ';'
		#subroutineName '(' expressionList ')' | (className | varName) '.' subroutineName '(' expressionList ')'
		self._acceptNextToken('do')
		funcname = self._acceptNextToken('identifier')

		argc = 0
		if self._tryNextToken('.'):
			self._acceptNextToken('.')
			type = self.symbolTable.typeOf(funcname)
			if type != None:
				argc += 1
				self.writer.writePush(self.symbolTable.kindOf(funcname), self.symbolTable.indexOf(funcname))
				funcname = type + '.' + self._acceptNextToken('identifier')				#game.run()
			else:
				funcname = funcname + '.' + self._acceptNextToken('identifier')			#Game.run()
		else:
			argc += 1
			funcname = self.classname + '.' + funcname 										#run()
			self.writer.writePush('pointer', 0)
	
		self._acceptNextToken('(')
		argc += self.compileExpressionList()
		self._acceptNextToken(')')
		self._acceptNextToken(';')

		self.writer.writeCall(funcname, argc)
		self.writer.writePop('temp', 0)

	def compileLet(self):
		#'let' varName ('[' expression ']')? '=' expression ';'
		self._acceptNextToken('let')
		varName = self._acceptNextToken('identifier')
		if self._tryNextToken('['):
			self.writer.writePush(self.symbolTable.kindOf(varName), self.symbolTable.indexOf(varName))
			self._acceptNextToken('[')
			self.compileExpression()
			self._acceptNextToken(']')
			self.writer.writeArithmetic('add')
			self._acceptNextToken('=')
			self.compileExpression()
			self._acceptNextToken(';')
			self.writer.writePop('temp', 0)
			self.writer.writePop('pointer', 1)
			self.writer.writePush('temp', 0)
			self.writer.writePop('that', 0)
		else:
			self._acceptNextToken('=')
			self.compileExpression()
			self._acceptNextToken(';')
			self.writer.writePop(self.symbolTable.kindOf(varName), self.symbolTable.indexOf(varName))

	def compileWhile(self):
		#'while' '(' expression ')''{' statements '}'
		index = str(self.labelIndex)
		self.labelIndex += 1

		self.writer.writeLabel('WHILE' + index)
		self._acceptNextToken('while')
		self._acceptNextToken('(')
		self.compileExpression()
		self._acceptNextToken(')')
		self.writer.writeArithmetic('not')

		self.writer.writeIf('WHILE_END' + index)
		self._acceptNextToken('{')
		self.compileStatements()
		self._acceptNextToken('}')
		self.writer.writeGoto('WHILE' + index)
		self.writer.writeLabel('WHILE_END' + index)

	def compileReturn(self):
		#'return' expression? ';'
		self._acceptNextToken('return')

		if self._tryNextToken(';'):
			self._acceptNextToken(';')
			self.writer.writePush('constant', 0)
		else:
			self.compileExpression()
			self._acceptNextToken(';')
		self.writer.writeReturn()

	def compileIf(self):
		#'if' '(' expression ')' '{' statements '}'
		#('else' '{' statements '}')?
		index = str(self.labelIndex);
		self.labelIndex += 1

		self._acceptNextToken('if')
		self._acceptNextToken('(')
		self.compileExpression()
		self._acceptNextToken(')')
		self.writer.writeArithmetic('not')
		self.writer.writeIf('IF_TRUE' + index)

		self._acceptNextToken('{')
		self.compileStatements()
		self._acceptNextToken('}')
		self.writer.writeGoto('IF_FALSE' + index)
		self.writer.writeLabel('IF_TRUE' + index)

		if self._tryNextToken('else'):
			self._acceptNextToken('else')
			self._acceptNextToken('{')
			self.compileStatements()
			self._acceptNextToken('}')
		self.writer.writeLabel('IF_FALSE' + index)

	def compileExpression(self):
		#term(op term)*
		self.compileTerm()
		while self._tryNextToken(OP):
			op = self._acceptNextToken(OP)
			self.compileTerm()
			if op == '*':
				self.writer.writeCall('Math.multiply', 2)
			elif op == '/':
				self.writer.writeCall('Math.divide', 2)
			else:
				self.writer.writeArithmetic(OP_COMMAND[op])

	def compileTerm(self):
		#integerConstant|stringConstant|keywordConstant|varName|
		
		if self._tryNextToken('('):										#'('expression')'
			self._acceptNextToken('(')
			self.compileExpression()
			self._acceptNextToken(')')
		elif self._tryNextToken(['-', '~']):							#unaryOp term
			unaryOp = self._acceptNextToken(['-', '~'])
			self.compileTerm()
			if unaryOp == '-':
				self.writer.writeArithmetic('neg')
			else:
				self.writer.writeArithmetic('not')
		else:
			first_s = self._acceptNextToken(TERM)
			if self._tryNextToken('['):									#varName'['expression']'
				self.writer.writePush(self.symbolTable.kindOf(first_s), self.symbolTable.indexOf(first_s))
				self._acceptNextToken('[')
				self.compileExpression()
				self._acceptNextToken(']')
				self.writer.writeArithmetic('add')
				self.writer.writePop('pointer', 1)
				self.writer.writePush('that', 0)
			elif self._tryNextToken('('):								#subroutineCall run()
				self.writer.writePush('pointer', 0)
				self._acceptNextToken('(')
				argc = self.compileExpressionList() + 1
				self._acceptNextToken(')')
				self.writer.writeCall(self.classname + '.' + first_s, argc)
			elif self._tryNextToken('.'):								#subroutineCall game.run()
				self._acceptNextToken('.')
				idenfitier = self._acceptNextToken('identifier')
				type = self.symbolTable.typeOf(first_s)
				argc = 0
				callname = first_s
				if type != None:
					argc += 1
					callname = type
					self.writer.writePush(self.symbolTable.kindOf(first_s), self.symbolTable.indexOf(first_s))
				self._acceptNextToken('(')
				argc += self.compileExpressionList()
				self._acceptNextToken(')')
				self.writer.writeCall(callname + '.' + idenfitier, argc)
			else:
				tokenType = self.tokenizer.tokenType()
				if tokenType == 'integerConstant':
					self.writer.writePush('constant', int(first_s))
				elif tokenType == 'stringConstant':
					self.writer.writePush('constant', len(first_s))
					self.writer.writeCall('String.new', 1)
					for c in first_s:
						self.writer.writePush('constant', ord(c))
						self.writer.writeCall('String.appendChar', 2)
				elif tokenType == 'identifier':
					self.writer.writePush(self.symbolTable.kindOf(first_s), self.symbolTable.indexOf(first_s))
				else:
					if first_s == 'null' or first_s == 'false':
						self.writer.writePush('constant', 0)
					elif first_s == 'true':
						self.writer.writePush('constant', 1)
						self.writer.writeArithmetic('neg')
					elif first_s == 'this':
						self.writer.writePush('pointer', 0)

	def compileExpressionList(self):
		#(expression(','expression)*))?
		argc = 0
		if self._tryNextToken(TERM):
			self.compileExpression()
			argc += 1
			while self._tryNextToken(','):
				self._acceptNextToken(',')
				self.compileExpression()
				argc += 1
		return argc
class CompilationEngine:

    def __init__(self, inputFile, outputFile):
        self.tokenizer = JackTokenizer(inputFile)
        self.vmWriter = VMWriter(outputFile)
        self.symbolTable = SymbolTable()
        self.classname = ""
        self.CompileClass()
        self.whilecounter = 0
        self.ifcounter = 0

    def CompileClass(self):
        #classname
        self.tokenizer.advance()
        self.classname = self.tokenizer.identifier()
        self.tokenizer.advance()
        # ignore {
        self.tokenizer.advance()

        while self.tokenizer.keyWord() == "static" or self.tokenizer.keyWord() == "field":
            self.CompileClassVarDec()

        while self.tokenizer.keyWord() == "constructor" or self.tokenizer.keyWord() == "function" or self.tokenizer.keyWord() == "method":
            self.CompileSubroutine()

        #ignore }
        self.tokenizer.advance()



    def CompileClassVarDec(self):

        kind = self.tokenizer.keyWord()
        self.tokenizer.advance()
        type = self.compileType()
        name = self.tokenizer.identifier()
        self.symbolTable.define(name, type, kind)
        self.tokenizer.advance()

        # add the rest of var names, if there are
        while self.tokenizer.symbol() == ",":
            self.tokenizer.advance()
            name = self.tokenizer.identifier()
            self.symbolTable.define(name, type, kind)
            self.tokenizer.advance()

        # ignore ;
        self.tokenizer.advance()

    def CompileSubroutine(self):

        self.symbolTable.startSubroutine()
        self.ifcounter = 0
        self.whilecounter = 0
        # constructor | function | method
        functype = self.tokenizer.keyWord()
        self.tokenizer.advance()

        if functype == "method":
            self.symbolTable.define("this", self.classname, "arg")

        self.tokenizer.advance()

        subrotineName = self.classname + "." + self.tokenizer.identifier()
        self.tokenizer.advance()

        # ( parameterList )
        self.tokenizer.advance()
        self.compileParameterList()
        self.tokenizer.advance()

        # subrotineBody
        # ignore {
        self.tokenizer.advance()
        # varDec*
        while self.tokenizer.keyWord() == "var":
            self.compileVarDec()

        self.vmWriter.writeFunction(subrotineName, self.symbolTable.varCount("var"))
        # allocate memory for constructor
        # if functype == "constructor":
        #     self.vmWriter.writePush("constant" , self.symbolTable.varCount("field"))
        #     self.vmWriter.writeCall("Memory.alloc", "1")

        if functype == "constructor" or functype == "method":
            if functype == "constructor":
                self.vmWriter.writePush("constant" , self.symbolTable.varCount("field"))
                self.vmWriter.writeCall("Memory.alloc", "1")
            else:
                self.vmWriter.writePush("argument", "0")
            self.vmWriter.writePop("pointer", "0")


        # statements
        self.compileStatements()

        # ignore }
        self.tokenizer.advance()

    def compileParameterList(self):
        # if not )
        if self.tokenizer.tokenType() != 1:

            # type varName
            argtype = self.compileType()
            argname = self.tokenizer.identifier()
            self.symbolTable.define(argname, argtype, "arg")
            self.tokenizer.advance()

            # (, type varName)*
            while self.tokenizer.symbol() == ",":
                self.tokenizer.advance()
                argtype = self.compileType()
                argname = self.tokenizer.identifier()
                self.symbolTable.define(argname, argtype, "arg")
                self.tokenizer.advance()

    def compileVarDec(self):

        # var
        self.tokenizer.advance()

        # type
        type = self.compileType()

        # varName
        varname = self.tokenizer.identifier()
        self.symbolTable.define(varname, type, "var")
        self.tokenizer.advance()

        # (, varName)*
        while self.tokenizer.symbol() == ",":
            self.tokenizer.advance()
            varname = self.tokenizer.identifier()
            self.symbolTable.define(varname, type, "var")

            self.tokenizer.advance()

        # ignore ;
        self.tokenizer.advance()


    def compileStatements(self):

        while self.tokenizer.tokenType() == 0:
            if self.tokenizer.keyWord() == "let":
                self.compileLet()
            elif self.tokenizer.keyWord() == "if":
                self.compileIf()
            elif self.tokenizer.keyWord() == "while":
                self.compileWhile()
            elif self.tokenizer.keyWord() == "do":
                self.compileDo()
            elif self.tokenizer.keyWord() == "return":
                self.compileReturn()


    def compileDo(self):

        self.tokenizer.advance()
        self.compileSubRoutineCall()
        self.vmWriter.writePop("temp", "0")

        # ignore ;
        self.tokenizer.advance()

    def compileLet(self):

        # let
        self.tokenizer.advance()
        # varName
        varname = self.tokenizer.identifier()
        varkind = self.symbolTable.kindOf(varname)

        self.tokenizer.advance()

        # ([ expression ])?
        if self.tokenizer.symbol() == "[":
            self.tokenizer.advance()
            self.CompileExpression()
            if varkind == "field":
                self.vmWriter.writePush("this", self.symbolTable.indexOf(varname))
            elif varkind == "var":
                self.vmWriter.writePush("local", self.symbolTable.indexOf(varname))
            elif varkind == "arg":
                self.vmWriter.writePush("argument", self.symbolTable.indexOf(varname))
            elif varkind == "static":
                self.vmWriter.writePush("static", self.symbolTable.indexOf(varname))
            self.vmWriter.writeArithmetic("add")

            #ignore ]
            self.tokenizer.advance()
            #ignore =
            self.tokenizer.advance()
            self.CompileExpression()
            self.vmWriter.writePop("temp", "0")

            # that
            self.vmWriter.writePop("pointer", "1")
            self.vmWriter.writePush("temp", "0")
            self.vmWriter.writePop("that", "0")
            self.tokenizer.advance()


        else:

            # ignore =
            self.tokenizer.advance()

            # expression
            self.CompileExpression()

            if varkind == "field":
                self.vmWriter.writePop("this", self.symbolTable.indexOf(varname))
            elif varkind == "var":
                self.vmWriter.writePop("local", self.symbolTable.indexOf(varname))
            elif varkind == "arg":
                self.vmWriter.writePop("argument", self.symbolTable.indexOf(varname))
            elif varkind == "static":
                self.vmWriter.writePop("static", self.symbolTable.indexOf(varname))

            #ignore ;
            self.tokenizer.advance()


    def compileWhile(self):

        # while
        self.tokenizer.advance()

        # ( expression )
        self.tokenizer.advance()
        whileindex = self.whilecounter
        self.whilecounter += 1
        self.vmWriter.writeLabel("WHILE_EXP" + str(whileindex))
        self.CompileExpression()
        self.vmWriter.writeArithmetic("not")
        self.vmWriter.writeIf("WHILE_END" + str(whileindex))
        self.tokenizer.advance()

        # ignore {
        self.tokenizer.advance()

        # statements
        self.compileStatements()

        # ignore }
        self.tokenizer.advance()
        self.vmWriter.writeGoto("WHILE_EXP" + str(whileindex))
        self.vmWriter.writeLabel("WHILE_END" + str(whileindex))

    def compileReturn(self):

        # return
        self.tokenizer.advance()

        # expression?
        if self.isTerm():
            self.CompileExpression()
            self.vmWriter.writeReturn()
        else:
            self.vmWriter.writePush("constant", "0")
            self.vmWriter.writeReturn()

        # ignore;
        self.tokenizer.advance()


    def compileIf(self):
        #if
        self.tokenizer.advance()
        # ( expression )
        self.tokenizer.advance()
        self.CompileExpression()
        ifindex = self.ifcounter
        self.ifcounter += 1
        self.vmWriter.writeIf("IF_TRUE" + str(ifindex))
        self.vmWriter.writeGoto("IF_FALSE" + str(ifindex))
        self.vmWriter.writeLabel("IF_TRUE" + str(ifindex))
        self.tokenizer.advance()

        # { statements }
        self.tokenizer.advance()
        self.compileStatements()
        self.tokenizer.advance()

        if self.tokenizer.tokenType() == 0 and self.tokenizer.keyWord() == "else":
            # else
            self.vmWriter.writeGoto("IF_END" + str(ifindex))
            self.vmWriter.writeLabel("IF_FALSE" + str(ifindex))

            self.tokenizer.advance()

            # { statements }
            self.tokenizer.advance()
            self.compileStatements()
            self.tokenizer.advance()

            self.vmWriter.writeLabel("IF_END" + str(ifindex))

        else:
            self.vmWriter.writeLabel("IF_FALSE" + str(ifindex))


    def CompileExpression(self):
        #term
        self.CompileTerm()
        # (op term)*
        op = self.tokenizer.symbol()
        while self.tokenizer.tokenType() == 1 and op in operators:
            self.tokenizer.advance()
            self.CompileTerm()
            if op == "=":
                self.vmWriter.writeArithmetic("eq")
            elif op == "+":
                self.vmWriter.writeArithmetic("add")
            elif op == "-":
                self.vmWriter.writeArithmetic("sub")
            elif op == "*":
                self.vmWriter.writeCall("Math.multiply", "2")
            elif op == "/":
                self.vmWriter.writeCall("Math.divide", "2")
            elif op == "&amp;":
                self.vmWriter.writeArithmetic("and")
            elif op == "|":
                self.vmWriter.writeArithmetic("or")
            elif op == "&lt;":
                self.vmWriter.writeArithmetic("lt")
            elif op == "&gt;":
                self.vmWriter.writeArithmetic("gt")
            op = self.tokenizer.symbol()

    def CompileTerm(self):
        if self.tokenizer.tokenType() == 3:
            self.vmWriter.writePush("constant", self.tokenizer.intVal())
            self.tokenizer.advance()

        elif self.tokenizer.tokenType() == 4:
            conststring = self.tokenizer.stringVal()
            self.vmWriter.writePush("constant", str(len(conststring)))
            self.vmWriter.writeCall("String.new", "1")
            for i in range(len(conststring)):
                self.vmWriter.writePush("constant", str(ord(conststring[i])))
                self.vmWriter.writeCall("String.appendChar", "2")

            self.tokenizer.advance()

        elif self.tokenizer.tokenType() == 0:
            keywordconst = self.tokenizer.keyWord()
            if keywordconst == "true":
                self.vmWriter.writePush("constant", "0")
                self.vmWriter.writeArithmetic("not")
            elif keywordconst == "false" or keywordconst == "null":
                self.vmWriter.writePush("constant", "0")
            elif keywordconst == "this":
                self.vmWriter.writePush("pointer", "0")
            self.tokenizer.advance()

        elif self.tokenizer.tokenType() == 2:
            # varName [ expression]
            if self.tokenizer.tokens[self.tokenizer.currentToken +1] == '[':
                varname = self.tokenizer.identifier()
                varkind = self.symbolTable.kindOf(varname)
                self.tokenizer.advance()
                # [ expression ]
                self.tokenizer.advance()
                self.CompileExpression()
                if varkind == "field":
                    self.vmWriter.writePush("this", self.symbolTable.indexOf(varname))
                elif varkind == "var":
                    self.vmWriter.writePush("local", self.symbolTable.indexOf(varname))
                elif varkind == "arg":
                    self.vmWriter.writePush("argument", self.symbolTable.indexOf(varname))
                elif varkind == "static":
                    self.vmWriter.writePush("static", self.symbolTable.indexOf(varname))
                self.vmWriter.writeArithmetic("add")
                # that
                self.vmWriter.writePop("pointer", "1")
                self.vmWriter.writePush("that", "0")
                self.tokenizer.advance()
            # subrutine call
            elif self.tokenizer.tokens[self.tokenizer.currentToken +1] == '(' or self.tokenizer.tokens[self.tokenizer.currentToken +1] == '.':
                self.compileSubRoutineCall()
            # varname
            else:
                varname = self.tokenizer.identifier()
                varkind = self.symbolTable.kindOf(varname)
                if varkind == "field":
                    self.vmWriter.writePush("this", self.symbolTable.indexOf(varname))
                elif varkind == "var":
                    self.vmWriter.writePush("local", self.symbolTable.indexOf(varname))
                elif varkind == "arg":
                    self.vmWriter.writePush("argument", self.symbolTable.indexOf(varname))
                elif varkind == "static":
                    self.vmWriter.writePush("static", self.symbolTable.indexOf(varname))
                self.tokenizer.advance()

        elif self.tokenizer.tokenType() == 1 and self.tokenizer.symbol() == '(':
            # ( expression )
            self.tokenizer.advance()
            self.CompileExpression()
            self.tokenizer.advance()
        else:
            #unary!!!
            op = self.tokenizer.symbol()
            self.tokenizer.advance()
            self.CompileTerm()
            if op == "-":
                self.vmWriter.writeArithmetic("neg")
            elif op == "~":
                self.vmWriter.writeArithmetic("not")

    def compileSubRoutineCall(self):
        # subroutineName  | (className | varName)
        identifier = self.tokenizer.identifier()
        self.tokenizer.advance()
        #no "." only name
        if self.tokenizer.symbol() == '(':
            # ( expressionList ) -- subroutine of type method
            self.tokenizer.advance()
            self.vmWriter.writePush("pointer", "0")
            argnum = self.CompileExpressionList()
            self.vmWriter.writeCall(self.classname + "." + identifier, str(argnum +1))

            self.tokenizer.advance()
        else:
            # . -- class.function or var.method
            self.tokenizer.advance()
            # subroutineName
            subname = self.tokenizer.identifier()
            self.tokenizer.advance()

            self.tokenizer.advance()
            if identifier in self.symbolTable.classtable or identifier in self.symbolTable.subroutinetable:
                # varname!!!
                if identifier in self.symbolTable.subroutinetable:
                    if self.symbolTable.kindOf(identifier) == "var":
                        self.vmWriter.writePush("local", self.symbolTable.indexOf(identifier))
                    else:
                        self.vmWriter.writePush("argument", self.symbolTable.indexOf(identifier))
                else:
                    if self.symbolTable.kindOf(identifier) == "static":
                        self.vmWriter.writePush("static", self.symbolTable.indexOf(identifier))
                    else:
                        self.vmWriter.writePush("this", self.symbolTable.indexOf(identifier))


                argnum = self.CompileExpressionList()
                identifierclass = self.symbolTable.typeOf(identifier)
                self.vmWriter.writeCall(identifierclass + "." + subname, str(argnum +1))
            else:
                argnum = self.CompileExpressionList()
                self.vmWriter.writeCall(identifier + "." + subname, str(argnum))
            self.tokenizer.advance()

    def CompileExpressionList(self):
        # (expression
        i = 0
        if self.isTerm():
            i += 1
            # (, expression)
            self.CompileExpression()
            while self.tokenizer.symbol() == ',':
                i+= 1
                self.tokenizer.advance()
                self.CompileExpression()
        return i

    def isTerm(self):
        if self.tokenizer.tokenType() == 3 or self.tokenizer.tokenType() == 4:
            return True
        if self.tokenizer.tokenType() == 0 and self.tokenizer.keyWord() in keyword_const:
            return True
        if self.tokenizer.tokenType() == 1 and self.tokenizer.symbol() == '(' :
            return True
        if self.tokenizer.tokenType() == 1 and (self.tokenizer.symbol() == '-' or self.tokenizer.symbol() == '~'):
            return True
        if self.tokenizer.tokenType() == 2:
            return True
        return False

    def compileType(self):
        if self.tokenizer.tokenType() == 0:
            typen = self.tokenizer.keyWord()
        else:
            typen = self.tokenizer.identifier()
        self.tokenizer.advance()
        return typen
	def __init__(self, src, output):
		self.tokenizer = JackTokenizer(src)
		self.writer = VMWriter(output)
		self.symbolTable = SymbolTable()
		self.labelIndex = 0
Exemple #37
0
class CompliationEngine(object):
    """
    Effects the actual compilation output. Gets its input from a
    JackTokenizer and emits its parsed structure into an output file/stream
    """

    MAP = {"<": "&lt;", ">": "&gt;", '"': "&quot;", "&": "&amp;"}

    def __init__(self, tokenizer, out_file_name):
        """
        Constructor
        """
        self._tokenizer = tokenizer
        self._vm_writer = VMWriter(out_file_name)
        self._class_name = None
        self._symbol_table = SymbolTable()
        self._counter = 0
        self._subroutine_name = None

    def Compile(self):
        token = str(self._tokenizer.next_token())
        if token == "class":
            self.CompileClass(token)

    def CompileClass(self, token):
        """
        takes 'class' as token
        and end the compilation
        """
        self._class_name = self._tokenizer.next_token()  # got the class name
        str(self._tokenizer.next_token())  # '{'
        token = self._tokenizer.next_token()  # field declarations

        # For declaring Class Level Variable

        while token in ["field", "static"]:
            token = self.CompileClassVarDec(token)

        # Class Methods
        while token in ["function", "method", "constructor"]:
            token = self.CompileSubroutine(token)

        self._vm_writer.writer_close()
        self._symbol_table.printSymbolTables()

    def CompileSubroutine(self, token):
        """
        Takes any among 'function', 'method', 'constructor'
        and return token after end of subroutine '}' 
        or simple next subroutine token
        """
        function_modifier = token

        str(self._tokenizer.next_token())  # return type
        function_name = str(self._tokenizer.next_token())  # name of function

        self._subroutine_name = function_name

        self._symbol_table.startSubRoutine(function_name)
        if function_modifier == "method":
            self._symbol_table.define(["this", self._class_name, "argument"])

        str(self._tokenizer.next_token())  # '('

        token = str(self._tokenizer.next_token())  # 'arguments'

        while token != ")":
            token = self.CompileParamList(token)

        str(self._tokenizer.next_token())  # '{'
        token = str(self._tokenizer.next_token())  # Statements or '}'

        while token == "var":
            token = self.CompileVarDec(token)

        local_variables = self._symbol_table.varCount("local")

        # Writing Function VM
        self._vm_writer.write_subroutine(self._class_name, function_name, local_variables)
        if function_name == "new":
            no_of_fields = self._symbol_table.varCount("field")
            self._vm_writer.write_push("constant", no_of_fields)
            self._vm_writer.write_call("Memory", "alloc", 1)
            self._vm_writer.write_pop("pointer", 0)
        if function_modifier == "method":
            self._vm_writer.write_push("argument", 0)
            self._vm_writer.write_pop("pointer", 0)
        """temp_buffer = ""
        while local_variables > 0:
            temp_buffer += 'push constant 0\n'
            local_variables -= 1
        
        self._out_file_object.write(temp_buffer)
        self._out_file_object.flush()"""

        while token != "}":
            token = self.CompileStatements(token)

        token = str(self._tokenizer.next_token())  # next subroutine
        return token

    def CompileStatements(self, token):
        if token == "return":
            return self.CompileReturn(token)
        if token == "do":
            return self.CompileDo(token)
        if token == "let":
            return self.CompileLet(token)
        if token == "while":
            return self.CompileWhile(token)
        if token == "if":
            return self.CompileIf(token)

    def CompileIf(self, token):
        """
        Takes 'if' keyword and returns next statement token
        """
        self._counter += 1  # for linear label names
        str(self._tokenizer.next_token())  # '('

        token = str(self._tokenizer.next_token())
        token = self.CompileExpression(token)  # returns ')'

        self._vm_writer.write_arithmatic("~")
        label = self._class_name + "." + "if." + str(self._counter) + ".L1"
        self._vm_writer.write_if_goto(label)

        str(self._tokenizer.next_token())  # '}'
        token = str(self._tokenizer.next_token())

        goto_label = self._class_name + "." + "if." + str(self._counter) + ".L2"

        while token != "}":
            token = self.CompileStatements(token)

        self._vm_writer.write_goto(goto_label)
        self._vm_writer.write_label(label)

        # optional else Command
        token = str(self._tokenizer.next_token())
        if token == "else":
            token = self.CompileElse(token)

        self._vm_writer.write_label(goto_label)

        return token

    def CompileElse(self, token):
        """
        Takes 'else' token and return next statement token
        """

        str(self._tokenizer.next_token())  # '{'

        token = str(self._tokenizer.next_token())
        while token != "}":
            token = self.CompileStatements(token)

        token = str(self._tokenizer.next_token())
        return token

    def CompileWhile(self, token):
        """
        Takes 'while' token and returns next statement token
        """
        self._counter += 1  # for linear label names

        label = self._class_name + "." + "while." + str(self._counter) + ".L1"
        self._vm_writer.write_label(label)

        str(self._tokenizer.next_token())  # '('

        token = str(self._tokenizer.next_token())
        token = self.CompileExpression(token)  # 'returns ')'

        self._vm_writer.write_arithmatic("~")  # ~cond

        if_label = self._class_name + "." + "while." + str(self._counter) + ".L2"
        self._vm_writer.write_if_goto(if_label)

        str(self._tokenizer.next_token())  # '{'

        token = str(self._tokenizer.next_token())
        while token != "}":
            token = self.CompileStatements(token)

        self._vm_writer.write_goto(label)  # 'goto label'
        self._vm_writer.write_label(if_label)  # label for next statement

        token = str(self._tokenizer.next_token())
        return token

    def CompileDo(self, token):
        identifier = str(self._tokenizer.next_token())  # identifer or class name

        token = str(self._tokenizer.next_token())
        class_name = identifier
        no_of_arguments = 0
        if token == ".":
            method_or_function = str(self._tokenizer.next_token())
            str(self._tokenizer.next_token())  # '('
            id_type = self._symbol_table.typeOf(identifier)

        else:
            class_name = self._class_name
            method_or_function = identifier
            no_of_arguments += 1
            self._vm_writer.write_push("pointer", "0")
            id_type = None

        token = str(self._tokenizer.next_token())

        if id_type != None:
            segment = self._symbol_table.kindOf(identifier)
            index = self._symbol_table.indexOf(identifier)
            self._vm_writer.write_push(segment, index)
            no_of_arguments += 1
            class_name = id_type

        no_arguments = 0
        if token != ")":
            token, no_arguments = self.CompilerExpressionList(token)  # return value is ')'

        no_of_arguments += no_arguments

        self._vm_writer.write_call(class_name, method_or_function, no_of_arguments)
        str(self._tokenizer.next_token())  # ';'

        # 'void functions will return constant 0 which should be discarded'
        self._vm_writer.write_pop("temp", "0")
        token = str(self._tokenizer.next_token())
        return token

    def CompileLet(self, token):
        """
        Function receiver 'let' and return ';'
        """
        identifier = str(self._tokenizer.next_token())  # left hand side identifier
        segment = self._symbol_table.kindOf(identifier)
        index = str(self._symbol_table.indexOf(identifier))

        token = str(self._tokenizer.next_token())  # = or [
        if_array = False
        if token == "[":
            if_array = True
            token = str(self._tokenizer.next_token())
            token = self.CompileExpression(token)  # ']'
            self._vm_writer.write_push(segment, index)
            self._vm_writer.write_arithmatic("+")

            # Equal Expression
            token = str(self._tokenizer.next_token())

        # Right Hand Side Expression
        token = str(self._tokenizer.next_token())
        token = self.CompileExpression(token)

        # End Statements
        if if_array:
            self._vm_writer.write_pop("temp", 0)
            self._vm_writer.write_pop("pointer", 1)
            self._vm_writer.write_push("temp", 0)
            self._vm_writer.write_pop("that", 0)
        else:
            self._vm_writer.write_pop(segment, index)

        token = str(self._tokenizer.next_token())
        return token

    def CompileReturn(self, token):
        """
        Takes 'return' token
        if simple return pushes dummy constant and returns 0
        """
        token = str(self._tokenizer.next_token())  # ';'?
        if token == ";":
            self._vm_writer.write_push("constant", "0")
        else:
            token = self.CompileExpression(token)  # ';'

        self._vm_writer.write_return()
        return str(self._tokenizer.next_token())

    def CompilerExpressionList(self, token):
        no_of_argument = 1
        token = self.CompileExpression(token)  # returns ','

        while token == ",":
            no_of_argument += 1
            token = str(self._tokenizer.next_token())
            token = self.CompileExpression(token)
        return token, no_of_argument

    def CompileExpression(self, token):
        """
        Expression 
        """
        token = self.CompileTerm(token)

        if token in Lexical.OP:
            operator = token
            token = str(self._tokenizer.next_token())  # Next term
            token = self.CompileTerm(token)
            self._vm_writer.write_arithmatic(operator)
        return token

    def CompileTerm(self, token):
        """
        Takes the term token and returns the token after the term
        """
        if token.isdigit():
            self._vm_writer.write_push("constant", token)
        elif token[0] == '"':
            no_of_character = len(token) - 2  # removing "
            self._vm_writer.write_push("constant", no_of_character)
            self._vm_writer.write_call("String", "new", 1)
            for idx in range(1, len(token) - 1):
                self._vm_writer.write_push("constant", ord(token[idx]))
                self._vm_writer.write_call("String", "appendChar", 2)
        elif token == "true":
            self._vm_writer.write_push("constant", "1")
            self._vm_writer.write_arithmatic("-", "NEG")
        elif token in ["false", "null"]:
            self._vm_writer.write_push("constant", "0")
        elif token == "this":
            self._vm_writer.write_push("pointer", "0")
        elif token == "-":
            return self.CompileNegOperator(token)
        elif token == "~":
            return self.CompileNotOperator(token)
        elif token == "(":
            token = str(self._tokenizer.next_token())  # Term token
            token = self.CompileExpression(token)  # Returns ')'
        elif self._tokenizer.expected_token() == "[":

            identifier = token
            index = self._symbol_table.indexOf(identifier)
            segment = self._symbol_table.kindOf(identifier)
            self._vm_writer.write_push(segment, index)

            str(self._tokenizer.next_token())  # '['

            token = str(self._tokenizer.next_token())
            token = self.CompileExpression(token)  # return value is ']'

            self._vm_writer.write_arithmatic("+")
            self._vm_writer.write_pop("pointer", "1")
            self._vm_writer.write_push("that", "0")

        elif self._tokenizer.expected_token() == ".":
            identifier = token
            str(self._tokenizer.next_token())  # '.'
            method_or_function = str(self._tokenizer.next_token())

            str(self._tokenizer.next_token())  # '('

            token = str(self._tokenizer.next_token())
            no_of_arguments = 0

            class_name = identifier
            id_type = self._symbol_table.typeOf(identifier)
            print identifier, id_type
            if id_type != None:
                segment = self._symbol_table.kindOf(identifier)
                index = self._symbol_table.indexOf(identifier)
                self._vm_writer.write_push(segment, index)
                no_of_arguments += 1
                class_name = id_type

            no_arguments = 0
            if token != ")":
                token, no_arguments = self.CompilerExpressionList(token)

            no_of_arguments += no_arguments
            self._vm_writer.write_call(class_name, method_or_function, no_of_arguments)
        else:
            identifier = token
            index = self._symbol_table.indexOf(identifier)
            segment = self._symbol_table.kindOf(identifier)
            self._vm_writer.write_push(segment, index)

        token = str(self._tokenizer.next_token())
        return token

    def CompileNegOperator(self, token):
        token = str(self._tokenizer.next_token())
        token = self.CompileTerm(token)
        self._vm_writer.write_arithmatic("-", "NEG")
        return token

    def CompileNotOperator(self, token):
        """
        Takes '~' as argument as return ')'
        """
        token = str(self._tokenizer.next_token())  # '('?
        if token != "(":
            token = self.CompileTerm(token)
        else:
            token = str(self._tokenizer.next_token())  #
            token = self.CompileExpression(token)  # returns inner ')' res
            token = str(self._tokenizer.next_token())  # outer ')'

        self._vm_writer.write_arithmatic("~")
        return token

    def CompileParamList(self, token):
        """
        Takes type of the first argument of the 
        subroutine
        """
        id_type = token  # type of var variable
        kind = "argument"
        identifier = str(self._tokenizer.next_token())  # identifier name
        identifier_details = [identifier, id_type, kind]
        self._symbol_table.define(identifier_details)

        token = str(self._tokenizer.next_token())
        if token == ",":
            token = str(self._tokenizer.next_token())
            return self.CompileParamList(token)
        return token

    def CompileVarDec(self, token):
        """
        Takes either of 'field' or 'static' as token
        return next statement either 'var' or do, let, if, while 
        """
        id_type = str(self._tokenizer.next_token())  # type of var variable
        kind = "local"
        identifier = str(self._tokenizer.next_token())  # identifier name
        identifier_details = [identifier, id_type, kind]
        self._symbol_table.define(identifier_details)
        token = str(self._tokenizer.next_token())  # ',' or ';

        while token == ",":
            identifier_details = []
            identifier = str(self._tokenizer.next_token())  # identifier name
            identifier_details = [identifier, id_type, kind]
            self._symbol_table.define(identifier_details)
            token = str(self._tokenizer.next_token())  # ',' or ';

        return str(self._tokenizer.next_token())

    def CompileClassVarDec(self, token):
        class_var_modifer = str(token)  # 'field' or 'static'

        # primitive or user defined class
        class_var_type = str(self._tokenizer.next_token())
        identifier = str(self._tokenizer.next_token())

        identifier_details = [identifier, class_var_type, class_var_modifer]
        self._symbol_table.define(identifier_details)

        token = self._tokenizer.next_token()

        while token == ",":
            identifier = str(self._tokenizer.next_token())
            identifier_details = [identifier, class_var_type, class_var_modifer]
            self._symbol_table.define(identifier_details)
            token = str(self._tokenizer.next_token())

        token = self._tokenizer.next_token()

        if token in ["field", "static"]:
            return self.CompileClassVarDec(token)

        return token
class CompilationEngine:

    def __init__(self, input_file, output_file):
        self.jack_tokenizer = JackTokenizer(input_file)
        self.symbol_table = SymbolTable()
        self.writer = VMWriter(output_file)
        self.class_name = ""
        self.subroutine_name = ""
        self.return_type = ""
        self.label_counter_if = 0
        self.label_counter_while = 0
        self.num_args_called_function = 0
        self.is_unary = False
        self.dic_arithmetic = {"+" : "add" , "-" : "sub", "*" : "call Math.multiply 2",
                               "/" : "call Math.divide 2", "&" : "and", "|" : "or", "<" : "lt", ">" : "gt", "=" : "eq"}

    def compile_class(self):
        # "class className {
        for i in range(NUM_TOKENS_CLASS_DEC):
            self.jack_tokenizer.has_more_tokens()
            self.jack_tokenizer.advance()
            # saves the className
            if self.jack_tokenizer.token_type() == IDENTIFIER:
                self.class_name = self.jack_tokenizer.identifier()
        # classVarDec* or SubroutineDec*
        while self.jack_tokenizer.has_more_tokens():
            self.jack_tokenizer.advance()
            token_type = self.jack_tokenizer.token_type()
            if token_type == KEYWORD and (self.jack_tokenizer.key_word() == "static" or
                                                  self.jack_tokenizer.key_word() == "field"):
                self.compile_class_var_dec()
            if token_type == KEYWORD and (self.jack_tokenizer.key_word() == "function" or
                                                  self.jack_tokenizer.key_word() == "method" or
                                                  self.jack_tokenizer.key_word() == "constructor"):
                self.compile_subroutine()
            if token_type == SYMBOL and self.jack_tokenizer.symbol() == "}":
                break

    def compile_class_var_dec(self):
        # "static" of "field"
        kind = self.jack_tokenizer.key_word()
        self.jack_tokenizer.has_more_tokens()
        self.jack_tokenizer.advance()
        # type
        if self.jack_tokenizer.token_type() == KEYWORD:
            type = self.jack_tokenizer.key_word()
        else:
            type = self.jack_tokenizer.identifier()
        while self.jack_tokenizer.has_more_tokens():
            self.jack_tokenizer.advance()
            token_type = self.jack_tokenizer.token_type()
            if token_type == IDENTIFIER:
                name = self.jack_tokenizer.identifier()
                self.symbol_table.define(name,type,kind)
            elif token_type == SYMBOL:
                if self.jack_tokenizer.symbol() == ";":
                    break


    def compile_subroutine(self):
        self.symbol_table.start_subroutine()
        self.subroutine_name = ""
        self.return_type = ""
        self.label_counter_if = 0
        self.label_counter_while = 0
        #  the curr token : "constructor" or "function" or "method
        type_of_subroutine = self.jack_tokenizer.key_word()
        self.jack_tokenizer.has_more_tokens()
        self.jack_tokenizer.advance()
        # the curr token : return type of the subroutine
        if self.jack_tokenizer.token_type() == KEYWORD:
            self.return_type = self.jack_tokenizer.key_word()
        else:
            self.return_type = self.jack_tokenizer.identifier()
        self.jack_tokenizer.has_more_tokens()
        self.jack_tokenizer.advance()
        self.subroutine_name = self.jack_tokenizer.identifier()
        while self.jack_tokenizer.has_more_tokens():
            self.jack_tokenizer.advance()
            if self.jack_tokenizer.symbol() == "(":
                if type_of_subroutine == "method":
                    self.symbol_table.define(THIS, self.class_name, ARG)
                self.compile_parameter_list()
                # the curr token should be -  ")"
            if self.jack_tokenizer.symbol() == '{':
                while self.jack_tokenizer.has_more_tokens():
                    self.jack_tokenizer.advance()
                    token_type = self.jack_tokenizer.token_type()
                    if token_type == KEYWORD:
                        if self.jack_tokenizer.key_word() == "var":
                            self.compile_var_dec()
                            continue
                        else:
                            self.writer.write_function(self.class_name +
                                                       "." + self.subroutine_name, self.symbol_table.var_count(VAR))
                            if type_of_subroutine == "constructor":
                                self.writer.write_push(CONST, self.symbol_table.var_count(FIELD))
                                self.writer.write_call("Memory.alloc", 1)
                                self.writer.write_pop("pointer", 0)
                            elif type_of_subroutine == "method":
                                self.writer.write_push(ARGUMENT, 0)
                                self.writer.write_pop("pointer", 0)
                            self.compile_statements()
                            # the curr token should be -  "}"
                            break
                break


    def compile_parameter_list(self):
        kind = ARG
        while self.jack_tokenizer.has_more_tokens():
            self.jack_tokenizer.advance()
            token_type = self.jack_tokenizer.token_type()
            # int, bool....
            if token_type == KEYWORD:
                type = self.jack_tokenizer.key_word()
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
                name = self.jack_tokenizer.identifier()
                self.symbol_table.define(name, type, kind)
            # className
            elif token_type == IDENTIFIER:
                type = self.jack_tokenizer.identifier()
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
                name = self.jack_tokenizer.identifier()
                self.symbol_table.define(name, type, kind)
            # end of parameter list
            if token_type == SYMBOL and self.jack_tokenizer.symbol() == ")":
                    break


    def compile_var_dec(self):
        # should be "var"
        kind = self.jack_tokenizer.key_word()
        self.jack_tokenizer.has_more_tokens()
        self.jack_tokenizer.advance()
        # type
        if self.jack_tokenizer.token_type() == KEYWORD:
            type = self.jack_tokenizer.key_word()
        else:
            type = self.jack_tokenizer.identifier()
        while self.jack_tokenizer.has_more_tokens():
            self.jack_tokenizer.advance()
            token_type = self.jack_tokenizer.token_type()
            if token_type == IDENTIFIER:
                name = self.jack_tokenizer.identifier()
                self.symbol_table.define(name, type, kind)
            if token_type == SYMBOL:
                if self.jack_tokenizer.symbol() == ";":
                    break


    def compile_statements(self):
        while True:
            if self.jack_tokenizer.token_type() == KEYWORD and self.jack_tokenizer.key_word() == "do":
                self.compile_do()
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
            if self.jack_tokenizer.token_type() == KEYWORD and self.jack_tokenizer.key_word() == "let":
                self.compile_let()
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
            if self.jack_tokenizer.token_type() == KEYWORD and self.jack_tokenizer.key_word() == "while":
                self.compile_while()
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
            if self.jack_tokenizer.token_type() == KEYWORD and self.jack_tokenizer.key_word() == "return":
                self.compile_return()
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
            # compile_if returns advanced
            if self.jack_tokenizer.token_type() == KEYWORD and self.jack_tokenizer.key_word() == "if":
                self.compile_if()
            if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == "}":
                break


    def compile_do(self):
        self.num_args_called_function = 0
        self.compile_subroutine_call()
        self.writer.write_pop(TEMP , 0)
        self.jack_tokenizer.has_more_tokens()
        self.jack_tokenizer.advance()
        # return from compile_subroutine_call with ";"

    def compile_let(self):
        init = True
         # the curr token - "let"
        while self.jack_tokenizer.has_more_tokens():
            self.jack_tokenizer.advance()
            token_type = self.jack_tokenizer.token_type()
            if token_type == IDENTIFIER:
                name = self.jack_tokenizer.identifier()
                type = self.symbol_table.type_of(name)
                kind = self.symbol_table.kind_of(name)
                index = self.symbol_table.index_of(name)
            if token_type == SYMBOL:
                # there is an assignment to an array
                if self.jack_tokenizer.symbol() == "[":
                    self.jack_tokenizer.has_more_tokens()
                    self.jack_tokenizer.advance()
                    #  handle  - [expression]
                    self.compile_expression()
                    # the curr token -  "]"
                    self.writer.write_push(self.find_segment(kind), index)
                    self.writer.write_arithmetic("add")
                    self.writer.write_pop("pointer", 1)
                    init = False
                # should return from the compile_expression only with ";" or "]"
                if self.jack_tokenizer.symbol() == "=":
                    self.jack_tokenizer.has_more_tokens()
                    self.jack_tokenizer.advance()
                    # handle the = expression
                    self.compile_expression()
                    # that is only for array
                    if init == False: # was also if type == "Array"
                        self.writer.write_pop(THAT, 0)
                    else:
                        self.writer.write_pop(self.find_segment(kind), index)
                # end of let statement
                if self.jack_tokenizer.symbol() == ";":
                    break


    def compile_while(self):
        while_counter = self.label_counter_while
        self.label_counter_while += 1
        # the curr token - "while"
        self.writer.write_label("WHILE_EXP" + str(while_counter))
        while self.jack_tokenizer.has_more_tokens():
            self.jack_tokenizer.advance()
            token_type = self.jack_tokenizer.token_type()
            if token_type == SYMBOL:
                if self.jack_tokenizer.symbol() == "(":
                    self.jack_tokenizer.has_more_tokens()
                    self.jack_tokenizer.advance()
                    self.compile_expression()
                    # the curr token - ")"
                    self.writer.write_arithmetic("not")
                    self.writer.write_if("WHILE_END" + str(while_counter))
                if self.jack_tokenizer.symbol() == "{":
                    self.jack_tokenizer.has_more_tokens()
                    self.jack_tokenizer.advance()
                    self.compile_statements()
                    # the curr token - "}"
                    self.writer.write_go_to("WHILE_EXP" + str(while_counter))
                    self.writer.write_label("WHILE_END" + str(while_counter))
                if token_type == SYMBOL and self.jack_tokenizer.symbol() == "}":
                    break


    def compile_return(self):
        # the curr token - "return"
        self.jack_tokenizer.has_more_tokens()
        self.jack_tokenizer.advance()
        if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == ";":
            self.writer.write_push(CONST, "0")
        else:
            self.compile_expression()
            # should return from "compile_expression" only with ";"
        self.writer.write_return()

    def compile_if(self):
        if_counter = self.label_counter_if
        self.label_counter_if += 1
        # the curr token - "if"
        while self.jack_tokenizer.has_more_tokens():
            self.jack_tokenizer.advance()
            token_type = self.jack_tokenizer.token_type()
            if token_type == SYMBOL:
                if self.jack_tokenizer.symbol() == "(":
                    self.jack_tokenizer.has_more_tokens()
                    self.jack_tokenizer.advance()
                    self.compile_expression()
                    # the curr token - ")"
                    self.writer.write_if("IF_TRUE" + str(if_counter))
                    self.writer.write_go_to("IF_FALSE" + str(if_counter))
                if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == "{":
                    self.writer.write_label("IF_TRUE" + str(if_counter))
                    self.jack_tokenizer.has_more_tokens()
                    self.jack_tokenizer.advance()
                    self.compile_statements()
                # ~~~~~~~~~~ change : was token_type ~~~~~~~~~~~~~~
                if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == "}":
                    break
        self.jack_tokenizer.has_more_tokens()
        self.jack_tokenizer.advance()
        if self.jack_tokenizer.token_type() == KEYWORD and self.jack_tokenizer.key_word() == "else":
            # print "else"
            self.writer.write_go_to("IF_END" + str(if_counter))
            self.writer.write_label("IF_FALSE" + str(if_counter))
            self.jack_tokenizer.has_more_tokens()
            self.jack_tokenizer.advance()
            # print "{"
            self.jack_tokenizer.has_more_tokens()
            self.jack_tokenizer.advance()
            self.compile_statements()
            # print "}"
            self.jack_tokenizer.has_more_tokens()
            self.jack_tokenizer.advance()
            self.writer.write_label("IF_END" + str(if_counter))
        else:
            self.writer.write_label("IF_FALSE" + str(if_counter))


    def compile_subroutine_call(self):
        to_add = False
        self.jack_tokenizer.has_more_tokens()
        self.jack_tokenizer.advance()
        # "subRoutineName" or ("className" | "varName", as part of className.subRoutineName)
        called_statement = self.jack_tokenizer.identifier()
        type = self.symbol_table.type_of(called_statement)
        kind = self.symbol_table.kind_of(called_statement)
        index = self.symbol_table.index_of(called_statement)


        self.jack_tokenizer.has_more_tokens()
        self.jack_tokenizer.advance()
        # case of "subRoutineCall(expressionList)
        if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == "(":
            to_add = True
            called_statement = self.class_name + "." + called_statement
            self.writer.write_push(POINTER, 0)
            self.compile_expression_list()
            # the curr token - ")"
        # (className | varName).subroutineName(expressionList)
        elif self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == ".":
            self.jack_tokenizer.has_more_tokens()
            self.jack_tokenizer.advance()
            # subroutineName
            if kind <> NONE:
                to_add = True
                self.writer.write_push(self.find_segment(kind), index)
                called_statement = type + "." + self.jack_tokenizer.identifier()
            else:
               called_statement = called_statement + "." + self.jack_tokenizer.identifier()
            self.jack_tokenizer.has_more_tokens()
            self.jack_tokenizer.advance()
            # "("
            # expressionList
            self.compile_expression_list()
            # ")"
        if to_add:
            self.writer.write_call(called_statement, self.num_args_called_function + 1)
        else:
            self.writer.write_call(called_statement, self.num_args_called_function)

    def compile_expression(self):
        is_print_unary = False
        if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == "-":
            self.is_unary = True
        self.compile_term()
        while self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() in\
                ["+", "-", "*", "/", "&", "|", "<", ">", "="]:
            arit_symbol = self.jack_tokenizer.symbol()
            self.jack_tokenizer.has_more_tokens()
            self.jack_tokenizer.advance()
            if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == "-":
                self.is_unary = True
                is_print_unary = True
            self.compile_term()
            # if not is_print_unary and
            self.writer.write_arithmetic(self.dic_arithmetic[arit_symbol])


    def compile_term(self):
        while True:
            token_type = self.jack_tokenizer.token_type()
            if token_type == SYMBOL and not self.is_unary and self.jack_tokenizer.symbol() in\
                    [",", ";", ")", "}","]", "+", "-", "*", "/", "&", "|", "<", ">", "="]:
                break
            if token_type == INT_CONST:
                self.writer.write_push(CONST, self.jack_tokenizer.int_val())
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
                break
            if token_type == STRING_CONST:
                self.compile_string()
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
                break
            if token_type == KEYWORD and self.jack_tokenizer.key_word() in ["true", "false", "null"]:
                self.writer.write_push(CONST, 0)
                if self.jack_tokenizer.key_word() == "true":
                    self.writer.write_arithmetic("not")
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
                break
            # like in return this
            if token_type == KEYWORD and self.jack_tokenizer.key_word() == "this":
                self.writer.write_push(POINTER, 0)
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
                break
            if token_type == SYMBOL and self.jack_tokenizer.symbol() in ["~", "-"]:
                symbol = self.jack_tokenizer.symbol()
                self.is_unary = False
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
                self.compile_term()
                if symbol == "~":
                    self.writer.write_arithmetic("not")
                else:
                    self.writer.write_arithmetic("neg")
                break
            if token_type == SYMBOL and self.jack_tokenizer.symbol() == "(":
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
                self.compile_expression()
                # should return from compile_expression only with ")"
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
                break
            if token_type == IDENTIFIER:
                is_add = True
                name = self.jack_tokenizer.identifier()
                kind = self.symbol_table.kind_of(name)
                index = self.symbol_table.index_of(name)
                if name[0].isupper():
                    is_add = False
                self.jack_tokenizer.has_more_tokens()
                self.jack_tokenizer.advance()
                if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() in\
                        [",", ";", ")", "}","]", "+", "-", "*", "/", "&", "|", "<", ">", "=", "&amp;", "&lt;","&gt;"]:
                    # in case of a > ...or b;
                    self.writer.write_push(self.find_segment(kind), self.symbol_table.index_of(name))
                    break
                if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == "[":
                    self.jack_tokenizer.has_more_tokens()
                    self.jack_tokenizer.advance()
                    self.compile_expression()
                    # should return only "]"
                    self.writer.write_push(self.find_segment(kind), self.symbol_table.index_of(name))
                    self.writer.write_arithmetic("add")
                    self.writer.write_pop(POINTER, 1)
                    self.writer.write_push(THAT, 0)
                    self.jack_tokenizer.has_more_tokens()
                    self.jack_tokenizer.advance()
                    break
                if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == "(":
                    self.writer.write_push(POINTER, 0)
                    self.compile_expression_list()
                    self.jack_tokenizer.has_more_tokens()
                    self.jack_tokenizer.advance()
                    # case of a = ... bar()
                    self.writer.write_call(self.class_name + "." + name,self.num_args_called_function + 1)
                    break
                # (className | varName).subroutineName(expressionList)
                if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == ".":
                    self.jack_tokenizer.has_more_tokens()
                    self.jack_tokenizer.advance()
                    # subroutineName
                    if is_add:
                        type = self.symbol_table.type_of(name)
                        name = type + "." + self.jack_tokenizer.identifier()
                    else:
                        name = name + "." + self.jack_tokenizer.identifier()
                    self.jack_tokenizer.has_more_tokens()
                    self.jack_tokenizer.advance()
                    # "("
                    # expressionList
                    if is_add:
                        self.writer.write_push(self.find_segment(kind), index)
                    self.compile_expression_list()
                    # ")"
                    if is_add:
                        self.writer.write_call(name, self.num_args_called_function + 1)
                    else:
                        self.writer.write_call(name, self.num_args_called_function)
            self.jack_tokenizer.has_more_tokens()
            self.jack_tokenizer.advance()

    def compile_expression_list(self):
        num_args = 0
        while self.jack_tokenizer.has_more_tokens():
            self.jack_tokenizer.advance()
            if self.jack_tokenizer.token_type() == SYMBOL and self.jack_tokenizer.symbol() == ")":
                break
            else:
                num_args += 1
                self.compile_expression()
                if self.jack_tokenizer.symbol() == ")":
                    break
                # print ","
        self.num_args_called_function = num_args

    def find_segment(self, kind):
        if kind == ARG:
            return ARGUMENT
        if kind == VAR:
            return LCL
        if kind == FIELD:
            return THIS
        if kind == STATIC:
            return STATIC

    def compile_string(self):
        length = len(self.jack_tokenizer.string_val())
        self.writer.write_push(CONST, length)
        self.writer.write_call("String.new", 1)
        for i in range(len(self.jack_tokenizer.string_val())):
            uni = ord(self.jack_tokenizer.string_val()[i])
            self.writer.write_push(CONST, uni)
            self.writer.write_call("String.appendChar", 2)
class CompilationEngine:
    """Recursive top-down parser"""

    def __init__(self, inFile, outFile):
        """Creates a new compilation engine with the given input and output.
        The next routine called must be compileClass()"""
        self.tokenizer = JackTokenizer(inFile)
        self.targetFile = open(outFile, 'w')
        self.getNext()
        self.classTable = None
        self.className = ''
        self.writer = VMWriter(outFile)
        self.labelWhile = 1
        self.labelIf = 1

    def getNext(self):
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()

    def compileClass(self):
        """Compiles a complete class"""
        self.classTable = SymbolTable()
        # 'class' className '{' classVarDec* subroutineDec* '}'
        # class
        self.getNext()
        # className
        self.className = self.tokenizer.getToken()
        self.getNext()
        # {
        self.getNext()

        token = self.tokenizer.getToken()
        while token in ["static", "field"]:
            self.compileDec()
            token = self.tokenizer.getToken()

        token = self.tokenizer.getToken()
        while token in ["constructor", "function", "method"]:
            self.compileSubroutine()
            token = self.tokenizer.getToken()
        # }
        self.getNext()


    def compileSubroutine(self):
        """Compiles a complete method, function, or constructor."""
        # subroutine dec
        self.classTable.startSubroutine()
        # ('constructor' | 'function' | 'method') ('void' | type) subroutineName '(' parameterList ')' subroutineBody
        # ('constructor' | 'function' | 'method')
        subroutineType = self.tokenizer.getToken()
        self.getNext()
        # ('void' | type)
        self.getNext()

        # subroutineName
        name = self.tokenizer.getToken()
        self.getNext()
        # (
        self.getNext()
        # parameterList
        self.compileParameterList(subroutineType == 'method')
        # )
        self.getNext()

        # subroutine body
        # '{' varDec* statements '}'
        # {
        self.getNext()

        # varDec*
        while self.tokenizer.getToken() == 'var':
            self.compileDec()
        numOfVars = self.classTable.varCount(Toolbox.VAR)

        if subroutineType == 'function':
            self.writer.writeFunction(self.className + "." + name, numOfVars)
        elif subroutineType == 'constructor':
            self.writer.writeFunction(self.className + "." + name, numOfVars)
            # push constant (num of fields)
            # call Memory.alloc 1
            # pop pointer 0
            fields = self.classTable.varCount(Toolbox.FIELD)
            self.writer.writePush(Toolbox.CONST, fields)
            self.writer.writeCall('Memory.alloc', 1)
            self.writer.writePop(Toolbox.POINTER, 0)
        else:  # method
            self.writer.writeFunction(self.className + "." + name, numOfVars)
            # push argument 0
            # pop pointer 0
            self.writer.writePush(Toolbox.SEG_ARG, 0)
            self.writer.writePop(Toolbox.POINTER, 0)

        # statements
        self.compileStatements()
        # }
        self.getNext()

    def compileParameterList(self, method=False):
        """Compiles a (possibly empty) parameter list,
        not including the enclosing "()"."""
        tokenType, name = '', ''

        if method:  # Add this to method's var list.
            self.classTable.define(None, None, Toolbox.ARG)

        if self.tokenizer.tokenType() != self.tokenizer.SYMBOL:  # param list not empty
            while True:
                tokenType = self.tokenizer.getToken()
                self.getNext()

                name = self.tokenizer.getToken()
                self.classTable.define(name, tokenType, Toolbox.ARG)
                self.getNext()

                if self.tokenizer.getToken() == ')':
                    break

                self.getNext()  # ','

    def compileStatements(self):  # (letStatement | ifStatement | whileStatement | doStatement | returnStatement)*
        """Compiles a sequence of statements,
        not including the enclosing "{}"."""
        token = self.tokenizer.getToken()
        while token in ["let", "if", "while", "do", "return"]:
            if token == 'let':
                self.compileLet()
            elif token == 'if':
                self.compileIf()
            elif token == 'while':
                self.compileWhile()
            elif token == 'do':
                self.compileDo()
            elif token == 'return':
                self.compileReturn()
            token = self.tokenizer.getToken()

    def compileSubroutineCall(self, name, printIdentifier=True):
     # subroutineName '(' expressionList ') ' | ( className | varName) '.' subroutineName '(' expressionList ') '

        var = None
        nArgs = 0
        if printIdentifier:
            # subroutineName | ( className | varName)
            self.getNext()

        var = self.classTable.searchScope(name)

        if self.tokenizer.getToken() == '.':
            if var:
                # push <this>
                self.writer.writePush(var[0], var[1])
                nArgs += 1
                className = var[2]  # Use the type instead of the variable name
            else:
                className = name
            self.getNext()
            subroutineName = self.tokenizer.getToken()
            self.getNext()
        else:
            # push <this>
            self.writer.writePush(Toolbox.POINTER, 0)
            nArgs += 1
            className = self.className
            subroutineName = name

        name = className + '.' + subroutineName
        # '('
        self.getNext()
        nArgs += self.compileExpressionList()

        self.writer.writeCall(name, nArgs)
        # ')'
        self.getNext()

    def compileDo(self):  # 'do' subroutineCall ';'
        """Compiles a do statement"""
        # do
        self.getNext()
        # subroutineCall
        self.compileSubroutineCall(self.tokenizer.getToken())
        self.writer.writePop(Toolbox.TEMP, 0)
        # ;
        if self.tokenizer.getToken() == ';':
            self.getNext()

    def compileLet(self):  # 'let' varName ('[' expression ']')? '=' expression ';'
        """Compiles a let statement"""
        # let
        # self.targetFile.write(T_LET)
        self.getNext()
        # var name
        name = self.tokenizer.getToken()
        # search scope
        segment, index, type = self.classTable.searchScope(name)

        self.getNext()
        # [
        array = False
        if self.tokenizer.getToken() == '[':
            array = True
            self.writer.writePush(segment, index)
            self.getNext()
            # expression
            self.compileExpression()
            # ]
            self.getNext()
            self.writer.writeArithmetic('add')
        # =
        self.getNext()
        # expression
        self.compileExpression()

        if array:
            self.writer.writePop(Toolbox.TEMP, 0)
            self.writer.writePop(Toolbox.TEMP, 1)
            self.writer.writePush(Toolbox.TEMP, 0)
            self.writer.writePush(Toolbox.TEMP, 1)

            self.writer.writePop(Toolbox.POINTER, 1)
            self.writer.writePop(Toolbox.THAT, 0)
        else:
            self.writer.writePop(segment, index)

        # ;
        token = self.tokenizer.getToken()
        if token == ';':
            self.getNext()

    def compileWhile(self):  # while' '(' expression ')' '{' statements '}'
        """Compiles a while statement"""
        # while
        label = str(self.labelWhile)
        self.labelWhile += 1
        self.writer.writeLabel('while' + label)
        self.getNext()
        # (
        self.getNext()
        # expression
        self.compileExpression()
        # )
        self.getNext()
        self.writer.writeArithmetic('not')
        self.writer.writeIf('endwhile' + label)
        # {
        self.getNext()
        # statements
        self.compileStatements()
        # }
        self.getNext()
        self.writer.writeGoto('while' + label)
        self.writer.writeLabel('endwhile' + label)

    def compileReturn(self):  # 'return' expression? ';'
        """Compiles a return statement"""
        # return
        self.getNext()
        # expression
        if not (self.tokenizer.getToken() == ";"):
            self.compileExpression()
        else:
            self.writer.writePush(Toolbox.CONST, 0)
        self.writer.writeReturn()
        # ;
        self.getNext()

    def compileIf(self):  # 'if' '(' expression ')' '{' statements '}' ( 'else' '{' statements '}' )?
        """Compiles an if statement, possibly with a trailing else clause"""
        # if
        label = 'if' + str(self.labelIf)
        self.labelIf += 1

        self.getNext()
        # (
        self.getNext()
        # expression
        self.compileExpression()
        # )
        self.getNext()

        self.writer.writeArithmetic('not')
        self.writer.writeIf('else' + label)

        # {
        self.getNext()
        # statements
        self.compileStatements()
        # }
        self.getNext()

        self.writer.writeGoto('end' + label)
        self.writer.writeLabel('else' + label)

        # else
        if self.tokenizer.getToken() == 'else':
            self.getNext()
            # {
            self.getNext()
            # expression
            self.compileStatements()
            # }
            self.getNext()
        self.writer.writeLabel('end' + label)

    def compileExpression(self):
        """Compiles an expression"""
        # term (op term)*

        self.compileTerm()
        token = self.tokenizer.getToken()
        while token in ['+', '/', '-', '*', '&', '|', '>', '<', '=']:
            self.getNext()
            self.compileTerm()
            self.writer.writeArithmetic(token)

            token = self.tokenizer.getToken()


    def compileTerm(self):  #integerConstant | stringConstant | keywordConstant | varName | varName '[' expression']' |
                            # subroutineCall | '(' expression ')' | unaryOp term
        """Compiles a term"""

        token = self.tokenizer.getToken()
        tokenType = self.tokenizer.tokenType()

        if tokenType == self.tokenizer.INT_CONST:
            self.writer.writePush(Toolbox.CONST, token)
            self.getNext()
        elif tokenType == self.tokenizer.STRING_CONST:
            self.writer.writePush(Toolbox.CONST, len(token))
            self.writer.writeCall('String.new', 1)

            for c in token:
                self.writer.writePush(Toolbox.CONST, ord(c))
                self.writer.writeCall('String.appendChar', 2)

            self.getNext()
        elif tokenType == self.tokenizer.KEYWORD:  # true | false | null | this
            self.compileKeywordConstant(token)
        elif tokenType == self.tokenizer.IDENTIFIER:
            name = token
            self.getNext()
            token = self.tokenizer.getToken()
            if token == '[':
                self.compileVarName(name)
                self.getNext()
                self.compileExpression()
                self.getNext()
                self.writer.writeArithmetic('add')
                self.writer.writePop(Toolbox.POINTER, 1)
                self.writer.writePush(Toolbox.THAT, 0)
            elif token in ['(', '.']:
                self.compileSubroutineCall(name, False)
            else:
                self.compileVarName(name)

        elif token == '(':
            self.getNext()
            self.compileExpression()
            self.getNext()
        elif token in ['-', '~']:
            self.compileUnary(token)


    def compileExpressionList(self):
        """Compiles a (possibly empty) comma separated list of expressions"""
        nArgs = 0

        if self.tokenizer.getToken() != ')':
            self.compileExpression()
            nArgs += 1

            while self.tokenizer.getToken() == ',':
                self.getNext()
                self.compileExpression()
                nArgs += 1

        return nArgs

    def compileDec(self):  # 'var' type varName (',' varName)* ';'
        """Compiles a var declaration"""
        # keyword 'var'
        token = self.tokenizer.getToken()
        kind = None
        if token == 'var':
            kind = Toolbox.VAR
        elif token == 'field':
            kind = Toolbox.FIELD
        elif token == 'static':
            kind = Toolbox.STATIC
        self.getNext()
        tokenType = self.tokenizer.getToken()

        # type can be an identifier or a keyword
        self.getNext()

        # var name
        name = self.tokenizer.getToken()
        self.classTable.define(name, tokenType, kind)
        self.getNext()
        while self.tokenizer.tokenType() == self.tokenizer.SYMBOL and self.tokenizer.getToken() == ',':
            # ,
            self.getNext()
            name = self.tokenizer.getToken()
            self.classTable.define(name, tokenType, kind)
            # var name
            self.getNext()
        # ;
        self.getNext()

    def compileVarName(self, name):
        segment, index, type = self.classTable.searchScope(name)
        self.writer.writePush(segment, index)

    def compileKeywordConstant(self, keyword):
        if keyword == 'false' or keyword == 'null':
            self.writer.writePush(Toolbox.CONST, 0)
        if keyword == 'true':
            self.writer.writePush(Toolbox.CONST, 0)
            self.writer.writeArithmetic('not')
        if keyword == 'this':
            self.writer.writePush(Toolbox.POINTER, 0)
        self.getNext()

    def compileUnary(self, token):
        """
        Compiles an unary operator with its operand (term)
        :param token: unary token
        """
        self.getNext()  # '~' or '-'
        self.compileTerm()  # operand

        if token == '-':
            self.writer.writeArithmetic('neg')
        else:  # token is '~'
            self.writer.writeArithmetic('not')
class CompilationEngine:

    keywordConsts = ["null", "true", "false", "this"] 
    def __init__(self, tokenizer, outputFile, vmFile):
        from SymbolTable import SymbolTable
        from VMWriter import VMWriter
        self.tokenizer = tokenizer
        self.outputFile = outputFile
        self.symbolTable = SymbolTable()
        self.vmWriter = VMWriter(vmFile)
        self.labelNum = 0
        print(outputFile)
    
    def compileClass(self):
        from JackTokenizer import JackTokenizer
        self.indentLevel = 0
        NUM_OPENING_STATEMENTS = 3
        classVarOpenings = ['static', 'field']
        subOpenings = ['constructor', 'function', 'method']

        if self.tokenizer.currentToken != "class":
            raise Exception("Keyword 'class' expected")
        self.writeFormatted("<class>")
        self.indentLevel += 1
        self.printToken() #Should print 'class'
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #Should print class name
            self.className = self.tokenizer.identifier()
            self.writeClassOrSubInfo("class", False)

        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #Should print '{'
        
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
        
        self.fieldCount = 0
        while self.tokenizer.hasMoreTokens() and self.tokenizer.keyWord() in classVarOpenings:
            if self.tokenizer.keyWord() == "field":
                self.fieldCount += 1
            self.compileClassVarDec()
        while(self.tokenizer.hasMoreTokens() and self.tokenizer.tokenType == JackTokenizer.KEYWORD 
                and self.tokenizer.keyWord() in subOpenings):
            self.compileSubroutine()
        self.printToken()
        self.writeFormatted("</class>")
        self.indentLevel -= 1
    
    def compileClassVarDec(self):
        from JackTokenizer import JackTokenizer
        from SymbolTable import SymbolTable 
        self.writeFormatted("<classVarDec>")
        self.indentLevel += 1
        self.printToken() #Should print static or field
        if self.tokenizer.tokenType == JackTokenizer.KEYWORD:
            if self.tokenizer.keyWord() == "static":
                kind = SymbolTable.STATIC
            elif self.tokenizer.keyWord() == "field":
                kind = SymbolTable.FIELD
            else:
                raise Exception("Invalid kind of class variable " + self.tokenizer.keyWord())
        else:
            raise Exception("Keyword expected")
        
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #Should print the variable type
            identifierType = self.tokenizer.currentToken
            isKeyword = self.tokenizer.tokenType == JackTokenizer.KEYWORD

        if not isKeyword:
            self.writeClassOrSubInfo("class", True)

        varNames = []
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #Should print variable name
            varNames.append(self.tokenizer.currentToken)
            if self.tokenizer.hasMoreTokens(): 
                self.tokenizer.advance()

        while self.tokenizer.symbol() != ";" and self.tokenizer.hasMoreTokens():
            if self.tokenizer.symbol() != ",":
                raise Exception("Invalid variable list")
            self.printToken() #Should print ','
            self.tokenizer.advance()
            self.printToken() #Should print variable name
            varNames.append(self.tokenizer.currentToken)
            if kind == SymbolTable.FIELD:
                self.fieldCount += 1
            if not self.tokenizer.hasMoreTokens():
                raise Exception("More tokens expected")
            self.tokenizer.advance()
        self.printToken()
    

        for name in varNames:
            self.symbolTable.define(name, identifierType, kind)
            self.writeVarInfo(name, False)


        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
        self.indentLevel -= 1
        self.writeFormatted("</classVarDec>")

    def compileSubroutine(self):
        from JackTokenizer import JackTokenizer
        from SymbolTable import SymbolTable
        self.writeFormatted("<subroutineDec>")
        self.symbolTable.startSubroutine()
        self.indentLevel += 1
        NUM_OPENING_STATEMENTS = 4
        
        self.printToken() #Should print 'constructor', 'function', or 'method'
        self.isConstructor = False
        self.isMethod = False
        if self.tokenizer.keyWord() == "constructor":
            self.isConstructor = True
        elif self.tokenizer.keyWord() == "method":
            self.isMethod = True
            self.symbolTable.define("this", self.className, SymbolTable.ARG)

        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance() 
            self.printToken() #Should print the type or 'void'

        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance() 
            self.printToken() #Should print the subroutine name
            self.subName = self.tokenizer.identifier()

        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance() 
            self.printToken() #Should print opening '(' before parameter list

        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance() 
        self.compileParameterList()
        self.printToken() #Should print closing ")" after parameter list
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()

        self.numLocalVariables = 0
        self.compileSubroutineBody()
        self.indentLevel -= 1
        self.writeFormatted("</subroutineDec>")
    
    def compileSubroutineBody(self):
        from JackTokenizer import JackTokenizer
        from SymbolTable import SymbolTable
        from VMWriter import VMWriter
        self.writeFormatted("<subroutineBody>")
        self.indentLevel += 1
        self.printToken() #Should print "{"
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
        
        while(self.tokenizer.hasMoreTokens() and self.tokenizer.tokenType == JackTokenizer.KEYWORD
                and self.tokenizer.keyWord() == "var"):
            self.compileVarDec()
        
        self.vmWriter.writeFunction(self.className + "." + self.subName, self.numLocalVariables) 
        if self.isConstructor:
            self.vmWriter.writePush("constant", self.fieldCount)
            self.vmWriter.writeCall("Memory.alloc", 1) #allocate space for this object
            self.vmWriter.writePop("pointer", 0) #assign object to 'this'
        elif self.isMethod:
            self.vmWriter.writePush(SymbolTable.ARG, 0)
            self.vmWriter.writePop("pointer", VMWriter.THIS_POINTER)
            
        self.compileStatements()
        self.printToken() #Should print closing "}"
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
        self.indentLevel -= 1
        self.writeFormatted("</subroutineBody>")

    def compileParameterList(self):
        from JackTokenizer import JackTokenizer
        from SymbolTable import SymbolTable
        self.writeFormatted("<parameterList>")
        self.indentLevel += 1

        if self.tokenizer.currentToken != ")":
            self.printToken() #Should print the type
            argType = self.tokenizer.currentToken
            self.tokenizer.advance()
            self.printToken() #Should print the name
            argName = self.tokenizer.currentToken
            self.symbolTable.define(argName, argType, SymbolTable.ARG)
            self.writeVarInfo(argName, False)
            self.tokenizer.advance()


        while self.tokenizer.tokenType != JackTokenizer.SYMBOL or self.tokenizer.symbol() != ")":
            self.printToken() #Should print a comma
            if self.tokenizer.currentToken != ",":
                raise Exception("Comma expected")
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
                self.printToken() #Should print the argument type
                argType = self.tokenizer.currentToken
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
                self.printToken() #Should print the argument name
                argName = self.tokenizer.currentToken
                self.symbolTable.define(argName, argType, SymbolTable.ARG)
                self.writeVarInfo(argName, False)
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
            
        self.indentLevel -= 1
        self.writeFormatted("</parameterList>")

    def compileVarDec(self):
        from JackTokenizer import JackTokenizer
        from SymbolTable import SymbolTable
        self.numLocalVariables += 1
        self.writeFormatted("<varDec>")
        self.indentLevel += 1
        
        varNames = []
        self.printToken() #Should print 'var'
        if self.tokenizer.currentToken != "var":
            raise Exception("'var' keyword expected")
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #Should print the type
            varType = self.tokenizer.currentToken
            isKeyword = self.tokenizer.tokenType == JackTokenizer.KEYWORD

        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance() 
            self.printToken() #Should print the var name
            varNames.append(self.tokenizer.currentToken) 
        
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()

        while(self.tokenizer.hasMoreTokens() and 
                (self.tokenizer.tokenType != JackTokenizer.SYMBOL or self.tokenizer.symbol() != ";")):
            self.printToken() #Should print ','
            self.tokenizer.advance()
            self.printToken() #Should print the var name
            varNames.append(self.tokenizer.currentToken)
            self.tokenizer.advance()
            self.numLocalVariables += 1
        
        #If the type is not a keyword (e.g. int) that means it's a class and we should print identifier info
        if not isKeyword:
            self.writeClassOrSubInfo("class", "True")

        for name in varNames:
            self.symbolTable.define(name, varType, SymbolTable.VAR)
            self.writeVarInfo(name, False)

        self.printToken() #Should print ';'
        self.tokenizer.advance()
        self.indentLevel -= 1
        self.writeFormatted("</varDec>")

    def compileStatements(self):
        from JackTokenizer import JackTokenizer
        self.writeFormatted("<statements>")
        self.indentLevel += 1
        stmtStarts = ['do', 'while', 'let', 'if', 'return']
        while(self.tokenizer.hasMoreTokens() and self.tokenizer.tokenType == JackTokenizer.KEYWORD 
              and self.tokenizer.keyWord() in stmtStarts):
            if self.tokenizer.keyWord() == "do":
                self.compileDo()
            elif self.tokenizer.keyWord() == "while":
                self.compileWhile()
            elif self.tokenizer.keyWord() == "let":
                self.compileLet()
            elif self.tokenizer.keyWord() == "if":
                self.compileIf()
            elif self.tokenizer.keyWord() == "return":
                self.compileReturn()
        self.indentLevel -= 1
        self.writeFormatted("</statements>")

    def compileDo(self):
        from JackTokenizer import JackTokenizer
        self.writeFormatted("<doStatement>")
        self.indentLevel += 1
        if self.tokenizer.keyWord() != "do":
            raise Exception("'do' keyword expected")
        self.printToken()

        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.compileSubroutineCall()
            self.vmWriter.writePop("temp", 0) #This pops and ignores the returned value 

        self.printToken() #Print ';'
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
        self.indentLevel -= 1
        self.writeFormatted("</doStatement>")

    def compileLet(self):
        from SymbolTable import SymbolTable
        from VMWriter import VMWriter
        self.writeFormatted("<letStatement>")
        self.indentLevel += 1
        isArray = False
        if self.tokenizer.keyWord() != "let":
            raise Exception("Let keyword expected")
        self.printToken() #Should print "let"
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #Should print varname
            varName = self.tokenizer.identifier()
            self.writeVarInfo(self.tokenizer.identifier(), True)
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #Should print '[' or '='
            print("compileLet - [ or = " + self.tokenizer.currentToken)
        if self.tokenizer.currentToken == "[":
            isArray = True
            self.tokenizer.advance()

             
            if self.symbolTable.isDefined(varName):
                varKind = self.symbolTable.kindOf(varName)
                self.vmWriter.writePush(varKind, self.symbolTable.indexOf(varName))

                self.compileExpression()
                self.printToken() #Should print ']'
                self.vmWriter.writeArithmetic("add")
                segment = "that"
                index = 0

            else:
                raise Exception("Symbol " + varName + " is not defined")
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
                self.printToken() #Should print '='
        else:
            #If it goes down this path this is just a regular variable not an array
            varKind = self.symbolTable.kindOf(varName)
            segment = varKind
            index = self.symbolTable.indexOf(varName)

        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()


        print("compileLet - after equals " + self.tokenizer.currentToken)
        self.compileExpression()
        if isArray:
            self.vmWriter.writePop("temp", 0)
            self.vmWriter.writePop("pointer", VMWriter.THAT_POINTER)
            self.vmWriter.writePush("temp", 0)

        self.vmWriter.writePop(segment, index)
        self.printToken() #print ";"
        
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
        self.indentLevel -= 1
        self.writeFormatted("</letStatement>")

    def compileWhile(self):
        from JackTokenizer import JackTokenizer
        self.writeFormatted("<whileStatement>")
        self.indentLevel += 1

        self.labelNum += 1
        firstLabel = "W" + str(self.labelNum)
        self.labelNum += 1
        secondLabel = "W" + str(self.labelNum)

        if not(self.tokenizer.tokenType == JackTokenizer.KEYWORD and self.tokenizer.keyWord() == "while"):
            raise Exception("'while' keyword was expected")
        self.printToken() #print 'while'
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #print '('
            self.vmWriter.writeLabel(firstLabel)
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.compileExpression()
            self.vmWriter.writeArithmetic("not")
            self.vmWriter.writeIf(secondLabel)
            self.printToken() #print ')'
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #print '{'
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.compileStatements()
            self.vmWriter.writeGoto(firstLabel)
            self.printToken() #print '}'
            self.vmWriter.writeLabel(secondLabel)
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
        self.indentLevel -= 1
        self.writeFormatted("</whileStatement>")

    def compileReturn(self):
        from JackTokenizer import JackTokenizer
        self.writeFormatted("<returnStatement>")
        self.indentLevel += 1
        if self.tokenizer.keyWord() != "return":
            raise Exception("'return' keyword was expected")
        self.printToken() #print 'return' keyword
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
        if not(self.tokenizer.tokenType == JackTokenizer.SYMBOL and self.tokenizer.symbol() == ";"):
            self.compileExpression()
        else:
            #When the function's return type is void it should always return 0
            self.vmWriter.writePush("constant", 0)
        self.printToken() #print ";"
        self.vmWriter.writeReturn()
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
        self.indentLevel -= 1
        self.writeFormatted("</returnStatement>")

    def compileIf(self):
        from JackTokenizer import JackTokenizer
        self.writeFormatted("<ifStatement>")
        self.indentLevel += 1
        trueLabel = "IF-TRUE" + str(self.labelNum)
        falseLabel = "IF-FALSE" + str(self.labelNum)
        endLabel = "END-IF" + str(self.labelNum)
        self.labelNum += 1
        if self.tokenizer.keyWord() != "if":
            raise Exception("'if' keyword was expected")
        self.printToken() #print 'if'
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #print '('
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.compileExpression()
            self.printToken() #print ')'
            self.vmWriter.writeIf(trueLabel)
            self.vmWriter.writeGoto(falseLabel)
            self.vmWriter.writeLabel(trueLabel)
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #print '{'
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.compileStatements()
            self.printToken() #print '}'
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
        if self.tokenizer.tokenType == JackTokenizer.KEYWORD and self.tokenizer.keyWord() == "else":
            self.vmWriter.writeGoto(endLabel)
            self.vmWriter.writeLabel(falseLabel)
            self.printToken() #print 'else'
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
                self.printToken() #print '{'
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
                self.compileStatements()
            self.printToken() #print '}'
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
            self.vmWriter.writeLabel(endLabel)
        else:
            #In this case the if statement doesn't have an else so we 
            #don't need the end label
            self.vmWriter.writeLabel(falseLabel)
        self.indentLevel -= 1
        self.writeFormatted("</ifStatement>")

    def compileExpression(self):
        from JackTokenizer import JackTokenizer

        #There are 2 symbol arrays which each correspond to a different array with 
        #the commands/functions to call for the given operator in the same index
        functionSymbols = [ '*', '/']
        functionNames = ["Math.multiply", "Math.divide"]
        builtInCommands = ["add", "sub", "and", "or", "lt", "gt", "eq"]
        builtInSymbols = ['+', '-', '&amp;', '|', '&lt;', '&gt;', '=']
        self.writeFormatted("<expression>")
        self.indentLevel += 1
        print("About to call compile term current token is " + self.tokenizer.currentToken)
        self.compileTerm()
        while(self.tokenizer.tokenType == JackTokenizer.SYMBOL and 
                (self.tokenizer.symbol() in builtInSymbols or self.tokenizer.symbol() in functionSymbols)):
            self.printToken()
            operator = self.tokenizer.symbol() 
            print("Current operator " + self.tokenizer.currentToken)
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
                self.compileTerm()

            if operator in builtInSymbols:
                self.vmWriter.writeArithmetic(builtInCommands[builtInSymbols.index(operator)])
            else:
                #Both multiply and divide take two arguments
                self.vmWriter.writeCall(functionNames[functionSymbols.index(operator)], 2)

            
        self.indentLevel -= 1
        self.writeFormatted("</expression>")

    def compileTerm(self):
        from JackTokenizer import JackTokenizer
        from VMWriter import VMWriter
        print("Opening token is " + self.tokenizer.currentToken)
        unaryOps = ['-', '~']
        unaryCommands = ["neg", "not"]
        self.writeFormatted("<term>")
        self.indentLevel += 1
        self.printToken()
        if self.tokenizer.tokenType == JackTokenizer.IDENTIFIER:
            name = self.tokenizer.identifier()
            self.tokenizer.advance()
            print("second token in IDENTIFIER " + self.tokenizer.currentToken)
            if self.tokenizer.tokenType == JackTokenizer.SYMBOL:
                if self.tokenizer.symbol() == ".":
                    if self.symbolTable.isDefined(name):
                        self.writeVarInfo(name, True)
                    else:
                        self.writeClassOrSubInfo("class", True)

                    self.printToken() #Should print '.'
                    self.tokenizer.advance()
                    self.printToken() #Should print subroutine name
                    subName = self.tokenizer.identifier()

                    self.tokenizer.advance() 
                    self.printToken() #Should print '('

                    #If the subroutine is a method call we must first push the object before 
                    #pushing the rest of the arguments
                    if self.symbolTable.isDefined(name):
                        self.vmWriter.writePush(self.symbolTable.kindOf(name), self.symbolTable.indexOf(name))

                    self.numExpressions = 0
                    self.tokenizer.advance()
                    self.compileExpressionList()
                    self.printToken() #Should print ')'
                    
                    if self.symbolTable.isDefined(name):
                        #Must add 1 to the number of arguments since we pushed the object that the method is operating on
                        self.vmWriter.writeCall(self.symbolTable.typeOf(name) + "." + subName, self.numExpressions + 1)
                    else:
                        self.vmWriter.writeCall(name + "." + subName, self.numExpressions)

                    self.tokenizer.advance()
                elif self.tokenizer.symbol() == "(":
                    self.printToken()
                    self.writeClassOrSubInfo("subroutine", True)
                    if self.tokenizer.hasMoreTokens():
                        self.tokenizer.advance()

                        self.vmWriter.writePush("pointer", VMWriter.THIS_POINTER)
                        self.compileExpressionList()
                        self.numExpressions += 1

                        self.printToken() #Print ')'
                        self.vmWriter.writeCall(self.className +  "." + name, self.numExpressions)
                        if self.tokenizer.hasMoreTokens():
                            self.tokenizer.advance()
                elif self.tokenizer.symbol() == "[":
                    self.writeVarInfo(name, True)
                    self.printToken()

                    self.vmWriter.writePush(self.symbolTable.kindOf(name), self.symbolTable.indexOf(name))
                    if self.tokenizer.hasMoreTokens():
                        self.tokenizer.advance()
                        self.compileExpression()
                        self.printToken() #Should print ']'

                        self.vmWriter.writeArithmetic("add")
                        self.vmWriter.writePop("pointer", VMWriter.THAT_POINTER)
                        self.vmWriter.writePush("that", 0)
                        if self.tokenizer.hasMoreTokens():
                            self.tokenizer.advance()
                else:
                    self.vmWriter.writePush(self.symbolTable.kindOf(name), self.symbolTable.indexOf(name))
                    self.writeVarInfo(name, True)
        elif self.tokenizer.tokenType == JackTokenizer.SYMBOL and self.tokenizer.symbol() == "(":
            self.tokenizer.advance()
            print("second token in (expression)" + self.tokenizer.currentToken)
            self.compileExpression()
            self.printToken() #print ')'
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
        elif self.tokenizer.tokenType == JackTokenizer.SYMBOL and self.tokenizer.symbol() in unaryOps:
            op = self.tokenizer.symbol()
            self.tokenizer.advance()
            print("second token in unary " + self.tokenizer.currentToken)
            self.compileTerm()
            self.vmWriter.writeArithmetic(unaryCommands[unaryOps.index(op)])
        elif self.tokenizer.tokenType == JackTokenizer.INT_CONST:
            self.vmWriter.writePush("constant", self.tokenizer.intVal())
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
        elif self.tokenizer.currentToken in CompilationEngine.keywordConsts:
            if self.tokenizer.keyWord() == "null" or self.tokenizer.keyWord() == "false":
                self.vmWriter.writePush("constant", 0)
            elif self.tokenizer.keyWord() == "true":
                self.vmWriter.writePush("constant", 1)
                self.vmWriter.writeArithmetic("neg") #Value of true is -1
            elif self.tokenizer.keyWord() == "this":
                self.vmWriter.writePush("pointer", VMWriter.THIS_POINTER) 
            else:
                raise Exception("Invalid keyword constant " + self.tokenizer.keyWord())

            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
        elif self.tokenizer.tokenType == JackTokenizer.STRING_CONST:
            self.vmWriter.writePush("constant", len(self.tokenizer.stringVal()))
            self.vmWriter.writeCall("String.new", 1)
            for char in self.tokenizer.stringVal():
                self.vmWriter.writePush("constant", ord(char))
                self.vmWriter.writeCall("String.appendChar", 2)

            if self.tokenizer.hasMoreTokens():
               self.tokenizer.advance() 
        else:
            raise Exception("Invalid term provided")
        print("The current token is " + self.tokenizer.currentToken)
        self.indentLevel -= 1
        self.writeFormatted("</term>")

    def compileExpressionList(self):
        from JackTokenizer import JackTokenizer
        self.writeFormatted("<expressionList>")
        self.indentLevel += 1
        self.numExpressions = 0 #The number of expressions in this list

        #I sort of feel guilty for doing this since this relies on knowing that
        #the expression list is surrounded by parenthesis and according to the spec
        #it should not know that (it would require modifying this message if I wanted to use an expression list anywhere else).
        #However, also according to the spec I should create a <subroutineCall> XML element or I shouldn't depending
        #on which part of the spec you trust.
        while not(self.tokenizer.tokenType == JackTokenizer.SYMBOL and self.tokenizer.symbol() == ")"):
           self.compileExpression() 
           self.numExpressions += 1
           if self.tokenizer.tokenType == JackTokenizer.SYMBOL and self.tokenizer.symbol() == ",":
               self.printToken() #print ','
               if self.tokenizer.hasMoreTokens():
                   self.tokenizer.advance()
        self.indentLevel -= 1
        self.writeFormatted("</expressionList>")

    def compileSubroutineCall(self):
        from JackTokenizer import JackTokenizer
        from VMWriter import VMWriter
        self.printToken() #Should print either the subroutine name or the class/object the
        #subroutine is a member of
        firstToken = self.tokenizer.currentToken
        secondToken = ""
        isClassOrObj = False
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()
            self.printToken() #Should print '.' or '(' 
        if self.tokenizer.tokenType == JackTokenizer.SYMBOL and self.tokenizer.symbol() == ".":
            isClassOrObj = True
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance() 
                self.printToken() #Should print subroutine name
                secondToken = self.tokenizer.currentToken
            if self.tokenizer.hasMoreTokens():
                self.tokenizer.advance()
                self.printToken() #Should print opening '('
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()

            #If the subroutine is a method call we must first push the object before 
            #pushing the rest of the arguments
            if secondToken != "" and self.symbolTable.isDefined(firstToken):
                self.vmWriter.writePush(self.symbolTable.kindOf(firstToken), self.symbolTable.indexOf(firstToken))
            
            if secondToken == "":
                self.vmWriter.writePush("pointer", VMWriter.THIS_POINTER)

            self.compileExpressionList()
            

            self.printToken() #Should print ')'
        if self.tokenizer.hasMoreTokens():
            self.tokenizer.advance()

         
        if secondToken != "":
            if self.symbolTable.isDefined(firstToken):
                callName = self.symbolTable.typeOf(firstToken) + "." + secondToken
                self.numExpressions += 1
            else:
                callName = firstToken + "." + secondToken
        else:
            self.numExpressions += 1
            callName = self.className + "." + firstToken

        self.vmWriter.writeCall(callName, self.numExpressions) 

        if isClassOrObj and self.symbolTable.isDefined(firstToken):
            self.writeVarInfo(firstToken, True) #Writing information about an object
        elif isClassOrObj:
            self.writeClassOrSubInfo("class", True) #Writing information about a class
        self.writeClassOrSubInfo("subroutine", True)

    def printToken(self):
        from JackTokenizer import JackTokenizer
        if self.tokenizer.tokenType == JackTokenizer.KEYWORD:
           self.writeFormatted("<keyword>" + self.tokenizer.keyWord() + "</keyword>")
        elif self.tokenizer.tokenType == JackTokenizer.SYMBOL:
            self.writeFormatted("<symbol>" + self.tokenizer.symbol() + "</symbol>")
        elif self.tokenizer.tokenType == JackTokenizer.IDENTIFIER:
            self.writeFormatted("<identifier>" + self.tokenizer.identifier() + "</identifier>")
        elif self.tokenizer.tokenType == JackTokenizer.INT_CONST:
            self.writeFormatted("<integerConstant>" + self.tokenizer.intVal() + "</integerConstant>")
        elif self.tokenizer.tokenType == JackTokenizer.STRING_CONST:
            self.writeFormatted("<stringConstant>" + self.tokenizer.stringVal() + "</stringConstant>")

    def writeFormatted(self, string):
        self.outputFile.write("  " * self.indentLevel + string + "\n")
    
    def writeVarInfo(self, varName, inUse):
        from SymbolTable import SymbolTable
        self.writeFormatted("<IdentifierInfo>")
        self.indentLevel += 1
        self.writeFormatted("<type>" + self.symbolTable.typeOf(varName) + "</type>")
        self.writeFormatted("<kind>" + self.symbolTable.stringKindOf(varName) + "</kind>")
        self.writeFormatted("<index>" + str(self.symbolTable.indexOf(varName)) + "</index>")
        self.writeFormatted("<inUse>" + str(inUse) + "</inUse>")
        self.indentLevel -= 1
        self.writeFormatted("</IdentifierInfo>")

    def writeClassOrSubInfo(self, kind, inUse):
       self.writeFormatted("<IdentifierInfo>")
       self.indentLevel += 1
       self.writeFormatted("<kind>" + kind + "</kind>")
       self.writeFormatted("<inUse>" + str(inUse) + "</inUse>")
       self.indentLevel -= 1
       self.writeFormatted("</IdentifierInfo>")