Implement enumeration type
This commit is contained in:
parent
50970f3289
commit
18c4e79012
67
boot/ast.cc
67
boot/ast.cc
@ -103,7 +103,7 @@ namespace elna::boot
|
||||
{
|
||||
}
|
||||
|
||||
primitive_type_expression *type_expression::is_primitive()
|
||||
named_type_expression *type_expression::is_named()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@ -133,17 +133,22 @@ namespace elna::boot
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name)
|
||||
enumeration_type_expression *type_expression::is_enumeration()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
named_type_expression::named_type_expression(const struct position position, const std::string& name)
|
||||
: type_expression(position), name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void primitive_type_expression::accept(parser_visitor *visitor)
|
||||
void named_type_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
primitive_type_expression *primitive_type_expression::is_primitive()
|
||||
named_type_expression *named_type_expression::is_named()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
@ -312,6 +317,26 @@ namespace elna::boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
procedure_type_expression *procedure_type_expression::is_procedure()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
enumeration_type_expression::enumeration_type_expression(const struct position position, std::vector<std::string>&& members)
|
||||
: type_expression(position), members(members)
|
||||
{
|
||||
}
|
||||
|
||||
void enumeration_type_expression::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
enumeration_type_expression *enumeration_type_expression::is_enumeration()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
|
||||
const bool exported, procedure_type_expression *heading, block *body)
|
||||
: definition(position, identifier, exported), m_heading(heading), body(body)
|
||||
@ -323,11 +348,6 @@ namespace elna::boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
procedure_type_expression *procedure_type_expression::is_procedure()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
procedure_type_expression& procedure_definition::heading()
|
||||
{
|
||||
return *m_heading;
|
||||
@ -417,8 +437,8 @@ namespace elna::boot
|
||||
return this;
|
||||
}
|
||||
|
||||
defer_statement::defer_statement(const struct position position)
|
||||
: node(position)
|
||||
defer_statement::defer_statement(const struct position position, std::vector<statement *>&& statements)
|
||||
: node(position), statements(std::move(statements))
|
||||
{
|
||||
}
|
||||
|
||||
@ -754,7 +774,7 @@ namespace elna::boot
|
||||
}
|
||||
|
||||
return_statement::return_statement(const struct position position, expression *return_expression)
|
||||
: node(position), m_return_expression(return_expression)
|
||||
: node(position), return_expression(return_expression)
|
||||
{
|
||||
}
|
||||
|
||||
@ -768,14 +788,25 @@ namespace elna::boot
|
||||
return this;
|
||||
}
|
||||
|
||||
expression *return_statement::return_expression()
|
||||
{
|
||||
return m_return_expression;
|
||||
}
|
||||
|
||||
return_statement::~return_statement()
|
||||
{
|
||||
delete m_return_expression;
|
||||
delete this->return_expression;
|
||||
}
|
||||
|
||||
case_statement::case_statement(const struct position position,
|
||||
expression *condition, std::vector<switch_case>&& cases)
|
||||
: node(position), m_condition(condition), cases(std::move(cases))
|
||||
{
|
||||
}
|
||||
|
||||
void case_statement::accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
expression& case_statement::condition()
|
||||
{
|
||||
return *m_condition;
|
||||
}
|
||||
|
||||
assign_statement::assign_statement(const struct position position, designator_expression *lvalue,
|
||||
|
@ -113,9 +113,12 @@ nil {
|
||||
xor {
|
||||
return yy::parser::make_XOR(this->location);
|
||||
}
|
||||
\| {
|
||||
or {
|
||||
return yy::parser::make_OR(this->location);
|
||||
}
|
||||
\| {
|
||||
return yy::parser::make_PIPE(this->location);
|
||||
}
|
||||
\~ {
|
||||
return yy::parser::make_NOT(this->location);
|
||||
}
|
||||
@ -128,6 +131,12 @@ cast {
|
||||
defer {
|
||||
return yy::parser::make_DEFER(this->location);
|
||||
}
|
||||
case {
|
||||
return yy::parser::make_CASE(this->location);
|
||||
}
|
||||
of {
|
||||
return yy::parser::make_OF(this->location);
|
||||
}
|
||||
[A-Za-z_][A-Za-z0-9_]* {
|
||||
return yy::parser::make_IDENTIFIER(yytext, this->location);
|
||||
}
|
||||
|
@ -111,31 +111,37 @@ along with GCC; see the file COPYING3. If not see
|
||||
BEGIN_BLOCK "begin"
|
||||
END_BLOCK "end"
|
||||
DEFER "defer"
|
||||
%token OR "|" AND "&" XOR "xor"
|
||||
CASE "case"
|
||||
OF "of"
|
||||
PIPE "|"
|
||||
%token OR "or" AND "&" XOR "xor"
|
||||
EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">="
|
||||
SHIFT_LEFT "<<" SHIFT_RIGHT ">>"
|
||||
PLUS "+" MINUS "-"
|
||||
MULTIPLICATION "*" DIVISION "/" REMAINDER "%"
|
||||
|
||||
%left "|" "&" "xor"
|
||||
%left "or" "&" "xor"
|
||||
%left "=" "<>" "<" ">" "<=" ">="
|
||||
%left "<<" ">>"
|
||||
%left "+" "-"
|
||||
%left "*" "/" "%"
|
||||
|
||||
%type <elna::boot::literal_expression *> literal;
|
||||
%type <std::vector<elna::boot::literal_expression *>> case_labels;
|
||||
%type <elna::boot::switch_case> switch_case;
|
||||
%type <std::vector<elna::boot::switch_case>> switch_cases;
|
||||
%type <elna::boot::constant_definition *> constant_definition;
|
||||
%type <std::vector<elna::boot::constant_definition *>> constant_part constant_definitions;
|
||||
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part variable_declaration;
|
||||
%type <elna::boot::type_expression *> type_expression;
|
||||
%type <std::vector<elna::boot::type_expression *>> type_expressions;
|
||||
%type <elna::boot::traits_expression *> traits_expression;
|
||||
%type <elna::boot::expression *> expression operand qualident;
|
||||
%type <elna::boot::expression *> expression operand simple_expression;
|
||||
%type <elna::boot::field_access_expression *> qualident;
|
||||
%type <elna::boot::unary_expression *> unary_expression;
|
||||
%type <elna::boot::binary_expression *> binary_expression;
|
||||
%type <std::vector<elna::boot::expression *>> expressions actual_parameter_list;
|
||||
%type <elna::boot::designator_expression *> designator_expression;
|
||||
%type <elna::boot::assign_statement *> assign_statement;
|
||||
%type <elna::boot::procedure_call*> call_expression;
|
||||
%type <elna::boot::while_statement *> while_statement;
|
||||
%type <elna::boot::if_statement *> if_statement;
|
||||
@ -154,9 +160,9 @@ along with GCC; see the file COPYING3. If not see
|
||||
optional_fields required_fields formal_parameters;
|
||||
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;
|
||||
%type <elna::boot::cast_expression *> cast_expression;
|
||||
%type <elna::boot::defer_statement *> defer_statement;
|
||||
%type <std::pair<std::string, bool>> identifier_definition;
|
||||
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
|
||||
%type <std::vector<std::string>> identifiers;
|
||||
%%
|
||||
program:
|
||||
constant_part type_part variable_part procedure_part "begin" statements "end" "."
|
||||
@ -230,10 +236,6 @@ procedure_definitions:
|
||||
procedure_part:
|
||||
/* no procedure definitions */ {}
|
||||
| procedure_definitions { std::swap($$, $1); }
|
||||
assign_statement: designator_expression ":=" expression
|
||||
{
|
||||
$$ = new boot::assign_statement(boot::make_position(@1), $1, $3);
|
||||
}
|
||||
call_expression: designator_expression actual_parameter_list
|
||||
{
|
||||
$$ = new boot::procedure_call(boot::make_position(@1), $1);
|
||||
@ -293,11 +295,6 @@ return_statement:
|
||||
{
|
||||
$$ = new boot::return_statement(boot::make_position(@1));
|
||||
}
|
||||
defer_statement: DEFER statements "end"
|
||||
{
|
||||
$$ = new boot::defer_statement(boot::make_position(@1));
|
||||
std::swap($2, $$->statements);
|
||||
}
|
||||
literal:
|
||||
INTEGER
|
||||
{
|
||||
@ -333,7 +330,7 @@ traits_expression:
|
||||
$$ = new boot::traits_expression(boot::make_position(@1), $1);
|
||||
std::swap($3, $$->parameters);
|
||||
}
|
||||
qualident:
|
||||
simple_expression:
|
||||
literal { $$ = $1; }
|
||||
| designator_expression { $$ = $1; }
|
||||
| traits_expression { $$ = $1; }
|
||||
@ -342,7 +339,7 @@ qualident:
|
||||
| "(" expression ")" { $$ = $2; }
|
||||
operand:
|
||||
unary_expression { $$ = $1; }
|
||||
| qualident { $$ = $1; }
|
||||
| simple_expression { $$ = $1; }
|
||||
expression:
|
||||
binary_expression { $$ = $1; }
|
||||
| operand { $$ = $1; }
|
||||
@ -396,7 +393,7 @@ binary_expression:
|
||||
{
|
||||
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::conjunction);
|
||||
}
|
||||
| expression "|" expression
|
||||
| expression "or" expression
|
||||
{
|
||||
$$ = new boot::binary_expression(boot::make_position(@2), $1, $3, boot::binary_operator::disjunction);
|
||||
}
|
||||
@ -441,15 +438,12 @@ type_expressions:
|
||||
}
|
||||
| type_expression { $$.push_back($1); }
|
||||
designator_expression:
|
||||
qualident "[" expression "]"
|
||||
simple_expression "[" expression "]"
|
||||
{
|
||||
$$ = new boot::array_access_expression(boot::make_position(@2), $1, $3);
|
||||
}
|
||||
| qualident "." IDENTIFIER
|
||||
{
|
||||
$$ = new boot::field_access_expression(boot::make_position(@2), $1, $3);
|
||||
}
|
||||
| qualident "^"
|
||||
| qualident { $$ = $1; }
|
||||
| simple_expression "^"
|
||||
{
|
||||
$$ = new boot::dereference_expression(boot::make_position(@1), $1);
|
||||
}
|
||||
@ -457,13 +451,37 @@ designator_expression:
|
||||
{
|
||||
$$ = new boot::variable_expression(boot::make_position(@1), $1);
|
||||
}
|
||||
qualident: simple_expression "." IDENTIFIER
|
||||
{
|
||||
$$ = new boot::field_access_expression(boot::make_position(@2), $1, $3);
|
||||
}
|
||||
statement:
|
||||
assign_statement { $$ = $1; }
|
||||
designator_expression ":=" expression
|
||||
{
|
||||
$$ = new boot::assign_statement(boot::make_position(@1), $1, $3);
|
||||
}
|
||||
| while_statement { $$ = $1; }
|
||||
| if_statement { $$ = $1; }
|
||||
| return_statement { $$ = $1; }
|
||||
| call_expression { $$ = $1; }
|
||||
| defer_statement { $$ = $1; }
|
||||
| DEFER statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); }
|
||||
| CASE expression "of" switch_cases "end"
|
||||
{ $$ = new boot::case_statement(boot::make_position(@1), $2, std::move($4)); }
|
||||
switch_case: case_labels ":" statements { $$ = { .labels = std::move($1), .statements = std::move($3) }; }
|
||||
switch_cases:
|
||||
switch_case "|" switch_cases
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| switch_case { $$.push_back($1); }
|
||||
case_labels:
|
||||
literal "," case_labels
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| literal { $$.push_back($1); }
|
||||
statements:
|
||||
statement ";" statements
|
||||
{
|
||||
@ -507,10 +525,21 @@ type_expression:
|
||||
std::swap(result->parameters, $3);
|
||||
$$ = result;
|
||||
}
|
||||
| "(" identifiers ")"
|
||||
{
|
||||
$$ = new boot::enumeration_type_expression(boot::make_position(@1), std::move($2));
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
$$ = new boot::primitive_type_expression(boot::make_position(@1), $1);
|
||||
$$ = new boot::named_type_expression(boot::make_position(@1), $1);
|
||||
}
|
||||
identifiers:
|
||||
IDENTIFIER "," identifiers
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
}
|
||||
| IDENTIFIER { $$.emplace_back(std::move($1)); }
|
||||
variable_declaration: identifier_definitions ":" type_expression
|
||||
{
|
||||
std::shared_ptr<boot::type_expression> shared_type{ $3 };
|
||||
@ -561,16 +590,14 @@ type_definitions:
|
||||
type_part:
|
||||
/* no type definitions */ {}
|
||||
| "type" type_definitions { std::swap($$, $2); }
|
||||
formal_parameter: IDENTIFIER ":" type_expression
|
||||
{
|
||||
$$ = std::make_pair($1, $3);
|
||||
}
|
||||
formal_parameter:
|
||||
IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
|
||||
formal_parameters:
|
||||
/* no formal parameters */ {}
|
||||
| formal_parameter "," formal_parameters
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
}
|
||||
| formal_parameter { $$.emplace_back(std::move($1)); }
|
||||
actual_parameter_list:
|
||||
|
@ -114,7 +114,7 @@ namespace elna::boot
|
||||
unresolved_declaration->reference = this->current_type;
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(primitive_type_expression *type_expression)
|
||||
void declaration_visitor::visit(named_type_expression *type_expression)
|
||||
{
|
||||
auto unresolved_alias = this->unresolved.find(type_expression->name);
|
||||
|
||||
@ -177,13 +177,23 @@ namespace elna::boot
|
||||
this->current_type = type(result_type);
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(enumeration_type_expression *type_expression)
|
||||
{
|
||||
std::shared_ptr<enumeration_type> result_type = std::make_shared<enumeration_type>(type_expression->members);
|
||||
|
||||
this->current_type = type(result_type);
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(variable_declaration *declaration)
|
||||
{
|
||||
declaration->variable_type().accept(this);
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(constant_definition *)
|
||||
void declaration_visitor::visit(constant_definition *definition)
|
||||
{
|
||||
definition->body().accept(this);
|
||||
|
||||
this->symbols->enter(definition->identifier, std::make_shared<constant_info>(this->current_literal));
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(procedure_definition *definition)
|
||||
@ -249,9 +259,9 @@ namespace elna::boot
|
||||
|
||||
void declaration_visitor::visit(return_statement *statement)
|
||||
{
|
||||
if (statement->return_expression() != nullptr)
|
||||
if (statement->return_expression != nullptr)
|
||||
{
|
||||
statement->return_expression()->accept(this);
|
||||
statement->return_expression->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,6 +273,22 @@ namespace elna::boot
|
||||
}
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(case_statement *statement)
|
||||
{
|
||||
statement->condition().accept(this);
|
||||
for (const switch_case& case_block : statement->cases)
|
||||
{
|
||||
for (literal_expression *const case_label : case_block.labels)
|
||||
{
|
||||
case_label->accept(this);
|
||||
}
|
||||
for (struct statement *const statement : case_block.statements)
|
||||
{
|
||||
statement->accept(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(procedure_call *call)
|
||||
{
|
||||
call->callable().accept(this);
|
||||
@ -333,31 +359,38 @@ namespace elna::boot
|
||||
expression->base().accept(this);
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(literal<std::int32_t> *)
|
||||
void declaration_visitor::visit(literal<std::int32_t> *literal)
|
||||
{
|
||||
this->current_literal = literal->value;
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(literal<std::uint32_t> *)
|
||||
void declaration_visitor::visit(literal<std::uint32_t> *literal)
|
||||
{
|
||||
this->current_literal = literal->value;
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(literal<double> *)
|
||||
void declaration_visitor::visit(literal<double> *literal)
|
||||
{
|
||||
this->current_literal = literal->value;
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(literal<bool> *)
|
||||
void declaration_visitor::visit(literal<bool> *literal)
|
||||
{
|
||||
this->current_literal = literal->value;
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(literal<unsigned char> *)
|
||||
void declaration_visitor::visit(literal<unsigned char> *literal)
|
||||
{
|
||||
this->current_literal = literal->value;
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(literal<std::nullptr_t> *)
|
||||
void declaration_visitor::visit(literal<std::nullptr_t> *literal)
|
||||
{
|
||||
this->current_literal = literal->value;
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(literal<std::string> *)
|
||||
void declaration_visitor::visit(literal<std::string> *literal)
|
||||
{
|
||||
this->current_literal = literal->value;
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,11 @@ namespace elna::boot
|
||||
{
|
||||
}
|
||||
|
||||
type::type(std::shared_ptr<enumeration_type> enumeration)
|
||||
: tag(type_tag::enumeration), enumeration(enumeration)
|
||||
{
|
||||
}
|
||||
|
||||
void type::copy(const type& other)
|
||||
{
|
||||
switch (other.tag)
|
||||
@ -85,6 +90,9 @@ namespace elna::boot
|
||||
case type_tag::procedure:
|
||||
new (&procedure) std::shared_ptr<procedure_type>(other.procedure);
|
||||
break;
|
||||
case type_tag::enumeration:
|
||||
new (&enumeration) std::shared_ptr<enumeration_type>(other.enumeration);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,6 +129,9 @@ namespace elna::boot
|
||||
case type_tag::procedure:
|
||||
new (&procedure) std::shared_ptr<procedure_type>(std::move(other.procedure));
|
||||
break;
|
||||
case type_tag::enumeration:
|
||||
new (&enumeration) std::shared_ptr<enumeration_type>(std::move(other.enumeration));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,6 +189,9 @@ namespace elna::boot
|
||||
case type_tag::procedure:
|
||||
this->procedure.~shared_ptr<procedure_type>();
|
||||
break;
|
||||
case type_tag::enumeration:
|
||||
this->enumeration.~shared_ptr<enumeration_type>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,6 +237,12 @@ namespace elna::boot
|
||||
return tag == type_tag::procedure ? this->procedure : nullptr;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::shared_ptr<enumeration_type> type::get<enumeration_type>() const
|
||||
{
|
||||
return tag == type_tag::enumeration ? this->enumeration : nullptr;
|
||||
}
|
||||
|
||||
bool type::empty() const
|
||||
{
|
||||
return tag == type_tag::empty;
|
||||
@ -253,6 +273,11 @@ namespace elna::boot
|
||||
{
|
||||
}
|
||||
|
||||
enumeration_type::enumeration_type(const std::vector<std::string>& members)
|
||||
: members(members)
|
||||
{
|
||||
}
|
||||
|
||||
info::~info()
|
||||
{
|
||||
}
|
||||
@ -287,6 +312,11 @@ namespace elna::boot
|
||||
return std::static_pointer_cast<procedure_info>(shared_from_this());
|
||||
}
|
||||
|
||||
constant_info::constant_info(const variant& symbol)
|
||||
: symbol(symbol)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<symbol_table> builtin_symbol_table()
|
||||
{
|
||||
auto result = std::make_shared<symbol_table>();
|
||||
|
@ -78,7 +78,7 @@ namespace elna::gcc
|
||||
{
|
||||
return "()";
|
||||
}
|
||||
else if (is_pointer_type(unqualified_type))
|
||||
else if (POINTER_TYPE_P(unqualified_type))
|
||||
{
|
||||
tree pointer_target_type = TREE_TYPE(type);
|
||||
|
||||
@ -129,6 +129,10 @@ namespace elna::gcc
|
||||
{
|
||||
return print_aggregate_name(unqualified_type, "union");
|
||||
}
|
||||
else if (TREE_CODE(type) == ENUMERAL_TYPE)
|
||||
{
|
||||
return print_aggregate_name(unqualified_type, "enumeration");
|
||||
}
|
||||
else
|
||||
{
|
||||
return "<<unknown-type>>";
|
||||
|
@ -57,6 +57,10 @@ namespace elna::gcc
|
||||
{
|
||||
return make_node(UNION_TYPE);
|
||||
}
|
||||
else if (auto reference = type.get<boot::enumeration_type>())
|
||||
{
|
||||
return make_node(ENUMERAL_TYPE);
|
||||
}
|
||||
else if (auto reference = type.get<boot::pointer_type>())
|
||||
{
|
||||
return build_global_pointer_type(get_inner_alias(reference->base, symbols, unresolved, path));
|
||||
@ -227,7 +231,7 @@ namespace elna::gcc
|
||||
build_global_pointer_type(expression_type), this->current_expression);
|
||||
build_procedure_call(call_location, this->current_expression, call->arguments);
|
||||
}
|
||||
else if (is_pointer_type(expression_type) && TREE_CODE(TREE_TYPE(expression_type)) == FUNCTION_TYPE)
|
||||
else if (POINTER_TYPE_P(expression_type) && TREE_CODE(TREE_TYPE(expression_type)) == FUNCTION_TYPE)
|
||||
{
|
||||
build_procedure_call(call_location, this->current_expression, call->arguments);
|
||||
}
|
||||
@ -247,8 +251,7 @@ namespace elna::gcc
|
||||
expression->value().accept(this);
|
||||
tree cast_source = TREE_TYPE(this->current_expression);
|
||||
|
||||
if ((is_primitive_type(cast_target) || is_pointer_type(cast_target))
|
||||
&& (is_primitive_type(cast_source) || is_pointer_type(cast_source)))
|
||||
if (is_castable_type(cast_target) && (is_castable_type(cast_source)))
|
||||
{
|
||||
this->current_expression = build1_loc(get_location(&expression->position()), CONVERT_EXPR,
|
||||
cast_target, this->current_expression);
|
||||
@ -303,7 +306,8 @@ namespace elna::gcc
|
||||
for (boot::constant_definition *const constant : program->constants)
|
||||
{
|
||||
constant->accept(this);
|
||||
} for (boot::type_definition *const type : program->types)
|
||||
}
|
||||
for (boot::type_definition *const type : program->types)
|
||||
{
|
||||
type->accept(this);
|
||||
}
|
||||
@ -514,7 +518,7 @@ namespace elna::gcc
|
||||
tree generic_visitor::build_comparison_operation(boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right)
|
||||
{
|
||||
return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || is_pointer_type(TREE_TYPE(left)),
|
||||
return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || POINTER_TYPE_P(TREE_TYPE(left)),
|
||||
expression, operator_code, left, right, elna_bool_type_node);
|
||||
}
|
||||
|
||||
@ -624,7 +628,7 @@ namespace elna::gcc
|
||||
|
||||
location_t expression_location = get_location(&expression->position());
|
||||
|
||||
if ((is_pointer_type(left_type) || is_pointer_type(right_type))
|
||||
if ((POINTER_TYPE_P(left_type) || POINTER_TYPE_P(right_type))
|
||||
&& (expression->operation() == boot::binary_operator::sum
|
||||
|| expression->operation() == boot::binary_operator::subtraction))
|
||||
{
|
||||
@ -867,7 +871,7 @@ namespace elna::gcc
|
||||
get_identifier(declaration->identifier.c_str()), this->current_expression);
|
||||
bool result = this->symbols->enter(declaration->identifier, declaration_tree);
|
||||
|
||||
if (is_pointer_type(this->current_expression))
|
||||
if (POINTER_TYPE_P(this->current_expression))
|
||||
{
|
||||
DECL_INITIAL(declaration_tree) = elna_pointer_nil_node;
|
||||
}
|
||||
@ -976,7 +980,7 @@ namespace elna::gcc
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!is_integral_type(this->current_expression))
|
||||
else if (!is_integral_type(this->current_expression) && TREE_CODE(this->current_expression) != ENUMERAL_TYPE)
|
||||
{
|
||||
error_at(get_location(&trait->position()), "Type '%s' does not support trait '%s'",
|
||||
print_type(this->current_expression).c_str(), trait->name.c_str());
|
||||
@ -1030,7 +1034,7 @@ namespace elna::gcc
|
||||
return;
|
||||
}
|
||||
trait->parameters.front()->accept(this);
|
||||
auto field_type = trait->parameters.at(1)->is_primitive();
|
||||
auto field_type = trait->parameters.at(1)->is_named();
|
||||
|
||||
if (field_type == nullptr)
|
||||
{
|
||||
@ -1076,6 +1080,21 @@ namespace elna::gcc
|
||||
this->current_expression = build1(ADDR_EXPR,
|
||||
build_qualified_type(ptr_type, TYPE_QUAL_CONST), this->current_expression);
|
||||
}
|
||||
else if (TREE_CODE(aggregate_type) == ENUMERAL_TYPE)
|
||||
{
|
||||
tree iterator{ NULL_TREE };
|
||||
|
||||
for (iterator = TYPE_VALUES(aggregate_type); iterator != NULL_TREE; iterator = TREE_CHAIN(iterator))
|
||||
{
|
||||
if (IDENTIFIER_POINTER(TREE_PURPOSE(iterator)) == expression->field())
|
||||
{
|
||||
this->current_expression = TREE_VALUE(iterator);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->current_expression = error_mark_node;
|
||||
error_at(expression_location, "Unknown enumeration member '%s'", expression->field().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
tree field_declaration = find_field_by_name(expression_location,
|
||||
@ -1096,7 +1115,7 @@ namespace elna::gcc
|
||||
location_t expression_location = get_location(&expression->position());
|
||||
tree expression_type = TREE_TYPE(this->current_expression);
|
||||
|
||||
if (is_pointer_type(expression_type))
|
||||
if (POINTER_TYPE_P(expression_type))
|
||||
{
|
||||
this->current_expression = build1_loc(expression_location, INDIRECT_REF,
|
||||
TREE_TYPE(expression_type), this->current_expression);
|
||||
@ -1201,16 +1220,6 @@ namespace elna::gcc
|
||||
append_statement(else_label_expr);
|
||||
}
|
||||
|
||||
tree generic_visitor::build_label_decl(const char *name, location_t loc)
|
||||
{
|
||||
auto label_decl = build_decl(loc,
|
||||
LABEL_DECL, get_identifier(name), void_type_node);
|
||||
|
||||
DECL_CONTEXT(label_decl) = current_function_decl;
|
||||
|
||||
return label_decl;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::while_statement *statement)
|
||||
{
|
||||
auto prerequisite_location = get_location(&statement->body().prerequisite().position());
|
||||
@ -1245,7 +1254,7 @@ namespace elna::gcc
|
||||
|
||||
void generic_visitor::visit(boot::return_statement *statement)
|
||||
{
|
||||
boot::expression *return_expression = statement->return_expression();
|
||||
boot::expression *return_expression = statement->return_expression;
|
||||
location_t statement_position = get_location(&statement->position());
|
||||
tree set_result{ NULL_TREE };
|
||||
tree return_type = TREE_TYPE(TREE_TYPE(current_function_decl));
|
||||
@ -1285,7 +1294,7 @@ namespace elna::gcc
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::primitive_type_expression *type)
|
||||
void generic_visitor::visit(boot::named_type_expression *type)
|
||||
{
|
||||
auto looked_up = this->unresolved.find(type->name);
|
||||
tree symbol;
|
||||
@ -1362,10 +1371,85 @@ namespace elna::gcc
|
||||
this->current_expression = build_global_pointer_type(procedure_type_node);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::enumeration_type_expression *type)
|
||||
{
|
||||
tree composite_type_node = this->current_expression == NULL_TREE
|
||||
? make_node(ENUMERAL_TYPE)
|
||||
: this->current_expression;
|
||||
location_t enum_location = get_location(&type->position());
|
||||
const tree base_type = integer_type_node;
|
||||
|
||||
TREE_TYPE(composite_type_node) = base_type;
|
||||
ENUM_IS_SCOPED(composite_type_node) = 1;
|
||||
|
||||
tree *pp = &TYPE_VALUES(composite_type_node);
|
||||
std::size_t order{ 1 };
|
||||
|
||||
for (const std::string& member : type->members)
|
||||
{
|
||||
tree member_name = get_identifier(member.c_str());
|
||||
tree member_declaration = build_decl(enum_location, CONST_DECL, member_name, composite_type_node);
|
||||
|
||||
DECL_CONTEXT(member_declaration) = composite_type_node;
|
||||
DECL_INITIAL(member_declaration) = build_int_cst_type(composite_type_node, order++);
|
||||
TREE_CONSTANT(member_declaration) = 1;
|
||||
TREE_READONLY(member_declaration) = 1;
|
||||
|
||||
TYPE_MAX_VALUE(composite_type_node) = DECL_INITIAL(member_declaration);
|
||||
|
||||
*pp = build_tree_list(member_name, member_declaration);
|
||||
pp = &TREE_CHAIN(*pp);
|
||||
}
|
||||
TYPE_MIN_VALUE(composite_type_node) = DECL_INITIAL(TREE_VALUE(TYPE_VALUES(composite_type_node)));
|
||||
TYPE_UNSIGNED(composite_type_node) = TYPE_UNSIGNED(base_type);
|
||||
SET_TYPE_ALIGN(composite_type_node, TYPE_ALIGN(base_type));
|
||||
TYPE_SIZE(composite_type_node) = NULL_TREE;
|
||||
TYPE_PRECISION(composite_type_node) = TYPE_PRECISION(base_type);
|
||||
|
||||
layout_type(composite_type_node);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::defer_statement *statement)
|
||||
{
|
||||
enter_scope();
|
||||
visit_statements(statement->statements);
|
||||
defer(leave_scope());
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::case_statement *statement)
|
||||
{
|
||||
statement->condition().accept(this);
|
||||
|
||||
tree condition_expression = this->current_expression;
|
||||
tree end_label_declaration = create_artificial_label(UNKNOWN_LOCATION);
|
||||
tree switch_statements = alloc_stmt_list();
|
||||
|
||||
for (const boot::switch_case& case_block : statement->cases)
|
||||
{
|
||||
for (boot::literal_expression *const case_label : case_block.labels)
|
||||
{
|
||||
case_label->accept(this);
|
||||
tree case_label_declaration = create_artificial_label(get_location(&case_label->position()));
|
||||
tree case_expression = build_case_label(this->current_expression, NULL_TREE, case_label_declaration);
|
||||
|
||||
append_to_statement_list(case_expression, &switch_statements);
|
||||
}
|
||||
enter_scope();
|
||||
visit_statements(case_block.statements);
|
||||
append_to_statement_list(leave_scope(), &switch_statements);
|
||||
tree goto_end = fold_build1(GOTO_EXPR, void_type_node, end_label_declaration);
|
||||
|
||||
append_to_statement_list(goto_end, &switch_statements);
|
||||
TREE_USED(end_label_declaration) = 1;
|
||||
}
|
||||
tree switch_expression = build2(SWITCH_EXPR, TREE_TYPE(condition_expression),
|
||||
condition_expression, switch_statements);
|
||||
|
||||
append_statement(switch_expression);
|
||||
|
||||
tree end_label_expression = build1(LABEL_EXPR, void_type_node, end_label_declaration);
|
||||
append_statement(end_label_expression);
|
||||
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
}
|
||||
|
@ -26,12 +26,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
namespace elna::gcc
|
||||
{
|
||||
bool is_pointer_type(tree type)
|
||||
{
|
||||
gcc_assert(TYPE_P(type));
|
||||
return TREE_CODE(type) == POINTER_TYPE;
|
||||
}
|
||||
|
||||
bool is_integral_type(tree type)
|
||||
{
|
||||
gcc_assert(TYPE_P(type));
|
||||
@ -62,10 +56,12 @@ namespace elna::gcc
|
||||
return type == NULL_TREE || type == void_type_node;
|
||||
}
|
||||
|
||||
bool is_aggregate_type(tree type)
|
||||
bool is_castable_type(tree type)
|
||||
{
|
||||
gcc_assert(TYPE_P(type));
|
||||
return TREE_CODE(type) == RECORD_TYPE || TREE_CODE(type) == UNION_TYPE;
|
||||
auto code = TREE_CODE(type);
|
||||
|
||||
return is_primitive_type(type) || POINTER_TYPE_P(type) || code == ENUMERAL_TYPE;
|
||||
}
|
||||
|
||||
bool are_compatible_pointers(tree lhs_type, tree rhs)
|
||||
@ -73,8 +69,8 @@ namespace elna::gcc
|
||||
gcc_assert(TYPE_P(lhs_type));
|
||||
tree rhs_type = TREE_TYPE(rhs);
|
||||
|
||||
return (is_pointer_type(lhs_type) && rhs == elna_pointer_nil_node)
|
||||
|| (is_pointer_type(lhs_type) && lhs_type == rhs_type);
|
||||
return (POINTER_TYPE_P(lhs_type) && rhs == elna_pointer_nil_node)
|
||||
|| (POINTER_TYPE_P(lhs_type) && lhs_type == rhs_type);
|
||||
}
|
||||
|
||||
tree prepare_rvalue(tree rvalue)
|
||||
@ -152,12 +148,12 @@ namespace elna::gcc
|
||||
tree pointer{ NULL_TREE };
|
||||
tree offset{ NULL_TREE };
|
||||
|
||||
if (is_pointer_type(left_type) && is_integral_type(right_type))
|
||||
if (POINTER_TYPE_P(left_type) && is_integral_type(right_type))
|
||||
{
|
||||
pointer = left;
|
||||
offset = right;
|
||||
}
|
||||
else if (is_integral_type(left_type) && is_pointer_type(right_type))
|
||||
else if (is_integral_type(left_type) && POINTER_TYPE_P(right_type))
|
||||
{
|
||||
pointer = right;
|
||||
offset = left;
|
||||
@ -175,7 +171,7 @@ namespace elna::gcc
|
||||
}
|
||||
else if (binary_operator == boot::binary_operator::subtraction)
|
||||
{
|
||||
if (is_pointer_type(left_type) && is_integral_type(right_type))
|
||||
if (POINTER_TYPE_P(left_type) && is_integral_type(right_type))
|
||||
{
|
||||
tree pointer_type = left_type;
|
||||
tree offset_type = right_type;
|
||||
@ -187,7 +183,7 @@ namespace elna::gcc
|
||||
convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression);
|
||||
return fold_build2(POINTER_PLUS_EXPR, pointer_type, left, convert_expression);
|
||||
}
|
||||
else if (is_pointer_type(left_type) && is_pointer_type(right_type) && left_type == right_type)
|
||||
else if (POINTER_TYPE_P(left_type) && POINTER_TYPE_P(right_type) && left_type == right_type)
|
||||
{
|
||||
return fold_build2(POINTER_DIFF_EXPR, ssizetype, left, right);
|
||||
}
|
||||
@ -224,9 +220,9 @@ namespace elna::gcc
|
||||
}
|
||||
tree field_declaration = TYPE_FIELDS(type);
|
||||
|
||||
if (!is_aggregate_type(type))
|
||||
if (!RECORD_OR_UNION_TYPE_P(type))
|
||||
{
|
||||
error_at(expression_location, "type '%s' does not have a field named '%s'",
|
||||
error_at(expression_location, "Type '%s' does not have a field named '%s'",
|
||||
print_type(type).c_str(), field_name.c_str());
|
||||
return error_mark_node;
|
||||
}
|
||||
@ -243,7 +239,7 @@ namespace elna::gcc
|
||||
}
|
||||
if (field_declaration == NULL_TREE)
|
||||
{
|
||||
error_at(expression_location, "record type does not have a field named '%s'", field_name.c_str());
|
||||
error_at(expression_location, "Aggregate type does not have a field '%s'", field_name.c_str());
|
||||
return error_mark_node;
|
||||
}
|
||||
return field_declaration;
|
||||
@ -253,4 +249,13 @@ namespace elna::gcc
|
||||
{
|
||||
return build_pointer_type_for_mode(type, VOIDmode, true);
|
||||
}
|
||||
|
||||
tree build_label_decl(const char *name, location_t loc)
|
||||
{
|
||||
auto label_decl = build_decl(loc, LABEL_DECL, get_identifier(name), void_type_node);
|
||||
|
||||
DECL_CONTEXT(label_decl) = current_function_decl;
|
||||
|
||||
return label_decl;
|
||||
}
|
||||
}
|
||||
|
@ -62,17 +62,19 @@ namespace elna::boot
|
||||
class if_statement;
|
||||
class while_statement;
|
||||
class return_statement;
|
||||
class case_statement;
|
||||
class traits_expression;
|
||||
class block;
|
||||
class program;
|
||||
class binary_expression;
|
||||
class unary_expression;
|
||||
class primitive_type_expression;
|
||||
class named_type_expression;
|
||||
class array_type_expression;
|
||||
class pointer_type_expression;
|
||||
class record_type_expression;
|
||||
class union_type_expression;
|
||||
class procedure_type_expression;
|
||||
class enumeration_type_expression;
|
||||
class variable_expression;
|
||||
class array_access_expression;
|
||||
class field_access_expression;
|
||||
@ -100,16 +102,18 @@ namespace elna::boot
|
||||
virtual void visit(while_statement *) = 0;
|
||||
virtual void visit(return_statement *) = 0;
|
||||
virtual void visit(defer_statement *) = 0;
|
||||
virtual void visit(case_statement *) = 0;
|
||||
virtual void visit(block *) = 0;
|
||||
virtual void visit(program *) = 0;
|
||||
virtual void visit(binary_expression *) = 0;
|
||||
virtual void visit(unary_expression *) = 0;
|
||||
virtual void visit(primitive_type_expression *) = 0;
|
||||
virtual void visit(named_type_expression *) = 0;
|
||||
virtual void visit(array_type_expression *) = 0;
|
||||
virtual void visit(pointer_type_expression *) = 0;
|
||||
virtual void visit(record_type_expression *) = 0;
|
||||
virtual void visit(union_type_expression *) = 0;
|
||||
virtual void visit(procedure_type_expression *) = 0;
|
||||
virtual void visit(enumeration_type_expression *) = 0;
|
||||
virtual void visit(variable_expression *) = 0;
|
||||
virtual void visit(array_access_expression *) = 0;
|
||||
virtual void visit(field_access_expression *) = 0;
|
||||
@ -188,28 +192,29 @@ namespace elna::boot
|
||||
class type_expression : public node
|
||||
{
|
||||
public:
|
||||
virtual primitive_type_expression *is_primitive();
|
||||
virtual named_type_expression *is_named();
|
||||
virtual array_type_expression *is_array();
|
||||
virtual pointer_type_expression *is_pointer();
|
||||
virtual record_type_expression *is_record();
|
||||
virtual union_type_expression *is_union();
|
||||
virtual procedure_type_expression *is_procedure();
|
||||
virtual enumeration_type_expression *is_enumeration();
|
||||
|
||||
protected:
|
||||
type_expression(const struct position position);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expression defining a basic type.
|
||||
* Expression refering to a type by its name.
|
||||
*/
|
||||
class primitive_type_expression : public type_expression
|
||||
class named_type_expression : public type_expression
|
||||
{
|
||||
public:
|
||||
const std::string name;
|
||||
|
||||
primitive_type_expression(const struct position position, const std::string& name);
|
||||
named_type_expression(const struct position position, const std::string& name);
|
||||
void accept(parser_visitor *visitor) override;
|
||||
primitive_type_expression *is_primitive() override;
|
||||
named_type_expression *is_named() override;
|
||||
};
|
||||
|
||||
class array_type_expression : public type_expression
|
||||
@ -269,6 +274,20 @@ namespace elna::boot
|
||||
union_type_expression *is_union() override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Enumeration type.
|
||||
*/
|
||||
class enumeration_type_expression : public type_expression
|
||||
{
|
||||
public:
|
||||
const std::vector<std::string> members;
|
||||
|
||||
enumeration_type_expression(const struct position, std::vector<std::string>&& members);
|
||||
|
||||
void accept(parser_visitor *visitor) override;
|
||||
enumeration_type_expression *is_enumeration() override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Variable declaration.
|
||||
*/
|
||||
@ -291,14 +310,6 @@ namespace elna::boot
|
||||
class literal_expression : public expression
|
||||
{
|
||||
public:
|
||||
virtual literal<std::int32_t> *is_int() = 0;
|
||||
virtual literal<std::uint32_t> *is_word() = 0;
|
||||
virtual literal<double> *is_float() = 0;
|
||||
virtual literal<bool> *is_bool() = 0;
|
||||
virtual literal<unsigned char> *is_char() = 0;
|
||||
virtual literal<std::nullptr_t> *is_nil() = 0;
|
||||
virtual literal<std::string> *is_string() = 0;
|
||||
|
||||
literal_expression *is_literal() override;
|
||||
|
||||
protected:
|
||||
@ -428,18 +439,34 @@ namespace elna::boot
|
||||
|
||||
class return_statement : public statement
|
||||
{
|
||||
expression *m_return_expression{ nullptr };
|
||||
|
||||
public:
|
||||
expression *const return_expression{ nullptr };
|
||||
|
||||
return_statement(const struct position position, expression *return_expression = nullptr);
|
||||
void accept(parser_visitor *visitor) override;
|
||||
virtual return_statement *is_return() override;
|
||||
|
||||
expression *return_expression();
|
||||
|
||||
virtual ~return_statement() override;
|
||||
};
|
||||
|
||||
struct switch_case
|
||||
{
|
||||
std::vector<literal_expression *> labels;
|
||||
std::vector<statement *> statements;
|
||||
};
|
||||
|
||||
class case_statement : public statement
|
||||
{
|
||||
expression *m_condition;
|
||||
|
||||
public:
|
||||
const std::vector<switch_case> cases;
|
||||
|
||||
case_statement(const struct position position, expression *condition, std::vector<switch_case>&& cases);
|
||||
void accept(parser_visitor *visitor) override;
|
||||
expression& condition();
|
||||
};
|
||||
|
||||
class designator_expression : public expression
|
||||
{
|
||||
public:
|
||||
@ -635,90 +662,6 @@ namespace elna::boot
|
||||
{
|
||||
}
|
||||
|
||||
literal<std::int32_t> *is_int() override
|
||||
{
|
||||
if (std::is_same<T, std::int32_t>::value)
|
||||
{
|
||||
return reinterpret_cast<literal<std::int32_t> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
literal<std::uint32_t> *is_word() override
|
||||
{
|
||||
if (std::is_same<T, std::uint32_t>::value)
|
||||
{
|
||||
return reinterpret_cast<literal<std::uint32_t> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
literal<double> *is_float() override
|
||||
{
|
||||
if (std::is_same<T, double>::value)
|
||||
{
|
||||
return reinterpret_cast<literal<double> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
literal<bool> *is_bool() override
|
||||
{
|
||||
if (std::is_same<T, bool>::value)
|
||||
{
|
||||
return reinterpret_cast<literal<bool> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
literal<unsigned char> *is_char() override
|
||||
{
|
||||
if (std::is_same<T, unsigned char>::value)
|
||||
{
|
||||
return reinterpret_cast<literal<unsigned char> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
literal<std::nullptr_t> *is_nil() override
|
||||
{
|
||||
if (std::is_same<T, std::nullptr_t>::value)
|
||||
{
|
||||
return reinterpret_cast<literal<std::nullptr_t> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
literal<std::string> *is_string() override
|
||||
{
|
||||
if (std::is_same<T, std::string>::value)
|
||||
{
|
||||
return reinterpret_cast<literal<std::string> *>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void accept(parser_visitor *visitor) override
|
||||
{
|
||||
visitor->visit(this);
|
||||
@ -728,9 +671,9 @@ namespace elna::boot
|
||||
class defer_statement : public statement
|
||||
{
|
||||
public:
|
||||
std::vector<statement *> statements;
|
||||
const std::vector<statement *> statements;
|
||||
|
||||
defer_statement(const struct position position);
|
||||
defer_statement(const struct position position, std::vector<statement *>&& statements);
|
||||
void accept(parser_visitor *visitor) override;
|
||||
defer_statement *is_defer() override;
|
||||
|
||||
|
@ -49,6 +49,8 @@ namespace elna::boot
|
||||
class declaration_visitor final : public parser_visitor, public error_container
|
||||
{
|
||||
type current_type;
|
||||
constant_info::variant current_literal;
|
||||
|
||||
std::shared_ptr<symbol_table> symbols;
|
||||
|
||||
procedure_type build_procedure(procedure_type_expression& type_expression);
|
||||
@ -58,7 +60,7 @@ namespace elna::boot
|
||||
|
||||
explicit declaration_visitor(const char *path, std::shared_ptr<symbol_table> symbols);
|
||||
|
||||
void visit(primitive_type_expression *type_expression) override;
|
||||
void visit(named_type_expression *type_expression) override;
|
||||
void visit(array_type_expression *type_expression) override;
|
||||
void visit(pointer_type_expression *type_expression) override;
|
||||
void visit(program *program) override;
|
||||
@ -66,15 +68,17 @@ namespace elna::boot
|
||||
void visit(record_type_expression *type_expression) override;
|
||||
void visit(union_type_expression *type_expression) override;
|
||||
void visit(procedure_type_expression *type_expression) override;
|
||||
void visit(enumeration_type_expression *type_expression) override;
|
||||
|
||||
void visit(variable_declaration *declaration) override;
|
||||
void visit(constant_definition *) override;
|
||||
void visit(constant_definition *definition) override;
|
||||
void visit(procedure_definition *definition) override;
|
||||
void visit(assign_statement *statement) override;
|
||||
void visit(if_statement *statement) override;
|
||||
void visit(while_statement *statement) override;
|
||||
void visit(return_statement *statement) override;
|
||||
void visit(defer_statement *statement) override;
|
||||
void visit(case_statement *statement) override;
|
||||
void visit(procedure_call *call) override;
|
||||
void visit(block *block) override;
|
||||
void visit(cast_expression *expression) override;
|
||||
@ -85,12 +89,12 @@ namespace elna::boot
|
||||
void visit(array_access_expression *expression) override;
|
||||
void visit(field_access_expression *expression) override;
|
||||
void visit(dereference_expression *expression) override;
|
||||
void visit(literal<std::int32_t> *) override;
|
||||
void visit(literal<std::uint32_t> *) override;
|
||||
void visit(literal<double> *) override;
|
||||
void visit(literal<bool> *) override;
|
||||
void visit(literal<unsigned char> *) override;
|
||||
void visit(literal<std::nullptr_t> *) override;
|
||||
void visit(literal<std::string> *) override;
|
||||
void visit(literal<std::int32_t> *literal) override;
|
||||
void visit(literal<std::uint32_t> *literal) override;
|
||||
void visit(literal<double> *literal) override;
|
||||
void visit(literal<bool> *literal) override;
|
||||
void visit(literal<unsigned char> *literal) override;
|
||||
void visit(literal<std::nullptr_t> *literal) override;
|
||||
void visit(literal<std::string> *literal) override;
|
||||
};
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ namespace elna::boot
|
||||
class pointer_type;
|
||||
class array_type;
|
||||
class procedure_type;
|
||||
class enumeration_type;
|
||||
|
||||
class type
|
||||
{
|
||||
@ -46,7 +47,8 @@ namespace elna::boot
|
||||
_union,
|
||||
pointer,
|
||||
array,
|
||||
procedure
|
||||
procedure,
|
||||
enumeration
|
||||
};
|
||||
type_tag tag{ type_tag::empty };
|
||||
union
|
||||
@ -58,6 +60,7 @@ namespace elna::boot
|
||||
std::shared_ptr<pointer_type> pointer;
|
||||
std::shared_ptr<array_type> array;
|
||||
std::shared_ptr<procedure_type> procedure;
|
||||
std::shared_ptr<enumeration_type> enumeration;
|
||||
};
|
||||
|
||||
void copy(const type& other);
|
||||
@ -72,6 +75,7 @@ namespace elna::boot
|
||||
explicit type(std::shared_ptr<pointer_type> pointer);
|
||||
explicit type(std::shared_ptr<array_type> array);
|
||||
explicit type(std::shared_ptr<procedure_type> procedure);
|
||||
explicit type(std::shared_ptr<enumeration_type> enumeration);
|
||||
|
||||
type(const type& other);
|
||||
type& operator=(const type& other);
|
||||
@ -141,8 +145,16 @@ namespace elna::boot
|
||||
procedure_type(return_t return_type = return_t());
|
||||
};
|
||||
|
||||
struct enumeration_type
|
||||
{
|
||||
std::vector<std::string> members;
|
||||
|
||||
explicit enumeration_type(const std::vector<std::string>& members);
|
||||
};
|
||||
|
||||
class type_info;
|
||||
class procedure_info;
|
||||
class constant_info;
|
||||
|
||||
class info : public std::enable_shared_from_this<info>
|
||||
{
|
||||
@ -174,6 +186,17 @@ namespace elna::boot
|
||||
std::shared_ptr<procedure_info> is_procedure() override;
|
||||
};
|
||||
|
||||
class constant_info : public info
|
||||
{
|
||||
public:
|
||||
using variant = typename
|
||||
std::variant<std::int32_t, std::uint32_t, double, bool, unsigned char, std::nullptr_t, std::string>;
|
||||
|
||||
const variant symbol;
|
||||
|
||||
explicit constant_info(const variant& symbol);
|
||||
};
|
||||
|
||||
/**
|
||||
* Symbol table.
|
||||
*/
|
||||
|
@ -47,7 +47,6 @@ namespace elna::gcc
|
||||
std::unordered_map<std::string, tree> unresolved;
|
||||
|
||||
void declare_procedure(boot::procedure_definition *const definition);
|
||||
tree build_label_decl(const char *name, location_t loc);
|
||||
tree build_procedure_type(boot::procedure_type_expression& type);
|
||||
void build_composite_type(const std::vector<boot::field_declaration>& fields,
|
||||
tree composite_type_node);
|
||||
@ -101,13 +100,15 @@ namespace elna::gcc
|
||||
void visit(boot::assign_statement *statement) override;
|
||||
void visit(boot::if_statement *statement) override;
|
||||
void visit(boot::while_statement *statement) override;
|
||||
void visit(boot::primitive_type_expression *type) override;
|
||||
void visit(boot::named_type_expression *type) override;
|
||||
void visit(boot::array_type_expression *type) override;
|
||||
void visit(boot::pointer_type_expression *type) override;
|
||||
void visit(boot::record_type_expression *type) override;
|
||||
void visit(boot::union_type_expression *type) override;
|
||||
void visit(boot::procedure_type_expression *type) override;
|
||||
void visit(boot::enumeration_type_expression *type) override;
|
||||
void visit(boot::return_statement *statement) override;
|
||||
void visit(boot::defer_statement *statement) override;
|
||||
void visit(boot::case_statement *statement) override;
|
||||
};
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ namespace elna::gcc
|
||||
{
|
||||
using symbol_table = boot::symbol_map<tree, tree, NULL_TREE>;
|
||||
|
||||
bool is_pointer_type(tree type);
|
||||
bool is_integral_type(tree type);
|
||||
bool is_numeric_type(tree type);
|
||||
bool is_primitive_type(tree type);
|
||||
@ -42,9 +41,9 @@ namespace elna::gcc
|
||||
|
||||
/**
|
||||
* \param type The type to evaluate.
|
||||
* \return Whether the given type is record or union.
|
||||
* \return Whether this type can be converted to another type.
|
||||
*/
|
||||
bool is_aggregate_type(tree type);
|
||||
bool is_castable_type(tree type);
|
||||
|
||||
/**
|
||||
* \param lhs Left hand value.
|
||||
@ -82,4 +81,5 @@ namespace elna::gcc
|
||||
tree build_field(location_t location, tree record_type, const std::string name, tree type);
|
||||
tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name);
|
||||
tree build_global_pointer_type(tree type);
|
||||
tree build_label_decl(const char *name, location_t loc);
|
||||
}
|
||||
|
392
source.elna
392
source.elna
@ -3,67 +3,69 @@ const
|
||||
SEEK_CUR* = 1;
|
||||
SEEK_END* = 2;
|
||||
|
||||
TOKEN_IDENTIFIER* = 1;
|
||||
TOKEN_IF* = 2;
|
||||
TOKEN_THEN* = 3;
|
||||
TOKEN_ELSE* = 4;
|
||||
TOKEN_ELSIF* = 5;
|
||||
TOKEN_WHILE* = 6;
|
||||
TOKEN_DO* = 7;
|
||||
TOKEN_PROC* = 8;
|
||||
TOKEN_BEGIN* = 9;
|
||||
TOKEN_END* = 10;
|
||||
TOKEN_EXTERN* = 11;
|
||||
TOKEN_CONST* = 12;
|
||||
TOKEN_VAR* = 13;
|
||||
TOKEN_ARRAY* = 14;
|
||||
TOKEN_OF* = 15;
|
||||
TOKEN_TYPE* = 16;
|
||||
TOKEN_RECORD* = 17;
|
||||
TOKEN_UNION* = 18;
|
||||
TOKEN_POINTER* = 19;
|
||||
TOKEN_TO* = 20;
|
||||
TOKEN_BOOLEAN* = 21;
|
||||
TOKEN_NIL* = 22;
|
||||
TOKEN_AND* = 23;
|
||||
TOKEN_OR* = 24;
|
||||
TOKEN_NOT* = 25;
|
||||
TOKEN_RETURN* = 26;
|
||||
TOKEN_CAST* = 27;
|
||||
TOKEN_SHIFT_LEFT* = 28;
|
||||
TOKEN_SHIFT_RIGHT* = 29;
|
||||
TOKEN_LEFT_PAREN* = 30;
|
||||
TOKEN_RIGHT_PAREN* = 31;
|
||||
TOKEN_LEFT_SQUARE* = 32;
|
||||
TOKEN_RIGHT_SQUARE* = 33;
|
||||
TOKEN_GREATER_EQUAL* = 34;
|
||||
TOKEN_LESS_EQUAL* = 35;
|
||||
TOKEN_GREATER_THAN* = 36;
|
||||
TOKEN_LESS_THAN* = 37;
|
||||
TOKEN_NOT_EQUAL* = 38;
|
||||
TOKEN_EQUAL* = 39;
|
||||
TOKEN_SEMICOLON* = 40;
|
||||
TOKEN_DOT* = 41;
|
||||
TOKEN_COMMA* = 42;
|
||||
TOKEN_PLUS* = 43;
|
||||
TOKEN_MINUS* = 44;
|
||||
TOKEN_MULTIPLICATION* = 45;
|
||||
TOKEN_DIVISION* = 46;
|
||||
TOKEN_REMAINDER* = 47;
|
||||
TOKEN_ASSIGNMENT* = 48;
|
||||
TOKEN_COLON* = 49;
|
||||
TOKEN_HAT* = 50;
|
||||
TOKEN_AT* = 51;
|
||||
TOKEN_COMMENT* = 52;
|
||||
TOKEN_INTEGER* = 53;
|
||||
TOKEN_WORD* = 54;
|
||||
TOKEN_CHARACTER* = 55;
|
||||
TOKEN_STRING* = 56;
|
||||
TOKEN_DEFER* = 57;
|
||||
TOKEN_EXCLAMATION* = 58;
|
||||
TOKEN_ARROW = 59;
|
||||
|
||||
type
|
||||
TokenKind* = (
|
||||
unknown,
|
||||
identifier,
|
||||
_if,
|
||||
_then,
|
||||
_else,
|
||||
_elsif,
|
||||
_while,
|
||||
_do,
|
||||
_proc,
|
||||
_begin,
|
||||
_end,
|
||||
_extern,
|
||||
_const,
|
||||
_var,
|
||||
array,
|
||||
_of,
|
||||
_type,
|
||||
_record,
|
||||
_union,
|
||||
pointer,
|
||||
to,
|
||||
boolean,
|
||||
_nil,
|
||||
and,
|
||||
_or,
|
||||
not,
|
||||
_return,
|
||||
_cast,
|
||||
shift_left,
|
||||
shift_right,
|
||||
left_paren,
|
||||
right_paren,
|
||||
left_square,
|
||||
right_square,
|
||||
greater_equal,
|
||||
less_equal,
|
||||
greater_than,
|
||||
less_than,
|
||||
not_equal,
|
||||
equal,
|
||||
semicolon,
|
||||
dot,
|
||||
comma,
|
||||
plus,
|
||||
minus,
|
||||
multiplication,
|
||||
division,
|
||||
remainder,
|
||||
assignment,
|
||||
colon,
|
||||
hat,
|
||||
at,
|
||||
comment,
|
||||
integer,
|
||||
word,
|
||||
character,
|
||||
string,
|
||||
_defer,
|
||||
exclamation,
|
||||
arrow
|
||||
);
|
||||
Position* = record
|
||||
line: Word;
|
||||
column: Word
|
||||
@ -93,7 +95,7 @@ type
|
||||
head: proc(^Byte) -> Char
|
||||
end;
|
||||
Token* = record
|
||||
kind: Int;
|
||||
kind: TokenKind;
|
||||
value: union
|
||||
int_value: Int;
|
||||
string: String;
|
||||
@ -208,12 +210,12 @@ end
|
||||
|
||||
proc is_alnum(c: Char) -> Bool;
|
||||
begin
|
||||
return is_digit(c) | is_alpha(c)
|
||||
return is_digit(c) or is_alpha(c)
|
||||
end
|
||||
|
||||
proc is_space(c: Char) -> Bool;
|
||||
begin
|
||||
return c = ' ' | c = '\n' | c = '\t'
|
||||
return c = ' ' or c = '\n' or c = '\t'
|
||||
end
|
||||
|
||||
proc substring(string: String, start: Word, count: Word) -> String;
|
||||
@ -413,7 +415,7 @@ end
|
||||
|
||||
proc is_ident(char: Char) -> Bool;
|
||||
begin
|
||||
return is_alnum(char) | char = '_'
|
||||
return is_alnum(char) or char = '_'
|
||||
end
|
||||
|
||||
proc lex_identifier(source_code: ^SourceCode, token_content: ^StringBuffer);
|
||||
@ -516,137 +518,137 @@ begin
|
||||
while i < tokens_size do
|
||||
current_token := tokens + i;
|
||||
|
||||
if current_token^.kind = TOKEN_IF then
|
||||
if current_token^.kind = TokenKind._if then
|
||||
write_s("IF")
|
||||
elsif current_token^.kind = TOKEN_THEN then
|
||||
elsif current_token^.kind = TokenKind._then then
|
||||
write_s("THEN")
|
||||
elsif current_token^.kind = TOKEN_ELSE then
|
||||
elsif current_token^.kind = TokenKind._else then
|
||||
write_s("ELSE")
|
||||
elsif current_token^.kind = TOKEN_ELSIF then
|
||||
elsif current_token^.kind = TokenKind._elsif then
|
||||
write_s("ELSIF")
|
||||
elsif current_token^.kind = TOKEN_WHILE then
|
||||
elsif current_token^.kind = TokenKind._while then
|
||||
write_s("WHILE")
|
||||
elsif current_token^.kind = TOKEN_DO then
|
||||
elsif current_token^.kind = TokenKind._do then
|
||||
write_s("DO")
|
||||
elsif current_token^.kind = TOKEN_PROC then
|
||||
elsif current_token^.kind = TokenKind._proc then
|
||||
write_s("PROC")
|
||||
elsif current_token^.kind = TOKEN_BEGIN then
|
||||
elsif current_token^.kind = TokenKind._begin then
|
||||
write_s("BEGIN")
|
||||
elsif current_token^.kind = TOKEN_END then
|
||||
elsif current_token^.kind = TokenKind._end then
|
||||
write_s("END")
|
||||
elsif current_token^.kind = TOKEN_EXTERN then
|
||||
elsif current_token^.kind = TokenKind._extern then
|
||||
write_s("EXTERN")
|
||||
elsif current_token^.kind = TOKEN_CONST then
|
||||
elsif current_token^.kind = TokenKind._const then
|
||||
write_s("CONST")
|
||||
elsif current_token^.kind = TOKEN_VAR then
|
||||
elsif current_token^.kind = TokenKind._var then
|
||||
write_s("VAR")
|
||||
elsif current_token^.kind = TOKEN_ARRAY then
|
||||
elsif current_token^.kind = TokenKind.array then
|
||||
write_s("ARRAY")
|
||||
elsif current_token^.kind = TOKEN_OF then
|
||||
elsif current_token^.kind = TokenKind._of then
|
||||
write_s("OF")
|
||||
elsif current_token^.kind = TOKEN_TYPE then
|
||||
elsif current_token^.kind = TokenKind._type then
|
||||
write_s("TYPE")
|
||||
elsif current_token^.kind = TOKEN_RECORD then
|
||||
elsif current_token^.kind = TokenKind._record then
|
||||
write_s("RECORD")
|
||||
elsif current_token^.kind = TOKEN_UNION then
|
||||
elsif current_token^.kind = TokenKind._union then
|
||||
write_s("UNION")
|
||||
elsif current_token^.kind = TOKEN_POINTER then
|
||||
elsif current_token^.kind = TokenKind.pointer then
|
||||
write_s("POINTER")
|
||||
elsif current_token^.kind = TOKEN_TO then
|
||||
elsif current_token^.kind = TokenKind.to then
|
||||
write_s("TO")
|
||||
elsif current_token^.kind = TOKEN_BOOLEAN then
|
||||
elsif current_token^.kind = TokenKind.boolean then
|
||||
write_s("BOOLEAN<");
|
||||
write_b(current_token^.value.boolean_value);
|
||||
write_c('>')
|
||||
elsif current_token^.kind = TOKEN_NIL then
|
||||
elsif current_token^.kind = TokenKind._nil then
|
||||
write_s("NIL")
|
||||
elsif current_token^.kind = TOKEN_AND then
|
||||
elsif current_token^.kind = TokenKind.and then
|
||||
write_s("AND")
|
||||
elsif current_token^.kind = TOKEN_OR then
|
||||
elsif current_token^.kind = TokenKind._or then
|
||||
write_s("OR")
|
||||
elsif current_token^.kind = TOKEN_NOT then
|
||||
elsif current_token^.kind = TokenKind.not then
|
||||
write_s("NOT")
|
||||
elsif current_token^.kind = TOKEN_RETURN then
|
||||
elsif current_token^.kind = TokenKind._return then
|
||||
write_s("RETURN")
|
||||
elsif current_token^.kind = TOKEN_CAST then
|
||||
elsif current_token^.kind = TokenKind._cast then
|
||||
write_s("CAST")
|
||||
elsif current_token^.kind = TOKEN_SHIFT_LEFT then
|
||||
elsif current_token^.kind = TokenKind.shift_left then
|
||||
write_s("<<")
|
||||
elsif current_token^.kind = TOKEN_SHIFT_RIGHT then
|
||||
elsif current_token^.kind = TokenKind.shift_right then
|
||||
write_s(">>")
|
||||
elsif current_token^.kind = TOKEN_IDENTIFIER then
|
||||
elsif current_token^.kind = TokenKind.identifier then
|
||||
write_c('<');
|
||||
write_s(current_token^.value.string);
|
||||
write_c('>')
|
||||
elsif current_token^.kind = TOKEN_LEFT_PAREN then
|
||||
elsif current_token^.kind = TokenKind.left_paren then
|
||||
write_s("(")
|
||||
elsif current_token^.kind = TOKEN_RIGHT_PAREN then
|
||||
elsif current_token^.kind = TokenKind.right_paren then
|
||||
write_s(")")
|
||||
elsif current_token^.kind = TOKEN_LEFT_SQUARE then
|
||||
elsif current_token^.kind = TokenKind.left_square then
|
||||
write_s("[")
|
||||
elsif current_token^.kind = TOKEN_RIGHT_SQUARE then
|
||||
elsif current_token^.kind = TokenKind.right_square then
|
||||
write_s("]")
|
||||
elsif current_token^.kind = TOKEN_GREATER_EQUAL then
|
||||
elsif current_token^.kind = TokenKind.greater_equal then
|
||||
write_s(">=")
|
||||
elsif current_token^.kind = TOKEN_LESS_EQUAL then
|
||||
elsif current_token^.kind = TokenKind.less_equal then
|
||||
write_s("<=")
|
||||
elsif current_token^.kind = TOKEN_GREATER_THAN then
|
||||
elsif current_token^.kind = TokenKind.greater_than then
|
||||
write_s(">")
|
||||
elsif current_token^.kind = TOKEN_LESS_THAN then
|
||||
elsif current_token^.kind = TokenKind.less_than then
|
||||
write_s("<")
|
||||
elsif current_token^.kind = TOKEN_EQUAL then
|
||||
elsif current_token^.kind = TokenKind.equal then
|
||||
write_s("=")
|
||||
elsif current_token^.kind = TOKEN_NOT_EQUAL then
|
||||
elsif current_token^.kind = TokenKind.not_equal then
|
||||
write_s("<>")
|
||||
elsif current_token^.kind = TOKEN_SEMICOLON then
|
||||
elsif current_token^.kind = TokenKind.semicolon then
|
||||
write_c(';')
|
||||
elsif current_token^.kind = TOKEN_DOT then
|
||||
elsif current_token^.kind = TokenKind.dot then
|
||||
write_c('.')
|
||||
elsif current_token^.kind = TOKEN_COMMA then
|
||||
elsif current_token^.kind = TokenKind.comma then
|
||||
write_c(',')
|
||||
elsif current_token^.kind = TOKEN_PLUS then
|
||||
elsif current_token^.kind = TokenKind.plus then
|
||||
write_c('+')
|
||||
elsif current_token^.kind = TOKEN_MINUS then
|
||||
elsif current_token^.kind = TokenKind.minus then
|
||||
write_c('-')
|
||||
elsif current_token^.kind = TOKEN_MULTIPLICATION then
|
||||
elsif current_token^.kind = TokenKind.multiplication then
|
||||
write_c('*')
|
||||
elsif current_token^.kind = TOKEN_DIVISION then
|
||||
elsif current_token^.kind = TokenKind.division then
|
||||
write_c('/')
|
||||
elsif current_token^.kind = TOKEN_REMAINDER then
|
||||
elsif current_token^.kind = TokenKind.remainder then
|
||||
write_c('%')
|
||||
elsif current_token^.kind = TOKEN_ASSIGNMENT then
|
||||
elsif current_token^.kind = TokenKind.assignment then
|
||||
write_s(":=")
|
||||
elsif current_token^.kind = TOKEN_COLON then
|
||||
elsif current_token^.kind = TokenKind.colon then
|
||||
write_c(':')
|
||||
elsif current_token^.kind = TOKEN_HAT then
|
||||
elsif current_token^.kind = TokenKind.hat then
|
||||
write_c('^')
|
||||
elsif current_token^.kind = TOKEN_AT then
|
||||
elsif current_token^.kind = TokenKind.at then
|
||||
write_c('@')
|
||||
elsif current_token^.kind = TOKEN_COMMENT then
|
||||
elsif current_token^.kind = TokenKind.comment then
|
||||
write_s("(* COMMENT *)")
|
||||
elsif current_token^.kind = TOKEN_INTEGER then
|
||||
elsif current_token^.kind = TokenKind.integer then
|
||||
write_c('<');
|
||||
write_i(current_token^.value.int_value);
|
||||
write_c('>')
|
||||
elsif current_token^.kind = TOKEN_WORD then
|
||||
elsif current_token^.kind = TokenKind.word then
|
||||
write_c('<');
|
||||
write_i(current_token^.value.int_value);
|
||||
write_s("u>")
|
||||
elsif current_token^.kind = TOKEN_CHARACTER then
|
||||
elsif current_token^.kind = TokenKind.character then
|
||||
write_c('<');
|
||||
write_i(cast(current_token^.value.char_value: Int));
|
||||
write_s("c>")
|
||||
elsif current_token^.kind = TOKEN_STRING then
|
||||
elsif current_token^.kind = TokenKind.string then
|
||||
write_s("\"...\"")
|
||||
elsif current_token^.kind = TOKEN_DEFER then
|
||||
elsif current_token^.kind = TokenKind._defer then
|
||||
write_s("DEFER")
|
||||
elsif current_token^.kind = TOKEN_EXCLAMATION then
|
||||
elsif current_token^.kind = TokenKind.exclamation then
|
||||
write_c('!')
|
||||
elsif current_token^.kind = TOKEN_ARROW then
|
||||
elsif current_token^.kind = TokenKind.arrow then
|
||||
write_s("->")
|
||||
else
|
||||
write_s("UNKNOWN<");
|
||||
write_i(current_token^.kind);
|
||||
write_i(cast(current_token^.kind: Int));
|
||||
write_c('>')
|
||||
end;
|
||||
write_c(' ');
|
||||
@ -661,65 +663,65 @@ var
|
||||
current_token: Token;
|
||||
begin
|
||||
if "if" = token_content then
|
||||
current_token.kind := TOKEN_IF
|
||||
current_token.kind := TokenKind._if
|
||||
elsif "then" = token_content then
|
||||
current_token.kind := TOKEN_THEN
|
||||
current_token.kind := TokenKind._then
|
||||
elsif "else" = token_content then
|
||||
current_token.kind := TOKEN_ELSE
|
||||
current_token.kind := TokenKind._else
|
||||
elsif "elsif" = token_content then
|
||||
current_token.kind := TOKEN_ELSIF
|
||||
current_token.kind := TokenKind._elsif
|
||||
elsif "while" = token_content then
|
||||
current_token.kind := TOKEN_WHILE
|
||||
current_token.kind := TokenKind._while
|
||||
elsif "do" = token_content then
|
||||
current_token.kind := TOKEN_DO
|
||||
current_token.kind := TokenKind._do
|
||||
elsif "proc" = token_content then
|
||||
current_token.kind := TOKEN_PROC
|
||||
current_token.kind := TokenKind._proc
|
||||
elsif "begin" = token_content then
|
||||
current_token.kind := TOKEN_BEGIN
|
||||
current_token.kind := TokenKind._begin
|
||||
elsif "end" = token_content then
|
||||
current_token.kind := TOKEN_END
|
||||
current_token.kind := TokenKind._end
|
||||
elsif "extern" = token_content then
|
||||
current_token.kind := TOKEN_EXTERN
|
||||
current_token.kind := TokenKind._extern
|
||||
elsif "const" = token_content then
|
||||
current_token.kind := TOKEN_CONST
|
||||
current_token.kind := TokenKind._const
|
||||
elsif "var" = token_content then
|
||||
current_token.kind := TOKEN_VAR
|
||||
current_token.kind := TokenKind._var
|
||||
elsif "array" = token_content then
|
||||
current_token.kind := TOKEN_ARRAY
|
||||
current_token.kind := TokenKind.array
|
||||
elsif "of" = token_content then
|
||||
current_token.kind := TOKEN_OF
|
||||
current_token.kind := TokenKind._of
|
||||
elsif "type" = token_content then
|
||||
current_token.kind := TOKEN_TYPE
|
||||
current_token.kind := TokenKind._type
|
||||
elsif "record" = token_content then
|
||||
current_token.kind := TOKEN_RECORD
|
||||
current_token.kind := TokenKind._record
|
||||
elsif "union" = token_content then
|
||||
current_token.kind := TOKEN_UNION
|
||||
current_token.kind := TokenKind._union
|
||||
elsif "pointer" = token_content then
|
||||
current_token.kind := TOKEN_POINTER
|
||||
current_token.kind := TokenKind.pointer
|
||||
elsif "to" = token_content then
|
||||
current_token.kind := TOKEN_TO
|
||||
current_token.kind := TokenKind.to
|
||||
elsif "true" = token_content then
|
||||
current_token.kind := TOKEN_BOOLEAN;
|
||||
current_token.kind := TokenKind.boolean;
|
||||
current_token.value.boolean_value := true
|
||||
elsif "false" = token_content then
|
||||
current_token.kind := TOKEN_BOOLEAN;
|
||||
current_token.kind := TokenKind.boolean;
|
||||
current_token.value.boolean_value := false
|
||||
elsif "nil" = token_content then
|
||||
current_token.kind := TOKEN_NIL
|
||||
current_token.kind := TokenKind._nil
|
||||
elsif "and" = token_content then
|
||||
current_token.kind := TOKEN_AND
|
||||
current_token.kind := TokenKind.and
|
||||
elsif "or" = token_content then
|
||||
current_token.kind := TOKEN_OR
|
||||
current_token.kind := TokenKind._or
|
||||
elsif "not" = token_content then
|
||||
current_token.kind := TOKEN_NOT
|
||||
current_token.kind := TokenKind.not
|
||||
elsif "return" = token_content then
|
||||
current_token.kind := TOKEN_RETURN
|
||||
current_token.kind := TokenKind._return
|
||||
elsif "cast" = token_content then
|
||||
current_token.kind := TOKEN_CAST
|
||||
current_token.kind := TokenKind._cast
|
||||
elsif "defer" = token_content then
|
||||
current_token.kind := TOKEN_DEFER
|
||||
current_token.kind := TokenKind._defer
|
||||
else
|
||||
current_token.kind := TOKEN_IDENTIFIER;
|
||||
current_token.kind := TokenKind.identifier;
|
||||
current_token.value.string := string_dup(token_content)
|
||||
end;
|
||||
|
||||
@ -743,154 +745,154 @@ begin
|
||||
current_token := tokens + tokens_size^;
|
||||
first_char := source_code_head(source_code);
|
||||
|
||||
if is_alpha(first_char) | first_char = '_' then
|
||||
if is_alpha(first_char) or first_char = '_' then
|
||||
lex_identifier(@source_code, @token_buffer);
|
||||
current_token^ := categorize_identifier(string_buffer_clear(@token_buffer))
|
||||
elsif is_digit(first_char) then
|
||||
lex_number(@source_code, @current_token^.value.int_value);
|
||||
|
||||
if source_code_expect(@source_code, 'u') then
|
||||
current_token^.kind := TOKEN_WORD;
|
||||
current_token^.kind := TokenKind.word;
|
||||
source_code_advance(@source_code)
|
||||
else
|
||||
current_token^.kind := TOKEN_INTEGER
|
||||
current_token^.kind := TokenKind.integer
|
||||
end
|
||||
elsif first_char = '(' then
|
||||
source_code_advance(@source_code);
|
||||
|
||||
if source_code_empty(@source_code) then
|
||||
current_token^.kind := TOKEN_LEFT_PAREN
|
||||
current_token^.kind := TokenKind.left_paren
|
||||
elsif source_code_head(source_code) = '*' then
|
||||
source_code_advance(@source_code);
|
||||
|
||||
if lex_comment(@source_code, @token_buffer) then
|
||||
current_token^.value.string := string_dup(string_buffer_clear(@token_buffer));
|
||||
current_token^.kind := TOKEN_COMMENT
|
||||
current_token^.kind := TokenKind.comment
|
||||
else
|
||||
current_token^.kind := 0
|
||||
current_token^.kind := TokenKind.unknown
|
||||
end
|
||||
else
|
||||
current_token^.kind := TOKEN_LEFT_PAREN
|
||||
current_token^.kind := TokenKind.left_paren
|
||||
end
|
||||
elsif first_char = ')' then
|
||||
current_token^.kind := TOKEN_RIGHT_PAREN;
|
||||
current_token^.kind := TokenKind.right_paren;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = '\'' then
|
||||
source_code_advance(@source_code);
|
||||
|
||||
if lex_character(@source_code, @current_token^.value.char_value) & source_code_expect(@source_code, '\'') then
|
||||
current_token^.kind := TOKEN_CHARACTER;
|
||||
current_token^.kind := TokenKind.character;
|
||||
source_code_advance(@source_code)
|
||||
else
|
||||
current_token^.kind := 0
|
||||
current_token^.kind := TokenKind.unknown
|
||||
end
|
||||
elsif first_char = '"' then
|
||||
source_code_advance(@source_code);
|
||||
|
||||
if lex_string(@source_code, @token_buffer) then
|
||||
current_token^.kind := TOKEN_STRING;
|
||||
current_token^.kind := TokenKind.string;
|
||||
current_token^.value.string := string_dup(string_buffer_clear(@token_buffer))
|
||||
else
|
||||
current_token^.kind := 0
|
||||
current_token^.kind := TokenKind.unknown
|
||||
end
|
||||
elsif first_char = '[' then
|
||||
current_token^.kind := TOKEN_LEFT_SQUARE;
|
||||
current_token^.kind := TokenKind.left_square;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = ']' then
|
||||
current_token^.kind := TOKEN_RIGHT_SQUARE;
|
||||
current_token^.kind := TokenKind.right_square;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = '>' then
|
||||
source_code_advance(@source_code);
|
||||
|
||||
if source_code_empty(@source_code) then
|
||||
current_token^.kind := TOKEN_GREATER_THAN
|
||||
current_token^.kind := TokenKind.greater_than
|
||||
elsif source_code_head(source_code) = '=' then
|
||||
current_token^.kind := TOKEN_GREATER_EQUAL;
|
||||
current_token^.kind := TokenKind.greater_equal;
|
||||
source_code_advance(@source_code)
|
||||
elsif source_code_head(source_code) = '>' then
|
||||
current_token^.kind := TOKEN_SHIFT_RIGHT;
|
||||
current_token^.kind := TokenKind.shift_right;
|
||||
source_code_advance(@source_code)
|
||||
else
|
||||
current_token^.kind := TOKEN_GREATER_THAN
|
||||
current_token^.kind := TokenKind.greater_than
|
||||
end
|
||||
elsif first_char = '<' then
|
||||
source_code_advance(@source_code);
|
||||
|
||||
if source_code_empty(@source_code) then
|
||||
current_token^.kind := TOKEN_LESS_THAN
|
||||
current_token^.kind := TokenKind.less_than
|
||||
elsif source_code_head(source_code) = '=' then
|
||||
current_token^.kind := TOKEN_LESS_EQUAL;
|
||||
current_token^.kind := TokenKind.less_equal;
|
||||
source_code_advance(@source_code)
|
||||
elsif source_code_head(source_code) = '<' then
|
||||
current_token^.kind := TOKEN_SHIFT_LEFT;
|
||||
current_token^.kind := TokenKind.shift_left;
|
||||
source_code_advance(@source_code)
|
||||
elsif source_code_head(source_code) = '>' then
|
||||
current_token^.kind := TOKEN_NOT_EQUAL;
|
||||
current_token^.kind := TokenKind.not_equal;
|
||||
source_code_advance(@source_code)
|
||||
else
|
||||
current_token^.kind := TOKEN_LESS_THAN
|
||||
current_token^.kind := TokenKind.less_than
|
||||
end
|
||||
elsif first_char = '=' then
|
||||
current_token^.kind := TOKEN_EQUAL;
|
||||
current_token^.kind := TokenKind.equal;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = ';' then
|
||||
current_token^.kind := TOKEN_SEMICOLON;
|
||||
current_token^.kind := TokenKind.semicolon;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = '.' then
|
||||
current_token^.kind := TOKEN_DOT;
|
||||
current_token^.kind := TokenKind.dot;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = ',' then
|
||||
current_token^.kind := TOKEN_COMMA;
|
||||
current_token^.kind := TokenKind.comma;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = '+' then
|
||||
current_token^.kind := TOKEN_PLUS;
|
||||
current_token^.kind := TokenKind.plus;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = '-' then
|
||||
source_code_advance(@source_code);
|
||||
|
||||
if source_code_empty(@source_code) then
|
||||
current_token^.kind := TOKEN_MINUS
|
||||
current_token^.kind := TokenKind.minus
|
||||
elsif source_code_head(source_code) = '>' then
|
||||
current_token^.kind := TOKEN_ARROW;
|
||||
current_token^.kind := TokenKind.arrow;
|
||||
source_code_advance(@source_code)
|
||||
else
|
||||
current_token^.kind := TOKEN_MINUS
|
||||
current_token^.kind := TokenKind.minus
|
||||
end
|
||||
elsif first_char = '*' then
|
||||
current_token^.kind := TOKEN_MULTIPLICATION;
|
||||
current_token^.kind := TokenKind.multiplication;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = '/' then
|
||||
current_token^.kind := TOKEN_DIVISION;
|
||||
current_token^.kind := TokenKind.division;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = '%' then
|
||||
current_token^.kind := TOKEN_REMAINDER;
|
||||
current_token^.kind := TokenKind.remainder;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = ':' then
|
||||
source_code_advance(@source_code);
|
||||
|
||||
if source_code_empty(@source_code) then
|
||||
current_token^.kind := TOKEN_COLON
|
||||
current_token^.kind := TokenKind.colon
|
||||
elsif source_code_head(source_code) = '=' then
|
||||
current_token^.kind := TOKEN_ASSIGNMENT;
|
||||
current_token^.kind := TokenKind.assignment;
|
||||
source_code_advance(@source_code)
|
||||
else
|
||||
current_token^.kind := TOKEN_COLON
|
||||
current_token^.kind := TokenKind.colon
|
||||
end
|
||||
elsif first_char = '^' then
|
||||
current_token^.kind := TOKEN_HAT;
|
||||
current_token^.kind := TokenKind.hat;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = '@' then
|
||||
current_token^.kind := TOKEN_AT;
|
||||
current_token^.kind := TokenKind.at;
|
||||
source_code_advance(@source_code)
|
||||
elsif first_char = '!' then
|
||||
current_token^.kind := TOKEN_EXCLAMATION;
|
||||
current_token^.kind := TokenKind.exclamation;
|
||||
source_code_advance(@source_code)
|
||||
else
|
||||
current_token^.kind := 0;
|
||||
current_token^.kind := TokenKind.unknown;
|
||||
source_code_advance(@source_code)
|
||||
end;
|
||||
|
||||
if current_token^.kind <> 0 then
|
||||
if current_token^.kind <> TokenKind.unknown then
|
||||
tokens_size^ := tokens_size^ + 1u;
|
||||
skip_spaces(@source_code)
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user