%{ #define YY_NO_UNISTD_H #define YY_USER_ACTION token_position = elna::source::position{ line_no, column_no }; column_no += yyleng; #include #include "elna/source/lexer.hpp" elna::source::token::value yylval{}; elna::source::position token_position{}; static std::size_t column_no = 1; static std::size_t line_no = 1; %} %option noyywrap %option never-interactive %% \-\-.* { /* Skip the comment */ } [\ \t\r] { /* Skip the whitespaces */ } \n { ++line_no; column_no = 1; } if { yylval.nil = nullptr; return static_cast(elna::source::token::type::when); } then { yylval.nil = nullptr; return static_cast(elna::source::token::type::then); } while { yylval.nil = nullptr; return static_cast(elna::source::token::type::loop); } do { yylval.nil = nullptr; return static_cast(elna::source::token::type::_do); } proc { yylval.nil = nullptr; return static_cast(elna::source::token::type::procedure); } begin { yylval.nil = nullptr; return static_cast(elna::source::token::type::begin); } end { yylval.nil = nullptr; return static_cast(elna::source::token::type::end); } const { yylval.nil = nullptr; return static_cast(elna::source::token::type::let); } var { yylval.nil = nullptr; return static_cast(elna::source::token::type::var); } True { yylval.number = 1; return static_cast(elna::source::token::type::boolean); } False { yylval.number = 0; return static_cast(elna::source::token::type::boolean); } [A-Za-z_][A-Za-z0-9_]* { new((void *) &yylval.identifier) std::string(yytext); return static_cast(elna::source::token::type::identifier); } [0-9]+ { yylval.number = strtol(yytext, NULL, 10); return static_cast(elna::source::token::type::number); } \( { yylval.nil = nullptr; return static_cast(elna::source::token::type::left_paren); } \) { yylval.nil = nullptr; return static_cast(elna::source::token::type::right_paren); } \>= { new((void *) &yylval.identifier) std::string(1, 'g'); return static_cast(elna::source::token::type::comparison_operator); } \<= { new((void *) &yylval.identifier) std::string(1, 'l'); return static_cast(elna::source::token::type::comparison_operator); } (>|<) { new((void *) &yylval.identifier) std::string(yytext); return static_cast(elna::source::token::type::comparison_operator); } \/= { new((void *) &yylval.identifier) std::string(1, 'n'); return static_cast(elna::source::token::type::comparison_operator); } = { yylval.nil = nullptr; return static_cast(elna::source::token::type::equals); } ; { yylval.nil = nullptr; return static_cast(elna::source::token::type::semicolon); } \. { yylval.nil = nullptr; return static_cast(elna::source::token::type::dot); } , { yylval.nil = nullptr; return static_cast(elna::source::token::type::comma); } (\+|\-) { new((void *) &yylval.identifier) std::string(yytext); return static_cast(elna::source::token::type::term_operator); } (\*|\/) { new((void *) &yylval.identifier) std::string(yytext); return static_cast(elna::source::token::type::factor_operator); } := { yylval.nil = nullptr; return static_cast(elna::source::token::type::assignment); } : { yylval.nil = nullptr; return static_cast(elna::source::token::type::colon); } . { return -1; } %% namespace elna::source { result tokenize(const std::filesystem::path& path) { int yytoken; std::vector tokens; yyin = fopen(path.c_str(), "rb"); if (yyin == nullptr) { throw std::ios_base::failure("File does not exist"); } do { yytoken = yylex(); if (yytoken < 0) { return result(unexpected_character{ std::string{ yytext[0] }, path, token_position }); } tokens.emplace_back(static_cast(yytoken), std::move(yylval), token_position); } while (yytoken != 0); return result(std::in_place, std::move(tokens), position{ line_no, column_no }, path); } }