def visitMethod_decl(self, ctx:DecafParser.Method_declContext):
        method_name = ctx.ID(0).getText()
        return_type = ctx.TYPE(0)
        line_number = ctx.start.line

        # Checks if the method has already been declared.
        if self.st.probe(method_name) != None:
            print('[Error]: The method ' + method_name + ' on line: ' + line_number + 'was already declared!')
        else:
            self.body += method_name
            self.body += ':\n'

        params = []

        # Loops through paramaters and creates a var symbol for them and appends them to a list.
        if len(params) > 1:
            for param in range(len(ctx.ID())):
                param_name = ctx.ID(param).getText()
                params.append(param_name)
                var_symbol = self.st.probe(param_name)
                if var_symbol == None:
                    var_symbol = VarSymbol(id=param_name, type='int', line=ctx.start.line, size=8, mem=self.st.stack_pointer)
                    self.st.addSymbol(var_symbol)
                    var_addr = var_symbol.getAddr()
                    self.body += '\tmovq %rax, -' + str(var_addr[0]) + '(%rsp)\n'

            params.pop(0)

        method_symbol = MethodSymbol(id=method_name, type=return_type, line=line_number, params=params)
        self.st.addSymbol(method_symbol)

        visit = self.visitChildren(ctx)
        return visit
    def visit_ProcedureDecl(self, node):
        proc_name = node.proc_name
        proc_symbol = ProcedureSymbol(proc_name)
        self.current_scope.insert(proc_symbol)

        print('ENTER scope: %s' % proc_name)
        # Scope for parameters and local variables
        procedure_scope = ScopedSymbolTable(
            scope_name=proc_name,
            scope_level=self.current_scope.scope_level + 1,
            enclosing_scope=self.current_scope)

        self.current_scope = procedure_scope

        # Insert parameters into the procedure scope
        for param in node.params:
            param_type = self.current_scope.lookup(param.type_node.value)
            param_name = param.var_node.value
            var_symbol = VarSymbol(param_name, param_type)
            self.current_scope.insert(var_symbol)
            proc_symbol.params.append(var_symbol)

        self.visit(node.block_node)
        print(procedure_scope)
        self.current_scope = self.current_scope.enclosing_scope
        print('LEAVE scope: %s' % proc_name)
Beispiel #3
0
    def visitField_decl(self, ctx:DecafParser.Field_declContext):
        line_num = ctx.start.line
        data_type = ctx.data_type().getText()
        field_decls = ctx.field_arg()
                
        for f in field_decls:
            
            array_size = 0
            field_symbol = self.st.probe(f.getText())
            
            if f.int_literal() != None:
                
                array_size = f.int_literal().getText()
                
                if int(array_size) <= 0:
                
                    print('Error on line', line_num,', array \'', f.ID().getText(),'\' must have a declaration value greater than 0')
            
            if field_symbol != None:
    
                print('Error on line', line_num,', variable \'', f.ID().getText(),'\' has already been declared on line',field_symbol.line)
                
            else:

                field_symbol = VarSymbol(id=f.ID().getText(),
                                         type=data_type,
                                         line=line_num,
                                         size=8,
                                         mem=HEAP)
                
                self.st.addSymbol(field_symbol)
                        
        self.visitChildren(ctx)
    def visit_FunctionDecl(self, node):
        func_name = node.func_name

        type_name = node.return_type.value
        type_symbol = self.current_scope.lookup(str.upper(type_name))
        func_symbol = FunctionSymbol(func_name, type_symbol)

        self.current_scope.insert(func_symbol)

        print('ENTER scope: %s' % func_name)

        # Scope for parameters and local variables
        function_scope = ScopedSymbolTable(
            scope_name=func_name,
            scope_level=self.current_scope.scope_level + 1,
            enclosing_scope=self.current_scope)

        self.current_scope = function_scope

        # Insert parameters into the function_scope
        for param in node.params:
            param_type = self.current_scope.lookup(
                str.upper(param.type_node.value))
            param_name = param.var_node.value
            var_symbol = VarSymbol(param_name, param_type)
            self.current_scope.insert(var_symbol)
            func_symbol.params.append(var_symbol)

        self.visit(node.block_node)
        print(function_scope)
        self.current_scope = self.current_scope.enclosing_scope
        print('LEAVE scope: %s' % func_name)
    def visitVar_decl(self, ctx: DecafParser.Var_declContext):
        line_num = ctx.start.line
        var_ids = ctx.ID()
        data_type = ctx.data_type().getText()

        for v in var_ids:

            id_symbol = self.st.probe(v.getText())

            if id_symbol != None:

                # 1
                print('Error on line ' + str(line_num) + ', variable \'' +
                      v.getText() + '\' has already been declared on line ' +
                      str(id_symbol.line))

            else:

                id_symbol = VarSymbol(id=v.getText(),
                                      type=data_type,
                                      line=line_num,
                                      size=8,
                                      mem=STACK)

                self.st.addSymbol(id_symbol)

        self.visitChildren(ctx)
Beispiel #6
0
    def visitMethod_decl(self, ctx: DecafParser.Method_declContext):
        line_num = ctx.start.line
        method_name = ctx.ID(0).getText()
        method_type = ctx.return_type().getText()
        method_params = []

        for i in range(len(ctx.data_type())):
            param_type = ctx.data_type(i).getText()
            param_name = ctx.ID(i + 1).getText()
            param_symbol = VarSymbol(id=param_name, type=param_type, line=line_num, size=8, mem=STACK)
            method_params.append(param_symbol)

        method_symbol = MethodSymbol(method_name,
                                     method_type,
                                     line_num,
                                     method_params)
        self.st.addSymbol(method_symbol)

        self.body += method_name + ':\n'
        if method_name == 'main':
            self.body += 'movq %rsp, %rbp\n'

        self.st.enterScope()
        for i in range(len(method_params)):
            self.st.addSymbol(method_params[i])
            self.body += 'movq ' + param_registers[i] + ',' + str(method_params[i].getAddr()) + '(%rsp)\n'

        self.visitChildren(ctx)
        self.body += 'ret\n'
        self.st.exitScope()
Beispiel #7
0
    def visitField_decl(self, ctx: DecafParser.Field_declContext):
        line_num = ctx.start.line
        data_type = ctx.data_type().getText()

        field_count = len(ctx.field_name())
        for i in range(field_count):
            field_name = ctx.field_name(i).getText()

            if ctx.field_name(i).int_literal():
                array_size = int(ctx.field_name(i).int_literal().getText())
                if array_size <= 0:
                    print('Error on line', line_num, 'array declared with length 0')
            else:
                array_size = 1

            field_symbol = self.st.probe(field_name)

            if field_symbol:
                print('Error on line', line_num, 'field', field_name, 'is already declared on line', field_symbol.line)
            else:
                field_symbol = VarSymbol(id=field_name,
                                         type=data_type,
                                         line=line_num,
                                         size=8 * array_size,
                                         mem=HEAP)
                self.st.addSymbol(field_symbol)

        self.visitChildren(ctx)
    def visitVar_decl(self, ctx:DecafParser.Var_declContext):

        # Loops through all variables (to evaluate int x, y, z for example.)
        for i in range(len(ctx.ID())):
            var_name = ctx.ID(i).getText()
            var_symbol = self.st.probe(var_name)
            if "[" in var_name:
                array_var_name = ctx.ID(i).getText()
                split_var = array_var_name.split('[', 1)[0]
            else:
                if var_symbol == None:
                    var_symbol = VarSymbol(id=var_name, type='int', line=ctx.start.line, size=8, mem=self.st.stack_pointer)
                    self.st.addSymbol(var_symbol)
                    var_addr = var_symbol.getAddr()
                    self.body += '\tmovq %rax, -' + str(var_addr[0]) + '(%rsp)\n'
                else:
                    print('[Error]:', var_symbol.id + ', declared on line', ctx.start.line, 'has already been declared on line', var_symbol.line)

        visit = self.visitChildren(ctx)
        return visit
    def visit_VarDecl(self, node):
        type_name = node.type_node.value
        type_symbol = self.current_scope.lookup(type_name)

        # We have all the information we need to create a variable symbol.
        # Create the symbol and insert it into the symbol table.
        var_name = node.var_node.value
        var_symbol = VarSymbol(var_name, type_symbol)

        # Signal an error if the table alrady has a symbol
        # with the same name
        if self.current_scope.lookup(var_name, current_scope_only=True):
            raise Exception("Error: Duplicate identifier '%s' found" %
                            var_name)

        self.current_scope.insert(var_symbol)
Beispiel #10
0
    def visit_VarDecl(self, node):
        type_name = node.type_node.value
        type_symbol = self.current_scope.lookup(type_name)

        var_name = node.var_node.value
        var_symbol = VarSymbol(var_name, type_symbol)

        if(self.current_scope.lookup(var_name, current_scope_only=True) is not None):
            raise NameError("Cannot initialize a variable that has already been declared '" + str(var_name) + "' on line: " + str(node.token.get_line()))

        self.current_scope.insert(var_symbol)

        if(node.assign_node):
            self.visit(node.assign_node)

        return var_symbol
    def visitVardeclr(self, ctx: DecafParser.VardeclrContext):
        vtype = None
        vid = None
        for i in ctx.children:
            tkn = i.getText()
            if tkn == 'int' or tkn == 'boolean':
                vtype = tkn
            elif tkn == ',' or tkn == ';':
                continue
            elif tkn != None:
                vid = tkn
                if self.st.probe(vid) != None:
                    raiseErr("Variable " + vid + " already declared in scope.",
                             ctx)

                self.st.addSymbol(VarSymbol(vid, vtype, 0, 8, 0))
        return self.visitChildren(ctx)
Beispiel #12
0
    def visitVar_decl(self, ctx: DecafParser.Var_declContext):
        # semantic rule: No identifier is declared twice in the same scope
        # test with testdata/semantics/illegal-01.dcf
        line_num = ctx.start.line
        for var_decl in ctx.ID():
            var_name = var_decl.getText()  # gets the variable name (eg. x)
            var_symbol = self.st.probe(
                var_name)  # search Symbol Table for variable entry

            if var_symbol != None:  # if variable does NOT exist in Symbol Table
                print('Error on line', line_num, 'variable \'', var_name,
                      '\' already declared on line', var_symbol.line)
            else:
                var_symbol = VarSymbol(id=var_name,
                                       type='int',
                                       line=line_num,
                                       size=8,
                                       mem=STACK)
                self.st.addSymbol(
                    var_symbol
                )  # add var_symbol to the scope (st abbreviation of SymbolTable)

        return self.visitChildren(ctx)
Beispiel #13
0
    def visitMethod_arg(self, ctx: DecafParser.Method_argContext):
        line_num = ctx.start.line
        data_type = ctx.data_type().getText()
        var_decls = ctx.ID().getText()
        var_symbol = self.st.probe(var_decls)

        if var_symbol != None:
            # 1
            print(
                'Error on line', line_num, ', variable \'', var_decls,
                '\' has already been declared on line ' + str(var_symbol.line))

        else:

            print(var_decls)
            var_symbol = VarSymbol(id=var_decls,
                                   type=data_type,
                                   line=line_num,
                                   size=8,
                                   mem=STACK)

            self.st.addSymbol(var_symbol)

        self.visitChildren(ctx)
Beispiel #14
0
    def visitMethod_decl(self, ctx:DecafParser.Method_declContext):
        data_type = ""
        line_num = ctx.start.line
        method_name = ctx.ID().getText()
        method_args = ctx.method_arg()
        method_params = []
        
        if ctx.data_type() != None:
            data_type = ctx.data_type().getText()
        else:
            data_type = "void"

        for i in method_args:
            arg_type = i.data_type().getText()
            method_arg = VarSymbol(id=i.ID().getText(), type=arg_type, line=line_num, size=8, mem=STACK)
            method_params.append(method_arg)

        method_symbol = MethodSymbol(id=method_name,
                                         type=data_type,
                                         line=line_num,
                                         params=method_params)
        
        self.body += method_name + ':\n'
        
        if method_name == 'main':
            self.body += 'movq %rsp, %rbp\n'
            
        self.st.enterScope()
        for i in range(len(method_params)):
            self.st.addSymbol(method_params[i])
            #Saving each method parameter onto a location on the stack(Memory)
            self.body += 'movq ' + param_registers[i] + ',' + str(method_params[i].getAddr()) + '(%rsp)\n'
        
        self.visitChildren(ctx)
        self.body += 'ret\n'
        self.st.exitScope()
    def visitField_decl(self, ctx:DecafParser.Field_declContext):
        for i in range(len(ctx.field_name())):
            var_name = ctx.field_name(i).getText()
            var_symbol = self.st.probe(var_name)

            # Declaration is an array.
            if "[" in var_name:
                array_var_name = ctx.field_name(i).getText()
                split_var = array_var_name.split('[', 1)[0]
                if var_symbol == None:
                    var_symbol = VarSymbol(id=split_var, type='int', line=ctx.start.line, size=8, mem=self.st.stack_pointer)
                    self.st.addSymbol(var_symbol)
                    var_addr = var_symbol.getAddr()
                    self.body += '\tmovq %rax, -' + str(var_addr[0]) + '(%rsp)\n'
            else:
                if var_symbol == None:
                    var_symbol = VarSymbol(id=var_name, type='int', line=ctx.start.line, size=8, mem=self.st.stack_pointer)
                    self.st.addSymbol(var_symbol)
                    var_addr = var_symbol.getAddr()
                    self.body += '\tmovq %rax, -' + str(var_addr[0]) + '(%rsp)\n'
                else:
                    print('[Error]:', var_symbol.id + ', declared on line', ctx.start.line, 'has already been declared on line', var_symbol.line)
        visit = self.visitChildren(ctx)
        return visit
    def visitVar_decal(self, ctx: DecafParser.Var_decalContext):
        line_number = ctx.start.line
        var_name = ctx.var_name(0).id(0).getText()
        var_value = ctx.var_value()

        if self.st.lookup(var_name) != None:
            if self.st.lookup(var_name).type == "array" and ctx.assign_op:
                value = var_value.getText()
                """
                check if an array is being evaluated to anything but an array
                """
                try:
                    if self.st.lookup(value).type != "int":
                        print(
                            "ERROR: cannot evaluate array to int, line number:",
                            line_number)
                    else:
                        int(value)
                except:
                    print("ERROR: cannot evaluate array to int, line number:",
                          line_number)
        """
        check if a varible is decalred twice
        """
        if "=" in ctx.getText():
            pass
        else:

            if self.st.probe(var_name) != None:
                print("ERROR: varible", "'" + var_name + "'", "decalred twice",
                      " on line", line_number)
            else:
                for i in range(len(ctx.var_name())):
                    if "[" in var_name:
                        Feild_decalsysmbol = VarSymbol(
                            id=var_name.id().getText(),
                            type="array",
                            line=line_number,
                            size=8,
                            mem=SymbolTable.HEAP)
                        self.st.addSymbol(Feild_decalsysmbol)
                    else:
                        if ctx.var_type(0) != None:
                            Feild_decalsysmbol = VarSymbol(
                                id=ctx.var_name(i).id(0).getText(),
                                type=ctx.var_type(0).getText(),
                                line=line_number,
                                size=8,
                                mem=SymbolTable.STACK)
                            self.st.addSymbol(Feild_decalsysmbol)

        VarNames = ctx.var_name()
        for i in range(len(VarNames)):
            for j in range(i + 1, len(VarNames)):
                if VarNames[i].getText() == VarNames[j].getText():
                    print("ERROR: varible", "'" + VarNames[i].getText() + "'",
                          "decalred twice", " on line", line_number)
                else:
                    for k in VarNames:
                        Feild_decalsysmbol = VarSymbol(id=k,
                                                       type=type,
                                                       line=ctx.var_type(i),
                                                       size=8,
                                                       mem=SymbolTable.STACK)
                        self.st.addSymbol(Feild_decalsysmbol)

        if ctx.assign_op() != None:
            """var_name_type = self.st.lookup(var_name).type"""
            """
            check that the operands of "+="  and -= is not a boolean or int
            """
            if "+=" in ctx.assign_op().getText() or "-=" in ctx.assign_op(
            ).getText():
                for items in ctx.var_name():
                    var_name = items.getText()
                    var_name_type = self.st.lookup(var_name).type
                    if var_name_type == "boolean":
                        if ctx.var_value().getText(
                        ) == "true" or ctx.var_value().getText() == "false":
                            print(
                                "ERROR: cannot assign boolean here, line number:",
                                line_number)
                        else:
                            var_name_type = self.st.lookup(var_name).type
                            var_value_type = self.st.lookup(
                                var_value.id().getText()).type
                            if var_name_type and var_value_type != "int":
                                print(
                                    "ERROR: type int must be used when using",
                                    ctx.assign_op().getText(), "line number",
                                    line_number)
            else:
                if self.st.lookup(var_value.id()) != None:
                    """
                    check a var_name is being assinged to the same type of var_value
                    """
                    if self.st.lookup(var_name).type != self.st.lookup(
                            var_value.id().getText()).type:
                        var_name_type = self.st.lookup(var_name).type
                        var_value_type = self.st.lookup(
                            var_value.id().getText()).type
                        print("cannot assign", var_name_type, "to",
                              var_value_type)
                else:
                    if self.st.lookup(var_name) != None:
                        if self.st.lookup(var_name).type == "int":
                            try:
                                int(var_value.getText())
                            except:
                                pass
                                #var_name_type = self.st.lookup(var_name).type
                                #print("cannot assign", var_name_type,"to this type here", line_number )

        if ctx.var_name(0).expr() != None:
            exprID = ctx.var_name(0).expr().getText()
            exprType = self.st.lookup(exprID).type
            """
            check the type of expression as it must be int
            """
            if exprType != "int":
                print(
                    "ERROR: expected int, got " + exprType +
                    " instead, line number:", line_number)
        """
        check if an array has an int and not any other type
        """
        if "[" in ctx.var_name(0).getText():
            if self.st.lookup(var_name).type != "array":
                errorType = self.st.lookup(var_name).type
                print("ERROR: varible needs to be an array type not",
                      errorType, "on line", line_number)
        """
        check var name existed before it assinged
        """
        if var_name:
            var_symbol = self.st.lookup(var_name)
            if var_symbol != None:
                for i in range(len(ctx.var_name())):
                    if "=" in ctx.getText():
                        #get var_name from the text
                        var_name = ctx.var_name(i).id(0).getText()
                        #get symbol of vars from symbol table
                        var_symbol = self.st.lookup(var_name)
                        #get address of symbol
                        var_addr = var_symbol.getAddr()

                        self.body += 'movq ' + str(var_addr) + '(%rsp), %rax\n'
            else:
                print(
                    "ERROR:", "varible referanced but never assinged " + "'" +
                    var_name + "' " + "on line", line_number)

        if var_value != None:
            var_value = var_value.getText()
            if '()' in var_value:
                var_value = self.st.lookup(var_value)
                if var_symbol != None:
                    pass
                else:
                    print(
                        "ERROR:", "varible referanced but never assinged " +
                        "'" + var_name + "' " + "on line", line_number)
        return self.visitChildren(ctx)
    def visitFeild_decal(self, ctx: DecafParser.Feild_decalContext):
        """
        line_number is used in all further methods, it is used to get the line number which 
        something is written on
        """
        line_number = ctx.start.line
        Feildtype = ctx.field_type().getText()
        """get the id of the vield decal"""
        feildVarName = ctx.feild_name(0).id().getText()
        """get the field name to check if it already exisits"""
        VarName = ctx.feild_name(0)

        if self.st.probe(feildVarName) != None:
            print("ERROR: varible", "'" + feildVarName + "'", "decalred twice",
                  " on line", line_number)
        else:
            """check if the var_name contains a [ is it does then it's a array varible """
            if "[" in VarName.getText():

                int_litereal = None
                for i in range(len(ctx.feild_name())):
                    int_litereal = ctx.feild_name(i).int_litereal()

                if int_litereal != None:
                    int_litereal = int_litereal.getText()
                    """check  that the int litereal is bigger than zero"""
                    if int(int_litereal) > 0:
                        """if everything is samanticly valid add the array to the symbol table"""
                        Feild_decalsysmbol = VarSymbol(
                            id=VarName.id().getText(),
                            type="array",
                            line=line_number,
                            size=8,
                            mem=SymbolTable.HEAP)
                        self.st.addSymbol(Feild_decalsysmbol)
                    else:
                        print(
                            "ERROR: arrays of length zero are not allowed" +
                            ", line", line_number)

            else:
                Feild_decalsysmbol = VarSymbol(id=feildVarName,
                                               type=Feildtype,
                                               line=line_number,
                                               size=8,
                                               mem=SymbolTable.HEAP)

                self.st.addSymbol(Feild_decalsysmbol)
        val = self.visitChildren(ctx)
        feildVarNames = ctx.feild_name()
        """
        loop through the array of all feild decals and check if any of them have 
        already decalred by comparing the all of the field names againt each other
        """
        for i in range(len(feildVarNames)):
            for j in range(i + 1, len(feildVarNames)):
                if feildVarNames[i].getText() == feildVarNames[j].getText():
                    print("ERROR: varible",
                          "'" + feildVarNames[i].getText() + "'",
                          "decalred twice", " on line", line_number)
                else:
                    """if everything is valid add to symbol table"""
                    for k in feildVarNames:
                        Feild_decalsysmbol = VarSymbol(id=k,
                                                       type=Feildtype,
                                                       line=line_number,
                                                       size=8,
                                                       mem=SymbolTable.HEAP)
                        self.st.addSymbol(Feild_decalsysmbol)
        return val
    def visitMethod_decl(self, ctx: DecafParser.Method_declContext):

        self.params
        param_types = []
        ctx.method_param_type()
        #line used for debugging
        #print(ctx.method_param_type(0).getText())
        method_name = ctx.id(0).getText()
        return_type = ctx.method_type().getText()
        line_number = ctx.start.line

        for i in range(len(ctx.method_param_type())):
            param_types.append(ctx.method_param_type(i).getText())

        for i in range(len(ctx.method_Param_names())):
            self.params.append(ctx.method_Param_names(i).getText())

        #line used for debugging
        #print(ctx.method_Param_names(0).getText())

        for i in range(len(param_types)):
            if self.params == []:
                method_params = VarSymbol(id=self.params[i],
                                          type=param_types[i],
                                          line=line_number,
                                          size=8,
                                          mem=SymbolTable.STACK)
                self.st.addSymbol(method_params)
            else:
                method_params = VarSymbol(id=self.params[i],
                                          type=param_types[i],
                                          line=line_number,
                                          size=8,
                                          mem=SymbolTable.STACK)
                self.st.addSymbol(method_params)

                method_symbol = MethodSymbol(id=method_name,
                                             type=return_type,
                                             line=line_number,
                                             params=ctx.method_Param_names())
                self.st.addSymbol(method_symbol)
        if self.st.lookup(method_name) != None:
            for i in range(len(self.st.lookup(method_name).params)):

                method_params = VarSymbol(
                    id=ctx.method_Param_names(i).getText(),
                    type=ctx.method_param_type(i).getText(),
                    line=line_number,
                    size=8,
                    mem=SymbolTable.STACK)
                self.st.addSymbol(method_params)
        """don't add main to code more than once"""
        if "main" in method_name:
            pass
        else:
            self.body += method_name + ":" + "\n"
        """get the statment in the return statment"""
        returnStatment = ctx.block().statement()
        if returnStatment != None:
            for item in returnStatment:
                if "if" in item.getText():
                    pass
                elif "return" in item.getText():
                    if self.st.lookup(item.expr(0)) == None:
                        """if return of method is void then throw and error"""
                        if return_type == "void":
                            print("method on line:", line_number,
                                  "should not return anything")
                        elif return_type == "int":
                            """try to int the expr, if that fails throw an error"""
                            try:
                                int(item.expr(0).getText())
                            except:
                                print(
                                    "ERROR: wrong return type found for method on line:",
                                    line_number)
                        elif self.st.lookup(
                                item.expr(0).getText()).type != return_type:
                            print(
                                "ERROR: type of retrun statement does not match method return type, line number:",
                                line_number)
                        else:
                            Addr = self.st.lookup(
                                item.expr(0).getText()).getAddr()

                            self.st.stack_pointer[-1] += 8
                            self.body += 'movq %rax, ' + str(
                                -self.st.stack_pointer[-1]) + '(%rsp)\n'

                            self.body += "movq " + str(
                                Addr) + " (%rbp), " + " %rax" + "\n" ""

        if return_type == "int" and returnStatment == []:
            print("ERROR: method missing return statement", line_number)
        if return_type == "boolean" and returnStatment == []:
            print("ERROR: method missing return statement", line_number)
        return self.visitChildren(ctx)