Support hexadecimal literals
This commit is contained in:
@@ -117,7 +117,7 @@ namespace elna::boot
|
|||||||
}
|
}
|
||||||
++current_position;
|
++current_position;
|
||||||
}
|
}
|
||||||
result.pop_back();
|
result.pop_back(); // Remove the terminating quote character.
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
509
boot/lexer.ll
509
boot/lexer.ll
@@ -32,248 +32,289 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
|
|
||||||
%x IN_COMMENT
|
%x IN_COMMENT
|
||||||
|
|
||||||
|
ID1 [A-Za-z_]
|
||||||
|
ID2 [A-Za-z0-9_]
|
||||||
|
HIGIT [0-9a-fA-F]
|
||||||
|
BIGIT [01]
|
||||||
|
|
||||||
%%
|
%%
|
||||||
%{
|
%{
|
||||||
this->location.step();
|
this->location.step();
|
||||||
%}
|
%}
|
||||||
|
|
||||||
<IN_COMMENT>{
|
<IN_COMMENT>{
|
||||||
\*\) BEGIN(INITIAL);
|
\*\) BEGIN(INITIAL);
|
||||||
[^*\n]+ ; /* Eat comment in chunks. */
|
[^*\n]+ ; /* Eat comment in chunks. */
|
||||||
\* ; /* Eat the lone star. */
|
\* ; /* Eat the lone star. */
|
||||||
\n+ {
|
\n+ {
|
||||||
this->location.lines(yyleng);
|
this->location.lines(yyleng);
|
||||||
this->location.step();
|
this->location.step();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
\(\* BEGIN(IN_COMMENT);
|
\(\* BEGIN(IN_COMMENT);
|
||||||
[ \t\r] {
|
[ \t\r] {
|
||||||
this->location.step();
|
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+ {
|
end {
|
||||||
this->location.lines(yyleng);
|
return yy::parser::make_END_BLOCK(this->location);
|
||||||
}
|
}
|
||||||
if {
|
extern {
|
||||||
return yy::parser::make_IF(this->location);
|
return yy::parser::make_EXTERN(this->location);
|
||||||
}
|
}
|
||||||
then {
|
const {
|
||||||
return yy::parser::make_THEN(this->location);
|
return yy::parser::make_CONST(this->location);
|
||||||
}
|
}
|
||||||
else {
|
var {
|
||||||
return yy::parser::make_ELSE(this->location);
|
return yy::parser::make_VAR(this->location);
|
||||||
}
|
}
|
||||||
elsif {
|
type {
|
||||||
return yy::parser::make_ELSIF(this->location);
|
return yy::parser::make_TYPE(this->location);
|
||||||
}
|
}
|
||||||
while {
|
record {
|
||||||
return yy::parser::make_WHILE(this->location);
|
return yy::parser::make_RECORD(this->location);
|
||||||
}
|
}
|
||||||
do {
|
union {
|
||||||
return yy::parser::make_DO(this->location);
|
return yy::parser::make_UNION(this->location);
|
||||||
}
|
}
|
||||||
proc {
|
true {
|
||||||
return yy::parser::make_PROCEDURE(this->location);
|
return yy::parser::make_BOOLEAN(true, this->location);
|
||||||
}
|
}
|
||||||
begin {
|
false {
|
||||||
return yy::parser::make_BEGIN_BLOCK(this->location);
|
return yy::parser::make_BOOLEAN(false, this->location);
|
||||||
}
|
}
|
||||||
end {
|
nil {
|
||||||
return yy::parser::make_END_BLOCK(this->location);
|
return yy::parser::make_NIL(this->location);
|
||||||
}
|
}
|
||||||
extern {
|
\& {
|
||||||
return yy::parser::make_EXTERN(this->location);
|
return yy::parser::make_AND(this->location);
|
||||||
}
|
}
|
||||||
const {
|
xor {
|
||||||
return yy::parser::make_CONST(this->location);
|
return yy::parser::make_XOR(this->location);
|
||||||
}
|
}
|
||||||
var {
|
or {
|
||||||
return yy::parser::make_VAR(this->location);
|
return yy::parser::make_OR(this->location);
|
||||||
}
|
}
|
||||||
type {
|
\| {
|
||||||
return yy::parser::make_TYPE(this->location);
|
return yy::parser::make_PIPE(this->location);
|
||||||
}
|
}
|
||||||
record {
|
\~ {
|
||||||
return yy::parser::make_RECORD(this->location);
|
return yy::parser::make_NOT(this->location);
|
||||||
}
|
}
|
||||||
union {
|
return {
|
||||||
return yy::parser::make_UNION(this->location);
|
return yy::parser::make_RETURN(this->location);
|
||||||
}
|
}
|
||||||
true {
|
module {
|
||||||
return yy::parser::make_BOOLEAN(true, this->location);
|
return yy::parser::make_MODULE(this->location);
|
||||||
}
|
}
|
||||||
false {
|
program {
|
||||||
return yy::parser::make_BOOLEAN(false, this->location);
|
return yy::parser::make_PROGRAM(this->location);
|
||||||
}
|
}
|
||||||
nil {
|
import {
|
||||||
return yy::parser::make_NIL(this->location);
|
return yy::parser::make_IMPORT(this->location);
|
||||||
}
|
}
|
||||||
\& {
|
cast {
|
||||||
return yy::parser::make_AND(this->location);
|
return yy::parser::make_CAST(this->location);
|
||||||
}
|
}
|
||||||
xor {
|
defer {
|
||||||
return yy::parser::make_XOR(this->location);
|
return yy::parser::make_DEFER(this->location);
|
||||||
}
|
}
|
||||||
or {
|
case {
|
||||||
return yy::parser::make_OR(this->location);
|
return yy::parser::make_CASE(this->location);
|
||||||
}
|
}
|
||||||
\| {
|
of {
|
||||||
return yy::parser::make_PIPE(this->location);
|
return yy::parser::make_OF(this->location);
|
||||||
}
|
}
|
||||||
\~ {
|
{ID1}{ID2}* {
|
||||||
return yy::parser::make_NOT(this->location);
|
return yy::parser::make_IDENTIFIER(yytext, this->location);
|
||||||
}
|
}
|
||||||
return {
|
#{ID1}{ID2}* {
|
||||||
return yy::parser::make_RETURN(this->location);
|
return yy::parser::make_TRAIT(yytext + 1, this->location);
|
||||||
}
|
}
|
||||||
module {
|
[[:digit:]]+u {
|
||||||
return yy::parser::make_MODULE(this->location);
|
unsigned long result = strtoul(yytext, NULL, 10);
|
||||||
}
|
|
||||||
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));
|
|
||||||
|
|
||||||
return yy::parser::make_CHARACTER(std::string(&character, 1), this->location);
|
if (errno == ERANGE)
|
||||||
}
|
{
|
||||||
'\\[0nabtfrv\\'"?]' {
|
REJECT;
|
||||||
char escape = escape_char(yytext[2]);
|
}
|
||||||
if (escape == escape_invalid_char)
|
else
|
||||||
{
|
{
|
||||||
REJECT;
|
return yy::parser::make_WORD(result, this->location);
|
||||||
}
|
}
|
||||||
return yy::parser::make_CHARACTER(std::string(&escape, 1), this->location);
|
}
|
||||||
}
|
[[:digit:]]+ {
|
||||||
\"[[:print:]]*\" {
|
long result = strtol(yytext, NULL, 10);
|
||||||
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]);
|
if (errno == ERANGE)
|
||||||
driver.add_error<syntax_error>(ss.str(), driver.input_file, this->location);
|
{
|
||||||
}
|
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);
|
||||||
|
}
|
||||||
%%
|
%%
|
||||||
|
@@ -1074,6 +1074,12 @@ begin
|
|||||||
return return_code
|
return return_code
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
proc f();
|
||||||
|
var x: Char;
|
||||||
|
begin
|
||||||
|
x := '\x4'
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
exit(process(count, parameters))
|
exit(process(count, parameters))
|
||||||
end.
|
end.
|
||||||
|
Reference in New Issue
Block a user