Implement the sizeof operator
This commit is contained in:
		
							
								
								
									
										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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user