コード例 #1
0
 def __init__(self, filename):
     if os.path.isdir(filename):
         self._files = [
             filename + '/' + x for x in os.listdir(filename)
             if x.endswith(".vm")
         ]
         self._isdir = True
         self._name = filename + '/' + filename.split('/')[-1] + '.asm'
     elif os.path.isfile(filename) and filename.endswith('.vm'):
         self._files = [filename]
         self._isdir = False
         self._name = filename.replace('.vm', '.asm')
     else:
         self._files = list()
         self._isdir = False
         return
     self._output = []
     self._code = CodeWriter(self._name)
     if self._isdir:
         self._code.write_init()
     for file in self._files:
         self._parser = Parser(file)
         self._code.filename(file.replace('.vm', '').split('/')[-1])
         self.translate()
     self._code.close()
コード例 #2
0
def main():
    if sys.argv[1][-2:] != "vm":
        print("Error: wrong file type for input, use \".vm\" file !")
        sys.exit()

    inputfile = sys.argv[1]
    #inputfile = "BasicTest.vm"
    outputfile = inputfile[:-2] + "asm"

    par = Parse(inputfile)
    cw = CodeWriter(outputfile)

    while par.hasMoreCommands():
        par.advance()
        ctype = par.cmdType()
        #print(par.current_cmd)
        #print(par.cmdType())
        #print(par.arg1())
        #print(par.arg2())
        if ctype == "C_ARITHMETIC":
            cw.writeArithmetic(par.arg1())
        elif ctype == "C_PUSH" or ctype == "C_POP":
            cw.writePushPop(ctype, par.arg1(), par.arg2())

    cw.close()
コード例 #3
0
def main():

    output_list = []
    if len(sys.argv) == 2:
        file_name = str(os.path.splitext(sys.argv[1])[0])
        file_ext = os.path.splitext(sys.argv[1])[1]

    if len(sys.argv) != 2 or file_ext != ".vm":
        print("Usage: translator.py <inputFile>.vm")
        return

    try:
        parser = Parser(file_name, file_ext)
        writer = CodeWriter(file_name)
    except IOError as e:
        print(e)
        return
    else:
        while parser.hasMoreCommands():
            parser.advance()
            cmd = parser.command_type()
            if cmd != "C_RETURN":
                argument1 = parser.arg1()
            if cmd in ["C_POP", "C_PUSH", "C_FUNCTION", "C_CALL"]:
                argument2 = parser.arg2()
            if cmd == "C_ARITHMETIC":
                writer.write_arithmetic(argument1)
            if cmd in ["C_POP", "C_PUSH"]:
                writer.write_push_pop(cmd, argument1, argument2)
        writer.close()
コード例 #4
0
 def __init__(self, vm_file):
     self.filename = vm_file
     self.basename = os.path.splitext(os.path.basename(vm_file))[0]
     self.writer = CodeWriter(self.basename)
     self.directory = os.path.dirname(vm_file)
     self.suffix = '.asm'
     self.abspath = os.path.abspath(self.filename)
コード例 #5
0
ファイル: parser.py プロジェクト: kjlundsgaard/Nand2Tetris
 def __init__(self, filenames):
     self.asm_commands_list = []
     file_basenames = set(
         [os.path.splitext(os.path.basename(f))[0] for f in filenames])
     if 'Sys' in file_basenames:
         self.write_init()
     for f in filenames:
         file_data = (line for line in read_file(f))
         writer = CodeWriter(f)
         command = self.advance(file_data)
         while command:
             parsed_elements = self.parse(command)
             if parsed_elements:
                 self.asm_commands_list.append(
                     writer.compose(parsed_elements))
             command = self.advance(file_data)
コード例 #6
0
def add_bootstrap_code(asmfile, filename):
    """Provide the bootstrap code in assembly"""

    global_variables.function_list.append('Sys')
    # Open assembly file to receive init code
    assembly_file = open(asmfile, 'a')

    # Get basename of the file in provided filepath
    input_file_basename = os.path.basename(filename)

    code_writer = CodeWriter(input_file_basename)
    bootstrap_code = code_writer.write_init()

    assembly_file.write(bootstrap_code)

    assembly_file.close()
コード例 #7
0
ファイル: main.py プロジェクト: krzysztofzywot/vm-translator
def get_code_writer(output_file_name):
    try:
        code_writer = CodeWriter(output_file_name)
    except IOError:
        print("Cannot create an output asm file.")
        sys.exit(3)

    return code_writer
コード例 #8
0
    def translate(self):

        codewriter = CodeWriter(path)

        if os.path.isdir(path):
            os.chdir(path)
            for vm_file in os.listdir('.'):
                if os.path.splitext(vm_file)[1] == '.vm':
                    print(vm_file)
                    self.translate_single_file(vm_file, codewriter)
        else:
            self.translate_single_file(path, codewriter)
コード例 #9
0
def main():
    p=Path(sys.argv[1])
    ctabel = CmdTable()
    out_filename= p.stem
    inputfile_list = {}
    if p.is_file():
        outputfile = str(p.parent / (out_filename + ".asm"))
        inputfile_list[str(p)] = p.stem
    elif p.is_dir():
        outputfile = p / (out_filename + ".asm")
        for pfile in p.glob('*.vm'):
            inputfile_list[str(pfile)] = pfile.stem

    fout = open(outputfile, mode='w')
    cw = CodeWriter(fout, ctabel)
    if p.is_dir():
        cw.writeBoot()

    for inf, infname in inputfile_list.items():
        write_vm1(inf, infname, ctabel, cw)
    fout.close()
コード例 #10
0
def main():
    if len(sys.argv) < 2:
        print(u"使い方: %s FILENAME" % sys.argv[0])
        sys.exit(1)

    path = sys.argv[1]

    if path.endswith(".vm"):  #file
        with CodeWriter(path[:-3] + ".asm") as c:
            translate_file(path, c)
        print("Translated to " + path[:-3] + ".asm")
    else:  #dir
        if path.endswith("/"):
            path = path[:-1]
        # glob.glob (PATHを再帰的に取得)
        files = glob.glob("%s/*" % path)
        for f in files:
            if f.endswith(".vm"):
                print(f)
                with CodeWriter(f[:-3] + ".asm") as c:
                    translate_file(f, c)
        print("Translated to" + path + ".asm")
コード例 #11
0
def translate_file(vm_file, asmfile):

    current_file_name = os.path.basename(vm_file)[:-3]
    # Initiate list of functions/files names and variables and append current file
    global_variables.function_list.append(current_file_name)

    with open(vm_file, 'r') as vmfile:
        # Create assembly file to receive translated code
        assembly_file = open(asmfile, 'a')

        parser = Parser()
        assembly_code = ""
        code_writer = CodeWriter(current_file_name)

        for line in vmfile:
            if is_blank_or_is_comment(line):
                pass
            else:
                command = parser.clean_line(line)
                command_type = parser.command_type(command)

                if command_type == "C_ARITHMETIC":
                    assembly_code = code_writer.write_arithmetic(command)

                elif command_type in ["C_LABEL", "C_GOTO", "C_IF"]:
                    command_args = parser.command_args(command)
                    assembly_code = code_writer.write_control_flow(
                        command_args)

                elif command_type in ["C_CALL", "C_RETURN", "C_FUNCTION"]:
                    command_args = parser.command_args(command)
                    assembly_code = code_writer.write_subroutines(command_args)

                else:
                    command_args = parser.command_args(command)
                    assembly_code = code_writer.write_push_pop(command_args)

                assembly_file.write(assembly_code)

        assembly_file.close()

    # Reset list of functions processed in the current file
    global_variables.function_list.clear()
コード例 #12
0
ファイル: main.py プロジェクト: imoken1122/python-nand2tetris
    else:
        return 0


if __name__ == "__main__":

    path, flag = sys.argv[1], int(
        sys.argv[2]
    ),  # dir name existing .vm file, wheather exist many file(1) or not(0)
    allasm_code = []

    if flag == 0:
        f_list = list(map(lambda x: path + '/' + x, os.listdir(path)))
        file = [f for f in f_list if re.search('.vm', f) != None][0][:-3]
        init_flag = get_init_flag(file)
        codewriter = CodeWriter(file, init_flag)
        parser = Parser(file)
        allasm_code += vm2asm_translater(codewriter, parser)
    else:
        old_return_addr = 0
        old_labelNum = 0
        init_flag = 1
        f_list = list(map(lambda x: path + '/' + x, os.listdir(path)))
        for f in f_list:
            if re.search('.*\.vm', f) != None:
                file = re.sub('\.vm', '', f)
                codewriter = CodeWriter(file, init_flag)
                parser = Parser(file)
                codewriter.labelNum = old_labelNum
                codewriter.return_address = old_return_addr
                allasm_code += vm2asm_translater(codewriter, parser)
コード例 #13
0
class VMTranslator():
    '''
    Manages the translation effort, bridging the gap between the Parser and Codewriter objects. 
    A new Parser is created for each file in the directory.
    '''
    def __init__(self, filename):
        if os.path.isdir(filename):
            self._files = [
                filename + '/' + x for x in os.listdir(filename)
                if x.endswith(".vm")
            ]
            self._isdir = True
            self._name = filename + '/' + filename.split('/')[-1] + '.asm'
        elif os.path.isfile(filename) and filename.endswith('.vm'):
            self._files = [filename]
            self._isdir = False
            self._name = filename.replace('.vm', '.asm')
        else:
            self._files = list()
            self._isdir = False
            return
        self._output = []
        self._code = CodeWriter(self._name)
        if self._isdir:
            self._code.write_init()
        for file in self._files:
            self._parser = Parser(file)
            self._code.filename(file.replace('.vm', '').split('/')[-1])
            self.translate()
        self._code.close()

    def translate(self):
        # using input from parser, translate and output
        while self._parser.has_more_commands():
            self._parser.advance()
            if self._parser.command_type() in ['C_ARITHMETIC', 'C_BOOLEAN']:
                self._code.write_arithmetic(self._parser.command())
            elif self._parser.command_type() in ['C_POP', 'C_PUSH']:
                self._code.write_pushpop(self._parser.command_type(),
                                         self._parser.arg1(),
                                         self._parser.arg2())
            elif self._parser.command_type() == 'C_LABEL':
                self._code.write_label(self._parser.arg1())
            elif self._parser.command_type() == 'C_GOTO':
                self._code.write_goto(self._parser.arg1())
            elif self._parser.command_type() == 'C_IF':
                self._code.write_if(self._parser.arg1())
            elif self._parser.command_type() == 'C_FUNCTION':
                self._code.write_function(self._parser.arg1(),
                                          self._parser.arg2())
            elif self._parser.command_type() == 'C_CALL':
                self._code.write_call(self._parser.arg1(), self._parser.arg2())
            elif self._parser.command_type() == 'C_RETURN':
                self._code.write_return()
コード例 #14
0
def main():
    arg_len = len(sys.argv)
    file_list = []
    output_file = ""
    parsers = []

    if arg_len == 1:
        dir_name = os.getcwd()
        output_file = dir_name + '/' + dir_name.split('/')[-1] + ".asm"
        for f in os.listdir(dir_name):
            if f.endswith(".vm"):
                file_list.append(f)
        if not file_list:
            print("Error, no .vm files in current directory")
            return
    elif arg_len == 2:
        if os.path.isdir(sys.argv[1]):
            output_file = sys.argv[1] + sys.argv[1].split('/')[-2] + ".asm"
            for f in os.listdir(sys.argv[1]):
                if f.endswith(".vm"):
                    file_list.append(f)
            if not file_list:
                print("Error, no .vm files in given directory")
                return
            file_list = [sys.argv[1] + "/" + f for f in file_list]
        else:
            if os.path.splitext(sys.argv[1])[1] != ".vm":
                print("Error, .vm file not specified")
                return
            else:
                file_list.append(sys.argv[1])
                output_file = os.path.splitext(sys.argv[1])[0] + ".asm"
    try:
        writer = CodeWriter(output_file)
    except IOError as e:
        print("In codewriter: ")
        print(e)
        return
    else:
        try:
            parsers = [Parser(f) for f in file_list]
        except IOError as e:
            print("In parsers: ")
            print(e)
            return
        else:
            writer.write_init()
            for p in parsers:
                writer.set_file_name(p.static_name)
                while p.hasMoreCommands():
                    p.advance()
                    cmd = p.command_type()
                    if cmd != "C_RETURN":
                        argument1 = p.arg1()
                    if cmd in ["C_POP", "C_PUSH", "C_FUNCTION",
                               "C_CALL"]:
                        argument2 = p.arg2()
                    if cmd == "C_ARITHMETIC":
                        writer.write_arithmetic(argument1)
                    elif cmd in ["C_POP", "C_PUSH"]:
                        writer.write_push_pop(cmd, argument1,
                                              argument2)
                    elif cmd == "C_LABEL":
                        writer.write_label(argument1)
                    elif cmd == "C_GOTO":
                        writer.write_goto(argument1)
                    elif cmd == "C_IF":
                        writer.write_if(argument1)
                    elif cmd == "C_FUNCTION":
                        writer.write_function(argument1, int(argument2))
                    elif cmd == "C_CALL":
                        writer.write_call(argument1, argument2)
                    elif cmd == "C_RETURN":
                        writer.write_return()
        writer.close()
コード例 #15
0
from parser import Parser
from codewriter import CodeWriter
import sys
import re

if __name__ == "__main__":
    path = sys.argv[1]
    codewriter = CodeWriter(path)
    parser = Parser(path)

    while parser.hasMoreCommands():
        parser.advance()
        print(parser.current_cmd)
        cmdtype = parser.commandType()
        arg1 = parser.arg1()
        if cmdtype == 'C_ARITHMETIC':
            codewriter.writeArithmetic(arg1)
        elif cmdtype in ['C_PUSH', 'C_POP']:
            arg2 = parser.arg2()
            codewriter.wirtePushPop(cmdtype, arg1, arg2)

    codewriter.fileToOutput()
コード例 #16
0
ファイル: codegenerator.py プロジェクト: xmonkee/JackCompiler
 def __init__(self):
    self.codewriter = CodeWriter()
コード例 #17
0
ファイル: VMtoHack.py プロジェクト: ccard/csci410python
pop_type='C_POP'
lable_type='C_LABEL'
goto_type='C_GOTO'
if_type='C_IF'
funct_type='C_FUNCTION'
ret_type='C_RETURN'
call_type='C_CALL'

in_file=''
out_file=''

#for directories
directory = []
is_dir=False

writer = CodeWriter()

#------------------------------------------------------------------------------
# Check user input
#------------------------------------------------------------------------------
if len(sys.argv) < 1: #Checks to see if user put in file
	print('incorrect number of args!')
	print('assembler.py <file.vm|directry path>')
	sys.exit(0)

in_file=sys.argv[1]

#Checks for correct file name if not then assumes directory
if re.search('.*\.vm',in_file) is None:
	is_dir=True
	#goes through the directory and finds the .vm files
コード例 #18
0
ファイル: VMtoHack.py プロジェクト: ccard/csci410python
else:
	#Strips .vm of the end and adds .asm
	temp_out=re.search('(.*)(\.vm)',in_file)
	out_file+=temp_out.group(1)+'.asm'

#------------------------------------------------------------------------------
# Main
#------------------------------------------------------------------------------

#For directories passed in
if is_dir:
	cur_dir = os.getcwd()
	temp_dir = re.search('([\/"\\"]{1})([A-Za-z0-9\.\_\-\s]*$)',cur_dir)
	fileName = temp_dir.group(2)+'.asm'
	#opens the file named after the directory with .asm appended
	writer = CodeWriter(cur_dir+'/'+fileName)
	writer.writeInit()
	for d in directory:
		#Strips .vm of the end to get the file name
		temp_out=re.search('(.*[\.\/]+)(.*)(\.vm)',d)
		out_file = temp_out.group(2)

		#sets current file name
		writer.setFileName(out_file)

		#opens the input file
		par = Parser(d)
		#while not eof
		while par.hasMoreCommands():
			par.advance()
			cType = par.commandType()
コード例 #19
0
ファイル: codegenerator.py プロジェクト: xmonkee/JackCompiler
class CodeGenerator():
   def __init__(self):
      self.codewriter = CodeWriter()

   def codegen(self, ast):
      """Entry point into codeGenerator.Starts the recursive compilation and 
      returns the final result to calling function"""
      self.class_({},ast.next_sec())
      return self.codewriter.get_code()

   def class_(self, state, ast):
      """Create class symbol table and pass on control to classVarDec and 
      subroutineDec.  No code geneartion here"""
      ast.next() #'class keyword'
      state['classname'] = ast.next_val()
      ast.next() #'{'
      state['sym_tbl'] = SymbolTable()
      while(ast.get_key() == 'classVarDec'):
         self.classVarDec(state, ast.next_sec())
      while(ast.get_key() == 'subroutineDec'):
         self.subroutineDec(state, ast.next_sec())
      ast.next() #'}'
      return

   def classVarDec(self, state, ast):
      """Parse static and field and add to symbol table"""
      var_kind = ast.next_val()
      var_type = ast.next_val()
      var_name = ast.next_val()
      state['sym_tbl'].add(var_name, var_kind, var_type)
      while(ast.next_val() != ';'):
         var_name = ast.next_val()
         state['sym_tbl'].add(var_name, var_kind, var_type)
      return

   def subroutineDec(self, state, ast):
      statelocal = state.copy() #we keep a local frame for each function
      statelocal['sym_tbl'] = SymbolTable(state['sym_tbl']) 
      statelocal['fkind'] = ast.next_val() #constructor, function, method
      statelocal['fype']= ast.next_val() #return type
      statelocal['fname'] = ast.next_val() #function name
      statelocal['cf_count'] = 0 #control flow labels
      #new symbol table with parent linkage
      if statelocal['fkind'] == 'method':
         statelocal['sym_tbl'].var_counter['argument'] += 1
      ast.next() #'('
      self.parameterList(statelocal,ast.next_sec())
      ast.next() #')'
      self.subroutineBody(statelocal, ast.next_sec())
      return
   
   def parameterList(self, state, ast):
      if(ast.get_val() is not None):
         var_type = ast.next_val()
         var_name = ast.next_val()
         state['sym_tbl'].add(var_name, 'argument', var_type)
         while(ast.get_val() == ','):
            ast.next()
            var_type = ast.next_val()
            var_name = ast.next_val()
            state['sym_tbl'].add(var_name, 'argument', var_type)
      return

   def subroutineBody(self, state, ast):
      ast.next() # '{'
      while(ast.get_key() == 'varDec'):
         self.varDec(state, ast.next_sec())
      self.codewriter.function(state)
      self.statements(state, ast.next_sec())
      ast.next() # '}'
      return

   def varDec(self, state, ast):
      ast.next() #'var'
      var_type = ast.next_val()
      var_name = ast.next_val()
      state['sym_tbl'].add(var_name, 'local', var_type)
      while(ast.next_val() != ';'):
         var_name = ast.next_val()
         state['sym_tbl'].add(var_name, 'local', var_type)
      return

   def statements(self, state, ast):
      xstatements = {
            'returnStatement':self.returnStatement,
            'ifStatement':self.ifStatement,
            'letStatement':self.letStatement,
            'whileStatement':self.whileStatement,
            'doStatement':self.doStatement }
      xstatement = ast.get_key()
      while(xstatement is not None):
         xstatements[xstatement](state, ast.next_sec())
         xstatement = ast.get_key()
      return

   def doStatement(self, state, ast):
      ast.next() #'do'
      self.subroutineCall(state,ast.next_sec())
      self.codewriter.pop('temp',  0) #throw away void return
      ast.next() #';'
      return

   def returnStatement(self, state, ast):
      ast.next() #'return'
      if ast.get_key() == 'expression':
         self.expression(state, ast.next_sec())
      else:
         self.codewriter.push('constant', 0)
      self.codewriter.raw('return')
      ast.next() #';'
      return

   def ifStatement(self, state, ast):
      cf_count = state['cf_count']
      state['cf_count'] += 1
      ast.next() # 'if'
      ast.next() # '('
      self.expression(state, ast.next_sec())
      ast.next() # ')'
      self.codewriter.if_goto('IF_TRUE',cf_count)
      self.codewriter.goto('IF_FALSE',cf_count)
      ast.next() # '{'
      self.codewriter.label('IF_TRUE', cf_count)
      self.statements(state, ast.next_sec())
      ast.next() # '}'
      if(ast.get_val() == 'else'):
         self.codewriter.goto('IF_END',cf_count)
      self.codewriter.label('IF_FALSE', cf_count)
      if(ast.get_val() == 'else'):
         ast.next() # 'else'
         ast.next() # '{'
         self.statements(state, ast.next_sec())
         ast.next() # '}'
         self.codewriter.label('IF_END', cf_count)
      return


      self.codewriter.label('IF_FALSE', cf_count)
      return

   def whileStatement(self, state, ast):
      cf_count = state['cf_count']
      state['cf_count'] += 1
      self.codewriter.label('WHILE_EXP', cf_count)
      ast.next() # 'while'
      ast.next() # '('
      self.expression(state, ast.next_sec())
      ast.next() # ')'
      self.codewriter.raw('not')
      self.codewriter.if_goto('WHILE_END',cf_count)
      ast.next() # '{'
      self.statements(state, ast.next_sec())
      ast.next() # '}'
      self.codewriter.goto('WHILE_EXP', cf_count)
      self.codewriter.label('WHILE_END', cf_count)
      return

   def letStatement(self, state, ast):
      ast.next() # 'let'
      varname = ast.next_val()
      if ast.get_val() == '[':
         ast.next() # '['
         self.expression(state, ast.next_sec())
         self.codewriter.push_var(state['sym_tbl'].lookup(varname))
         self.codewriter.raw('add')
         ast.next() # ']'
         ast.next() # '='
         self.expression(state, ast.next_sec())
         self.codewriter.pop('temp', 0)
         self.codewriter.pop('pointer', 1)
         self.codewriter.push('temp', 0)
         self.codewriter.pop('that', 0)
      else:
         ast.next() # '='
         self.expression(state, ast.next_sec())
         self.codewriter.pop_var(state['sym_tbl'].lookup(varname))
      ast.next() # ';'
      return

   def subroutineCall(self, state, ast):
      if state['sym_tbl'].lookup(ast.get_val()) is not None: #other class method call
         objname = ast.next_val()
         obj = state['sym_tbl'].lookup(objname)
         ast.next() # dot
         fname = ast.next_val()
         self.codewriter.push_var(obj) #push object as first argument
         ast.next() # '('
         argc = self.expressionList(state, ast.next_sec()) #push other arguments 
         #argc is number of "actual" arguments
         ast.next() # ')'
         self.codewriter.call(obj.type, fname, argc+1)
      else: #not other class method call 
         firstname = ast.next_val()
         if ast.get_val() == '.': #Class.function()
            classname = firstname
            ast.next()
            fname = ast.next_val() 
            ast.next() # '('
            argc = self.expressionList(state, ast.next_sec()) #push other arguments 
            #argc is number of "actual" arguments
            ast.next() # ')'
            self.codewriter.call(classname, fname, argc)
         else: #self method call
            classname = state['classname'] #own class name
            fname = firstname
            self.codewriter.push('pointer', 0) #push this as first argument
            ast.next() # '('
            argc = self.expressionList(state, ast.next_sec()) #push other arguments 
            ast.next() # ')'
            self.codewriter.call(classname, fname, argc+1)
      return

   def expressionList(self, state, ast):
      argc = 0
      if ast.get() is not None:
         self.expression(state, ast.next_sec())
         argc += 1
         while(ast.get_val() is not None):
            ast.next()
            self.expression(state, ast.next_sec())
            argc += 1
      return argc

   def expression(self, state, ast):
      ops = {
            '+': 'add',
            '-': 'sub',
            '*': 'call Math.multiply 2',
            '/': 'call Math.divide 2',
            '|': 'or',
            '&amp;' : 'and',
            '=': 'eq',
            '&lt;' : 'lt',
            '&gt;' : 'gt'
            }
      self.term(state, ast.next_sec())
      while(ast.get_val() is not None):
         op = ast.next_val()
         self.term(state, ast.next_sec())
         self.codewriter.raw(ops[op])
      return
   
   def term(self, state, ast):
      key = ast.get_key()
      if key == 'integerConstant':
         self.codewriter.push('constant', ast.next_val())
      elif key == 'stringConstant':
         self.codewriter.string(ast.next_val())
      elif key == 'keyword':
         val = ast.next_val()
         if val == 'true':
            self.codewriter.raw('push constant 0\nnot')
         elif val == 'false':
            self.codewriter.raw('push constant 0')
         elif val == 'null':
            self.codewriter.raw('push constant 0')
         elif val == 'this':
            self.codewriter.push_this()
      elif key == 'arrayAccess':
         nast = ast.next_sec()
         varname = nast.next_val()
         nast.next() # '['
         self.expression(state, nast.next_sec())
         nast.next() # ']'
         self.codewriter.push_var(state['sym_tbl'].lookup(varname))
         self.codewriter.raw('add') #base address + index
         self.codewriter.pop('pointer', 1) #store indexed address in 'that'
         self.codewriter.push('that', 0)
      elif key == 'subroutineCall':
         self.subroutineCall(state, ast.next_sec())
      elif key == 'bracketExp':
         nast = ast.next_sec()
         nast.next() #'('
         self.expression(state, nast.next_sec())
         nast.next() #')'
      elif key == 'unaryOpTerm':
         nast = ast.next_sec()
         op = nast.next_val()
         self.term(state, nast.next_sec())
         if op == '-':
            self.codewriter.raw('neg')
         if op == '~':
            self.codewriter.raw('not')
      elif key == 'identifier':
         self.codewriter.push_var(state['sym_tbl'].lookup(ast.next_val()))