Cast expressions
This commit is contained in:
		
							
								
								
									
										91
									
								
								example.elna
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								example.elna
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
type
 | 
			
		||||
  TokenValue = union
 | 
			
		||||
    intValue: Int;
 | 
			
		||||
    stringValue: String
 | 
			
		||||
    stringValue: pointer to Char
 | 
			
		||||
  end,
 | 
			
		||||
  Token = record
 | 
			
		||||
    kind: Int;
 | 
			
		||||
@@ -12,7 +12,9 @@ type
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
const
 | 
			
		||||
  SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2;
 | 
			
		||||
  SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2,
 | 
			
		||||
  POINTER_SIZE = 8, TOKEN_SIZE = 16,
 | 
			
		||||
  TOKEN_IDENTIFIER = 1;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- External procedures.
 | 
			
		||||
@@ -27,9 +29,13 @@ proc write(fd: Int, buf: pointer to Char, count: Int): Int; extern;
 | 
			
		||||
proc malloc(size: Int): pointer to Char; extern;
 | 
			
		||||
proc free(ptr: pointer to Char); extern;
 | 
			
		||||
proc calloc(nmemb: Int, size: Int): pointer to Char; extern;
 | 
			
		||||
proc realloc(ptr: pointer to Char, size: Int): pointer to Char; extern;
 | 
			
		||||
 | 
			
		||||
proc memset(ptr: pointer to Char, c: Int, n: Int): pointer to Char; extern;
 | 
			
		||||
 | 
			
		||||
proc strncmp(s1: pointer to Char, s2: pointer to Char, n: Word): Int; extern;
 | 
			
		||||
proc strncpy(dst: pointer to Char, src: pointer to Char, dsize: Word): pointer to Char; extern;
 | 
			
		||||
proc strncpy(dst: pointer to Char, src: pointer to Char, dsize: Word): pointer to Char; extern;
 | 
			
		||||
proc strlen(ptr: pointer to Char): Word; extern;
 | 
			
		||||
 | 
			
		||||
proc exit(code: Int); extern;
 | 
			
		||||
@@ -68,7 +74,7 @@ begin
 | 
			
		||||
    digit := value % 10;
 | 
			
		||||
	value := value / 10;
 | 
			
		||||
 | 
			
		||||
	buffer[n] := Char(Int('0') + digit);
 | 
			
		||||
	buffer[n] := cast(cast('0' as Int) + digit as Char);
 | 
			
		||||
	n := n - 1
 | 
			
		||||
  end;
 | 
			
		||||
  while n < 10 do
 | 
			
		||||
@@ -82,6 +88,26 @@ begin
 | 
			
		||||
  write_i(value)
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
proc is_digit(c: Char): Bool;
 | 
			
		||||
begin
 | 
			
		||||
  return cast(c as Int) >= cast('0' as Int) and cast(c as Int) <= cast('9' as Int)
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
proc is_alpha(c: Char): Bool;
 | 
			
		||||
begin
 | 
			
		||||
  return cast(c as Int) >= cast('A' as Int) and cast(c as Int) <= cast('z' as Int)
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
proc is_alnum(c: Char): Bool;
 | 
			
		||||
begin
 | 
			
		||||
  return is_digit(c) or is_alpha(c)
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
proc is_space(c: Char): Bool;
 | 
			
		||||
begin
 | 
			
		||||
  return c = ' ' or c = '\n'
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- End of standard procedures.
 | 
			
		||||
--
 | 
			
		||||
@@ -130,17 +156,68 @@ begin
 | 
			
		||||
  return input
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
proc skip_spaces(input: pointer to Char): pointer to Char;
 | 
			
		||||
begin
 | 
			
		||||
  while is_space(input^) do
 | 
			
		||||
    input := input + 1
 | 
			
		||||
  end;
 | 
			
		||||
  return input
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
proc lex_identifier(input: pointer to Char): pointer to Char;
 | 
			
		||||
begin
 | 
			
		||||
  while is_alnum(input^) or input^ = '_' do
 | 
			
		||||
    input := input + 1
 | 
			
		||||
  end;
 | 
			
		||||
  return input
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
proc compile();
 | 
			
		||||
var
 | 
			
		||||
  input: pointer to Char,
 | 
			
		||||
  input_pointer: pointer to Char;
 | 
			
		||||
  input_pointer: pointer to Char,
 | 
			
		||||
  token_end: pointer to Char,
 | 
			
		||||
  token_length: Int,
 | 
			
		||||
  tokens: pointer to Token,
 | 
			
		||||
  current_token: pointer to Token,
 | 
			
		||||
  tokens_size: Int,
 | 
			
		||||
  i: Int;
 | 
			
		||||
begin
 | 
			
		||||
  tokens_size := 0;
 | 
			
		||||
  tokens := cast(0 as pointer to Token);
 | 
			
		||||
 | 
			
		||||
  input := read_source("example.elna");
 | 
			
		||||
 | 
			
		||||
  input_pointer := input;
 | 
			
		||||
  input_pointer := skip_spaces(input);
 | 
			
		||||
 | 
			
		||||
  while input_pointer^ /= '\0' do
 | 
			
		||||
    write(0, input_pointer, 1);
 | 
			
		||||
    input_pointer := input_pointer + 1
 | 
			
		||||
    if is_alpha(input_pointer^) or input_pointer^ = '_' then
 | 
			
		||||
      token_end := lex_identifier(input_pointer + 1);
 | 
			
		||||
	  token_length := cast(token_end as Int) - cast(input_pointer as Int);
 | 
			
		||||
 | 
			
		||||
	  tokens := cast(realloc(tokens, tokens_size + TOKEN_SIZE) as pointer to Token);
 | 
			
		||||
      current_token := tokens + tokens_size;
 | 
			
		||||
 | 
			
		||||
	  current_token^.kind := TOKEN_IDENTIFIER;
 | 
			
		||||
	  current_token^.value.stringValue := cast(calloc(token_length + 1, 1) as pointer to Char);
 | 
			
		||||
	  strncpy(current_token^.value.stringValue, input_pointer, token_length);
 | 
			
		||||
 | 
			
		||||
      tokens_size := tokens_size + TOKEN_SIZE;
 | 
			
		||||
 | 
			
		||||
	  input_pointer := token_end
 | 
			
		||||
	else
 | 
			
		||||
      input_pointer := input_pointer + 1
 | 
			
		||||
	end
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  i := 0;
 | 
			
		||||
  while i < tokens_size do
 | 
			
		||||
    current_token := tokens + i;
 | 
			
		||||
 | 
			
		||||
    write_s(current_token^.value.stringValue);
 | 
			
		||||
	write_c('\n');
 | 
			
		||||
 | 
			
		||||
	i := i + TOKEN_SIZE
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  free(input)
 | 
			
		||||
 
 | 
			
		||||
@@ -20,40 +20,21 @@ namespace gcc
 | 
			
		||||
        this->symbol_map = symbol_table;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(source::call_expression *statement)
 | 
			
		||||
    void generic_visitor::visit(source::call_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        auto symbol = this->symbol_map->lookup(statement->name());
 | 
			
		||||
 | 
			
		||||
        if (statement->name() == "Int" || statement->name() == "Word" || statement->name() == "Bool"
 | 
			
		||||
                || statement->name() == "Float" || statement->name() == "Char")
 | 
			
		||||
        {
 | 
			
		||||
            if (statement->arguments().size() != 1)
 | 
			
		||||
            {
 | 
			
		||||
                error_at(get_location(&statement->position()),
 | 
			
		||||
                        "procedure '%s' expects 1 argument, %lu given",
 | 
			
		||||
                        statement->name().c_str(), statement->arguments().size());
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            auto& argument = statement->arguments().at(0);
 | 
			
		||||
            argument->accept(this);
 | 
			
		||||
            tree argument_type = TREE_TYPE(this->current_expression);
 | 
			
		||||
 
 | 
			
		||||
            this->current_expression = build1_loc(get_location(&argument->position()), CONVERT_EXPR,
 | 
			
		||||
                    symbol->payload, this->current_expression);
 | 
			
		||||
        }
 | 
			
		||||
        else if (symbol)
 | 
			
		||||
        if (auto symbol = this->symbol_map->lookup(expression->name()))
 | 
			
		||||
        {
 | 
			
		||||
            tree return_type = TREE_TYPE(TREE_TYPE(symbol->payload));
 | 
			
		||||
            tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(symbol->payload));
 | 
			
		||||
            tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload);
 | 
			
		||||
 | 
			
		||||
            std::vector<tree> arguments(statement->arguments().size());
 | 
			
		||||
            for (std::size_t i = 0; i < statement->arguments().size(); ++i)
 | 
			
		||||
            std::vector<tree> arguments(expression->arguments().size());
 | 
			
		||||
            for (std::size_t i = 0; i < expression->arguments().size(); ++i)
 | 
			
		||||
            {
 | 
			
		||||
                statement->arguments().at(i)->accept(this);
 | 
			
		||||
                expression->arguments().at(i)->accept(this);
 | 
			
		||||
                arguments[i] = this->current_expression;
 | 
			
		||||
            }
 | 
			
		||||
            tree stmt = build_call_array_loc(get_location(&statement->position()),
 | 
			
		||||
            tree stmt = build_call_array_loc(get_location(&expression->position()),
 | 
			
		||||
                    return_type, printf_fn, arguments.size(), arguments.data());
 | 
			
		||||
 | 
			
		||||
            if (return_type == void_type_node)
 | 
			
		||||
@@ -68,12 +49,24 @@ namespace gcc
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            error_at(get_location(&statement->position()),
 | 
			
		||||
            error_at(get_location(&expression->position()),
 | 
			
		||||
                    "procedure '%s' not declared",
 | 
			
		||||
                    statement->name().c_str());
 | 
			
		||||
                    expression->name().c_str());
 | 
			
		||||
            this->current_expression = error_mark_node;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(source::cast_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        tree cast_target = build_type(expression->target());
 | 
			
		||||
        gcc_assert(cast_target != NULL_TREE);
 | 
			
		||||
 | 
			
		||||
        expression->value().accept(this);
 | 
			
		||||
 | 
			
		||||
        this->current_expression = build1_loc(get_location(&expression->position()), CONVERT_EXPR,
 | 
			
		||||
                cast_target, this->current_expression);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(source::program *program)
 | 
			
		||||
    {
 | 
			
		||||
        for (const auto definition : program->value_definitions)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,12 @@ namespace gcc
 | 
			
		||||
            && TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_integral_type(tree type)
 | 
			
		||||
    {
 | 
			
		||||
        gcc_assert(TYPE_P(type));
 | 
			
		||||
        return type == integer_type_node || type == unsigned_type_node;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tree tree_chain_base::head()
 | 
			
		||||
    {
 | 
			
		||||
        return first;
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,8 @@ namespace gcc
 | 
			
		||||
 | 
			
		||||
        void visit(source::program *program) override;
 | 
			
		||||
        void visit(source::procedure_definition *definition) override;
 | 
			
		||||
        void visit(source::call_expression *statement) override;
 | 
			
		||||
        void visit(source::call_expression *expression) override;
 | 
			
		||||
        void visit(source::cast_expression *expression) override;
 | 
			
		||||
        void visit(source::number_literal<std::int32_t> *literal) override;
 | 
			
		||||
        void visit(source::number_literal<std::uint32_t> *literal) override;
 | 
			
		||||
        void visit(source::number_literal<double> *literal) override;
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ namespace gcc
 | 
			
		||||
    void init_ttree();
 | 
			
		||||
    bool is_pointer_type(tree type);
 | 
			
		||||
    bool is_string_type(tree type);
 | 
			
		||||
    bool is_integral_type(tree type);
 | 
			
		||||
 | 
			
		||||
    class tree_chain_base
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,7 @@ namespace source
 | 
			
		||||
    class procedure_definition;
 | 
			
		||||
    class type_definition;
 | 
			
		||||
    class call_expression;
 | 
			
		||||
    class cast_expression;
 | 
			
		||||
    class assign_statement;
 | 
			
		||||
    class if_statement;
 | 
			
		||||
    class while_statement;
 | 
			
		||||
@@ -74,6 +75,7 @@ namespace source
 | 
			
		||||
        virtual void visit(procedure_definition *) = 0;
 | 
			
		||||
        virtual void visit(type_definition *) = 0;
 | 
			
		||||
        virtual void visit(call_expression *) = 0;
 | 
			
		||||
        virtual void visit(cast_expression *) = 0;
 | 
			
		||||
        virtual void visit(expression_statement *) = 0;
 | 
			
		||||
        virtual void visit(assign_statement *) = 0;
 | 
			
		||||
        virtual void visit(if_statement *) = 0;
 | 
			
		||||
@@ -109,7 +111,8 @@ namespace source
 | 
			
		||||
        virtual void visit(constant_definition *definition) override;
 | 
			
		||||
        virtual void visit(procedure_definition *definition) override;
 | 
			
		||||
        virtual void visit(type_definition *definition) override;
 | 
			
		||||
        virtual void visit(call_expression *statement) override;
 | 
			
		||||
        virtual void visit(call_expression *expression) override;
 | 
			
		||||
        virtual void visit(cast_expression *expression) override;
 | 
			
		||||
        virtual void visit(expression_statement *statement) override;
 | 
			
		||||
        virtual void visit(assign_statement *statement) override;
 | 
			
		||||
        virtual void visit(if_statement *) override;
 | 
			
		||||
@@ -136,55 +139,6 @@ namespace source
 | 
			
		||||
        virtual void visit(string_literal *) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Operand representing a subexpression in the 3 address code.
 | 
			
		||||
     */
 | 
			
		||||
    struct operand
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        virtual ~operand() = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct integer_operand final : public operand
 | 
			
		||||
    {
 | 
			
		||||
        std::int32_t m_value;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        explicit integer_operand(const std::int32_t value);
 | 
			
		||||
 | 
			
		||||
        std::int32_t value() const;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class variable_operand final : public operand
 | 
			
		||||
    {
 | 
			
		||||
        std::string m_name;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        explicit variable_operand(const std::string& name);
 | 
			
		||||
 | 
			
		||||
        const std::string& name() const;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct temporary_variable final : public operand
 | 
			
		||||
    {
 | 
			
		||||
        std::size_t m_counter;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        explicit temporary_variable(const std::size_t counter);
 | 
			
		||||
 | 
			
		||||
        std::size_t counter() const;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct label_operand final : public operand
 | 
			
		||||
    {
 | 
			
		||||
        std::size_t m_counter;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        explicit label_operand(const std::size_t counter);
 | 
			
		||||
 | 
			
		||||
        std::size_t counter() const;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * AST node.
 | 
			
		||||
     */
 | 
			
		||||
@@ -219,9 +173,6 @@ namespace source
 | 
			
		||||
 | 
			
		||||
    class expression : public node
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        std::shared_ptr<operand> place;
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        /**
 | 
			
		||||
         * \param position Source code position.
 | 
			
		||||
@@ -448,7 +399,7 @@ namespace source
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Call statement.
 | 
			
		||||
     * Procedure call expression.
 | 
			
		||||
     */
 | 
			
		||||
    class call_expression : public expression
 | 
			
		||||
    {
 | 
			
		||||
@@ -469,6 +420,24 @@ namespace source
 | 
			
		||||
        virtual ~call_expression() override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Cast expression.
 | 
			
		||||
     */
 | 
			
		||||
    class cast_expression : public expression
 | 
			
		||||
    {
 | 
			
		||||
        type_expression *m_target;
 | 
			
		||||
        expression *m_value;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        cast_expression(const struct position position, type_expression *target, expression *value);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        type_expression& target();
 | 
			
		||||
        expression& value();
 | 
			
		||||
 | 
			
		||||
        virtual ~cast_expression() override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class expression_statement : public statement
 | 
			
		||||
    {
 | 
			
		||||
        expression *m_body;
 | 
			
		||||
 
 | 
			
		||||
@@ -33,14 +33,20 @@ namespace source
 | 
			
		||||
        definition->body().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(call_expression *statement)
 | 
			
		||||
    void empty_visitor::visit(call_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        for (auto& argument : statement->arguments())
 | 
			
		||||
        for (auto& argument : expression->arguments())
 | 
			
		||||
        {
 | 
			
		||||
            argument->accept(this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(cast_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        expression->target().accept(this);
 | 
			
		||||
        expression->value().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(expression_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        statement->body().accept(this);
 | 
			
		||||
@@ -185,50 +191,6 @@ namespace source
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    operand::~operand()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    integer_operand::integer_operand(const std::int32_t value)
 | 
			
		||||
        : m_value(value)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::int32_t integer_operand::value() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    variable_operand::variable_operand(const std::string& name)
 | 
			
		||||
        : m_name(name)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const std::string& variable_operand::name() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    temporary_variable::temporary_variable(const std::size_t counter)
 | 
			
		||||
        : m_counter(counter)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::size_t temporary_variable::counter() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_counter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    label_operand::label_operand(const std::size_t counter)
 | 
			
		||||
        : m_counter(counter)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::size_t label_operand::counter() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_counter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    node::node(const struct position position)
 | 
			
		||||
        : source_position(position)
 | 
			
		||||
    {
 | 
			
		||||
@@ -766,6 +728,32 @@ namespace source
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cast_expression::cast_expression(const struct position position, type_expression *target, expression *value)
 | 
			
		||||
        : expression(position), m_target(target), m_value(value)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void cast_expression::accept(parser_visitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    type_expression& cast_expression::target()
 | 
			
		||||
    {
 | 
			
		||||
        return *m_target;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expression& cast_expression::value()
 | 
			
		||||
    {
 | 
			
		||||
        return *m_value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cast_expression::~cast_expression()
 | 
			
		||||
    {
 | 
			
		||||
        delete m_target;
 | 
			
		||||
        delete m_value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expression_statement::expression_statement(const struct position position, expression *body)
 | 
			
		||||
        : statement(position), m_body(body)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -106,6 +106,12 @@ not                     {
 | 
			
		||||
return                  {
 | 
			
		||||
                            return yy::parser::make_RETURN(this->location);
 | 
			
		||||
                        }
 | 
			
		||||
cast                    {
 | 
			
		||||
                            return yy::parser::make_CAST(this->location);
 | 
			
		||||
                        }
 | 
			
		||||
as                      {
 | 
			
		||||
                            return yy::parser::make_AS(this->location);
 | 
			
		||||
                        }
 | 
			
		||||
[A-Za-z_][A-Za-z0-9_]*  {
 | 
			
		||||
                            return yy::parser::make_IDENTIFIER(yytext, this->location);
 | 
			
		||||
                        }
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@
 | 
			
		||||
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION
 | 
			
		||||
%token BEGIN_BLOCK END_BLOCK EXTERN
 | 
			
		||||
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
 | 
			
		||||
%token AND OR NOT
 | 
			
		||||
%token AND OR NOT CAST AS
 | 
			
		||||
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
 | 
			
		||||
%token PLUS MINUS MULTIPLICATION DIVISION REMAINDER
 | 
			
		||||
%token ASSIGNMENT COLON HAT AT
 | 
			
		||||
@@ -97,6 +97,7 @@
 | 
			
		||||
%type <std::pair<std::string, elna::source::type_expression *>> field_declaration;
 | 
			
		||||
%type <std::vector<std::pair<std::string, elna::source::type_expression *>>> field_list;
 | 
			
		||||
%type <std::vector<elna::source::conditional_statements *>> elsif_statement_list;
 | 
			
		||||
%type <elna::source::cast_expression *> cast_expression;
 | 
			
		||||
%%
 | 
			
		||||
program:
 | 
			
		||||
    type_part constant_part procedure_part variable_part BEGIN_BLOCK optional_statements END_BLOCK DOT
 | 
			
		||||
@@ -183,6 +184,10 @@ call_expression: IDENTIFIER actual_parameter_list
 | 
			
		||||
            $$ = new elna::source::call_expression(elna::source::make_position(@1), $1);
 | 
			
		||||
            std::swap($$->arguments(), $2);
 | 
			
		||||
        }
 | 
			
		||||
cast_expression: CAST LEFT_PAREN expression AS type_expression RIGHT_PAREN
 | 
			
		||||
        {
 | 
			
		||||
            $$ = new elna::source::cast_expression(elna::source::make_position(@1), $5, $3);
 | 
			
		||||
        }
 | 
			
		||||
while_statement: WHILE expression DO optional_statements END_BLOCK
 | 
			
		||||
        {
 | 
			
		||||
            auto body = new elna::source::conditional_statements($2);
 | 
			
		||||
@@ -247,6 +252,7 @@ literal:
 | 
			
		||||
pointer:
 | 
			
		||||
    literal { $$ = $1; }
 | 
			
		||||
    | designator_expression { $$ = $1; }
 | 
			
		||||
    | cast_expression { $$ = $1; }
 | 
			
		||||
    | call_expression { $$ = $1; }
 | 
			
		||||
    | LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }
 | 
			
		||||
summand:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user