diff --git a/gcc/elna-diagnostic.cc b/gcc/elna-diagnostic.cc index 4990f52..8e804ab 100644 --- a/gcc/elna-diagnostic.cc +++ b/gcc/elna-diagnostic.cc @@ -28,6 +28,10 @@ namespace gcc { return "Float"; } + else if (type == elna_char_type_node) + { + return "Char"; + } else { return "<>"; diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index ca0a48e..407d998 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -42,6 +42,10 @@ namespace gcc { format_number = "%f\n"; } + else if (argument_type == elna_char_type_node) + { + format_number = "%c\n"; + } else { error_at(get_location(&argument->position()), @@ -125,9 +129,14 @@ namespace gcc mpfr_clear(number); } - void generic_visitor::visit(source::boolean_literal *literal) + void generic_visitor::visit(source::number_literal *boolean) { - this->current_expression = build_int_cst_type(boolean_type_node, literal->boolean()); + this->current_expression = build_int_cst_type(boolean_type_node, boolean->number()); + } + + void generic_visitor::visit(source::char_literal *character) + { + this->current_expression = build_int_cstu(elna_char_type_node, character->character()); } void generic_visitor::visit(source::binary_expression *expression) @@ -262,6 +271,10 @@ namespace gcc { declaration_type = double_type_node; } + else if (declaration->type().base() == "Char") + { + declaration_type = elna_char_type_node; + } else { error_at(get_location(&declaration->type().position()), diff --git a/gcc/elna-tree.cc b/gcc/elna-tree.cc index b151e82..690b8e1 100644 --- a/gcc/elna-tree.cc +++ b/gcc/elna-tree.cc @@ -1,3 +1,11 @@ #include "elna/gcc/elna-tree.h" +#include "stor-layout.h" + tree elna_global_trees[ELNA_TI_MAX]; + +void elna_init_ttree(void) +{ + elna_char_type_node = make_unsigned_type(8); + TYPE_STRING_FLAG(elna_char_type_node) = 1; +} diff --git a/gcc/elna1.cc b/gcc/elna1.cc index b93b322..d086f3e 100644 --- a/gcc/elna1.cc +++ b/gcc/elna1.cc @@ -66,7 +66,7 @@ struct GTY (()) language_function static bool elna_langhook_init(void) { build_common_tree_nodes(false); - enumeral_node = make_node(ENUMERAL_TYPE); + elna_init_ttree(); /* I don't know why this has to be done explicitly. */ void_list_node = build_tree_list(NULL_TREE, void_type_node); diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index 6fa35b9..68c6b20 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -29,7 +29,8 @@ namespace gcc void visit(source::call_statement *statement) override; void visit(source::number_literal *literal) override; void visit(source::number_literal *literal) override; - void visit(source::boolean_literal *literal) override; + void visit(source::number_literal *boolean) override; + void visit(source::char_literal *character) override; void visit(source::binary_expression *expression) override; void visit(source::constant_definition *definition) override; void visit(source::declaration *declaration) override; diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h index 883f2a2..34cc5ef 100644 --- a/include/elna/gcc/elna-tree.h +++ b/include/elna/gcc/elna-tree.h @@ -7,10 +7,12 @@ enum elna_tree_index { - ELNA_TI_ENUMERAL_TYPE, + ELNA_TI_CHAR_TYPE, ELNA_TI_MAX }; extern GTY(()) tree elna_global_trees[ELNA_TI_MAX]; -#define enumeral_node elna_global_trees[ELNA_TI_ENUMERAL_TYPE] +#define elna_char_type_node elna_global_trees[ELNA_TI_CHAR_TYPE] + +void elna_init_ttree(void); diff --git a/include/elna/source/ast.h b/include/elna/source/ast.h index c9e797b..58687c1 100644 --- a/include/elna/source/ast.h +++ b/include/elna/source/ast.h @@ -48,7 +48,7 @@ namespace source class variable_expression; template class number_literal; - class boolean_literal; + class char_literal; /** * Interface for AST visitors. @@ -71,7 +71,8 @@ namespace source virtual void visit(variable_expression *) = 0; virtual void visit(number_literal *) = 0; virtual void visit(number_literal *) = 0; - virtual void visit(boolean_literal *) = 0; + virtual void visit(number_literal *) = 0; + virtual void visit(char_literal *) = 0; }; /** @@ -94,8 +95,9 @@ namespace source virtual void visit(type_expression *variable) override; virtual void visit(variable_expression *variable) override; virtual void visit(number_literal *number) override; - virtual void visit(number_literal *) override; - virtual void visit(boolean_literal *boolean) override; + virtual void visit(number_literal *number) override; + virtual void visit(number_literal *boolean) override; + virtual void visit(char_literal *character) override; }; /** @@ -452,15 +454,15 @@ namespace source } }; - class boolean_literal : public expression + class char_literal : public expression { - bool m_boolean; + unsigned char m_character; public: - boolean_literal(const struct position position, const bool value); + char_literal(const struct position position, const unsigned char value); virtual void accept(parser_visitor *visitor) override; - bool boolean() const noexcept; + unsigned char character() const noexcept; }; class variable_expression : public expression diff --git a/source/ast.cc b/source/ast.cc index b1e72d5..1c9e9ae 100644 --- a/source/ast.cc +++ b/source/ast.cc @@ -103,7 +103,11 @@ namespace source { } - void empty_visitor::visit(boolean_literal *boolean) + void empty_visitor::visit(number_literal *character) + { + } + + void empty_visitor::visit(char_literal *character) { } @@ -294,19 +298,19 @@ namespace source visitor->visit(this); } - boolean_literal::boolean_literal(const struct position position, const bool value) - : expression(position), m_boolean(value) + char_literal::char_literal(const struct position position, const unsigned char value) + : expression(position), m_character(value) { } - void boolean_literal::accept(parser_visitor *visitor) + void char_literal::accept(parser_visitor *visitor) { visitor->visit(this); } - bool boolean_literal::boolean() const noexcept + unsigned char char_literal::character() const noexcept { - return m_boolean; + return m_character; } variable_expression::variable_expression(const struct position position, const std::string& name) diff --git a/source/lexer.ll b/source/lexer.ll index 8aab50f..b518d9a 100644 --- a/source/lexer.ll +++ b/source/lexer.ll @@ -71,11 +71,15 @@ false { return yy::parser::make_IDENTIFIER(yytext, this->location); } [0-9]+ { - return yy::parser::make_NUMBER(strtol(yytext, NULL, 10), this->location); + return yy::parser::make_INTEGER(strtol(yytext, NULL, 10), this->location); } [0-9]+\.[0-9] { return yy::parser::make_FLOAT(strtof(yytext, NULL), this->location); } +'[^']' { + return yy::parser::make_CHARACTER( + std::string(yytext, 1, strlen(yytext) - 2), this->location); + } \( { return yy::parser::make_LEFT_PAREN(this->location); } diff --git a/source/parser.yy b/source/parser.yy index 3e86256..2873a4b 100644 --- a/source/parser.yy +++ b/source/parser.yy @@ -57,8 +57,9 @@ %start program; %token IDENTIFIER "identifier" -%token NUMBER "number" +%token INTEGER "integer" %token FLOAT "float" +%token CHARACTER "character" %token BOOLEAN %token IF WHILE DO %token CONST VAR PROCEDURE @@ -73,7 +74,8 @@ %type >> integer_literal; %type >> float_literal; -%type > boolean_literal; +%type >> boolean_literal; +%type > character_literal; %type > constant_definition; %type >> constant_definition_part constant_definitions; %type > variable_declaration; @@ -141,7 +143,7 @@ procedure_definitions: procedure_definition_part: /* no procedure definitions */ {} | procedure_definitions { std::swap($$, $1); } -integer_literal: NUMBER +integer_literal: INTEGER { $$ = std::make_unique>(elna::source::make_position(@1), $1); }; @@ -149,9 +151,13 @@ float_literal: FLOAT { $$ = std::make_unique>(elna::source::make_position(@1), $1); }; +character_literal: CHARACTER + { + $$ = std::make_unique(elna::source::make_position(@1), $1[0]); + }; boolean_literal: BOOLEAN { - $$ = std::make_unique(elna::source::make_position(@1), $1); + $$ = std::make_unique>(elna::source::make_position(@1), $1); }; compound_statement: BEGIN_BLOCK optional_statements END_BLOCK { @@ -187,6 +193,7 @@ pointer: integer_literal { $$ = std::move($1); } | float_literal { $$ = std::move($1); } | boolean_literal { $$ = std::move($1); } + | character_literal { $$ = std::move($1); } | variable_expression { $$ = std::move($1); } | LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); } summand: