示例#1
0
    def buildIncludeStatement(self, tree):
        """Build Include Statement"""
        # must have 2 children
        if (tree.getChildCount() != 2):
            raise RuntimeError("Invalid include statement: '" +
                               tree.getText() + "'")

        path = tree.getChild(1).getText()
        # check if correct format
        if ((path.startswith('"') and path.endswith('"'))
                or (path.startswith('<') and path.endswith('>'))):
            path = path[1:-1]

            # Let's add some definitions to the symbol table
            if (path == "stdio.h"):
                #printf
                argumentsList = ArgumentsList()
                argumentsList.add(
                    Argument("string",
                             AddressType(ArrayType(CharacterType(), -1))))
                argumentsList.makeUnlimited()

                self.sym.registerFunction('printf', IntegerType(),
                                          argumentsList, True)
                self.sym.registerFunction('scanf', IntegerType(),
                                          argumentsList, True)

            return IncludeStatement(path)
        else:
            raise RuntimeError("Invalid include statement: '" +
                               tree.getText() + "'")
    def test_nested_alias(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        st.registerAlias('a', integer)

        # call in scope
        self.assertEqual(type(st.getAlias('a').basetype), type(IntegerType()))

        # call in nested scope
        st.openScope()
        self.assertEqual(type(st.getAlias('a').basetype), type(IntegerType()))

        # define in nested scope
        st.registerAlias('a', character)

        # call in nested scope
        self.assertEqual(type(st.getAlias('a').basetype),
                         type(CharacterType()))

        # call original in main scope
        st.closeScope()
        self.assertEqual(type(st.getAlias('a').basetype), type(IntegerType()))
    def test_symbol_address_in_function_with_arguments(self):
        st = SymbolTable()

        integer = IntegerType()
        arrayinteger = ArrayType(integer, 3)

        # Create arguments
        argumentsList = ArgumentsList()
        argumentsList.add(Argument('a', integer))
        argumentsList.add(Argument('b', arrayinteger))

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(
            Parameter(
                VariableCallExpression(Symbol('b', arrayinteger, 0), None)))

        st.registerFunction('main', integer, argumentsList, True)
        function = st.getFunction('main', parametersList)

        st.openFunctionScope(function)
        self.assertEqual(st.getSymbol('a').address, 5)
        self.assertEqual(st.getSymbol('b').address, 6)
        st.registerSymbol('c', integer)
        self.assertEqual(st.getSymbol('c').address, 9)
        st.registerSymbol('d', arrayinteger)
        self.assertEqual(st.getSymbol('d').address, 10)
        st.registerSymbol('e', integer)
        self.assertEqual(st.getSymbol('e').address, 13)
        st.closeFunctionScope(function)

        self.assertEqual(function.getStaticSize(), 14)
        self.assertEqual(function.getParameterSize(), 4)
    def test_double_symbol_definition(self):
        st = SymbolTable()
        integer = IntegerType()

        st.registerSymbol('integer', integer)
        self.assertRaises(SymbolAlreadyRegisteredError,
                          lambda: st.registerSymbol('integer', integer))
    def test_function_label(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        # Create arguments
        argumentsList = ArgumentsList()
        argumentsList.add(Argument('a', integer))
        argumentsList.add(Argument('b', real))

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(Parameter(ConstantExpression(3.14, 'float')))

        # Register basic function, no arguments
        st.registerFunction('add', integer, argumentsList, True)

        # Check for label
        self.assertEqual(st.getFunction('add', parametersList).label, 'add0')

        # Check for label in scope
        st.openScope()
        st.registerFunction('add', integer, argumentsList, True)
        self.assertEqual(st.getFunction('add', parametersList).label, 'add1')
        st.closeScope()
示例#6
0
    def test_compile_function_statement_no_arguments_no_statements(self):
        function = Function('main', IntegerType(), ArgumentsList(), 0, "main0")
        statement = FunctionStatement(function, [], True)

        self.assertEqual(function.getStaticSize(), 5)
        self.assertEqual(function.getParameterSize(), 0)
        self.assertEqual(statement.compile(), "main0:\nssp 5\nretp\n")
    def test_function_register_with_unlimited_arguments(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        # Create arguments
        argumentsList = ArgumentsList()
        argumentsList.add(Argument('a', integer))
        argumentsList.makeUnlimited()

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(Parameter(ConstantExpression(3.14, 'float')))
        parametersList.add(Parameter(ConstantExpression(True, 'bool')))
        parametersList.add(Parameter(ConstantExpression(False, 'bool')))

        # Register basic function,  arguments
        st.registerFunction('printer', integer, argumentsList, True)

        # get basic function
        self.assertEqual(type(st.getFunction('printer', parametersList)),
                         Function)
    def test_function_register_and_get_no_arguments(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        # Register basic function, no arguments
        st.registerFunction('hello', integer, ArgumentsList(), True)

        # register function again, shouldn't work
        self.assertRaises(
            FunctionAlreadyRegisteredError, lambda: st.registerFunction(
                'hello', integer, ArgumentsList(), True))

        # register function again with other return type, shouldn't work
        self.assertRaises(
            FunctionAlreadyRegisteredError, lambda: st.registerFunction(
                'hello', boolean, ArgumentsList(), True))

        # get basic function
        self.assertEqual(type(st.getFunction('hello', ParametersList())),
                         Function)

        # get not known function, should not work
        self.assertRaises(FunctionNotRegisteredError,
                          lambda: st.getFunction('add', ParametersList()))
    def test_double_alias(self):
        st = SymbolTable()
        integer = IntegerType()

        st.registerAlias('integer', integer)
        self.assertRaises(AliasAlreadyRegisteredError,
                          lambda: st.registerAlias('integer', integer))
    def test_register_symbols_nested(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        st.registerSymbol('a', integer)

        st.openScope()
        st.registerSymbol('a', real)

        st.openScope()
        st.registerSymbol('a', boolean)

        st.openScope()
        st.registerSymbol('a', character)

        # Check
        self.assertEqual(type(st.getSymbol('a').basetype), CharacterType)

        st.closeScope()

        self.assertEqual(type(st.getSymbol('a').basetype), BooleanType)

        st.closeScope()

        self.assertEqual(type(st.getSymbol('a').basetype), RealType)

        st.closeScope()

        self.assertEqual(type(st.getSymbol('a').basetype), IntegerType)
示例#11
0
    def test_compile_function_arguments_no_statements(self):
        st = SymbolTable()

        integer = IntegerType()
        arrayinteger = ArrayType(integer, 3)

        # Create arguments
        argumentsList = ArgumentsList()
        argumentsList.add(Argument('a', integer))
        argumentsList.add(Argument('b', arrayinteger))

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(
            Parameter(
                VariableCallExpression(Symbol('b', arrayinteger, 0), None)))

        st.registerFunction('main', integer, argumentsList, True)
        function = st.getFunction('main', parametersList)
        st.openFunctionScope(function)

        st.closeFunctionScope(function)

        statement = FunctionStatement(function, [], True)

        self.assertEqual(function.getStaticSize(), 9)
        self.assertEqual(function.getParameterSize(), 4)
        self.assertEqual(statement.compile(), "main0:\nssp 9\nretp\n")
    def test_symbol_address_in_function(self):
        st = SymbolTable()

        integer = IntegerType()
        arrayinteger = ArrayType(integer, 3)

        # Create arguments
        argumentsList = ArgumentsList()

        # Create parameters
        parametersList = ParametersList()

        st.registerFunction('main', integer, argumentsList, 0)
        function = st.getFunction('main', parametersList)

        st.openFunctionScope(function)
        st.registerSymbol('a', integer)
        self.assertEqual(st.getSymbol('a').address, 5)
        st.registerSymbol('b', arrayinteger)
        self.assertEqual(st.getSymbol('b').address, 6)
        st.registerSymbol('c', integer)
        self.assertEqual(st.getSymbol('c').address, 9)
        st.closeFunctionScope(function)

        self.assertEqual(function.getStaticSize(), 10)
        self.assertEqual(function.getParameterSize(), 0)
    def test_alias_register(self):
        st = SymbolTable()
        integer = IntegerType()

        st.registerAlias('integer', integer)
        self.assertEqual(type(st.getAlias('integer').basetype), IntegerType)

        # call unknown alias
        self.assertRaises(AliasNotRegisteredError, lambda: st.getAlias('a'))
    def test_function_scoped(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        # Create arguments
        argumentsList = ArgumentsList()
        argumentsList.add(Argument('a', integer))
        argumentsList.add(Argument('b', real))

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(Parameter(ConstantExpression(3.14, 'float')))

        # Register basic function, no arguments
        st.registerFunction('add', integer, argumentsList, True)

        # Call function in main scope
        self.assertEqual(type(st.getFunction('add', parametersList)), Function)

        # open scope and get function again
        st.openScope()
        self.assertEqual(type(st.getFunction('add', parametersList)), Function)

        # register function in scope
        st.registerFunction('divide', integer, argumentsList, True)

        # call new function in scope
        self.assertEqual(type(st.getFunction('add', parametersList)), Function)

        # close scope and call new created function, shouldn't work
        st.closeScope()
        self.assertRaises(FunctionNotRegisteredError,
                          lambda: st.getFunction('divide', parametersList))

        # open scope and register add again
        st.openScope()
        st.registerFunction('add', integer, argumentsList, True)
        self.assertEqual(type(st.getFunction('add', parametersList)), Function)
        self.assertRaises(
            FunctionAlreadyRegisteredError,
            lambda: st.registerFunction('add', integer, argumentsList, True))
        st.closeScope()

        # register function in higher scope and call in lower scope
        st.registerFunction('multiply', integer, argumentsList, True)
        st.openScope()
        self.assertEqual(type(st.getFunction('multiply', parametersList)),
                         Function)
        self.assertRaises(
            FunctionNotRegisteredError,
            lambda: st.getFunction('multiplynotexisting', parametersList))
        st.closeScope
示例#15
0
    def buildType(self, tree):
        """Build Type"""
        token = None
        basetype = None

        if (tree.getChildCount() == 1):
            token = tree.getChild(0).getPayload()

            if (not isinstance(token, Token)):
                raise RuntimeError("Invalid type identifier: '" +
                                   tree.getText() + "'")

            if (token.type == CLexer.VOID):
                return VoidType()
            elif (token.type == CLexer.IDENTIFIER):
                if (tree.getChild(0).getText() == "bool"):
                    return BooleanType()
                elif (tree.getChild(0).getText() == "char"):
                    return CharacterType()
                elif (tree.getChild(0).getText() == "int"):
                    return IntegerType()
                elif (tree.getChild(0).getText() == "float"):
                    return RealType()
                elif (tree.getChild(0).getText() == "double"):
                    return RealType()
                else:
                    # Alias, check the symbol Table
                    return self.sym.getAlias(
                        tree.getChild(0).getText()).basetype
            else:
                raise RuntimeError("Invalid type identifier: '" +
                                   tree.getText() + "'")
        elif (tree.getChildCount() == 2):
            token = tree.getChild(0).getPayload()

            # Const Type
            if (isinstance(token, Token) and token.type == CLexer.CONST):
                return self.buildType(tree.getChild(1)).setConst(True)

            token = tree.getChild(1).getPayload()
            if (not isinstance(token, Token)):
                raise RuntimeError("Invalid type identifier: '" +
                                   tree.getText() + "'")

            if (token.type == CLexer.STAR):
                return AddressType(self.buildType(tree.getChild(0)))
            elif (token.type == CLexer.CONST):
                return self.buildType(tree.getChild(0)).setConst(True)
            else:
                raise RuntimeError("Invalid type identifier: '" +
                                   tree.getText() + "'")
        else:
            raise RuntimeError("Invalid type identifier: '" + tree.getText() +
                               "'")
    def test_not_registered_symbol_call(self):
        st = SymbolTable()
        integer = IntegerType()

        self.assertRaises(SymbolNotRegisteredError, lambda: st.getSymbol('a'))

        # open scope and register
        st.openScope()
        st.registerSymbol('a', integer)
        st.closeScope()

        self.assertRaises(SymbolNotRegisteredError, lambda: st.getSymbol('a'))
    def test_function_register_and_get_with_arguments(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        # Create arguments
        argumentsList = ArgumentsList()
        argumentsList.add(Argument('a', integer))
        argumentsList.add(Argument('b', real))

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(Parameter(ConstantExpression(3.14, 'float')))

        # fake ParametersList, has one parameters less
        fakeParametersList = ParametersList()
        fakeParametersList.add(Parameter(ConstantExpression(1, 'int')))

        # Register basic function,  arguments
        st.registerFunction('add', integer, argumentsList, True)

        # register function again, shouldn't work
        self.assertRaises(
            FunctionAlreadyRegisteredError,
            lambda: st.registerFunction('add', integer, argumentsList, True))

        # register function again with other return type, shouldn't work
        self.assertRaises(
            FunctionAlreadyRegisteredError,
            lambda: st.registerFunction('add', boolean, argumentsList, True))

        # get basic function
        self.assertEqual(type(st.getFunction('add', parametersList)), Function)

        # get not known function, should not work
        self.assertRaises(FunctionNotRegisteredError,
                          lambda: st.getFunction('hello', parametersList))

        # get the function with no arguments, shouldn't work
        self.assertRaises(FunctionNotRegisteredError,
                          lambda: st.getFunction('add', ParametersList()))

        # get the function with wrong arguments, shouldn't work
        self.assertRaises(FunctionNotRegisteredError,
                          lambda: st.getFunction('add', fakeParametersList))
    def test_register_symbols(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        address = AddressType(integer)
        character = CharacterType()
        array = ArrayType(integer, 10)

        st.registerSymbol('int', integer)
        st.registerSymbol('float', real)
        st.registerSymbol('bool', boolean)
        st.registerSymbol('char', character)

        st.registerSymbol('ptr', address)
        st.registerSymbol('array', array)
示例#19
0
 def __init__(self, value, basetype):
     Expression.__init__(self, None)
     if(basetype == "bool"):
         self.basetype = BooleanType()
         self.value = BooleanData(value)
     elif(basetype == "char"):
         self.basetype = CharacterType()
         self.value = CharacterData(value)
     elif(basetype == "int"):
         self.basetype = IntegerType()
         self.value = IntegerData(value)
     elif(basetype == "float"):
         self.basetype = RealType()
         self.value = RealData(value)
     elif(basetype == "string"):
         self.basetype = AddressType(ArrayType(CharacterType(), len(value)))
         self.value = StringData(value + "\0")
     else:
         raise RuntimeError("Trying to create constantexpession with unkown type")
示例#20
0
    def test_compile_function_no_arguments_statements(self):
        st = SymbolTable()

        integer = IntegerType()
        arrayinteger = ArrayType(integer, 3)

        # Create arguments
        argumentsList = ArgumentsList()

        # Create parameters
        parametersList = ParametersList()

        st.registerFunction('main', integer, argumentsList, True)
        function = st.getFunction('main', parametersList)
        st.openFunctionScope(function)

        st.closeFunctionScope(function)

        statement = FunctionStatement(function, [], True)

        self.assertEqual(function.getStaticSize(), 5)
        self.assertEqual(function.getParameterSize(), 0)
        self.assertEqual(statement.compile(), "main0:\nssp 5\nretp\n")
    def test_scope_allocated(self):
        st = SymbolTable()

        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()
        address = AddressType(integer)

        array = ArrayType(integer, 10)

        st.registerSymbol('a', integer)
        st.registerSymbol('b', real)
        st.registerSymbol('c', boolean)
        st.registerSymbol('d', character)
        st.registerSymbol('e', address)

        self.assertEqual(st.scope.allocated, 5)
        self.assertEqual(st.scope.getTotalAllocated(), 5)

        st.openScope()
        st.registerSymbol('a', integer)
        st.registerSymbol('b', real)
        st.registerSymbol('c', boolean)
        st.registerSymbol('d', character)
        st.registerSymbol('e', address)

        self.assertEqual(st.scope.allocated, 5)
        self.assertEqual(st.scope.getTotalAllocated(), 5)
        st.closeScope()

        self.assertEqual(st.scope.allocated, 5)
        self.assertEqual(st.scope.getTotalAllocated(), 10)
        st.registerSymbol('f', array)

        self.assertEqual(st.scope.allocated, 15)
        self.assertEqual(st.scope.getTotalAllocated(), 20)
    def test_function_parameter_size_array_full(self):
        st = SymbolTable()
        integer = IntegerType()
        arrayinteger = ArrayType(integer, 3)

        # Create arguments
        argumentsList = ArgumentsList()
        argumentsList.add(Argument('a', integer))
        argumentsList.add(Argument('b', arrayinteger))

        # Create array
        st.registerSymbol('b', arrayinteger)

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(
            Parameter(VariableCallExpression(st.getSymbol('b'), None)))

        # Register basic function, no arguments
        st.registerFunction('add', integer, argumentsList, True)
        function = st.getFunction('add', parametersList)

        self.assertEqual(function.getParameterSize(), 4)
示例#23
0
    def buildVariableExpression(self, tree):
        """Build Variable Expression"""
        if (tree.getChildCount() == 1):
            # Variable call
            identifier = tree.getChild(0).getText()
            # Check symbol Table if symbol exists
            symbol = self.sym.getSymbol(identifier)

            return VariableCallExpression(symbol, None)
        elif (tree.getChildCount() == 2):
            # Variable Definition
            basetype = self.buildType(tree.getChild(0))
            identifier = tree.getChild(1).getText()
            # Register in Symbol Table
            symbol = self.sym.registerSymbol(identifier, basetype)
            return VariableExpression(symbol)
        elif (tree.getChildCount() == 4):
            # Array
            token = tree.getChild(1).getPayload()
            if (not isinstance(token, Token)
                    or token.type != CLexer.LSQUAREBRACKET):
                raise RuntimeError("Invalid VariableExpression: '" +
                                   tree.getText() + "'")

            token = tree.getChild(3).getPayload()
            if (not isinstance(token, Token)
                    or token.type != CLexer.RSQUAREBRACKET):
                raise RuntimeError("Invalid VariableExpression: '" +
                                   tree.getText() + "'")

            if (tree.getChild(0).getChildCount() == 1):
                # call
                identifier = tree.getChild(0).getChild(0).getText()
                index = self.buildExpression(tree.getChild(2))

                # index can only be an int
                if (type(index.basetype) != type(IntegerType())):
                    raise RuntimeError(
                        "Array index can only be defined by an int")

                # get the value of the integer from the constantexpression
                index = index.value.integer

                # Check symbol Table if symbol exists
                symbol = self.sym.getSymbol(identifier)

                # Check if variable is an array
                if (symbol.basetype.isArray() == False):
                    raise RuntimeError(
                        "Tried to get an array which is not an array")

                # check if index is not out ofbounds
                if (symbol.basetype.getElementsCount() <= index):
                    raise RuntimeError("Index of array is out of bounds")

                return VariableCallExpression(symbol, index)
            elif (tree.getChild(0).getChildCount() == 2):
                # definition
                basetype = self.buildType(tree.getChild(0).getChild(0))
                identifier = tree.getChild(0).getChild(1).getText()
                arraySize = self.buildExpression(tree.getChild(2))

                # Arraysize can only be an int
                if (type(arraySize.basetype) != type(IntegerType())):
                    raise RuntimeError(
                        "Array size can only be defined by an int")

                # get the value of the integer from the constantexpression
                arraySize = arraySize.value.integer

                # Create the arrayType
                arrayType = ArrayType(basetype, arraySize)

                # Register in Symbol Table
                symbol = self.sym.registerSymbol(identifier, arrayType)
                return VariableExpression(symbol)
            else:
                raise RuntimeError("Invalid VariableExpression: '" +
                                   tree.getText() + "'")
        else:
            raise RuntimeError("Invalid VariableExpression: '" +
                               tree.getText() + "'")