Implement the sizeof operator
This commit is contained in:
parent
be1a56a557
commit
5178027d9f
55
example.elna
55
example.elna
@ -13,8 +13,9 @@ type
|
|||||||
|
|
||||||
const
|
const
|
||||||
SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2,
|
SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2,
|
||||||
POINTER_SIZE = 8, TOKEN_SIZE = 16,
|
|
||||||
TOKEN_IDENTIFIER = 1;
|
TOKEN_IDENTIFIER = 1, TOKEN_IF = 2, TOKEN_THEN = 3, TOKEN_ELSE = 4, TOKEN_ELSIF = 5,
|
||||||
|
TOKEN_WHILE = 6, TOKEN_DO = 7;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- External procedures.
|
-- External procedures.
|
||||||
@ -195,14 +196,28 @@ begin
|
|||||||
token_end := lex_identifier(input_pointer + 1);
|
token_end := lex_identifier(input_pointer + 1);
|
||||||
token_length := cast(token_end as Int) - cast(input_pointer as Int);
|
token_length := cast(token_end as Int) - cast(input_pointer as Int);
|
||||||
|
|
||||||
tokens := cast(realloc(tokens, tokens_size + TOKEN_SIZE) as pointer to Token);
|
tokens := cast(realloc(tokens, tokens_size + sizeof(Token)) as pointer to Token);
|
||||||
current_token := tokens + tokens_size;
|
current_token := tokens + tokens_size;
|
||||||
|
|
||||||
current_token^.kind := TOKEN_IDENTIFIER;
|
if strncmp("if", input_pointer, token_length) = 0 then
|
||||||
current_token^.value.stringValue := cast(calloc(token_length + 1, 1) as pointer to Char);
|
current_token^.kind := TOKEN_IF
|
||||||
strncpy(current_token^.value.stringValue, input_pointer, token_length);
|
elsif strncmp("then", input_pointer, token_length) = 0 then
|
||||||
|
current_token^.kind := TOKEN_THEN
|
||||||
|
elsif strncmp("else", input_pointer, token_length) = 0 then
|
||||||
|
current_token^.kind := TOKEN_ELSE
|
||||||
|
elsif strncmp("elsif", input_pointer, token_length) = 0 then
|
||||||
|
current_token^.kind := TOKEN_ELSIF
|
||||||
|
elsif strncmp("while", input_pointer, token_length) = 0 then
|
||||||
|
current_token^.kind := TOKEN_WHILE
|
||||||
|
elsif strncmp("do", input_pointer, token_length) = 0 then
|
||||||
|
current_token^.kind := TOKEN_DO
|
||||||
|
else
|
||||||
|
current_token^.kind := TOKEN_IDENTIFIER;
|
||||||
|
current_token^.value.stringValue := cast(calloc(token_length + 1, 1) as pointer to Char);
|
||||||
|
strncpy(current_token^.value.stringValue, input_pointer, token_length)
|
||||||
|
end;
|
||||||
|
|
||||||
tokens_size := tokens_size + TOKEN_SIZE;
|
tokens_size := tokens_size + sizeof(Token);
|
||||||
|
|
||||||
input_pointer := token_end
|
input_pointer := token_end
|
||||||
else
|
else
|
||||||
@ -214,10 +229,30 @@ begin
|
|||||||
while i < tokens_size do
|
while i < tokens_size do
|
||||||
current_token := tokens + i;
|
current_token := tokens + i;
|
||||||
|
|
||||||
write_s(current_token^.value.stringValue);
|
if current_token^.kind = TOKEN_IF then
|
||||||
write_c('\n');
|
write_s("IF")
|
||||||
|
elsif current_token^.kind = TOKEN_THEN then
|
||||||
|
write_s("THEN")
|
||||||
|
elsif current_token^.kind = TOKEN_ELSE then
|
||||||
|
write_s("ELSE")
|
||||||
|
elsif current_token^.kind = TOKEN_ELSIF then
|
||||||
|
write_s("ELSIF")
|
||||||
|
elsif current_token^.kind = TOKEN_WHILE then
|
||||||
|
write_s("WHILE")
|
||||||
|
elsif current_token^.kind = TOKEN_DO then
|
||||||
|
write_s("DO")
|
||||||
|
elsif current_token^.kind = TOKEN_IDENTIFIER then
|
||||||
|
write_s("IDENTIFIER<");
|
||||||
|
write_s(current_token^.value.stringValue);
|
||||||
|
write_c('>')
|
||||||
|
else
|
||||||
|
write_s("UNKNOWN<");
|
||||||
|
write_i(current_token^.kind);
|
||||||
|
write_s('>')
|
||||||
|
end;
|
||||||
|
write_c(' ');
|
||||||
|
|
||||||
i := i + TOKEN_SIZE
|
i := i + sizeof(Token)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
free(input)
|
free(input)
|
||||||
|
@ -67,6 +67,13 @@ namespace gcc
|
|||||||
cast_target, this->current_expression);
|
cast_target, this->current_expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generic_visitor::visit(source::size_of_expression *expression)
|
||||||
|
{
|
||||||
|
auto body_type = build_type(expression->body());
|
||||||
|
|
||||||
|
this->current_expression = build1(CONVERT_EXPR, integer_type_node, TYPE_SIZE_UNIT(body_type));
|
||||||
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(source::program *program)
|
void generic_visitor::visit(source::program *program)
|
||||||
{
|
{
|
||||||
for (const auto definition : program->value_definitions)
|
for (const auto definition : program->value_definitions)
|
||||||
|
@ -43,6 +43,7 @@ namespace gcc
|
|||||||
void visit(source::procedure_definition *definition) override;
|
void visit(source::procedure_definition *definition) override;
|
||||||
void visit(source::call_expression *expression) override;
|
void visit(source::call_expression *expression) override;
|
||||||
void visit(source::cast_expression *expression) override;
|
void visit(source::cast_expression *expression) override;
|
||||||
|
void visit(source::size_of_expression *expression) override;
|
||||||
void visit(source::number_literal<std::int32_t> *literal) override;
|
void visit(source::number_literal<std::int32_t> *literal) override;
|
||||||
void visit(source::number_literal<std::uint32_t> *literal) override;
|
void visit(source::number_literal<std::uint32_t> *literal) override;
|
||||||
void visit(source::number_literal<double> *literal) override;
|
void visit(source::number_literal<double> *literal) override;
|
||||||
|
@ -42,6 +42,7 @@ namespace source
|
|||||||
class type_definition;
|
class type_definition;
|
||||||
class call_expression;
|
class call_expression;
|
||||||
class cast_expression;
|
class cast_expression;
|
||||||
|
class size_of_expression;
|
||||||
class assign_statement;
|
class assign_statement;
|
||||||
class if_statement;
|
class if_statement;
|
||||||
class while_statement;
|
class while_statement;
|
||||||
@ -76,6 +77,7 @@ namespace source
|
|||||||
virtual void visit(type_definition *) = 0;
|
virtual void visit(type_definition *) = 0;
|
||||||
virtual void visit(call_expression *) = 0;
|
virtual void visit(call_expression *) = 0;
|
||||||
virtual void visit(cast_expression *) = 0;
|
virtual void visit(cast_expression *) = 0;
|
||||||
|
virtual void visit(size_of_expression *) = 0;
|
||||||
virtual void visit(expression_statement *) = 0;
|
virtual void visit(expression_statement *) = 0;
|
||||||
virtual void visit(assign_statement *) = 0;
|
virtual void visit(assign_statement *) = 0;
|
||||||
virtual void visit(if_statement *) = 0;
|
virtual void visit(if_statement *) = 0;
|
||||||
@ -113,6 +115,7 @@ namespace source
|
|||||||
virtual void visit(type_definition *definition) override;
|
virtual void visit(type_definition *definition) override;
|
||||||
virtual void visit(call_expression *expression) override;
|
virtual void visit(call_expression *expression) override;
|
||||||
virtual void visit(cast_expression *expression) override;
|
virtual void visit(cast_expression *expression) override;
|
||||||
|
virtual void visit(size_of_expression *expression) override;
|
||||||
virtual void visit(expression_statement *statement) override;
|
virtual void visit(expression_statement *statement) override;
|
||||||
virtual void visit(assign_statement *statement) override;
|
virtual void visit(assign_statement *statement) override;
|
||||||
virtual void visit(if_statement *) override;
|
virtual void visit(if_statement *) override;
|
||||||
@ -438,6 +441,22 @@ namespace source
|
|||||||
virtual ~cast_expression() override;
|
virtual ~cast_expression() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sizeOf operator.
|
||||||
|
*/
|
||||||
|
class size_of_expression : public expression
|
||||||
|
{
|
||||||
|
type_expression *m_body;
|
||||||
|
|
||||||
|
public:
|
||||||
|
size_of_expression(const struct position position, type_expression *body);
|
||||||
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
|
type_expression& body();
|
||||||
|
|
||||||
|
virtual ~size_of_expression() override;
|
||||||
|
};
|
||||||
|
|
||||||
class expression_statement : public statement
|
class expression_statement : public statement
|
||||||
{
|
{
|
||||||
expression *m_body;
|
expression *m_body;
|
||||||
|
@ -47,6 +47,11 @@ namespace source
|
|||||||
expression->value().accept(this);
|
expression->value().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void empty_visitor::visit(size_of_expression *expression)
|
||||||
|
{
|
||||||
|
expression->body().accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(expression_statement *statement)
|
void empty_visitor::visit(expression_statement *statement)
|
||||||
{
|
{
|
||||||
statement->body().accept(this);
|
statement->body().accept(this);
|
||||||
@ -754,6 +759,26 @@ namespace source
|
|||||||
delete m_value;
|
delete m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_of_expression::size_of_expression(const struct position position, type_expression *body)
|
||||||
|
: expression(position), m_body(body)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void size_of_expression::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_expression& size_of_expression::body()
|
||||||
|
{
|
||||||
|
return *m_body;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_of_expression::~size_of_expression()
|
||||||
|
{
|
||||||
|
delete m_body;
|
||||||
|
}
|
||||||
|
|
||||||
expression_statement::expression_statement(const struct position position, expression *body)
|
expression_statement::expression_statement(const struct position position, expression *body)
|
||||||
: statement(position), m_body(body)
|
: statement(position), m_body(body)
|
||||||
{
|
{
|
||||||
|
@ -112,6 +112,9 @@ cast {
|
|||||||
as {
|
as {
|
||||||
return yy::parser::make_AS(this->location);
|
return yy::parser::make_AS(this->location);
|
||||||
}
|
}
|
||||||
|
sizeof {
|
||||||
|
return yy::parser::make_SIZEOF(this->location);
|
||||||
|
}
|
||||||
[A-Za-z_][A-Za-z0-9_]* {
|
[A-Za-z_][A-Za-z0-9_]* {
|
||||||
return yy::parser::make_IDENTIFIER(yytext, this->location);
|
return yy::parser::make_IDENTIFIER(yytext, this->location);
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION
|
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION
|
||||||
%token BEGIN_BLOCK END_BLOCK EXTERN
|
%token BEGIN_BLOCK END_BLOCK EXTERN
|
||||||
%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 AND OR NOT CAST AS
|
%token AND OR NOT CAST AS SIZEOF
|
||||||
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
||||||
%token PLUS MINUS MULTIPLICATION DIVISION REMAINDER
|
%token PLUS MINUS MULTIPLICATION DIVISION REMAINDER
|
||||||
%token ASSIGNMENT COLON HAT AT
|
%token ASSIGNMENT COLON HAT AT
|
||||||
@ -252,9 +252,13 @@ literal:
|
|||||||
pointer:
|
pointer:
|
||||||
literal { $$ = $1; }
|
literal { $$ = $1; }
|
||||||
| designator_expression { $$ = $1; }
|
| designator_expression { $$ = $1; }
|
||||||
|
| SIZEOF LEFT_PAREN type_expression RIGHT_PAREN
|
||||||
|
{
|
||||||
|
$$ = new elna::source::size_of_expression(elna::source::make_position(@1), $3);
|
||||||
|
}
|
||||||
| cast_expression { $$ = $1; }
|
| cast_expression { $$ = $1; }
|
||||||
| call_expression { $$ = $1; }
|
| call_expression { $$ = $1; }
|
||||||
| LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }
|
| LEFT_PAREN expression RIGHT_PAREN { $$ = $2; }
|
||||||
summand:
|
summand:
|
||||||
factor { $$ = std::move($1); }
|
factor { $$ = std::move($1); }
|
||||||
| factor MULTIPLICATION factor
|
| factor MULTIPLICATION factor
|
||||||
|
Loading…
x
Reference in New Issue
Block a user