Пример #1
0
    def assignment_or_function_call(token):
        """
        Implements recursive descent for the rule:
        <assignment_or_function_call> ==>
            24 TokenType.Identifier TokenType.AssignmentOperator <expression>
                TokenType.Semicolon |
            25 TokenType.Identifier TokenType.OpenBracket <expression>
                TokenType.CloseBracket TokenType.AssignmentOperator <expression>
                TokenType.Semicolon |
            26 TokenType.Identifier TokenType.OpenParen <expression_list>
                TokenType.CloseParen TokenType.Semicolon
        """
        if token.t_type == TokenType.Identifier:
            next_offset_before_statement = CG.next_offset

            # get the param's identifier and look it up
            identifier = token.lexeme
            Parser.error_on_variable_usage(identifier)
            er_lhs = Parser.s_table.find_in_all_scopes(identifier)

            Parser.match(token, TokenType.Identifier)

            if token.t_type == TokenType.AssignmentOperator:
                print(24, end=" ")
                Parser.match(token, TokenType.AssignmentOperator)
                er_rhs = Parser.expression(token)
                Parser.match(token, TokenType.Semicolon)
                CG.code_gen_assign(er_lhs, er_rhs)
            elif token.t_type == TokenType.OpenBracket:
                print(25, end=" ")
                Parser.match(token, TokenType.OpenBracket)
                er_subscript = Parser.expression(token)
                Parser.match(token, TokenType.CloseBracket)

                Parser.match(token, TokenType.AssignmentOperator)
                er_rhs = Parser.expression(token)
                Parser.match(token, TokenType.Semicolon)
                CG.code_gen_assign(er_lhs, er_rhs, dest_subscript=er_subscript)

            elif token.t_type == TokenType.OpenParen:
                print(26, end=" ")
                Parser.match(token, TokenType.OpenParen)
                param_list = Parser.expression_list(token)
                Parser.match(token, TokenType.CloseParen)
                Parser.match(token, TokenType.Semicolon)

                # First handle built-in functions
                if identifier in CG.BUILT_IN_FUNCTIONS.keys():
                    function, data_type = CG.BUILT_IN_FUNCTIONS[identifier]
                    function(data_type, param_list)

                else:
                    Parser.call_function(identifier, er_lhs, param_list)

            else:
                Parser.raise_production_not_found_error(
                    token, 'assignment_or_function_call')

            # Reclaim stack space that was used during this statement
            CG.next_offset = next_offset_before_statement
        else:
            Parser.raise_production_not_found_error(
                token, 'assignment_or_function_call')
Пример #2
0
    def variable_or_function_call(token):
        """
        Implements recursive descent for the rule:
        <variable_or_function_call> ==>
            49 TokenType.Identifier TokenType.OpenBracket <expression>
                TokenType.CloseBracket |
            50 TokenType.OpenParen <expression_list> TokenType.CloseParen |
            51 TokenType.Identifier
        :return:    an ExpressionRecord that holds:
                    49 the value at array_id[subscript], if it was an array
                    50 the return value of the function, if it was a function;
                    51 the value of the variable, if it was a variable id
        """
        if token.t_type == TokenType.Identifier:
            identifier = token.lexeme
            exp_rec = Parser.s_table.find_in_all_scopes(identifier)

            Parser.match(token, TokenType.Identifier)

            if token.t_type == TokenType.OpenBracket:
                print(49, end=" ")
                Parser.match(token, TokenType.OpenBracket)
                er_subscript = Parser.expression(token)

                # Input validation: verify that the subscript is an integer,
                # and that exp_rec contains an array
                if er_subscript.data_type != DataTypes.INT:
                    raise SemanticError("Subscript is not an integer",
                                        Parser.file_reader.get_line_data())
                if not DataTypes.is_array(exp_rec.data_type):
                    raise SemanticError(
                        "Subscript applied to variable %s, "
                        "which is not an array" % identifier,
                        Parser.file_reader.get_line_data())

                # Match ]: wait until after potential error messages to do this
                Parser.match(token, TokenType.CloseBracket)

                # TODO: make this a function in CG
                # Make a temp ExpressionRecord to hold the value at
                # array[subscript], and return it
                result_exp_rec = ExpressionRecord(DataTypes.array_to_basic(
                    exp_rec.data_type),
                                                  CG.next_offset,
                                                  is_temp=True,
                                                  is_reference=False)
                CG.next_offset -= 4
                CG.code_gen_assign(result_exp_rec,
                                   exp_rec,
                                   src_subscript=er_subscript)
                return result_exp_rec

            elif token.t_type == TokenType.OpenParen:
                print(50, end=" ")
                if not isinstance(exp_rec, FunctionSignature) and \
                        not identifier in CG.BUILT_IN_FUNCTIONS.keys():
                    raise SemanticError(
                        "Tried to call %s as a function, "
                        "but it was not a function." % identifier,
                        Parser.file_reader.get_line_data())

                # exp_rec is actually a function signature, so call it that
                func_signature = exp_rec
                Parser.match(token, TokenType.OpenParen)
                er_params = Parser.expression_list(token)
                Parser.match(token, TokenType.CloseParen)

                return Parser.call_function(identifier, func_signature,
                                            er_params)

            else:
                print(51, end=" ")
                return exp_rec
        else:
            raise Parser.raise_production_not_found_error(
                token, "variable_or_function_call")