Implement character escape sequences

This commit is contained in:
Eugen Wissner 2025-01-22 20:19:26 +01:00
parent 156506e8fa
commit 0dc95d4466
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
7 changed files with 83 additions and 52 deletions

View File

@ -12,6 +12,9 @@ type
dummy: Int dummy: Int
end; end;
const
SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2;
proc test_array(); proc test_array();
var a: T, x: Int; var a: T, x: Int;
begin begin
@ -66,19 +69,6 @@ begin
end end
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); proc test_param(d: Int, e: Int);
begin begin
writei(""); 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 ftell(stream: pointer to FILE): Int; extern;
proc fread(ptr: pointer to Char, size: Int, nmemb: Int, 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 write(fd: Int, buf: pointer to Char, count: Int): Int; extern;
proc malloc(size: Int): pointer to Char; extern; proc malloc(size: Int): pointer to Char; extern;
proc free(ptr: 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 memset(ptr: pointer to Char, c: Int, n: Int): pointer to Char; extern;
proc read_source(filename: String): pointer to Char; 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 var
input_file: pointer to FILE, input_file: pointer to FILE,
source_size: Int, source_size: Int,
@ -143,8 +133,7 @@ begin
source_size := ftell(input_file); source_size := ftell(input_file);
fseek(input_file, 0, SEEK_SET); fseek(input_file, 0, SEEK_SET);
input := malloc(source_size + 1); input := calloc(source_size + 1, 1);
memset(input, 0, source_size + 1);
fread(input, source_size, 1, input_file); fread(input, source_size, 1, input_file);
fclose(input_file); fclose(input_file);
@ -152,12 +141,6 @@ begin
return input return input
end; 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(); proc compile();
var var
input: pointer to Char, input: pointer to Char,
@ -166,7 +149,7 @@ begin
input := read_source("example.elna"); input := read_source("example.elna");
input_pointer := input; input_pointer := input;
while is_not_eof(input_pointer) do while input_pointer^ /= '\0' do
write(0, input_pointer, 1); write(0, input_pointer, 1);
input_pointer := input_pointer + 1 input_pointer := input_pointer + 1
end; end;
@ -179,7 +162,6 @@ begin
test_array(); test_array();
test_record(); test_record();
test_if(); test_if();
test_not();
test_param(8, 7); test_param(8, 7);
test_const_char(); test_const_char();
writei(test_return_int()); writei(test_return_int());

View File

@ -124,11 +124,14 @@ namespace gcc
void generic_visitor::visit(source::program *program) void generic_visitor::visit(source::program *program)
{ {
for (const auto definition : program->value_definitions)
{
definition->accept(this);
}
for (const auto& constant : program->type_definitions) for (const auto& constant : program->type_definitions)
{ {
constant->accept(this); constant->accept(this);
} }
tree parameter_types[] = { tree parameter_types[] = {
integer_type_node, integer_type_node,
build_pointer_type(build_pointer_type(char_type_node)) build_pointer_type(build_pointer_type(char_type_node))
@ -141,10 +144,6 @@ namespace gcc
enter_scope(); enter_scope();
for (const auto definition : program->value_definitions)
{
definition->accept(this);
}
for (const auto body_statement : program->body) for (const auto body_statement : program->body)
{ {
body_statement->accept(this); body_statement->accept(this);

View File

@ -736,7 +736,7 @@ namespace source
public: public:
unary_expression(const struct position position, expression *operand, unary_expression(const struct position position, expression *operand,
const unsigned char operation); const unary_operator operation);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
expression& operand(); expression& operand();

View File

@ -41,6 +41,8 @@ namespace source
{ {
public: public:
using symbol_ptr = std::shared_ptr<info<T>>; using symbol_ptr = std::shared_ptr<info<T>>;
using iterator = typename std::unordered_map<std::string, symbol_ptr>::iterator;
using const_iterator = typename std::unordered_map<std::string, symbol_ptr>::const_iterator;
private: private:
std::unordered_map<std::string, symbol_ptr> entries; std::unordered_map<std::string, symbol_ptr> 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 * Looks for symbol in the table by name. Returns nullptr if the symbol
* can not be found. * can not be found.

View File

@ -752,20 +752,9 @@ namespace source
} }
unary_expression::unary_expression(const struct position position, expression *operand, unary_expression::unary_expression(const struct position position, expression *operand,
const unsigned char operation) const unary_operator operation)
: expression(position), m_operand(std::move(operand)) : 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) void unary_expression::accept(parser_visitor *visitor)

View File

@ -112,13 +112,50 @@ return {
[0-9]+\.[0-9] { [0-9]+\.[0-9] {
return yy::parser::make_FLOAT(strtof(yytext, NULL), this->location); return yy::parser::make_FLOAT(strtof(yytext, NULL), this->location);
} }
'[^']' { '[[:print:]]' {
return yy::parser::make_CHARACTER( if (yytext[1] == '\\')
std::string(yytext, 1, strlen(yytext) - 2), this->location); {
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( 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); return yy::parser::make_LEFT_PAREN(this->location);

View File

@ -227,6 +227,7 @@ literal:
pointer: pointer:
literal { $$ = $1; } literal { $$ = $1; }
| designator_expression { $$ = $1; } | designator_expression { $$ = $1; }
| call_expression { $$ = $1; }
| LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); } | LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }
summand: summand:
factor { $$ = std::move($1); } factor { $$ = std::move($1); }
@ -243,11 +244,13 @@ summand:
factor: factor:
AT pointer 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 | 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; } | pointer { $$ = $1; }
comparand: comparand:
@ -296,7 +299,6 @@ expression:
$$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, 'o'); $$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, 'o');
} }
| logical_operand { $$ = $1; } | logical_operand { $$ = $1; }
| call_expression { $$ = $1; }
expressions: expressions:
expression COMMA expressions expression COMMA expressions
{ {