def p_unary_expr(p): '''UnaryExpr : PrimaryExpr | UnaryOp UnaryExpr | NOT UnaryExpr''' p[0] = Node('UnaryExpr') if len(p) == 2: p[0].typeList = p[1].typeList p[0].placeList = p[1].placeList p[0].sizeList = p[1].sizeList p[0].code = p[1].code elif p[1] == '!': if p[2].typeList[0] != ['bool']: compilation_errors.add('TypeMismatch', line_number.get()+1, 'Type should be boolean') else: p[0].typeList = p[2].typeList p[0].placeList = p[2].placeList p[0].sizeList = p[2].sizeList p[0].code = p[2].code newVar = helper.newVar(p[0].typeList[0], p[0].sizeList[0]) p[0].code.append(['!', newVar, p[2].placeList[0]]) else: if p[2].typeList[0][0] not in p[1].extra: compilation_errors.add('TypeMismatch', line_number.get()+1, 'Invalid type for unary expression') else: p[0].typeList = p[2].typeList p[0].placeList = p[2].placeList p[0].sizeList = p[2].sizeList p[0].code = p[2].code newVar = helper.newVar(p[0].typeList[0], p[0].sizeList[0]) p[0].code.append([p[1].extra['opcode'], newVar, p[2].placeList[0]])
def p_expr(p): '''Expression : UnaryExpr | Expression BinaryOp Expression''' p[0] = Node('Expression') if len(p) == 2: p[0].typeList = p[1].typeList p[0].placeList = p[1].placeList p[0].sizeList = p[1].sizeList p[0].code = p[1].code else: if p[1].typeList[0] != p[3].typeList[0]: compilation_errors.add('TypeMismatch', line_number.get()+1, 'Type should be same across binary operator') elif p[1].typeList[0][0] not in p[2].extra: compilation_errors.add('TypeMismatch', line_number.get()+1, 'Invalid type for binary expression') else: if len(p[2].typeList) > 0: # for boolean p[0].typeList = p[2].typeList else: p[0].typeList = p[1].typeList newVar = helper.newVar(p[0].typeList[0], p[1].sizeList[0]) p[0].code = p[1].code p[0].code += p[3].code if len(p[2].extra) < 3: p[0].code.append([p[2].extra['opcode'], newVar, p[1].placeList[0], p[3].placeList[0]]) else: p[0].code.append([p[2].extra['opcode'] + p[1].typeList[0][0], newVar, p[1].placeList[0], p[3].placeList[0]]) p[0].sizeList = p[1].sizeList p[0].placeList.append(newVar)
def p_continue(p): '''ContinueStmt : CONTINUE''' p[0] = Node('ContinueStmt') scope_ = helper.getNearest('for') if scope_ == -1: compilation_errors.add('Scope Error', line_number.get()+1, 'continue is not in a loop') return symTab = helper.symbolTables[scope_] p[0].code = [['goto', symTab.metadata['update']]]
def p_break(p): '''BreakStmt : BREAK''' p[0] = Node('BreakStmt') scope_ = helper.getNearest('for') if scope_ == -1: compilation_errors.add('Scope Error', line_number.get()+1, 'break is not in a loop') return symTab = helper.symbolTables[scope_] p[0].code = [['goto', symTab.metadata['end']]]
def p_return(p): '''ReturnStmt : RETURN ExpressionListPureOpt''' p[0] = Node('ReturnStmt') # TODO: return data should also be handled scope_ = helper.getNearest('func') if scope_ == -1: compilation_errors.add('Scope Error', line_number.get()+1, 'return is not in a function') return symTab = helper.symbolTables[scope_] p[0].code = [['goto', symTab.metadata['end']]]
def p_short_var_decl(p): ''' ShortVarDecl : IDENT DEFINE Expression ''' p[0] = Node('ShortVarDecl') if helper.checkId(p[1],'current'): compilation_errors.add("Redeclaration Error", line_number.get()+1,\ "%s already declared"%p[1]) try: helper.symbolTables[helper.getScope()].add(p[1],p[3].typeList[0]) helper.symbolTables[helper.getScope()].update(p[1], 'offset', helper.getOffset()) helper.symbolTables[helper.getScope()].update(p[1], 'size', p[3].sizeList[0]) helper.updateOffset(p[3].sizeList[0]) p[0].code = p[3].code p[0].code.append(['=', p[1], p[3].placeList[0]]) except: pass