Support hexadecimal literals

This commit is contained in:
2025-08-04 22:49:49 +02:00
parent 4b18a98581
commit b18effbdd8
3 changed files with 282 additions and 235 deletions

View File

@@ -117,7 +117,7 @@ namespace elna::boot
}
++current_position;
}
result.pop_back();
result.pop_back(); // Remove the terminating quote character.
return result;
}

View File

@@ -32,248 +32,289 @@ along with GCC; see the file COPYING3. If not see
%x IN_COMMENT
ID1 [A-Za-z_]
ID2 [A-Za-z0-9_]
HIGIT [0-9a-fA-F]
BIGIT [01]
%%
%{
this->location.step();
%}
<IN_COMMENT>{
\*\) BEGIN(INITIAL);
[^*\n]+ ; /* Eat comment in chunks. */
\* ; /* Eat the lone star. */
\n+ {
this->location.lines(yyleng);
this->location.step();
}
\*\) BEGIN(INITIAL);
[^*\n]+ ; /* Eat comment in chunks. */
\* ; /* Eat the lone star. */
\n+ {
this->location.lines(yyleng);
this->location.step();
}
}
\(\* BEGIN(IN_COMMENT);
[ \t\r] {
this->location.step();
\(\* BEGIN(IN_COMMENT);
[ \t\r] {
this->location.step();
}
\n+ {
this->location.lines(yyleng);
}
if {
return yy::parser::make_IF(this->location);
}
then {
return yy::parser::make_THEN(this->location);
}
else {
return yy::parser::make_ELSE(this->location);
}
elsif {
return yy::parser::make_ELSIF(this->location);
}
while {
return yy::parser::make_WHILE(this->location);
}
do {
return yy::parser::make_DO(this->location);
}
proc {
return yy::parser::make_PROCEDURE(this->location);
}
begin {
return yy::parser::make_BEGIN_BLOCK(this->location);
}
\n+ {
this->location.lines(yyleng);
}
if {
return yy::parser::make_IF(this->location);
}
then {
return yy::parser::make_THEN(this->location);
}
else {
return yy::parser::make_ELSE(this->location);
}
elsif {
return yy::parser::make_ELSIF(this->location);
}
while {
return yy::parser::make_WHILE(this->location);
}
do {
return yy::parser::make_DO(this->location);
}
proc {
return yy::parser::make_PROCEDURE(this->location);
}
begin {
return yy::parser::make_BEGIN_BLOCK(this->location);
}
end {
return yy::parser::make_END_BLOCK(this->location);
}
extern {
return yy::parser::make_EXTERN(this->location);
}
const {
return yy::parser::make_CONST(this->location);
}
var {
return yy::parser::make_VAR(this->location);
}
type {
return yy::parser::make_TYPE(this->location);
}
record {
return yy::parser::make_RECORD(this->location);
}
union {
return yy::parser::make_UNION(this->location);
}
true {
return yy::parser::make_BOOLEAN(true, this->location);
}
false {
return yy::parser::make_BOOLEAN(false, this->location);
}
nil {
return yy::parser::make_NIL(this->location);
}
\& {
return yy::parser::make_AND(this->location);
}
xor {
return yy::parser::make_XOR(this->location);
}
or {
return yy::parser::make_OR(this->location);
}
\| {
return yy::parser::make_PIPE(this->location);
}
\~ {
return yy::parser::make_NOT(this->location);
}
return {
return yy::parser::make_RETURN(this->location);
}
module {
return yy::parser::make_MODULE(this->location);
}
program {
return yy::parser::make_PROGRAM(this->location);
}
import {
return yy::parser::make_IMPORT(this->location);
}
cast {
return yy::parser::make_CAST(this->location);
}
defer {
return yy::parser::make_DEFER(this->location);
}
case {
return yy::parser::make_CASE(this->location);
}
of {
return yy::parser::make_OF(this->location);
}
[A-Za-z_][A-Za-z0-9_]* {
return yy::parser::make_IDENTIFIER(yytext, this->location);
}
#[A-Za-z_][A-Za-z0-9_]* {
return yy::parser::make_TRAIT(yytext + 1, this->location);
}
[0-9]+u {
return yy::parser::make_WORD(strtoul(yytext, NULL, 10), this->location);
}
[0-9]+ {
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);
}
'[[:print:]]' {
if (yytext[1] == '\\' || yytext[1] == '\'')
{
REJECT;
}
else
{
return yy::parser::make_CHARACTER(std::string(yytext, 1, 1), this->location);
}
}
'\\x[0-9a-fA-F]{1,2}' {
char character = static_cast<char>(std::stoi(yytext + 3, nullptr, 16));
end {
return yy::parser::make_END_BLOCK(this->location);
}
extern {
return yy::parser::make_EXTERN(this->location);
}
const {
return yy::parser::make_CONST(this->location);
}
var {
return yy::parser::make_VAR(this->location);
}
type {
return yy::parser::make_TYPE(this->location);
}
record {
return yy::parser::make_RECORD(this->location);
}
union {
return yy::parser::make_UNION(this->location);
}
true {
return yy::parser::make_BOOLEAN(true, this->location);
}
false {
return yy::parser::make_BOOLEAN(false, this->location);
}
nil {
return yy::parser::make_NIL(this->location);
}
\& {
return yy::parser::make_AND(this->location);
}
xor {
return yy::parser::make_XOR(this->location);
}
or {
return yy::parser::make_OR(this->location);
}
\| {
return yy::parser::make_PIPE(this->location);
}
\~ {
return yy::parser::make_NOT(this->location);
}
return {
return yy::parser::make_RETURN(this->location);
}
module {
return yy::parser::make_MODULE(this->location);
}
program {
return yy::parser::make_PROGRAM(this->location);
}
import {
return yy::parser::make_IMPORT(this->location);
}
cast {
return yy::parser::make_CAST(this->location);
}
defer {
return yy::parser::make_DEFER(this->location);
}
case {
return yy::parser::make_CASE(this->location);
}
of {
return yy::parser::make_OF(this->location);
}
{ID1}{ID2}* {
return yy::parser::make_IDENTIFIER(yytext, this->location);
}
#{ID1}{ID2}* {
return yy::parser::make_TRAIT(yytext + 1, this->location);
}
[[:digit:]]+u {
unsigned long result = strtoul(yytext, NULL, 10);
return yy::parser::make_CHARACTER(std::string(&character, 1), this->location);
}
'\\[0nabtfrv\\'"?]' {
char escape = escape_char(yytext[2]);
if (escape == escape_invalid_char)
{
REJECT;
}
return yy::parser::make_CHARACTER(std::string(&escape, 1), this->location);
}
\"[[:print:]]*\" {
std::optional<std::string> result = escape_string(yytext);
if (!result.has_value())
{
REJECT;
}
return yy::parser::make_STRING(result.value(), this->location);
}
\( {
return yy::parser::make_LEFT_PAREN(this->location);
}
\) {
return yy::parser::make_RIGHT_PAREN(this->location);
}
\[ {
return yy::parser::make_LEFT_SQUARE(this->location);
}
\] {
return yy::parser::make_RIGHT_SQUARE(this->location);
}
\<\< {
return yy::parser::make_SHIFT_LEFT(this->location);
}
\>\> {
return yy::parser::make_SHIFT_RIGHT(this->location);
}
\>= {
return yy::parser::make_GREATER_EQUAL(this->location);
}
\<= {
return yy::parser::make_LESS_EQUAL(this->location);
}
\> {
return yy::parser::make_GREATER_THAN(this->location);
}
\< {
return yy::parser::make_LESS_THAN(this->location);
}
\<\> {
return yy::parser::make_NOT_EQUAL(this->location);
}
= {
return yy::parser::make_EQUALS(this->location);
}
; {
return yy::parser::make_SEMICOLON(this->location);
}
\. {
return yy::parser::make_DOT(this->location);
}
, {
return yy::parser::make_COMMA(this->location);
}
\+ {
return yy::parser::make_PLUS(this->location);
}
\-> {
return yy::parser::make_ARROW(this->location);
}
\- {
return yy::parser::make_MINUS(this->location);
}
\* {
return yy::parser::make_MULTIPLICATION(this->location);
}
\/ {
return yy::parser::make_DIVISION(this->location);
}
% {
return yy::parser::make_REMAINDER(this->location);
}
:= {
return yy::parser::make_ASSIGNMENT(this->location);
}
: {
return yy::parser::make_COLON(this->location);
}
\^ {
return yy::parser::make_HAT(this->location);
}
@ {
return yy::parser::make_AT(this->location);
}
! {
return yy::parser::make_EXCLAMATION(this->location);
}
. {
std::stringstream ss;
if (errno == ERANGE)
{
REJECT;
}
else
{
return yy::parser::make_WORD(result, this->location);
}
}
[[:digit:]]+ {
long result = strtol(yytext, NULL, 10);
ss << "Illegal character 0x" << std::hex << static_cast<unsigned int>(yytext[0]);
driver.add_error<syntax_error>(ss.str(), driver.input_file, this->location);
}
if (errno == ERANGE)
{
REJECT;
}
else
{
return yy::parser::make_INTEGER(result, this->location);
}
}
0x{HIGIT}+ {
unsigned long result = strtoul(yytext, NULL, 16);
if (errno == ERANGE)
{
REJECT;
}
else
{
return yy::parser::make_WORD(result, this->location);
}
}
0b{BIGIT}+ {
unsigned long result = strtoul(yytext, NULL, 2);
if (errno == ERANGE)
{
REJECT;
}
else
{
return yy::parser::make_WORD(result, this->location);
}
}
[[:digit:]]+\.[[:digit:]]+ {
float result = strtof(yytext, NULL);
if (errno == ERANGE)
{
REJECT;
}
else
{
return yy::parser::make_FLOAT(result, this->location);
}
}
'[[:print:]]+' {
std::optional<std::string> result = escape_string(yytext);
if (!result.has_value() || result.value().size() != 1)
{
REJECT;
}
return yy::parser::make_CHARACTER(result.value(), this->location);
}
\"[[:print:]]*\" {
std::optional<std::string> result = escape_string(yytext);
if (!result.has_value())
{
REJECT;
}
return yy::parser::make_STRING(result.value(), this->location);
}
\( {
return yy::parser::make_LEFT_PAREN(this->location);
}
\) {
return yy::parser::make_RIGHT_PAREN(this->location);
}
\[ {
return yy::parser::make_LEFT_SQUARE(this->location);
}
\] {
return yy::parser::make_RIGHT_SQUARE(this->location);
}
\<\< {
return yy::parser::make_SHIFT_LEFT(this->location);
}
\>\> {
return yy::parser::make_SHIFT_RIGHT(this->location);
}
\>= {
return yy::parser::make_GREATER_EQUAL(this->location);
}
\<= {
return yy::parser::make_LESS_EQUAL(this->location);
}
\> {
return yy::parser::make_GREATER_THAN(this->location);
}
\< {
return yy::parser::make_LESS_THAN(this->location);
}
\<\> {
return yy::parser::make_NOT_EQUAL(this->location);
}
= {
return yy::parser::make_EQUALS(this->location);
}
; {
return yy::parser::make_SEMICOLON(this->location);
}
\. {
return yy::parser::make_DOT(this->location);
}
, {
return yy::parser::make_COMMA(this->location);
}
\+ {
return yy::parser::make_PLUS(this->location);
}
\-> {
return yy::parser::make_ARROW(this->location);
}
\- {
return yy::parser::make_MINUS(this->location);
}
\* {
return yy::parser::make_MULTIPLICATION(this->location);
}
\/ {
return yy::parser::make_DIVISION(this->location);
}
% {
return yy::parser::make_REMAINDER(this->location);
}
:= {
return yy::parser::make_ASSIGNMENT(this->location);
}
: {
return yy::parser::make_COLON(this->location);
}
\^ {
return yy::parser::make_HAT(this->location);
}
@ {
return yy::parser::make_AT(this->location);
}
! {
return yy::parser::make_EXCLAMATION(this->location);
}
. {
std::stringstream ss;
ss << "Illegal character 0x" << std::hex << static_cast<unsigned int>(yytext[0]);
driver.add_error<syntax_error>(ss.str(), driver.input_file, this->location);
}
%%

View File

@@ -1074,6 +1074,12 @@ begin
return return_code
end;
proc f();
var x: Char;
begin
x := '\x4'
end;
begin
exit(process(count, parameters))
end.