def condChecker(self, line, stmt, expr): if expr != _boolean: ErrorHandler.typeError(line, stmt, 2) self.error() return _error return _boolean
def intChecker(self, line, leftType, rightType, op): if leftType != _int or rightType != _int: ErrorHandler.typeError(line, op) self.error() return _error return _int
def visitAsignStmt(self, ctx: decafParser.AsignStmtContext): leftType = self.visit(ctx.location()) rightType = self.visit(ctx.expression()) if not leftType == rightType: ErrorHandler.typeError(ctx.start.line, "=") self.error()
def visitMethodCall(self, ctx: decafParser.MethodCallContext): name = ctx.ID().getText() methodSymbol = self.currentScope.resolve(name) # Check that the symbol is defined if not methodSymbol: ErrorHandler.nameError(ctx.start.line, name) self.error() # Check that the symbol is a method isMethod = isinstance(methodSymbol, symtab.MethodSymbol) if not isMethod: ErrorHandler.typeError(ctx.start.line, name, 3) self.error() # Check method signature signature = methodSymbol.args args = list() for arg in ctx.arg(): type = self.visit(arg) args.append(type) if not (signature == args): ErrorHandler.typeError(ctx.start.line, name, 4) self.error() # Return the type of the method # to be able to make methods calls from conditional statements return methodSymbol.type.name
def visitLocation(self, ctx: decafParser.LocationContext): name = ctx.ID().getText() symbol = self.currentScope.resolve(name) if not symbol: ErrorHandler.nameError(ctx.start.line, name) self.error() return _error # Check if it is a built-in type builtIn = False if symbol.type.name in self.T.builtIn: builtIn = True if builtIn: # Declared as a variable if isinstance(symbol, symtab.VariableSymbol): if ctx.expr is not None: ErrorHandler.typeError(ctx.start.line, symbol.name, 5) self.error() if ctx.loc is not None: ErrorHandler.attributeError(ctx.start.line, symbol.name, ctx.loc.getText()) self.error() return symbol.type.name # Declared as an array elif isinstance(symbol, symtab.ArraySymbol): try: index = int(ctx.expr.getText()) except ValueError: index = None if (index is None) or (index < 0) or (index >= int( symbol.num)): ErrorHandler.arrayError(ctx.start.line, symbol.name, 2) self.error() if ctx.loc is not None: ErrorHandler.attributeError(ctx.start.line, symbol.name, ctx.loc.getText()) self.error() return symbol.type.name if not builtIn: # Save the actual scope actualScope = self.currentScope # Because it has a member, we declare the struct as the current scope self.currentScope = self.structs.get(symbol.type.name) # Visit location type = self.visit(ctx.loc) # Restore actual scope self.currentScope = actualScope # Return the type of the location return type
def visitNegExp(self, ctx: decafParser.NegExpContext): exprType = self.visit(ctx.expression()) if exprType != _boolean: ErrorHandler.typeError(ctx.start.line, '!') self.error() return _error return _boolean
def visitMinExp(self, ctx: decafParser.MinExpContext): exprType = self.visit(ctx.expression()) if exprType != _int: ErrorHandler.typeError(ctx.start.line, '-') self.error() return _error return _int
def visitCondExp(self, ctx: decafParser.CondExpContext): op = ctx.op.getText() leftType = self.visit(ctx.left) rightType = self.visit(ctx.right) if leftType != _boolean or rightType != _boolean: ErrorHandler.typeError(ctx.start.line, op) self.error() return _error return _boolean
def visitEqExp(self, ctx: decafParser.EqExpContext): op = ctx.op.getText() eq = [_int, _char, _boolean] leftType = self.visit(ctx.left) rightType = self.visit(ctx.right) if leftType != rightType: ErrorHandler.typeError(ctx.line.start, op) self.error() return _error if (leftType not in eq) or (rightType not in eq): ErrorHandler.typeError(ctx.line.start, op) self.error() return _error return _boolean