def visitStatement(self, ctx: DecafParser.StatementContext):          
        #Rule 17 iterate through the expressions found within a for loop and check if they are digits by using a python built in feature, if not then the for loop is not valid and error displayed
        if ctx.FOR():
            for j, i in enumerate(ctx.expr()):
                if i.getText().isdigit() != True:
                    #Tell us which expr has the issue 0 = first 1 = second
                    print("[Rule 17] Expected type int for expr", j , "in this for loop but found error on line:", ctx.start.line, "is int?", i.getText().isdigit())

        #Rule 11 check if boolean has return in body! if not error out, simple check for a true or false within the statement
        if ctx.IF():
            temp = ctx.getText()
            if temp.find('true') == -1 and temp.find('false') == -1:
                print('[Rule 11] error on line', ctx.start.line, 'expected boolean type return value')
                         
        # rule 2, No identifier is used before it is declared, check if it exists in the symbol table, this rule was provided by Ryan via screencast on moodle
        if ctx.location():         
            id = ctx.location().ID().getText()
            if (self.st.lookup(id) == None):
                print("[Rule 2] error on line", ctx.start.line,'ID: (', id, ') not declared before use')
         
        if ctx.location():         
            if ctx.location().ID().getText() != None:
                if self.st.lookup(ctx.location().ID().getText()) == None:
                    print('[Rule 9] error ID  (', ctx.location().ID().getText(), ") does not exists in local/global variable or formal parameter, on line", ctx.start.line) 

        #Rule 15 check that location and expr have the same type by doing a lookup in the table if they exist if they do then test to see if types match otherwise
        #error and error if not in symbol table           
        if ctx.location() and ctx.expr():    
            lookup = self.st.lookup(ctx.location().getText())
            for i in ctx.expr():
                res = self.st.lookup(i.getText())
                if lookup == None and res == None or lookup and res and lookup.type != res.type:
                    print("[Rule 15] location and expr don't have same type")                                                     
    
        return self.visitChildren(ctx)
示例#2
0
    def visitStatement(self, ctx: DecafParser.StatementContext):
        line_num = ctx.start.line
        expression = ctx.expr(0)

        # 11 Expr of an if must have type bool
        if ctx.IF() != None:
            expr_type = self.visit(expression)
            expr_b_type = self.visit(expression.expr(0))

            print(expr_b_type)
            #if (expr_a_type != None and expr_a_type != 'boolean') or (expr_b_type != None and expr_b_type != 'boolean'):
            #print('Error on line ' + str(line_num) + ', expression in if must be of type boolean')

        elif ctx.location() != None:

            loc_type = self.visit(ctx.location())
            expr_type = self.visit(ctx.expr(0))
            operator = ctx.assign_op().getText()
            identifier = self.st.probe(ctx.location().getText())

            #2
            if identifier == None:
                print('Error on line ' + str(line_num) + ', identifier \'' +
                      ctx.location().getText() + '\' has not been declared')

            #16 - TODO change error message
            elif loc_type != None:
                if (loc_type != 'int'
                        or expr_type != 'int') and (operator == '-='
                                                    or operator == '+='):
                    print(
                        'Error on line ' + str(line_num) +
                        ' variables must be of type int when in an incrementing/decrementing assignment'
                    )

                #15
                elif loc_type != expr_type:
                    print('Error on line ' + str(line_num) +
                          ' type mismatched in expression')

        #17
        elif ctx.FOR() != None:

            expr_type_a = self.visit(ctx.expr(0))
            expr_type_b = self.visit(ctx.expr(1))

            if expr_type_a != 'int' or expr_type_b != 'int':

                print('Error on line ' + str(line_num) +
                      ' for statement expressions must be of type int')

        else:

            self.visitChildren(ctx)
    def visitStatement(self, ctx:DecafParser.StatementContext):
        if ctx.CONTINUE() != None:
            self.body += '\tjmp main\n'
        if ctx.BREAK() != None:
            self.body += '\tjmp main\n'
        if ctx.IF():
            self.st.enterScope()
            if_label = 'if-label-'+str(self.IF_LABEL_COUNT)
            self.body += '\tcmp %r11 %r10\n'
            self.body += '\tjl '+if_label+'l\n'
            self.body += '\tje '+if_label+'e\n'
            self.body += '\tjg '+if_label+'g\n'
            self.body += '\tret\n'
            self.body += if_label+':\n'
            self.IF_LABEL_COUNT = self.IF_LABEL_COUNT + 1
            ctx.expr()
            self.st.exitScope()
        if ctx.RETURN():
            if ctx.expr():
                return_value = str(ctx.expr(0).getText())
                self.body += '\tmovq $'+return_value+', %rax\n'
                self.body += '\tret\n'
            else:
                self.body += '\tret\n'
        if ctx.FOR():
            self.st.enterScope()
            start_value = ctx.expr(0)
            end_value = ctx.expr(1)
            self.body += '\tmovq $1, %rbx\n'
            self.body += '\tjmp begin-for-'+str(self.LOOP_COUNT)+'\n'
            self.body += 'begin-for-'+str(self.LOOP_COUNT)+':\n'
            self.body += '\tcmp $'+str(end_value)+ ', %rbx\n'
            self.body += '\tjge end-for-'+str(self.LOOP_COUNT)+'\n'
            visit = self.visitChildren(ctx)
            self.body += '\taddq $1, %rbx\n'
            self.body += '\tjmp begin-for-'+str(self.LOOP_COUNT)+'\n'
            self.body += 'end-for-'+str(self.LOOP_COUNT)+':\n'
            self.body += '\tret\n'

            self.LOOP_COUNT = self.LOOP_COUNT + 1
            self.st.exitScope()

        visit = self.visitChildren(ctx)
        return visit
    def visitStatement(self, ctx: DecafParser.StatementContext):
        line_number = ctx.start.line
        statmentName = ctx.location()

        if ctx.expr():
            #visit first expression
            self.visit(ctx.expr(0))

            #move the stack pointer and save value of first expression
            self.st.stack_pointer[-1] += 8
            self.body += 'movq %rax, ' + str(
                -self.st.stack_pointer[-1]) + '(%rsp)\n'

            #visit second expression
            self.visit(ctx.expr(0))

            self.body += 'movq ' + str(
                -self.st.stack_pointer[-1]) + '(%rsp), %r10\n'
            self.st.stack_pointer[-1] -= 8
            self.body += 'movq %rax, %r11\n'
        """if a loction exists then assign the locaton varible to look on the symbol table"""
        if ctx.location():
            location = self.st.lookup(ctx.location().getText())

            if ctx.expr():
                expr = ctx.expr(0).expr(0)

                if expr.literal():
                    if self.st.lookup(location.id).type == "boolean":
                        try:
                            """if the lookup if type returns a boolean then try to int the expression if that is possible throw an error"""
                            int(ctx.expr(0).expr(0).getText())
                            print(
                                "ERROR: cannot assign boolean to int, line number:",
                                line_number)
                        except:
                            """if that fails it can be assumed that the opertor is wrong"""
                            print(
                                "ERROR cannot use that operator with booleans, line number:",
                                line_number)

        if ctx.breaknCon() != None:
            self.breakncon = ctx.breaknCon().getText()
        if ctx.FOR():
            """try and int the item in side of the for loop if that fails error"""
            for items in ctx.expr():
                try:
                    int(items.getText())
                except:
                    if items.location() != None:
                        if self.st.lookup(
                                items.location().getText()).type != "int":
                            print("ERROR: type is not int. Line number:",
                                  line_number)
                    else:
                        print(
                            "ERROR: type int must be used here in for loop. Line number:",
                            line_number)
        """
        if an if statment exists then check  
        if the expression is an boolean
        
        check if you are comparing two things of the same types 
        """
        if ctx.IF() != None:

            if ctx.expr(0).bin_op() == None:
                if self.st.lookup(ctx.expr(0).getText()).type != "boolean":
                    print(
                        "ERROR", "cannot evaluate type " +
                        self.st.lookup(ctx.expr(0).getText()).type +
                        " to boolean, on line:", line_number)
            else:
                """get the eq operator """
                self.eq_op = ctx.expr(0).bin_op().eq_op().getText()
                if ctx.expr(0).bin_op():
                    """get the bin op """
                    bin_op = ctx.expr(0).bin_op().getText()

                    ids = ctx.expr(0).getText().replace(bin_op, "")
                    """make a list out of all the ids"""
                    listOfIds = list(ids)
                    """compare the operands of of bin_op and if they are not the same type then error"""
                    if self.st.lookup(listOfIds[0]).type != self.st.lookup(
                            listOfIds[1]).type:
                        print(
                            "cannot compare " +
                            self.st.lookup(listOfIds[0]).type + " with " +
                            self.st.lookup(listOfIds[1]).type + " line number",
                            line_number)
                else:
                    """if bin op is not found get the type of the expression and if it's not boolean, throw an error"""
                    if self.st.lookup(ctx.expr(0).getText()).type != "boolean":
                        print(
                            "ERROR: " + "cannot evaluate type int line number",
                            line_number)

        if self.eq_op != None:
            expression = ctx.expr(0).getText()
            ids = expression.replace(self.eq_op, "")
            idList = list(ids)
            """check if the operands logical and  or both boolean"""
            if self.st.lookup(idList[0]).type and self.st.lookup(
                    idList[1]).type != "boolean":
                print("ERROR: cannot use logical not here. Line number:",
                      line_number)
        expr = ctx.expr(0)
        expArrry = []
        if expr != None:
            if "+ " in expr.getText():
                """make an array of the epressions"""
                expArrry = expr.replace("+", ",")
                expArrry = expArrry.split(",")
        var_name = None
        varnames = None
        for varnames in expArrry:
            var_name = self.st.lookup(varnames)
            if var_name != None:
                pass
            else:
                """error if symbol is on symbol table already"""
                print(
                    "ERROR: varible referanced but never assinged " + " '" +
                    varnames + "' " + "on line", line_number)
        if statmentName != None:
            var_symbol = self.st.lookup(statmentName.getText())
            if var_symbol != None:
                pass
            else:
                print("ERROR:", "varible referanced but never assinged", "'",
                      statmentName.getText() + "'", "on line", line_number)
        return self.visitChildren(ctx)