Example #1
0
 def visitPrimary(self, parsetree: SmallCParser.PrimaryContext):
     try:
         if parsetree.INTEGER() is not None:
             value = int(parsetree.INTEGER().getText())
             return Primary(self.environment, value)
         elif parsetree.REAL() is not None:
             real = parsetree.REAL().getText()
             value = float(real)
             return Primary(self.environment, value)
         elif parsetree.CHARCONST() is not None:
             value = parsetree.CHARCONST().getText()
             # We are interested in the first character after the quotation
             # mark
             return Primary(self.environment, value[1])
         elif parsetree.BOOLEAN() is not None:
             value = parsetree.BOOLEAN().getText() == "true"
             return Primary(self.environment, value)
         elif parsetree.identifier() is not None:
             return self.visit(parsetree.identifier())
         elif parsetree.expr() is not None:
             return self.visit(parsetree.expr())
         elif parsetree.functioncall() is not None:
             return self.visit(parsetree.functioncall())
     except C2PException as e:
         line = parsetree.start.line
         column = parsetree.start.column
         MyErrorListener().semanticError(line, column, e.msg)
     line = parsetree.start.line
     column = parsetree.start.column
     msg = "unrecognized primary"
     MyErrorListener().semanticError(line, column, msg)
Example #2
0
    def visitVariable_id(self, parsetree: SmallCParser.Variable_idContext):
        is_pointer = parsetree.identifier().ASTERIKS() is not None
        is_alias = parsetree.identifier().AMPERSAND() is not None

        if parsetree.identifier().array_indexing() is None:
            array_size = 0
            array_elements = []
        else:
            # NOTE we assumed this is an integer
            array_size = int(parsetree.identifier(
            ).array_indexing().expr().getText())
            if parsetree.identifier().array_init() is not None:
                if parsetree.expr() is not None:
                    line = parsetree.start.line
                    column = parsetree.start.column
                    msg = "Illegal initialization for array '" + \
                        parsetree.identifier().IDENTIFIER().getText() + "'"
                    MyErrorListener().semanticError(line, column, msg)
                array_elements = self.visit(
                    parsetree.identifier().array_init())
                    
        if is_pointer or is_alias:
            identifier = parsetree.identifier().getChild(1).getText()
        else:
            identifier = parsetree.identifier().getChild(0).getText()

        if parsetree.expr() is None:
            expression = None
        else:
            expression = self.visit(parsetree.expr())

        return VariableIdentifier(self.environment, identifier, expression, is_pointer, is_alias, array_size, array_elements)
Example #3
0
 def visitStmt(self, parsetree: SmallCParser.StmtContext):
     if parsetree.compound_stmt() is not None:
         return self.visit(parsetree.compound_stmt())
     elif parsetree.cond_stmt() is not None:
         return self.visit(parsetree.cond_stmt())
     elif parsetree.while_stmt() is not None:
         return self.visit(parsetree.while_stmt())
     elif parsetree.for_stmt() is not None:
         return self.visit(parsetree.for_stmt())
     elif parsetree.BREAK() is not None:
         return BreakStatement(self.environment)
     elif parsetree.CONTINUE() is not None:
         return ContinueStatement(self.environment)
     elif parsetree.RETURN() is not None:
         expression = self.visit(parsetree.expr())
         return ReturnStatement(self.environment, expression)
     elif parsetree.expr() is not None:
         return self.visit(parsetree.expr())
     elif parsetree.assignment() is not None:
         return self.visit(parsetree.assignment())
     elif parsetree.functioncall() is not None:
         return self.visit(parsetree.functioncall())
     else:
         line = parsetree.start.line
         column = parsetree.start.column
         msg = "unrecognized statement"
         MyErrorListener().semanticError(line, column, msg)
Example #4
0
    def visitAssignment(self, parsetree: SmallCParser.AssignmentContext):
        identifier = self.visit(parsetree.identifier())
        expression = self.visit(parsetree.expr())

        if identifier.array_size:
            if parsetree.expr() is not None:
                line = parsetree.start.line
                column = parsetree.start.column
                msg = "Cannot reinitialize array '" + identifier.name + "'"
                MyErrorListener().semanticError(line, column, msg)

        try:
            return Assignment(self.environment, identifier, expression)
        except C2PException as e:
            line = parsetree.start.line
            column = parsetree.start.column
            MyErrorListener().semanticError(line, column, e.msg)
Example #5
0
 def visitExpr(self, parsetree: SmallCParser.ExprContext):
     if parsetree.assignment() is not None:
         return self.visit(parsetree.assignment())
     elif parsetree.condition() is not None:
         return self.visit(parsetree.condition())
     elif parsetree.functioncall() is not None:
         return self.visit(parsetree.functioncall())
     else:
         line = parsetree.start.line
         column = parsetree.start.column
         msg = "unrecognized expression"
         MyErrorListener().semanticError(line, column, msg)
Example #6
0
    def visitVar_decl(self, parsetree: SmallCParser.Var_declContext):
        type_specifier = self.visit(parsetree.type_specifier())
        type_object = type_specifier.type_object

        var_decl_list = self.visit(parsetree.var_decl_list())

        try:
            return VariableDeclaration(self.environment, type_object, var_decl_list)
        except C2PException as e:
            line = parsetree.start.line
            column = parsetree.start.column
            MyErrorListener().semanticError(line, column, e.msg)
Example #7
0
    def visitFunctioncall(self, parsetree: SmallCParser.FunctioncallContext):
        identifier = parsetree.identifier().IDENTIFIER().getText()
        if parsetree.param_list() is None:
            parameter_list = ParameterList(self.environment, [])
        else:
            parameter_list = self.visit(parsetree.param_list())

        try:
            return FunctionCall(self.environment, identifier, parameter_list)
        except C2PException as e:
            line = parsetree.start.line
            column = parsetree.start.column
            MyErrorListener().semanticError(line, column, e.msg)
Example #8
0
    def visitFactor(self, parsetree: SmallCParser.FactorContext):
        if parsetree.factor() is not None:
            factor = self.visit(parsetree.factor())
            if parsetree.EXCLAMATIONMARK() is not None:
                operator = parsetree.EXCLAMATIONMARK().getText()
            else:
                operator = parsetree.MINUS().getText()
            try:
                return Factor(self.environment, factor, operator)
            except C2PException as e:
                line = parsetree.start.line
                column = parsetree.start.column
                MyErrorListener().semanticError(line, column, e.msg)

        return self.visit(parsetree.primary())
Example #9
0
    def visitEquation(self, parsetree: SmallCParser.EquationContext):
        if parsetree.equation() is not None:
            equation = self.visit(parsetree.equation())
            term = self.visit(parsetree.term())
            if parsetree.MINUS() is None:
                operator = parsetree.PLUS().getText()
            else:
                operator = parsetree.MINUS().getText()
            try:
                return Equation(self.environment, equation, term, operator)
            except C2PException as e:
                line = parsetree.start.line
                column = parsetree.start.column
                MyErrorListener().semanticError(line, column, e.msg)

        return self.visit(parsetree.term())
Example #10
0
    def visitRelation(self, parsetree: SmallCParser.RelationContext):
        if len(parsetree.equation()) == 2:
            equation1 = self.visit(parsetree.equation(0))
            equation2 = self.visit(parsetree.equation(1))
            if parsetree.LEFTANGLE() is not None:
                operator = parsetree.LEFTANGLE().getText()
            else:
                operator = parsetree.RIGHTANGLE().getText()
            try:
                return Relation(self.environment, equation1, equation2, operator)
            except C2PException as e:
                line = parsetree.start.line
                column = parsetree.start.column
                MyErrorListener().semanticError(line, column, e.msg)

        return self.visit(parsetree.equation(0))
Example #11
0
    def visitComparison(self, parsetree: SmallCParser.ComparisonContext):
        if len(parsetree.relation()) == 2:
            relation1 = self.visit(parsetree.relation(0))
            relation2 = self.visit(parsetree.relation(1))
            if parsetree.EQUALITY() is not None:
                operator = parsetree.EQUALITY().getText()
            else:
                operator = parsetree.NEQUALITY().getText()
            try:
                return Comparison(self.environment, relation1, relation2, operator)
            except C2PException as e:
                line = parsetree.start.line
                column = parsetree.start.column
                MyErrorListener().semanticError(line, column, e.msg)

        return self.visit(parsetree.relation(0))
Example #12
0
    def visitTerm(self, parsetree: SmallCParser.TermContext):
        if parsetree.term() is not None:
            term = self.visit(parsetree.term())
            factor = self.visit(parsetree.factor())
            if parsetree.SLASH() is not None:
                operator = parsetree.SLASH().getText()
            elif parsetree.PROCENT() is not None:
                operator = parsetree.PROCENT().getText()
            else:
                operator = parsetree.ASTERIKS().getText()
            try:
                return Term(self.environment, term, factor, operator)
            except C2PException as e:
                line = parsetree.start.line
                column = parsetree.start.column
                MyErrorListener().semanticError(line, column, e.msg)

        return self.visit(parsetree.factor())
Example #13
0
    def visitFunction_definition(self, parsetree: SmallCParser.Function_definitionContext):
        self.environment.symbol_table.incrementScope()
        self.environment.call_stack.incrementDepth()

        type_spec = self.visit(parsetree.type_specifier())
        return_type = type_spec.type_object

        identifier = parsetree.identifier()
        func_name = identifier.IDENTIFIER().getText()
        return_type.is_pointer = identifier.ASTERIKS() is not None
        return_type.is_reference = identifier.AMPERSAND() is not None

        if parsetree.param_decl_list() is None:
            parameter_decl_list = ParameterDeclarationList(
                self.environment, [])
        else:
            parameter_decl_list = self.visit(parsetree.param_decl_list())

        address = self.environment.call_stack.getAddress()
        depth = self.environment.call_stack.getNestingDepth()

        self.environment.symbol_table.addFunction(
            func_name, return_type, parameter_decl_list, address, depth - 1)

        if parsetree.compound_stmt() is None:
            # forward declaration
            statements = None
        else:
            # function definition
            statements = self.visitCompound_stmt(parsetree.compound_stmt())

        self.environment.call_stack.decrementDepth()

        try:
            func = Function(self.environment, return_type, func_name, parameter_decl_list,
                            statements, parsetree.EXTERN() is not None)

            return func
        except C2PException as e:
            line = parsetree.start.line
            column = parsetree.start.column
            MyErrorListener().semanticError(line, column, e.msg)

        self.environment.symbol_table.decrementScope()
Example #14
0
def run(input_file, output, saveast):
    lexer = SmallCLexer(FileStream(input_file))
    stream = CommonTokenStream(lexer)
    parser = SmallCParser(stream)
    parser.removeErrorListeners()
    parser.addErrorListener(MyErrorListener())
    parsetree = parser.smallc_program()

    environment = Environment()
    ast = ASTGenerator(environment, parsetree).generate()

    if os.path.isfile(output):
        # empty the file so only new code is saved
        open(output, 'w').close()
    ast.generateCode(output)

    if saveast:
        ast.storeASTToDisk()
        draw(ast)
Example #15
0
    def visitIdentifier(self, parsetree: SmallCParser.IdentifierContext):
        indirection = parsetree.ASTERIKS() is not None
        address_of = parsetree.AMPERSAND() is not None

        if parsetree.array_indexing() is None:
            array_size = 0
        else:
            # NOTE we assumed this is an integer
            array_size = int(parsetree.array_indexing().expr())

        if indirection or address_of:
            name = parsetree.getChild(1).getText()
        else:
            name = parsetree.getChild(0).getText()
        try:
            return Identifier(self.environment, name, indirection, address_of, array_size)
        except C2PException as e:
            line = parsetree.start.line
            column = parsetree.start.column
            MyErrorListener().semanticError(line, column, e.msg)
Example #16
0
    def visitType_specifier(self, parsetree: SmallCParser.Type_specifierContext):
        is_const = parsetree.CONST() is not None

        typetext = parsetree.getChild(int(is_const)).getText()
        if typetext == "bool":
            typename = BooleanType()
        elif typetext == "char":
            typename = CharacterType()
        elif typetext == "int":
            typename = IntegerType()
        elif typetext == "void":
            typename = VoidType()
        elif typetext == "float":
            typename = FloatType()
        else:
            line = parsetree.start.line
            column = parsetree.start.column
            msg = "'" + typename + "' is not a recognized type"
            MyErrorListener().semanticError(line, column, msg)

        typename.is_const = is_const

        return TypeSpecifier(self.environment, typename)
Example #17
0
    def visitArray_init(self, parsetree: SmallCParser.Array_initContext):
        i = 2  # skip first two tokens
        array_elements = []

        type_specifier = parsetree.parentCtx.parentCtx.parentCtx.parentCtx.type_specifier()
        if type_specifier.CONST() is not None:
            array_type = type_specifier.getChild(1).getText()
        else:
            array_type = type_specifier.getChild(0).getText()

        children = parsetree.getChildCount()

        while(i < children):
            child = parsetree.getChild(i)
            if child.INTEGER() is not None:
                array_elements.append(int(child.INTEGER().getText()))
                if array_type != "int":
                    line = parsetree.start.line
                    column = parsetree.start.column
                    msg = "Element of type 'int' does not match array type '" + array_type + "'"
                    MyErrorListener().semanticError(line, column, msg)
            elif child.REAL() is not None:
                array_elements.append(float(child.REAL().getText()[:-1]))
                if array_type != "float":
                    line = parsetree.start.line
                    column = parsetree.start.column
                    msg = "Element of type 'float' does not match array type '" + array_type + "'"
                    MyErrorListener().semanticError(line, column, msg)
            elif child.CHARCONST() is not None:
                array_elements.append(child.CHARCONST().getText()[1])
                if array_type != "char":
                    line = parsetree.start.line
                    column = parsetree.start.column
                    msg = "Element of type 'char' does not match array type '" + array_type + "'"
                    MyErrorListener().semanticError(line, column, msg)
            elif child.BOOLEAN() is not None:
                array_elements.append(bool(child.BOOLEAN().getText()))
                if array_type != "bool":
                    line = parsetree.start.line
                    column = parsetree.start.column
                    msg = "Element of type 'bool' does not match array type '" + array_type + "'"
                    MyErrorListener().semanticError(line, column, msg)
            elif child.identifier() is not None:
                # extract variable identifier
                identifier_name = child.identifier().IDENTIFIER().getText()

                if child.identifier().array_indexing() is not None:
                    line = parsetree.start.line
                    column = parsetree.start.column
                    msg = "We do not support array indexing in array initializations at '" + \
                        identifier_name + "'"
                    MyErrorListener().semanticError(line, column, msg)

                # look it up in symbol table
                symbol = self.environment.symbol_table.getSymbol(
                    identifier_name)
                if symbol is None:
                    line = parsetree.start.line
                    column = parsetree.start.column
                    msg = "Use of undeclared variable identifier '" + identifier_name + "'"
                    MyErrorListener().semanticError(line, column, msg)
                else:
                    if array_type != symbol.type.getCSymbol():
                        line = parsetree.start.line
                        column = parsetree.start.column
                        msg = "Type of element '" + identifier_name + "': '" + \
                            symbol.type.getCSymbol() + "' does not match array type '" + \
                            array_type + "'"
                        MyErrorListener().semanticError(line, column, msg)
                    else:
                        # get indexed element value
                        array_elements.append(symbol.value)

            i += 2  # skip a comma

        return array_elements