/* * This Source Code Form is subject to the terms of the Mozilla Public License * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at http://mozilla.org/MPL/2.0/. */ %{ #define YY_NO_UNISTD_H #define YY_USER_ACTION this->location.columns(yyleng); #include #include "parser.hh" #undef YY_DECL #define YY_DECL yy::parser::symbol_type elna::boot::lexer::lex(elna::boot::driver& driver) #define yyterminate() return yy::parser::make_YYEOF(this->location) %} %option c++ noyywrap never-interactive %option yyclass="elna::boot::lexer" %x IN_COMMENT %% %{ 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] ; /* Skip the whitespaces. */ \n+ { this->location.lines(yyleng); this->location.step(); } 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); } array { return yy::parser::make_ARRAY(this->location); } of { return yy::parser::make_OF(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); } pointer { return yy::parser::make_POINTER(this->location); } to { return yy::parser::make_TO(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); } and { return yy::parser::make_AND(this->location); } or { return yy::parser::make_OR(this->location); } not { return yy::parser::make_NOT(this->location); } return { return yy::parser::make_RETURN(this->location); } cast { return yy::parser::make_CAST(this->location); } as { return yy::parser::make_AS(this->location); } sizeof { return yy::parser::make_SIZEOF(this->location); } [A-Za-z_][A-Za-z0-9_]* { return yy::parser::make_IDENTIFIER(yytext, 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(std::stoi(yytext + 3, nullptr, 16)); return yy::parser::make_CHARACTER(std::string(&character, 1), this->location); } '\\[0nabtfrv\\'"?]' { std::optional escape = elna::boot::escape_char(yytext[2]); if (escape.has_value()) { return yy::parser::make_CHARACTER(std::string(&escape.value(), 1), this->location); } else { REJECT; } } \"[[:print:]]*\" { std::string result; 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(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 escape = elna::boot::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_RIGHT_PAREN(this->location); } \[ { return yy::parser::make_LEFT_SQUARE(this->location); } \] { return yy::parser::make_RIGHT_SQUARE(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_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); } . { std::stringstream ss; ss << "Illegal character 0x" << std::hex << static_cast(yytext[0]); driver.error(this->location, ss.str()); } %%