diff --git a/example.elna b/example.elna index 080c6cd..80e2f50 100644 --- a/example.elna +++ b/example.elna @@ -12,6 +12,9 @@ type dummy: Int end; +const + SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2; + proc test_array(); var a: T, x: Int; begin @@ -66,19 +69,6 @@ begin end end; -proc test_not(); -var x: Bool; -begin - x := false; - - writei(""); - if not x then - writei("Test not true.") - else - writei("Test not false") - end -end; - proc test_param(d: Int, e: Int); begin writei(""); @@ -124,14 +114,14 @@ proc fseek(stream: pointer to FILE, off: Int, whence: Int): Int; extern; proc ftell(stream: pointer to FILE): Int; extern; proc fread(ptr: pointer to Char, size: Int, nmemb: Int, stream: pointer to FILE): Int; extern; proc write(fd: Int, buf: pointer to Char, count: Int): Int; extern; + proc malloc(size: Int): pointer to Char; extern; proc free(ptr: pointer to Char); extern; +proc calloc(nmemb: Int, size: Int): pointer to Char; extern; + proc memset(ptr: pointer to Char, c: Int, n: Int): pointer to Char; extern; proc read_source(filename: String): pointer to Char; -const - -- Bug: The procedure doesn't see global constants. - SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2; var input_file: pointer to FILE, source_size: Int, @@ -143,8 +133,7 @@ begin source_size := ftell(input_file); fseek(input_file, 0, SEEK_SET); - input := malloc(source_size + 1); - memset(input, 0, source_size + 1); + input := calloc(source_size + 1, 1); fread(input, source_size, 1, input_file); fclose(input_file); @@ -152,12 +141,6 @@ begin return input end; --- Bug: "while not is_eof(…) do" is a syntax error. -proc is_not_eof(buffer: pointer to Int): Bool; -begin - return buffer^ /= 0 -end; - proc compile(); var input: pointer to Char, @@ -166,7 +149,7 @@ begin input := read_source("example.elna"); input_pointer := input; - while is_not_eof(input_pointer) do + while input_pointer^ /= '\0' do write(0, input_pointer, 1); input_pointer := input_pointer + 1 end; @@ -179,7 +162,6 @@ begin test_array(); test_record(); test_if(); - test_not(); test_param(8, 7); test_const_char(); writei(test_return_int()); diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index e4339ea..60cdc87 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -124,11 +124,14 @@ namespace gcc void generic_visitor::visit(source::program *program) { + for (const auto definition : program->value_definitions) + { + definition->accept(this); + } for (const auto& constant : program->type_definitions) { constant->accept(this); } - tree parameter_types[] = { integer_type_node, build_pointer_type(build_pointer_type(char_type_node)) @@ -141,10 +144,6 @@ namespace gcc enter_scope(); - for (const auto definition : program->value_definitions) - { - definition->accept(this); - } for (const auto body_statement : program->body) { body_statement->accept(this); diff --git a/include/elna/source/ast.h b/include/elna/source/ast.h index 3c2c62a..fa61997 100644 --- a/include/elna/source/ast.h +++ b/include/elna/source/ast.h @@ -736,7 +736,7 @@ namespace source public: unary_expression(const struct position position, expression *operand, - const unsigned char operation); + const unary_operator operation); virtual void accept(parser_visitor *visitor) override; expression& operand(); diff --git a/include/elna/source/symbol.h b/include/elna/source/symbol.h index d05310f..bc6da9b 100644 --- a/include/elna/source/symbol.h +++ b/include/elna/source/symbol.h @@ -41,6 +41,8 @@ namespace source { public: using symbol_ptr = std::shared_ptr>; + using iterator = typename std::unordered_map::iterator; + using const_iterator = typename std::unordered_map::const_iterator; private: std::unordered_map entries; @@ -57,6 +59,26 @@ namespace source { } + iterator begin() + { + return entries.begin(); + } + + iterator end() + { + return entries.end(); + } + + const_iterator cbegin() const + { + return entries.cbegin(); + } + + const_iterator cend() const + { + return entries.cend(); + } + /** * Looks for symbol in the table by name. Returns nullptr if the symbol * can not be found. diff --git a/source/ast.cc b/source/ast.cc index 820c553..b082640 100644 --- a/source/ast.cc +++ b/source/ast.cc @@ -752,20 +752,9 @@ namespace source } unary_expression::unary_expression(const struct position position, expression *operand, - const unsigned char operation) - : expression(position), m_operand(std::move(operand)) + const unary_operator operation) + : expression(position), m_operand(std::move(operand)), m_operator(operation) { - switch (operation) - { - case '@': - this->m_operator = unary_operator::reference; - break; - case '!': - this->m_operator = unary_operator::negation; - break; - default: - __builtin_unreachable(); - } } void unary_expression::accept(parser_visitor *visitor) diff --git a/source/lexer.ll b/source/lexer.ll index 9bbe55d..64c763a 100644 --- a/source/lexer.ll +++ b/source/lexer.ll @@ -112,13 +112,50 @@ return { [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); +'[[:print:]]' { + if (yytext[1] == '\\') + { + REJECT; + } + else + { + return yy::parser::make_CHARACTER(std::string(yytext, 1, 1), this->location); + } + } +'\\[0nabtfrv\\'"?]' { + switch (yytext[2]) + { + case 'n': + return yy::parser::make_CHARACTER(std::string("\n"), this->location); + case 'a': + return yy::parser::make_CHARACTER(std::string("\a"), this->location); + case 'b': + return yy::parser::make_CHARACTER(std::string("\b"), this->location); + case 't': + return yy::parser::make_CHARACTER(std::string("\t"), this->location); + case 'f': + return yy::parser::make_CHARACTER(std::string("\f"), this->location); + case 'r': + return yy::parser::make_CHARACTER(std::string("\r"), this->location); + case 'v': + return yy::parser::make_CHARACTER(std::string("\v"), this->location); + case '\\': + return yy::parser::make_CHARACTER(std::string("\\"), this->location); + case '\'': + return yy::parser::make_CHARACTER(std::string("'"), this->location); + case '"': + return yy::parser::make_CHARACTER(std::string("\""), this->location); + case '?': + return yy::parser::make_CHARACTER(std::string("\?"), this->location); + case '0': + return yy::parser::make_CHARACTER(std::string("\0", 1), this->location); + default: + REJECT; + } } \"[^\"]*\" { return yy::parser::make_STRING( - std::string(yytext, 1, strlen(yytext) - 2), this->location); + 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 7ebf4a5..8393b31 100644 --- a/source/parser.yy +++ b/source/parser.yy @@ -227,6 +227,7 @@ literal: pointer: literal { $$ = $1; } | designator_expression { $$ = $1; } + | call_expression { $$ = $1; } | LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); } summand: factor { $$ = std::move($1); } @@ -243,11 +244,13 @@ summand: factor: AT pointer { - $$ = new elna::source::unary_expression(elna::source::make_position(@1), $2, '@'); + $$ = new elna::source::unary_expression(elna::source::make_position(@1), $2, + elna::source::unary_operator::reference); } | NOT pointer { - $$ = new elna::source::unary_expression(elna::source::make_position(@1), $2, '!'); + $$ = new elna::source::unary_expression(elna::source::make_position(@1), $2, + elna::source::unary_operator::negation); } | pointer { $$ = $1; } comparand: @@ -296,7 +299,6 @@ expression: $$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, 'o'); } | logical_operand { $$ = $1; } - | call_expression { $$ = $1; } expressions: expression COMMA expressions {