Implement the sizeof operator

This commit is contained in:
Eugen Wissner 2025-01-29 12:55:52 +01:00
parent be1a56a557
commit 5178027d9f
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
7 changed files with 106 additions and 12 deletions

View File

@ -13,8 +13,9 @@ type
const
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.
@ -195,14 +196,28 @@ begin
token_end := lex_identifier(input_pointer + 1);
token_length := cast(token_end as Int) - cast(input_pointer as Int);
tokens := cast(realloc(tokens, tokens_size + TOKEN_SIZE) as pointer to Token);
tokens := cast(realloc(tokens, tokens_size + sizeof(Token)) as pointer to Token);
current_token := tokens + tokens_size;
current_token^.kind := TOKEN_IDENTIFIER;
current_token^.value.stringValue := cast(calloc(token_length + 1, 1) as pointer to Char);
strncpy(current_token^.value.stringValue, input_pointer, token_length);
if strncmp("if", input_pointer, token_length) = 0 then
current_token^.kind := TOKEN_IF
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
else
@ -214,10 +229,30 @@ begin
while i < tokens_size do
current_token := tokens + i;
write_s(current_token^.value.stringValue);
write_c('\n');
if current_token^.kind = TOKEN_IF then
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;
free(input)

View File

@ -67,6 +67,13 @@ namespace gcc
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)
{
for (const auto definition : program->value_definitions)

View File

@ -43,6 +43,7 @@ namespace gcc
void visit(source::procedure_definition *definition) override;
void visit(source::call_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::uint32_t> *literal) override;
void visit(source::number_literal<double> *literal) override;

View File

@ -42,6 +42,7 @@ namespace source
class type_definition;
class call_expression;
class cast_expression;
class size_of_expression;
class assign_statement;
class if_statement;
class while_statement;
@ -76,6 +77,7 @@ namespace source
virtual void visit(type_definition *) = 0;
virtual void visit(call_expression *) = 0;
virtual void visit(cast_expression *) = 0;
virtual void visit(size_of_expression *) = 0;
virtual void visit(expression_statement *) = 0;
virtual void visit(assign_statement *) = 0;
virtual void visit(if_statement *) = 0;
@ -113,6 +115,7 @@ namespace source
virtual void visit(type_definition *definition) override;
virtual void visit(call_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(assign_statement *statement) override;
virtual void visit(if_statement *) override;
@ -438,6 +441,22 @@ namespace source
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
{
expression *m_body;

View File

@ -47,6 +47,11 @@ namespace source
expression->value().accept(this);
}
void empty_visitor::visit(size_of_expression *expression)
{
expression->body().accept(this);
}
void empty_visitor::visit(expression_statement *statement)
{
statement->body().accept(this);
@ -754,6 +759,26 @@ namespace source
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)
: statement(position), m_body(body)
{

View File

@ -112,6 +112,9 @@ cast {
as {
return yy::parser::make_AS(this->location);
}
sizeof {
return yy::parser::make_SIZEOF(this->location);
}
[A-Za-z_][A-Za-z0-9_]* {
return yy::parser::make_IDENTIFIER(yytext, this->location);
}

View File

@ -67,7 +67,7 @@
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION
%token BEGIN_BLOCK END_BLOCK EXTERN
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
%token AND OR NOT CAST AS
%token AND OR NOT CAST AS SIZEOF
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
%token PLUS MINUS MULTIPLICATION DIVISION REMAINDER
%token ASSIGNMENT COLON HAT AT
@ -252,9 +252,13 @@ literal:
pointer:
literal { $$ = $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; }
| call_expression { $$ = $1; }
| LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }
| LEFT_PAREN expression RIGHT_PAREN { $$ = $2; }
summand:
factor { $$ = std::move($1); }
| factor MULTIPLICATION factor