示例#1
0
    def _add_runtime(self):
        """Add Runtime Functions

        Adds each runtime function to the list of global functions.
        """
        # The runtime_functions list is defined in the CodeGenerator class
        for func_name in self.runtime_functions:
            # Get all parameters for these functions
            param_ids = []
            param_list = self.runtime_functions[func_name]
            for index, param in enumerate(param_list):
                # Build up each param, add it to the list
                id_obj = Identifier(name=param[0],
                                    type=param[1],
                                    size=None,
                                    params=None,
                                    mm_ptr=(index + 1))
                p_obj = Parameter(id=id_obj, direction=param[2])
                param_ids.append(p_obj)

            # Build the function's identifier
            func_id = Identifier(name=func_name,
                                 type='procedure',
                                 size=None,
                                 params=param_ids,
                                 mm_ptr=1)

            # Add the function to the global scope of the identifier table
            self._ids.add(func_id, is_global=True)

        return
示例#2
0
    def _parse_program_header(self):
        """27 """
        while not self._accept('keyword', 'the'):
            try:
                self._parse_statement()
            except ParserError:
                self._resync_at_token('symbol', ';')

            self._match('symbol', ';')
        self._match('keyword', 'program')

        id_name = self._current.value
        self._match('identifier')

        # Generate procedure label. This will be stored with the identifier
        # in place of the mm_ptr attribute since it will not be used
        label_id = self.get_label_id()

        # Add the new identifier to the global table
        id_obj = Identifier(id_name, 'program', None, None, label_id)
        self._ids.add(id_obj, is_global=True)

        self._match('keyword', 'is')

        # Generate the program entry point code
        self.generate_program_entry(id_obj.name, id_obj.mm_ptr, self.debug)

        # Push the scope to the program body level
        self._ids.push_scope(id_obj.name)

        # Add the program to the base scope so it can be resolved as owner
        self._ids.add(id_obj)

        return id_obj
示例#3
0
    def _parse_procedure_header(self, is_global):
        """<procedure_header> (Protected)

        Parses the <procedure_header> language structure.

            <procedure_header> ::=
                'procedure' <identifier> '(' [ <parameter_list> ] ')'

        Arguments:
            is_global: Denotes if the procedure is to be globally scoped.
        """
        self._match('keyword', 'procedure')

        id_name = self._current.value
        id_line = self._current.line

        self._match('identifier')
        self._match('symbol', '(')

        params = []

        if not self._check('symbol', ')'):
            params = self._parse_parameter_list(params)

        self._match('symbol', ')')

        # Generate procedure label. This will be stored with the identifier
        # in place of the mm_ptr attribute since it will not be used
        label_id = self.get_label_id()

        id_obj = Identifier(id_name, 'procedure', None, params, label_id)

        try:
            # Add the procedure identifier to the parent and its own table
            self._ids.add(id_obj, is_global=is_global)
            self._ids.push_scope(id_obj.name)
            self._ids.add(id_obj)
        except ParserNameError:
            self._name_error('name already declared at this scope', id_name,
                             id_line)

        # Attempt to add each encountered param at the procedure scope
        for param in params:
            try:
                self._ids.add(param.id, is_global=False)
            except ParserNameError:
                self._name_error('name already declared at global scope',
                                 param.id.name, id_line)

        # Define the entry point for the function w/ unique identifier
        self.generate('%s_%d:' % (id_obj.name, id_obj.mm_ptr))
        self.tab_push()

        # Define the beginning of the function body
        self.generate('goto %s_%d_begin;' % (id_obj.name, id_obj.mm_ptr))
        self.generate('')

        return id_obj
示例#4
0
    def _parse_variable_declaration(self, is_global=False, is_param=False):
        """<variable_declaration> (Protected)

        Parses the <variable_declaration> language structure.

            <variable_declaration> ::=
                <type_mark> <identifier> [ '[' <array_size> ']' ]

        Arguments:
            is_global: Denotes if the variable is to be globally scoped.
                (Default: False)
            id_table_add: Denotes if the variable is to be added to the
                identifier table.

        Returns:
            The Identifier class object of the variable encountered.
        """
        id_type = self._parse_type_mark()

        # Stores the array size of the variable
        var_size = None

        # Formally match the token to an identifier type
        var_token = self._match('identifier')

        if self._accept('symbol', '['):
            index_type = self._parse_number(generate_code=False)

            var_size = self._previous.value
            index_line = self._previous.line

            # Check the type to make sure this is an integer so that we can
            # allocate memory appropriately
            if index_type != 'integer':
                self._type_error('integer', index_type, index_line)
                raise ParserTypeError()

            self._match('symbol', ']')

        # Get the memory space pointer for this variable.
        mm_ptr = self.get_mm(var_size, is_param=is_param)

        # The declaration was valid, add the identifier to the table
        id_obj = Identifier(var_token.value, id_type, var_size, None, mm_ptr)

        if not is_param:
            try:
                self._ids.add(id_obj, is_global=is_global)
            except ParserNameError as e:
                self._name_error(str(e), var_token.value, var_token.line)

        return id_obj
示例#5
0
    def _parse_program_header(self):
        """<program_header> (Protected)

        Parses the <program_header> language structure.

            <program_header> ::=
                'program' <identifier> 'is'

        Returns:
            The id object with information about the procedure identifier.
        """
        self._match('keyword', 'program')

        id_name = self._current.value
        self._match('identifier')

        # Generate procedure label. This will be stored with the identifier
        # in place of the mm_ptr attribute since it will not be used
        label_id = self.get_label_id()

        # Add the new identifier to the global table
        id = Identifier(id_name, 'program', None, None, label_id)
        self._ids.add(id, is_global=True)

        self._match('keyword', 'is')

        # Push the return addr onto the stack
        self.comment('Setting program return address', self.debug)
        self.generate('MM[R[FP]] = (int)&&%s_%d_end;' % (id.name, id.mm_ptr))

        # Make the jump to the entry point
        self.generate('goto %s_%d_begin;' % (id.name, id.mm_ptr))

        # Make the main program return
        self.generate('')
        self.comment('Creating the program exit point', self.debug)
        self.generate('%s_%d_end:' % (id.name, id.mm_ptr))
        self.tab_push()
        self.generate('return 0;')
        self.tab_pop()
        self.generate('')

        # Push the scope to the program body level
        self._ids.push_scope(id.name)

        # Add the program to the base scope so it can be resolved as owner
        self._ids.add(id)

        return id
示例#6
0
    def _parse_variable_declaration(self, is_global=False, is_param=False):
        """31"""
        id_type = self._parse_type_mark()

        # Stores the array size of the variable
        var_size = None

        # Formally match the token to an identifier type
        var_token = self._match('identifier')

        if self._accept('symbol', '['):
            index_type = self._parse_number(generate_code=False)

            var_size = self._previous.value
            index_line = self._previous.line

            # Check the type to make sure this is an integer so that we can
            # allocate memory appropriately
            if index_type != 'int':
                self._type_error('int', index_type, index_line)
                raise ParserTypeError()

            self._match('symbol', ']')

        # Get the memory space pointer for this variable.
        mm_ptr = self.get_mm(var_size, is_param=is_param)

        # The declaration was valid, add the identifier to the table
        id_obj = Identifier(var_token.value, id_type, var_size, None, mm_ptr)

        if not is_param:
            try:
                self._ids.add(id_obj, is_global=is_global)
            except ParserNameError as e:
                self._name_error(str(e), var_token.value, var_token.line)

        return id_obj
示例#7
0
    def _parse_program_header(self):
        """<program_header> (Protected)

        Parses the <program_header> language structure.

            <program_header> ::=
                'program' <identifier> 'is'

        Returns:
            The id object with information about the procedure identifier.
        """
        self._match('keyword', 'program')

        id_name = self._current.value
        self._match('identifier')

        # Generate procedure label. This will be stored with the identifier
        # in place of the mm_ptr attribute since it will not be used
        label_id = self.get_label_id()

        # Add the new identifier to the global table
        id_obj = Identifier(id_name, 'program', None, None, label_id)
        self._ids.add(id_obj, is_global=True)

        self._match('keyword', 'is')

        # Generate the program entry point code
        self.generate_program_entry(id_obj.name, id_obj.mm_ptr, self.debug)

        # Push the scope to the program body level
        self._ids.push_scope(id_obj.name)

        # Add the program to the base scope so it can be resolved as owner
        self._ids.add(id_obj)

        return id_obj