def p_Assignment(p): ''' Assignment : LeftHandSide AssignmentOperator AssignmentExpression ''' if 'access_type' not in p[1].keys(): attributes = ST.lookup(p[1]['place']) if attributes == None: raise Exception("Undeclared variable used: %s" %(p[1]['place'])) if 'is_array' in attributes and attributes['is_array']: raise Exception("Array '%s' not indexed properly" %(p[1]['place'])) if attributes['type'] == p[3]['type']: TAC.emit(p[1]['place'], p[3]['place'], '', p[2]) else: raise Exception("Type Mismatch for symbol: %s" %(p[3]['place'])) else: dest = p[1]['name'] + '[' + p[1]['index'] + ']' TAC.emit(dest, p[3]['place'], '', '=') rules_store.append(p.slice)
def p_ReturnStatement(p): ''' ReturnStatement : RETURN Expression STMT_TERMINATOR | RETURN STMT_TERMINATOR ''' if(len(p)==3 and p[1]=='return'): TAC.emit('ret', '', '', '') else: # to_return = ST.lookup(ST.curr_scope, is_func=True)['ret_type'] to_return = global_return_type curr_returned = ST.lookup(p[2]['place']) if curr_returned != None: if to_return[0] != curr_returned['type']: raise Exception("Wrong return type in %s" %(ST.curr_scope)) if 'is_array' in curr_returned.keys() and len(curr_returned['arr_size']) != to_return[1]: raise Exception("Dimension mismatch in return statement in %s" %(ST.curr_scope)) elif curr_returned == None: if p[2]['type'] != to_return[0] or to_return[1] != 0: raise Exception("Wrong return type in %s" %(ST.curr_scope)) TAC.emit('ret', p[2]['place'], '', '') rules_store.append(p.slice)
def p_InclusiveOrExpression(p): ''' InclusiveOrExpression : ExclusiveOrExpression | InclusiveOrExpression BITWISE_OR ExclusiveOrExpression ''' if(len(p)==2): p[0] = p[1] return newPlace = ST.get_temp_var() p[0] = { 'place' : newPlace, 'type' : 'TYPE_ERROR' } if p[1]['type']=='TYPE_ERROR' or p[3]['type']=='TYPE_ERROR': return if p[1]['type'] == 'INT' and p[3]['type'] == 'INT' : TAC.emit(newPlace, p[1]['place'], p[3]['place'], '|') p[0]['type'] = 'INT' else: raise Exception('Error: Type is not compatible' + p[1]['place'] + ',' + p[3]['place'] + '.') rules_store.append(p.slice)
def p_AdditiveExpression(p): ''' AdditiveExpression : MultiplicativeExpression | AdditiveExpression PLUS MultiplicativeExpression | AdditiveExpression MINUS MultiplicativeExpression ''' if len(p) == 2: p[0] = p[1] return newPlace = ST.get_temp_var() p[0] = { 'place' : newPlace, 'type' : 'TYPE_ERROR' } if p[1]['type'] == 'TYPE_ERROR' or p[3]['type'] == 'TYPE_ERROR': return if p[1]['type'] == 'INT' and p[3]['type'] == 'INT': TAC.emit(newPlace, p[1]['place'], p[3]['place'], p[2]) p[0]['type'] = 'INT' else: raise Exception("Error: integer value is needed") rules_store.append(p.slice)
def p_IfMark1(p): ''' IfMark1 : ''' l1 = ST.make_label() l2 = ST.make_label() TAC.emit('ifgoto', p[-2]['place'], 'eq 0', l2) TAC.emit('goto', l1, '', '') TAC.emit('label', l1, '', '') ST.create_new_table(l1) p[0] = [l1, l2]
def p_VariableDeclarator(p): ''' VariableDeclarator : VariableDeclaratorId | VariableDeclaratorId ASSIGN VariableInitializer ''' p[0] = {} if len(p) == 2: p[0]['place'] = p[1] return elif type(p[3]) != type({}): return if 'is_array' in p[3].keys() and p[3]['is_array']: t = ST.get_temp_var() TAC.emit(t, '1', '', '=') for i in p[3]['place']: TAC.emit(t, t, i, '*') TAC.emit('declare', p[1], t, p[3]['type']) p[0]['place'] = (p[1], p[3]['place']) p[0]['type'] = p[3]['type'] elif 'ret_type' in p[3].keys(): p[0]['place'] = p[1] p[0]['type'] = p[3]['ret_type'] else: TAC.emit(p[1][0], p[3]['place'], '', p[2]) p[0]['place'] = p[1] if 'is_var' not in p[3]: attributes = ST.lookup(p[3]['place']) if 'is_array' in attributes and attributes['is_array']: p[0]['is_array'] = True p[0]['arr_size'] = attributes['arr_size'] else: p[0]['is_array'] = False p[0]['type'] = p[3]['type'] rules_store.append(p.slice)
def p_MethodInvocation(p): ''' MethodInvocation : Name L_PAREN ArgumentList R_PAREN | Name L_PAREN R_PAREN | Primary DOT Identifier L_PAREN ArgumentList R_PAREN | Primary DOT Identifier L_PAREN R_PAREN | SUPER DOT Identifier L_PAREN ArgumentList R_PAREN | SUPER DOT Identifier L_PAREN R_PAREN ''' # Check return type of function in symbol table if p[2] == '(': attributes = ST.lookup(p[1]['place'], is_func=True) if attributes == None and p[1]['place'] != "System.out.println": raise Exception("Undeclared function used: %s" %(p[1]['place'])) if p[1]['place'] == 'System.out.println': if len(p) == 5: for parameter in p[3]: TAC.emit('print',parameter['place'],'','') else: temp_var = ST.get_temp_var() if len(p) == 5: prototype = attributes['params'] if len(prototype) != len(p[3]): raise Exception("Wrong number of arguments to function call: %s" %(p[1]['place'])) for i in range(len(p[3])): parameter = p[3][i] proto = prototype[i] if parameter['type'] != proto['type']: raise Exception("Wrong type of arg passed to function %s; got %s but expected %s" %(p[1]['place'], parameter['type'], proto['type'])) TAC.emit('param',parameter['place'],'','') TAC.emit('call',p[1]['place'],temp_var,'') p[0] = { 'place' : temp_var, 'ret_type' : attributes['ret_type'] } rules_store.append(p.slice)
def p_MultiplicativeExpression(p): ''' MultiplicativeExpression : UnaryExpression | MultiplicativeExpression MULT UnaryExpression | MultiplicativeExpression DIVIDE UnaryExpression | MultiplicativeExpression MODULO UnaryExpression ''' if(len(p)==2): p[0] = p[1] return newPlace = ST.get_temp_var() p[0] = { 'place' : newPlace, 'type' : 'TYPE_ERROR' } if p[1]['type'] == 'TYPE_ERROR' or p[3]['type'] == 'TYPE_ERROR': return if p[2] == '*': if p[1]['type'] == 'INT' and p[3]['type'] == 'INT' : TAC.emit(newPlace,p[1]['place'], p[3]['place'], p[2]) p[0]['type'] = 'INT' else: raise Exception('Error: Type is not compatible'+p[1]['place']+','+p[3]['place']+'.') elif p[2] == '/' : if p[1]['type'] == 'INT' and p[3]['type'] == 'INT' : TAC.emit(newPlace, p[1]['place'], p[3]['place'], p[2]) p[0]['type'] = 'INT' else: raise Exception('Error: Type is not compatible' + p[1]['place'] + ',' + p[3]['place'] + '.') elif p[2] == '%': if p[1]['type'] == 'INT' and p[3]['type'] == 'INT' : TAC.emit(newPlace,p[1]['place'],p[3]['place'],p[2]) p[0]['type'] = 'INT' else: raise Exception('Error: Type is not compatible' + p[1]['place'] + ',' + p[3]['place'] + '.') rules_store.append(p.slice)
def p_WhMark2(p): '''WhMark2 : ''' TAC.emit('ifgoto',p[-2]['place'],'eq 0', p[-4][2]) TAC.emit('goto',p[-4][1],'','') TAC.emit('label',p[-4][1],'','')
def p_SwMark1(p): ''' SwMark1 : ''' l = ST.make_label() TAC.emit('label', l, '', '') p[0] = l
def p_IfMark4(p): ''' IfMark4 : ''' ST.end_scope() TAC.emit('label', p[-2][0], '', '')
def p_IfMark2(p): ''' IfMark2 : ''' ST.end_scope() TAC.emit('label', p[-2][1], '', '')
def p_EqualityExpression(p): ''' EqualityExpression : RelationalExpression | EqualityExpression EQUALS RelationalExpression | EqualityExpression NOT_EQUAL RelationalExpression ''' if(len(p)==2): p[0] = p[1] return l1 = ST.make_label() l2 = ST.make_label() l3 = ST.make_label() newPlace = ST.get_temp_var() p[0]={ 'place' : newPlace, 'type' : 'TYPE_ERROR' } if p[1]['type']=='TYPE_ERROR' or p[3]['type']=='TYPE_ERROR': return if p[1]['type'] == 'INT' and p[3]['type'] == 'INT' : if(p[2][0]=='='): TAC.emit('ifgoto', p[1]['place'], 'eq ' + p[3]['place'], l2) TAC.emit('label', l1, '', '') TAC.emit(newPlace, '0', '', '=') TAC.emit('goto', l3, '', '') TAC.emit('label', l2, '', '') TAC.emit(newPlace, '1', '', '=') TAC.emit('label', l3, '', '') p[0]['type'] = 'INT' else: TAC.emit('ifgoto', p[1]['place'], 'neq '+ p[3]['place'], l2) TAC.emit('label', l1, '', '') TAC.emit(newPlace, '0', '', '=') TAC.emit('goto', l3, '', '') TAC.emit('label', l2, '', '') TAC.emit(newPlace, '1', '', '=') TAC.emit('label', l3, '', '') p[0]['type'] = 'INT' else: raise Exception('Only INT type comparisions supported: ' + p[1]['place'] + ' and' + p[3]['place']) rules_store.append(p.slice)
def p_RelationalExpression(p): ''' RelationalExpression : ShiftExpression | RelationalExpression LST ShiftExpression | RelationalExpression GRT ShiftExpression | RelationalExpression LEQ ShiftExpression | RelationalExpression GEQ ShiftExpression | RelationalExpression INSTANCEOF ReferenceType ''' if len(p) == 2: p[0] = p[1] return l1 = ST.make_label() l2 = ST.make_label() l3 = ST.make_label() newPlace = ST.get_temp_var() p[0] = { 'place' : newPlace, 'type' : 'TYPE_ERROR' } if p[1]['type']=='TYPE_ERROR' or p[3]['type']=='TYPE_ERROR': return if p[1]['type'] == 'INT' and p[3]['type'] == 'INT' : if p[2]=='>': TAC.emit('ifgoto', p[1]['place'], 'gt ' + p[3]['place'], l2) TAC.emit('label', l1, '', '') TAC.emit(newPlace, '0', '', '=') TAC.emit('goto', l3, '', '') TAC.emit('label', l2, '', '') TAC.emit(newPlace, '1', '', '=') TAC.emit('label', l3, '', '') p[0]['type'] = 'INT' elif p[2]=='>=': TAC.emit('ifgoto', p[1]['place'], 'geq ' + p[3]['place'], l2) TAC.emit('label', l1, '', '') TAC.emit(newPlace, '0', '', '=') TAC.emit('goto', l3, '', '') TAC.emit('label', l2, '', '') TAC.emit(newPlace, '1', '', '=') TAC.emit('label', l3, '', '') p[0]['type'] = 'INT' elif p[2]=='<': TAC.emit('ifgoto', p[1]['place'], 'lt ' + p[3]['place'], l2) TAC.emit('label', l1, '', '') TAC.emit(newPlace, '0', '', '=') TAC.emit('goto', l3, '', '') TAC.emit('label', l2, '', '') TAC.emit(newPlace, '1', '', '=') TAC.emit('label', l3, '', '') p[0]['type'] = 'INT' elif p[2]=='<=': TAC.emit('ifgoto', p[1]['place'], 'leq ' + p[3]['place'], l2) TAC.emit('label', l1, '', '') TAC.emit(newPlace, '0', '', '=') TAC.emit('goto', l3, '', '') TAC.emit('label', l2, '', '') TAC.emit(newPlace, '1', '', '=') TAC.emit('label', l3, '', '') p[0]['type'] = 'INT' else: raise Exception('Error: Type is not compatible' + p[1]['place'] + ',' + p[3]['place'] + '.') rules_store.append(p.slice)
def p_doWhMark3(p): '''doWhMark3 : ''' TAC.emit('ifgoto',p[-2]['place'],'eq 0', p[-7][2]) TAC.emit('goto',p[-7][1],'','') TAC.emit('label',p[-7][2],'','')
def p_FoMark4(p): '''FoMark4 : ''' TAC.emit('ifgoto',p[-3]['place'],'eq 0', p[-4][2]) TAC.emit('goto',p[-4][1],'','') TAC.emit('label',p[-4][1],'','')
#!/usr/bin/env python import sys import ply.lex as lex import ply.yacc as yacc import lexer from three_address_code import TAC from new_sym_table import ScopeTable TAC = TAC() ST = ScopeTable() stackbegin = [] stackend = [] rules_store = [] global_return_type = None # Section 19.2 def p_Goal(p): '''Goal : CompilationUnit''' rules_store.append(p.slice) # Section 19.3 def p_Identfier(p): '''Identifier : IDENTIFIER''' p[0] = p[1] def p_Literal(p): ''' Literal : IntegerConst | FloatConst