Allow declaring type synonyms
This commit is contained in:
parent
ed1bb621d6
commit
2d61828903
@ -36,6 +36,10 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
return "String";
|
return "String";
|
||||||
}
|
}
|
||||||
|
else if (is_array_type(type))
|
||||||
|
{
|
||||||
|
return "array";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return "<<unknown-type>>";
|
return "<<unknown-type>>";
|
||||||
|
@ -282,6 +282,36 @@ namespace gcc
|
|||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generic_visitor::visit(source::type_definition *definition)
|
||||||
|
{
|
||||||
|
tree tree_type = build_type(definition->body());
|
||||||
|
|
||||||
|
if (tree_type == NULL_TREE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
location_t definition_location = get_location(&definition->position());
|
||||||
|
tree definition_tree = build_decl(definition_location, TYPE_DECL,
|
||||||
|
get_identifier(definition->identifier().c_str()), tree_type);
|
||||||
|
auto result = this->symbol_map.insert({ definition->identifier(), definition_tree });
|
||||||
|
|
||||||
|
if (result.second)
|
||||||
|
{
|
||||||
|
DECL_CONTEXT(definition_tree) = this->main_fndecl;
|
||||||
|
variable_chain.append(definition_tree);
|
||||||
|
|
||||||
|
auto declaration_statement = build1_loc(definition_location, DECL_EXPR,
|
||||||
|
void_type_node, definition_tree);
|
||||||
|
append_to_statement_list(declaration_statement, &this->current_statements);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error_at(definition_location,
|
||||||
|
"type '%s' already declared in this scope",
|
||||||
|
definition->identifier().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tree generic_visitor::build_type(source::type_expression& type)
|
tree generic_visitor::build_type(source::type_expression& type)
|
||||||
{
|
{
|
||||||
if (source::basic_type_expression *basic_type = type.is_basic())
|
if (source::basic_type_expression *basic_type = type.is_basic())
|
||||||
@ -306,6 +336,12 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
return elna_string_type_node;
|
return elna_string_type_node;
|
||||||
}
|
}
|
||||||
|
auto symbol = this->symbol_map.find(basic_type->base_name());
|
||||||
|
|
||||||
|
if (symbol != this->symbol_map.end())
|
||||||
|
{
|
||||||
|
return TREE_TYPE(symbol->second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (source::array_type_expression *array_type = type.is_array())
|
else if (source::array_type_expression *array_type = type.is_array())
|
||||||
{
|
{
|
||||||
@ -371,39 +407,47 @@ namespace gcc
|
|||||||
this->current_expression = symbol->second;
|
this->current_expression = symbol->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generic_visitor::visit(source::array_access_expression *expression)
|
||||||
|
{
|
||||||
|
expression->base().accept(this);
|
||||||
|
tree designator = this->current_expression;
|
||||||
|
|
||||||
|
expression->index().accept(this);
|
||||||
|
tree index = this->current_expression;
|
||||||
|
|
||||||
|
tree element_type = TREE_TYPE(TREE_TYPE(designator));
|
||||||
|
|
||||||
|
this->current_expression = build4_loc(get_location(&expression->position()),
|
||||||
|
ARRAY_REF, element_type, designator, index, NULL_TREE, NULL_TREE);
|
||||||
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(source::assign_statement *statement)
|
void generic_visitor::visit(source::assign_statement *statement)
|
||||||
{
|
{
|
||||||
auto lvalue = this->symbol_map.find(statement->lvalue());
|
statement->lvalue().accept(this);
|
||||||
|
|
||||||
|
auto lvalue = this->current_expression;
|
||||||
auto statement_location = get_location(&statement->position());
|
auto statement_location = get_location(&statement->position());
|
||||||
|
|
||||||
if (lvalue == this->symbol_map.end())
|
|
||||||
{
|
|
||||||
error_at(statement_location,
|
|
||||||
"variable '%s' not declared in the current scope",
|
|
||||||
statement->lvalue().c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
statement->rvalue().accept(this);
|
statement->rvalue().accept(this);
|
||||||
|
|
||||||
if (TREE_CODE(lvalue->second) == CONST_DECL)
|
if (TREE_CODE(lvalue) == CONST_DECL)
|
||||||
{
|
{
|
||||||
error_at(statement_location, "cannot modify constant '%s'",
|
error_at(statement_location, "cannot modify constant '%s'",
|
||||||
statement->lvalue().c_str());
|
statement->lvalue().is_variable()->name().c_str());
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (TREE_TYPE(this->current_expression) != TREE_TYPE(lvalue->second))
|
if (TREE_TYPE(this->current_expression) != TREE_TYPE(lvalue))
|
||||||
{
|
{
|
||||||
error_at(statement_location,
|
error_at(statement_location,
|
||||||
"cannot assign value of type %s to variable '%s' of type %s",
|
"cannot assign value of type %s to variable of type %s",
|
||||||
print_type(TREE_TYPE(this->current_expression)),
|
print_type(TREE_TYPE(this->current_expression)),
|
||||||
statement->lvalue().c_str(),
|
print_type(TREE_TYPE(lvalue)));
|
||||||
print_type(TREE_TYPE(lvalue->second)));
|
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto assignment = build2_loc(statement_location, MODIFY_EXPR,
|
auto assignment = build2_loc(statement_location, MODIFY_EXPR,
|
||||||
void_type_node, lvalue->second, this->current_expression);
|
void_type_node, lvalue, this->current_expression);
|
||||||
|
|
||||||
append_to_statement_list(assignment, &this->current_statements);
|
append_to_statement_list(assignment, &this->current_statements);
|
||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
|
@ -23,6 +23,12 @@ namespace gcc
|
|||||||
&& TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node;
|
&& TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_array_type(tree type)
|
||||||
|
{
|
||||||
|
gcc_assert(TYPE_P(type));
|
||||||
|
return TREE_CODE(type) == ARRAY_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
tree tree_chain_base::head()
|
tree tree_chain_base::head()
|
||||||
{
|
{
|
||||||
return first;
|
return first;
|
||||||
|
@ -197,7 +197,7 @@ static tree elna_langhook_builtin_function(tree decl)
|
|||||||
|
|
||||||
static bool elna_langhook_global_bindings_p(void)
|
static bool elna_langhook_global_bindings_p(void)
|
||||||
{
|
{
|
||||||
gcc_unreachable();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static tree elna_langhook_pushdecl(tree decl ATTRIBUTE_UNUSED)
|
static tree elna_langhook_pushdecl(tree decl ATTRIBUTE_UNUSED)
|
||||||
|
@ -40,8 +40,10 @@ namespace gcc
|
|||||||
void visit(source::string_literal *string) override;
|
void visit(source::string_literal *string) override;
|
||||||
void visit(source::binary_expression *expression) override;
|
void visit(source::binary_expression *expression) override;
|
||||||
void visit(source::constant_definition *definition) override;
|
void visit(source::constant_definition *definition) override;
|
||||||
|
void visit(source::type_definition *definition) override;
|
||||||
void visit(source::declaration *declaration) override;
|
void visit(source::declaration *declaration) override;
|
||||||
void visit(source::variable_expression *expression) override;
|
void visit(source::variable_expression *expression) override;
|
||||||
|
void visit(source::array_access_expression *expression) override;
|
||||||
void visit(source::assign_statement *statement) override;
|
void visit(source::assign_statement *statement) override;
|
||||||
void visit(source::if_statement *statement) override;
|
void visit(source::if_statement *statement) override;
|
||||||
void visit(source::while_statement *statement) override;
|
void visit(source::while_statement *statement) override;
|
||||||
|
@ -23,6 +23,7 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
void init_ttree();
|
void init_ttree();
|
||||||
bool is_string_type(tree type);
|
bool is_string_type(tree type);
|
||||||
|
bool is_array_type(tree type);
|
||||||
|
|
||||||
class tree_chain_base
|
class tree_chain_base
|
||||||
{
|
{
|
||||||
|
@ -37,6 +37,7 @@ namespace source
|
|||||||
class declaration;
|
class declaration;
|
||||||
class constant_definition;
|
class constant_definition;
|
||||||
class procedure_definition;
|
class procedure_definition;
|
||||||
|
class type_definition;
|
||||||
class call_statement;
|
class call_statement;
|
||||||
class compound_statement;
|
class compound_statement;
|
||||||
class assign_statement;
|
class assign_statement;
|
||||||
@ -49,6 +50,7 @@ namespace source
|
|||||||
class basic_type_expression;
|
class basic_type_expression;
|
||||||
class array_type_expression;
|
class array_type_expression;
|
||||||
class variable_expression;
|
class variable_expression;
|
||||||
|
class array_access_expression;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class number_literal;
|
class number_literal;
|
||||||
class char_literal;
|
class char_literal;
|
||||||
@ -62,6 +64,7 @@ namespace source
|
|||||||
virtual void visit(declaration *) = 0;
|
virtual void visit(declaration *) = 0;
|
||||||
virtual void visit(constant_definition *) = 0;
|
virtual void visit(constant_definition *) = 0;
|
||||||
virtual void visit(procedure_definition *) = 0;
|
virtual void visit(procedure_definition *) = 0;
|
||||||
|
virtual void visit(type_definition *) = 0;
|
||||||
virtual void visit(call_statement *) = 0;
|
virtual void visit(call_statement *) = 0;
|
||||||
virtual void visit(compound_statement *) = 0;
|
virtual void visit(compound_statement *) = 0;
|
||||||
virtual void visit(assign_statement *) = 0;
|
virtual void visit(assign_statement *) = 0;
|
||||||
@ -74,6 +77,7 @@ namespace source
|
|||||||
virtual void visit(basic_type_expression *) = 0;
|
virtual void visit(basic_type_expression *) = 0;
|
||||||
virtual void visit(array_type_expression *) = 0;
|
virtual void visit(array_type_expression *) = 0;
|
||||||
virtual void visit(variable_expression *) = 0;
|
virtual void visit(variable_expression *) = 0;
|
||||||
|
virtual void visit(array_access_expression *) = 0;
|
||||||
virtual void visit(number_literal<std::int32_t> *) = 0;
|
virtual void visit(number_literal<std::int32_t> *) = 0;
|
||||||
virtual void visit(number_literal<double> *) = 0;
|
virtual void visit(number_literal<double> *) = 0;
|
||||||
virtual void visit(number_literal<bool> *) = 0;
|
virtual void visit(number_literal<bool> *) = 0;
|
||||||
@ -89,6 +93,7 @@ namespace source
|
|||||||
virtual void visit(declaration *) override;
|
virtual void visit(declaration *) override;
|
||||||
virtual void visit(constant_definition *definition) override;
|
virtual void visit(constant_definition *definition) override;
|
||||||
virtual void visit(procedure_definition *definition) override;
|
virtual void visit(procedure_definition *definition) override;
|
||||||
|
virtual void visit(type_definition *definition) override;
|
||||||
virtual void visit(call_statement *statement) override;
|
virtual void visit(call_statement *statement) override;
|
||||||
virtual void visit(compound_statement *statement) override;
|
virtual void visit(compound_statement *statement) override;
|
||||||
virtual void visit(assign_statement *statement) override;
|
virtual void visit(assign_statement *statement) override;
|
||||||
@ -99,8 +104,9 @@ namespace source
|
|||||||
virtual void visit(binary_expression *expression) override;
|
virtual void visit(binary_expression *expression) override;
|
||||||
virtual void visit(unary_expression *expression) override;
|
virtual void visit(unary_expression *expression) override;
|
||||||
virtual void visit(basic_type_expression *) override;
|
virtual void visit(basic_type_expression *) override;
|
||||||
virtual void visit(array_type_expression *) override;
|
virtual void visit(array_type_expression *expression) override;
|
||||||
virtual void visit(variable_expression *) override;
|
virtual void visit(variable_expression *) override;
|
||||||
|
virtual void visit(array_access_expression *expression) override;
|
||||||
virtual void visit(number_literal<std::int32_t> *) override;
|
virtual void visit(number_literal<std::int32_t> *) override;
|
||||||
virtual void visit(number_literal<double> *) override;
|
virtual void visit(number_literal<double> *) override;
|
||||||
virtual void visit(number_literal<bool> *) override;
|
virtual void visit(number_literal<bool> *) override;
|
||||||
@ -358,6 +364,20 @@ namespace source
|
|||||||
virtual ~procedure_definition() override;
|
virtual ~procedure_definition() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class type_definition : public definition
|
||||||
|
{
|
||||||
|
type_expression *m_body;
|
||||||
|
|
||||||
|
public:
|
||||||
|
type_definition(const struct position position, const std::string& identifier,
|
||||||
|
type_expression *expression);
|
||||||
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
|
type_expression& body();
|
||||||
|
|
||||||
|
virtual ~type_definition() override;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call statement.
|
* Call statement.
|
||||||
*/
|
*/
|
||||||
@ -393,9 +413,49 @@ namespace source
|
|||||||
virtual ~compound_statement() override;
|
virtual ~compound_statement() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class designator_expression : public expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual variable_expression *is_variable();
|
||||||
|
virtual array_access_expression *is_array_access();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
designator_expression(const struct position position);
|
||||||
|
};
|
||||||
|
|
||||||
|
class variable_expression : public designator_expression
|
||||||
|
{
|
||||||
|
std::string m_name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
variable_expression(const struct position position, const std::string& name);
|
||||||
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
|
const std::string& name() const;
|
||||||
|
|
||||||
|
variable_expression *is_variable() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class array_access_expression : public designator_expression
|
||||||
|
{
|
||||||
|
designator_expression *m_base;
|
||||||
|
expression *m_index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
array_access_expression(const struct position position, designator_expression *base, expression *index);
|
||||||
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
|
designator_expression& base();
|
||||||
|
expression& index();
|
||||||
|
|
||||||
|
array_access_expression *is_array_access() override;
|
||||||
|
|
||||||
|
~array_access_expression() override;
|
||||||
|
};
|
||||||
|
|
||||||
class assign_statement : public statement
|
class assign_statement : public statement
|
||||||
{
|
{
|
||||||
std::string m_lvalue;
|
designator_expression *m_lvalue;
|
||||||
expression *m_rvalue;
|
expression *m_rvalue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -404,11 +464,11 @@ namespace source
|
|||||||
* \param lvalue Left-hand side.
|
* \param lvalue Left-hand side.
|
||||||
* \param rvalue Assigned expression.
|
* \param rvalue Assigned expression.
|
||||||
*/
|
*/
|
||||||
assign_statement(const struct position position, const std::string& lvalue,
|
assign_statement(const struct position position, designator_expression *lvalue,
|
||||||
expression *rvalue);
|
expression *rvalue);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
std::string& lvalue();
|
designator_expression& lvalue();
|
||||||
expression& rvalue();
|
expression& rvalue();
|
||||||
|
|
||||||
virtual ~assign_statement() override;
|
virtual ~assign_statement() override;
|
||||||
@ -537,17 +597,6 @@ namespace source
|
|||||||
const std::string& string() const;
|
const std::string& string() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class variable_expression : public expression
|
|
||||||
{
|
|
||||||
std::string m_name;
|
|
||||||
|
|
||||||
public:
|
|
||||||
variable_expression(const struct position position, const std::string& name);
|
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
|
||||||
|
|
||||||
const std::string& name() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class binary_expression : public expression
|
class binary_expression : public expression
|
||||||
{
|
{
|
||||||
expression *m_lhs;
|
expression *m_lhs;
|
||||||
|
@ -69,36 +69,5 @@ namespace source
|
|||||||
|
|
||||||
std::string what() const override;
|
std::string what() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct type_mismatch final : public error
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Kind of the operation on the type.
|
|
||||||
*/
|
|
||||||
enum class operation
|
|
||||||
{
|
|
||||||
dereference,
|
|
||||||
argument,
|
|
||||||
arithmetic,
|
|
||||||
comparison,
|
|
||||||
condition,
|
|
||||||
assignment
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \param name Given type.
|
|
||||||
* \param kind Kind of the operation on the type.
|
|
||||||
* \param path Source file name.
|
|
||||||
* \param position Operation position.
|
|
||||||
*/
|
|
||||||
type_mismatch(std::shared_ptr<const type> got, operation kind, const char *path,
|
|
||||||
const struct position position);
|
|
||||||
|
|
||||||
std::string what() const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<const type> got;
|
|
||||||
operation kind;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,11 @@ namespace source
|
|||||||
definition->body().accept(this);
|
definition->body().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void empty_visitor::visit(type_definition *definition)
|
||||||
|
{
|
||||||
|
definition->body().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(call_statement *statement)
|
void empty_visitor::visit(call_statement *statement)
|
||||||
{
|
{
|
||||||
for (auto& argument : statement->arguments())
|
for (auto& argument : statement->arguments())
|
||||||
@ -91,14 +96,21 @@ namespace source
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(array_type_expression *)
|
void empty_visitor::visit(array_type_expression *expression)
|
||||||
{
|
{
|
||||||
|
expression->base().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(variable_expression *)
|
void empty_visitor::visit(variable_expression *)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void empty_visitor::visit(array_access_expression *expression)
|
||||||
|
{
|
||||||
|
expression->base().accept(this);
|
||||||
|
expression->index().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(number_literal<std::int32_t> *)
|
void empty_visitor::visit(number_literal<std::int32_t> *)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -332,6 +344,27 @@ namespace source
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type_definition::type_definition(const struct position position, const std::string& identifier,
|
||||||
|
type_expression *body)
|
||||||
|
: definition(position, identifier), m_body(body)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void type_definition::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_expression& type_definition::body()
|
||||||
|
{
|
||||||
|
return *m_body;
|
||||||
|
}
|
||||||
|
|
||||||
|
type_definition::~type_definition()
|
||||||
|
{
|
||||||
|
delete m_body;
|
||||||
|
}
|
||||||
|
|
||||||
block::block(const struct position position, std::vector<definition *>&& definitions,
|
block::block(const struct position position, std::vector<definition *>&& definitions,
|
||||||
std::vector<declaration *>&& declarations,
|
std::vector<declaration *>&& declarations,
|
||||||
statement *body)
|
statement *body)
|
||||||
@ -415,8 +448,13 @@ namespace source
|
|||||||
return m_string;
|
return m_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
designator_expression::designator_expression(const struct position position)
|
||||||
|
: expression(position)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
variable_expression::variable_expression(const struct position position, const std::string& name)
|
variable_expression::variable_expression(const struct position position, const std::string& name)
|
||||||
: expression(position), m_name(name)
|
: designator_expression(position), m_name(name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,6 +468,42 @@ namespace source
|
|||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable_expression *variable_expression::is_variable()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_access_expression::array_access_expression(const struct position position,
|
||||||
|
designator_expression *base, expression *index)
|
||||||
|
: designator_expression(position), m_base(base), m_index(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void array_access_expression::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
expression& array_access_expression::index()
|
||||||
|
{
|
||||||
|
return *m_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
designator_expression& array_access_expression::base()
|
||||||
|
{
|
||||||
|
return *m_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_access_expression *array_access_expression::is_array_access()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_access_expression::~array_access_expression()
|
||||||
|
{
|
||||||
|
delete m_base;
|
||||||
|
}
|
||||||
|
|
||||||
binary_expression::binary_expression(const struct position position, expression *lhs,
|
binary_expression::binary_expression(const struct position position, expression *lhs,
|
||||||
expression *rhs, const unsigned char operation)
|
expression *rhs, const unsigned char operation)
|
||||||
: expression(position), m_lhs(std::move(lhs)), m_rhs(std::move(rhs))
|
: expression(position), m_lhs(std::move(lhs)), m_rhs(std::move(rhs))
|
||||||
@ -590,15 +664,25 @@ namespace source
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
assign_statement::assign_statement(const struct position position, const std::string& lvalue,
|
assign_statement::assign_statement(const struct position position, designator_expression *lvalue,
|
||||||
expression *rvalue)
|
expression *rvalue)
|
||||||
: statement(position), m_lvalue(lvalue), m_rvalue(rvalue)
|
: statement(position), m_lvalue(lvalue), m_rvalue(rvalue)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string& assign_statement::lvalue()
|
variable_expression *designator_expression::is_variable()
|
||||||
{
|
{
|
||||||
return m_lvalue;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_access_expression *designator_expression::is_array_access()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
designator_expression& assign_statement::lvalue()
|
||||||
|
{
|
||||||
|
return *m_lvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
expression& assign_statement::rvalue()
|
expression& assign_statement::rvalue()
|
||||||
|
@ -67,6 +67,10 @@ array {
|
|||||||
of {
|
of {
|
||||||
return yy::parser::make_OF(this->location);
|
return yy::parser::make_OF(this->location);
|
||||||
}
|
}
|
||||||
|
type {
|
||||||
|
return yy::parser::make_TYPE(this->location);
|
||||||
|
}
|
||||||
|
|
||||||
true {
|
true {
|
||||||
return yy::parser::make_BOOLEAN(true, this->location);
|
return yy::parser::make_BOOLEAN(true, this->location);
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
%token <std::string> STRING "string"
|
%token <std::string> STRING "string"
|
||||||
%token <bool> BOOLEAN
|
%token <bool> BOOLEAN
|
||||||
%token IF WHILE DO
|
%token IF WHILE DO
|
||||||
%token CONST VAR PROCEDURE ARRAY OF
|
%token CONST VAR PROCEDURE ARRAY OF TYPE
|
||||||
%token BEGIN_BLOCK END_BLOCK
|
%token BEGIN_BLOCK END_BLOCK
|
||||||
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
||||||
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
||||||
@ -87,6 +87,7 @@
|
|||||||
%type <elna::source::expression *> expression pointer summand factor address comparand;
|
%type <elna::source::expression *> expression pointer summand factor address comparand;
|
||||||
%type <std::vector<elna::source::expression *>> expressions actual_parameter_list;
|
%type <std::vector<elna::source::expression *>> expressions actual_parameter_list;
|
||||||
%type <elna::source::variable_expression *> variable_expression;
|
%type <elna::source::variable_expression *> variable_expression;
|
||||||
|
%type <elna::source::designator_expression *> designator_expression;
|
||||||
%type <elna::source::compound_statement *> compound_statement;
|
%type <elna::source::compound_statement *> compound_statement;
|
||||||
%type <elna::source::assign_statement *> assign_statement;
|
%type <elna::source::assign_statement *> assign_statement;
|
||||||
%type <elna::source::call_statement *> call_statement;
|
%type <elna::source::call_statement *> call_statement;
|
||||||
@ -95,26 +96,31 @@
|
|||||||
%type <elna::source::statement *> statement;
|
%type <elna::source::statement *> statement;
|
||||||
%type <std::vector<elna::source::statement *>> statements optional_statements;
|
%type <std::vector<elna::source::statement *>> statements optional_statements;
|
||||||
%type <elna::source::procedure_definition *> procedure_definition;
|
%type <elna::source::procedure_definition *> procedure_definition;
|
||||||
%type <std::vector<elna::source::procedure_definition *>> procedure_definitions
|
%type <std::vector<elna::source::procedure_definition *>> procedure_definitions procedure_definition_part;
|
||||||
procedure_definition_part;
|
%type <elna::source::type_definition *> type_definition;
|
||||||
|
%type <std::vector<elna::source::type_definition *>> type_definitions type_definition_part;
|
||||||
%type <elna::source::block *> block;
|
%type <elna::source::block *> block;
|
||||||
%%
|
%%
|
||||||
program: constant_definition_part procedure_definition_part variable_declaration_part statement DOT
|
program:
|
||||||
|
type_definition_part constant_definition_part procedure_definition_part variable_declaration_part statement DOT
|
||||||
{
|
{
|
||||||
std::vector<elna::source::definition *> definitions($1.size() + $2.size());
|
std::vector<elna::source::definition *> definitions($1.size() + $2.size() + $3.size());
|
||||||
std::vector<elna::source::definition *>::iterator definition = definitions.begin();
|
std::vector<elna::source::definition *>::iterator definition = definitions.begin();
|
||||||
|
|
||||||
for (auto& constant : $1)
|
for (auto& type : $1)
|
||||||
|
{
|
||||||
|
*definition++ = type;
|
||||||
|
}
|
||||||
|
for (auto& constant : $2)
|
||||||
{
|
{
|
||||||
*definition++ = constant;
|
*definition++ = constant;
|
||||||
}
|
}
|
||||||
for (auto& procedure : $2)
|
for (auto& procedure : $3)
|
||||||
{
|
{
|
||||||
*definition++ = procedure;
|
*definition++ = procedure;
|
||||||
}
|
}
|
||||||
driver.tree = std::make_unique<elna::source::program>(elna::source::position{},
|
driver.tree = std::make_unique<elna::source::program>(elna::source::position{},
|
||||||
std::move(definitions), std::move($3),
|
std::move(definitions), std::move($4), std::move($5));
|
||||||
std::move($4));
|
|
||||||
}
|
}
|
||||||
block: constant_definition_part variable_declaration_part statement
|
block: constant_definition_part variable_declaration_part statement
|
||||||
{
|
{
|
||||||
@ -170,7 +176,7 @@ compound_statement: BEGIN_BLOCK optional_statements END_BLOCK
|
|||||||
$$ = new elna::source::compound_statement(elna::source::make_position(@1));
|
$$ = new elna::source::compound_statement(elna::source::make_position(@1));
|
||||||
std::swap($$->statements(), $2);
|
std::swap($$->statements(), $2);
|
||||||
}
|
}
|
||||||
assign_statement: IDENTIFIER ASSIGNMENT expression
|
assign_statement: designator_expression ASSIGNMENT expression
|
||||||
{
|
{
|
||||||
$$ = new elna::source::assign_statement(elna::source::make_position(@1), $1, $3);
|
$$ = new elna::source::assign_statement(elna::source::make_position(@1), $1, $3);
|
||||||
}
|
}
|
||||||
@ -201,7 +207,7 @@ pointer:
|
|||||||
| boolean_literal { $$ = $1; }
|
| boolean_literal { $$ = $1; }
|
||||||
| character_literal { $$ = $1; }
|
| character_literal { $$ = $1; }
|
||||||
| string_literal { $$ = $1; }
|
| string_literal { $$ = $1; }
|
||||||
| variable_expression { $$ = $1; }
|
| designator_expression { $$ = $1; }
|
||||||
| LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }
|
| LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }
|
||||||
summand:
|
summand:
|
||||||
factor { $$ = std::move($1); }
|
factor { $$ = std::move($1); }
|
||||||
@ -280,8 +286,14 @@ expressions:
|
|||||||
$$.emplace($$.cbegin(), $1);
|
$$.emplace($$.cbegin(), $1);
|
||||||
}
|
}
|
||||||
| expression { $$.emplace_back(std::move($1)); }
|
| expression { $$.emplace_back(std::move($1)); }
|
||||||
variable_expression: IDENTIFIER
|
variable_expression:
|
||||||
{ $$ = new elna::source::variable_expression(elna::source::make_position(@1), $1); }
|
IDENTIFIER { $$ = new elna::source::variable_expression(elna::source::make_position(@1), $1); }
|
||||||
|
designator_expression:
|
||||||
|
variable_expression LEFT_SQUARE expression RIGHT_SQUARE
|
||||||
|
{
|
||||||
|
$$ = new elna::source::array_access_expression(elna::source::make_position(@1), $1, $3);
|
||||||
|
}
|
||||||
|
| variable_expression { $$ = $1; }
|
||||||
statement:
|
statement:
|
||||||
compound_statement { $$ = $1; }
|
compound_statement { $$ = $1; }
|
||||||
| assign_statement { $$ = $1; }
|
| assign_statement { $$ = $1; }
|
||||||
@ -324,9 +336,8 @@ variable_declaration_part:
|
|||||||
| VAR variable_declarations SEMICOLON { std::swap($$, $2); }
|
| VAR variable_declarations SEMICOLON { std::swap($$, $2); }
|
||||||
constant_definition: IDENTIFIER EQUALS integer_literal
|
constant_definition: IDENTIFIER EQUALS integer_literal
|
||||||
{
|
{
|
||||||
$$ = new elna::source::constant_definition(elna::source::make_position(@1),
|
$$ = new elna::source::constant_definition(elna::source::make_position(@1), $1, $3);
|
||||||
$1, $3);
|
}
|
||||||
};
|
|
||||||
constant_definitions:
|
constant_definitions:
|
||||||
constant_definition COMMA constant_definitions
|
constant_definition COMMA constant_definitions
|
||||||
{
|
{
|
||||||
@ -336,7 +347,21 @@ constant_definitions:
|
|||||||
| constant_definition { $$.emplace_back(std::move($1)); }
|
| constant_definition { $$.emplace_back(std::move($1)); }
|
||||||
constant_definition_part:
|
constant_definition_part:
|
||||||
/* no constant definitions */ {}
|
/* no constant definitions */ {}
|
||||||
| CONST constant_definitions SEMICOLON { std::swap($$, $2); };
|
| CONST constant_definitions SEMICOLON { std::swap($$, $2); }
|
||||||
|
type_definition: IDENTIFIER EQUALS type_expression
|
||||||
|
{
|
||||||
|
$$ = new elna::source::type_definition(elna::source::make_position(@1), $1, $3);
|
||||||
|
}
|
||||||
|
type_definitions:
|
||||||
|
type_definition COMMA type_definitions
|
||||||
|
{
|
||||||
|
std::swap($$, $3);
|
||||||
|
$$.emplace($$.cbegin(), std::move($1));
|
||||||
|
}
|
||||||
|
| type_definition { $$.emplace_back(std::move($1)); }
|
||||||
|
type_definition_part:
|
||||||
|
/* no type definitions */ {}
|
||||||
|
| TYPE type_definitions SEMICOLON { std::swap($$, $2); }
|
||||||
formal_parameter_list:
|
formal_parameter_list:
|
||||||
LEFT_PAREN RIGHT_PAREN {}
|
LEFT_PAREN RIGHT_PAREN {}
|
||||||
| LEFT_PAREN variable_declarations RIGHT_PAREN { std::swap($$, $2); }
|
| LEFT_PAREN variable_declarations RIGHT_PAREN { std::swap($$, $2); }
|
||||||
|
@ -24,7 +24,7 @@ namespace source
|
|||||||
|
|
||||||
name_collision::name_collision(const std::string& name, const char *path,
|
name_collision::name_collision(const std::string& name, const char *path,
|
||||||
const struct position current, const struct position previous)
|
const struct position current, const struct position previous)
|
||||||
: error(path, current), name(name), previous(previous)
|
: error(path, current), previous(previous), name(name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,16 +32,5 @@ namespace source
|
|||||||
{
|
{
|
||||||
return "Name '" + name + "' was already defined";
|
return "Name '" + name + "' was already defined";
|
||||||
}
|
}
|
||||||
|
|
||||||
type_mismatch::type_mismatch(std::shared_ptr<const type> got, operation kind,
|
|
||||||
const char *path, const struct position position)
|
|
||||||
: error(path, position), kind(kind), got(got)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string type_mismatch::what() const
|
|
||||||
{
|
|
||||||
return "Type cannot be used here.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ namespace source
|
|||||||
}
|
}
|
||||||
|
|
||||||
procedure_type::procedure_type(std::vector<std::shared_ptr<const type>> arguments, const std::size_t byte_size)
|
procedure_type::procedure_type(std::vector<std::shared_ptr<const type>> arguments, const std::size_t byte_size)
|
||||||
: arguments(std::move(arguments)), type(byte_size)
|
:type(byte_size), arguments(std::move(arguments))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user