Implement the Word type

This commit is contained in:
Eugen Wissner 2025-01-24 11:41:14 +01:00
parent 5548b66b15
commit 005e9dcc52
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
8 changed files with 109 additions and 32 deletions

View File

@ -250,7 +250,12 @@ namespace gcc
void generic_visitor::visit(source::number_literal<std::int32_t> *literal) void generic_visitor::visit(source::number_literal<std::int32_t> *literal)
{ {
this->current_expression = build_int_cst_type(integer_type_node, literal->number()); this->current_expression = build_int_cst(integer_type_node, literal->number());
}
void generic_visitor::visit(source::number_literal<std::uint32_t> *literal)
{
this->current_expression = build_int_cstu(unsigned_type_node, literal->number());
} }
void generic_visitor::visit(source::number_literal<double> *literal) void generic_visitor::visit(source::number_literal<double> *literal)

View File

@ -41,6 +41,7 @@ namespace gcc
void visit(source::procedure_definition *definition) override; void visit(source::procedure_definition *definition) override;
void visit(source::call_expression *statement) override; void visit(source::call_expression *statement) override;
void visit(source::number_literal<std::int32_t> *literal) 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; void visit(source::number_literal<double> *literal) override;
void visit(source::number_literal<bool> *boolean) override; void visit(source::number_literal<bool> *boolean) override;
void visit(source::number_literal<unsigned char> *character) override; void visit(source::number_literal<unsigned char> *character) override;

View File

@ -94,6 +94,7 @@ namespace source
virtual void visit(field_access_expression *is_field_access) = 0; virtual void visit(field_access_expression *is_field_access) = 0;
virtual void visit(dereference_expression *is_dereference) = 0; virtual void visit(dereference_expression *is_dereference) = 0;
virtual void visit(number_literal<std::int32_t> *) = 0; virtual void visit(number_literal<std::int32_t> *) = 0;
virtual void visit(number_literal<std::uint32_t> *) = 0;
virtual void visit(number_literal<double> *) = 0; virtual void visit(number_literal<double> *) = 0;
virtual void visit(number_literal<bool> *) = 0; virtual void visit(number_literal<bool> *) = 0;
virtual void visit(number_literal<unsigned char> *) = 0; virtual void visit(number_literal<unsigned char> *) = 0;
@ -130,6 +131,7 @@ namespace source
virtual void visit(field_access_expression *expression) override; virtual void visit(field_access_expression *expression) override;
virtual void visit(dereference_expression *expression) override; virtual void visit(dereference_expression *expression) override;
virtual void visit(number_literal<std::int32_t> *) override; virtual void visit(number_literal<std::int32_t> *) override;
virtual void visit(number_literal<std::uint32_t> *) override;
virtual void visit(number_literal<double> *) override; virtual void visit(number_literal<double> *) override;
virtual void visit(number_literal<bool> *) override; virtual void visit(number_literal<bool> *) override;
virtual void visit(number_literal<unsigned char> *) override; virtual void visit(number_literal<unsigned char> *) override;

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <list> #include <list>
#include <optional>
#include "elna/source/ast.h" #include "elna/source/ast.h"
#include "location.hh" #include "location.hh"
@ -37,5 +38,7 @@ namespace source
void error(const yy::location& loc, const std::string& message); void error(const yy::location& loc, const std::string& message);
const std::list<std::unique_ptr<struct error>>& errors() const noexcept; const std::list<std::unique_ptr<struct error>>& errors() const noexcept;
}; };
std::optional<char> escape_char(char escape);
} }
} }

View File

@ -167,6 +167,10 @@ namespace source
{ {
} }
void empty_visitor::visit(number_literal<std::uint32_t> *)
{
}
void empty_visitor::visit(number_literal<double> *) void empty_visitor::visit(number_literal<double> *)
{ {
} }

View File

@ -40,5 +40,38 @@ namespace source
{ {
return m_errors; return m_errors;
} }
std::optional<char> escape_char(char escape)
{
switch (escape)
{
case 'n':
return std::make_optional<char>('\n');
case 'a':
return std::make_optional<char>('\a');
case 'b':
return std::make_optional<char>('\b');
case 't':
return std::make_optional<char>('\t');
case 'f':
return std::make_optional<char>('\f');
case 'r':
return std::make_optional<char>('\r');
case 'v':
return std::make_optional<char>('\v');
case '\\':
return std::make_optional<char>('\\');
case '\'':
return std::make_optional<char>('\'');
case '"':
return std::make_optional<char>('"');
case '?':
return std::make_optional<char>('\?');
case '0':
return std::make_optional<char>('\0');
default:
return std::nullopt;
}
}
} }
} }

View File

@ -106,6 +106,9 @@ return {
[A-Za-z_][A-Za-z0-9_]* { [A-Za-z_][A-Za-z0-9_]* {
return yy::parser::make_IDENTIFIER(yytext, this->location); return yy::parser::make_IDENTIFIER(yytext, this->location);
} }
[0-9]+u {
return yy::parser::make_WORD(strtoul(yytext, NULL, 10), this->location);
}
[0-9]+ { [0-9]+ {
return yy::parser::make_INTEGER(strtol(yytext, NULL, 10), this->location); return yy::parser::make_INTEGER(strtol(yytext, NULL, 10), this->location);
} }
@ -113,7 +116,7 @@ return {
return yy::parser::make_FLOAT(strtof(yytext, NULL), this->location); return yy::parser::make_FLOAT(strtof(yytext, NULL), this->location);
} }
'[[:print:]]' { '[[:print:]]' {
if (yytext[1] == '\\') if (yytext[1] == '\\' || yytext[1] == '\'')
{ {
REJECT; REJECT;
} }
@ -122,45 +125,66 @@ return {
return yy::parser::make_CHARACTER(std::string(yytext, 1, 1), this->location); return yy::parser::make_CHARACTER(std::string(yytext, 1, 1), this->location);
} }
} }
'\\x[0-9a-fA-F]{2}' { '\\x[0-9a-fA-F]{1,2}' {
char character = static_cast<char>(std::stoi(yytext + 3, nullptr, 16)); char character = static_cast<char>(std::stoi(yytext + 3, nullptr, 16));
return yy::parser::make_CHARACTER(std::string(&character, 1), this->location); return yy::parser::make_CHARACTER(std::string(&character, 1), this->location);
} }
'\\[0nabtfrv\\'"?]' { '\\[0nabtfrv\\'"?]' {
switch (yytext[2]) std::optional<char> escape = source::escape_char(yytext[2]);
if (escape.has_value())
{
return yy::parser::make_CHARACTER(std::string(&escape.value(), 1), this->location);
}
else
{ {
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; REJECT;
} }
} }
\"[^\"]*\" { \"[[:print:]]*\" {
return yy::parser::make_STRING( std::string result;
std::string(yytext, 1, strlen(yytext) - 2), this->location); const char *current_position = yytext + 1;
while (*current_position != '\0')
{
if (*current_position == '\\' && *(current_position + 1) == 'x')
{
current_position += 2;
std::size_t processed;
char character = static_cast<char>(std::stoi(current_position, &processed, 16));
if (processed == 0)
{
REJECT;
}
else
{
current_position += processed - 1;
result.push_back(character);
}
}
else if (*current_position == '\\')
{
++current_position;
std::optional<char> escape = source::escape_char(*current_position);
if (escape.has_value())
{
result.push_back(escape.value());
}
else
{
REJECT;
}
}
else
{
result.push_back(*current_position);
}
++current_position;
}
result.pop_back();
return yy::parser::make_STRING(result, this->location);
} }
\( { \( {
return yy::parser::make_LEFT_PAREN(this->location); return yy::parser::make_LEFT_PAREN(this->location);

View File

@ -58,6 +58,7 @@
%token <std::string> IDENTIFIER "identifier" %token <std::string> IDENTIFIER "identifier"
%token <std::int32_t> INTEGER "integer" %token <std::int32_t> INTEGER "integer"
%token <std::uint32_t> WORD "word"
%token <float> FLOAT "float" %token <float> FLOAT "float"
%token <std::string> CHARACTER "character" %token <std::string> CHARACTER "character"
%token <std::string> STRING "string" %token <std::string> STRING "string"
@ -208,6 +209,10 @@ literal:
{ {
$$ = new elna::source::number_literal<std::int32_t>(elna::source::make_position(@1), $1); $$ = new elna::source::number_literal<std::int32_t>(elna::source::make_position(@1), $1);
} }
| WORD
{
$$ = new elna::source::number_literal<std::uint32_t>(elna::source::make_position(@1), $1);
}
| FLOAT | FLOAT
{ {
$$ = new elna::source::number_literal<double>(elna::source::make_position(@1), $1); $$ = new elna::source::number_literal<double>(elna::source::make_position(@1), $1);