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
|
||||
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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user