def visitExpr(self, ctx: DecafParser.ExprContext): line_num = ctx.start.line expr_type = "" if len(ctx.expr()) == 2: type_a = self.visit(ctx.expr(0)) type_b = self.visit(ctx.expr(1)) op = ctx.bin_op() if type_a == type_b: expr_type = type_a else: expr_type = None #print('Error on line', line_num, 'type mismatched in expression') #12 if (op.rel_op() != None or op.arith_op() != None ) and type_a != 'int' and type_b != 'int': print('Error on line ' + str(line_num) + ' operands must be of type int') #13 elif op.eq_op() != None and type_a != type_b: print('Error on line ' + str(line_num) + ' operands must be of same type') #14 elif op.cond_op() != None and (type_a != 'boolean' or type_b != 'boolean'): print('Error on line ' + str(line_num) + ' operands must be of type boolean') elif ctx.location() != None: var_name = ctx.location().ID().getText() var_symbol = self.st.lookup(var_name) if var_symbol != None: expr_type = var_symbol.type else: #2 expr_type = None print('Error on line ' + str(line_num) + ', ' + var_name + ' has not been declared') elif ctx.data_literal() != None: if ctx.data_literal().int_literal() != None: expr_type = 'int' elif ctx.data_literal().bool_literal() != None: expr_type = 'boolean' else: expr_type = None elif ctx.method_call() != None: method_name = ctx.method_call().method_name().getText() method_symbol = self.st.lookup(method_name) if method_symbol != None: expr_type = method_symbol.type self.visit(ctx.method_call()) else: method_symbol = None elif ctx.EXCLAMATION() != None: expr_type = self.visit(ctx.expr(0)) #14 if expr_type != 'boolean': print('Error on line ' + str(line_num) + ' operand must be of type boolean') else: self.visitChildren(ctx) return expr_type
def visitExpr(self, ctx: DecafParser.ExprContext): line_number = ctx.start.line method_call = ctx.method_call() bin_oper = "" if ctx.expr(0) != None: if ctx.expr(0).bin_op() != None: bin_oper = ctx.expr(0).bin_op().getText() if self.eq_op: pass else: expressions = ctx.expr(0) if expressions != None: if ctx.expr(0).location() and bin_oper != None: for items in ctx.expr(): locatons = items.getText() """ check that the operands of bin_op are ints """ if self.st.lookup(locatons).type != "int": print( "ERROR: can only use a airthmetic operation on ints", line_number) if ctx.expr(0) and bin_oper != None: if ctx.expr(0).location: pass else: airth_op = ctx.expr(0).bin_op().airth_op().getText() if airth_op in expressions.getText(): operands = ctx.expr(0).getText().replace( airth_op, "") listOfoperands = list(operands) """ if operands are not loctions (meaning not varibles), try to chnage the type to int, if that fails throw error """ for i in range(len(listOfoperands)): try: int(listOfoperands[i]) except: print( "ERROR: can only use a airthmetic operation on ints", line_number) """ check if a method call in side of an expression is not void as it must be a type to be evaluated to something for it to be used in an expression, void is anon type """ method_expr_params = [] if method_call != None: method_params = method_call.expr() if self.st.lookup(method_call.ID().getText()).type == "void": print( "ERROR: for method to be used here, method must return something" + " line numnber", line_number) if "()" in method_call.getText(): name = method_call.getText() name = name.replace("()", "") for names in method_params: method_expr_params = method_expr_params.append[names] if len(method_expr_params) < len( self.st.lookup(name).params): print( "ERROR: " + "method " + self.st.lookup(name).id + " epecting", len(self.st.lookup(name).params), "but got", len(method_expr_params), "on line", line_number) return self.visitChildren(ctx)