195 lines
6.8 KiB
Plaintext
195 lines
6.8 KiB
Plaintext
|
%{
|
||
|
#define YY_NO_UNISTD_H
|
||
|
#define YY_USER_ACTION token_position = elna::source::position{ line_no, column_no }; column_no += yyleng;
|
||
|
|
||
|
#include <fstream>
|
||
|
#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<int>(elna::source::token::type::when);
|
||
|
}
|
||
|
then {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::then);
|
||
|
}
|
||
|
while {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::loop);
|
||
|
}
|
||
|
do {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::_do);
|
||
|
}
|
||
|
proc {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::procedure);
|
||
|
}
|
||
|
begin {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::begin);
|
||
|
}
|
||
|
end {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::end);
|
||
|
}
|
||
|
const {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::let);
|
||
|
}
|
||
|
var {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::var);
|
||
|
}
|
||
|
True {
|
||
|
yylval.number = 1;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::boolean);
|
||
|
}
|
||
|
False {
|
||
|
yylval.number = 0;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::boolean);
|
||
|
}
|
||
|
[A-Za-z_][A-Za-z0-9_]* {
|
||
|
new((void *) &yylval.identifier) std::string(yytext);
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::identifier);
|
||
|
}
|
||
|
[0-9]+ {
|
||
|
yylval.number = strtol(yytext, NULL, 10);
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::number);
|
||
|
}
|
||
|
\( {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::left_paren);
|
||
|
}
|
||
|
\) {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::right_paren);
|
||
|
}
|
||
|
\>= {
|
||
|
new((void *) &yylval.identifier) std::string(1, 'g');
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::comparison_operator);
|
||
|
}
|
||
|
\<= {
|
||
|
new((void *) &yylval.identifier) std::string(1, 'l');
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::comparison_operator);
|
||
|
}
|
||
|
(>|<) {
|
||
|
new((void *) &yylval.identifier) std::string(yytext);
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::comparison_operator);
|
||
|
}
|
||
|
\/= {
|
||
|
new((void *) &yylval.identifier) std::string(1, 'n');
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::comparison_operator);
|
||
|
}
|
||
|
= {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::equals);
|
||
|
}
|
||
|
; {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::semicolon);
|
||
|
}
|
||
|
\. {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::dot);
|
||
|
}
|
||
|
, {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::comma);
|
||
|
}
|
||
|
(\+|\-) {
|
||
|
new((void *) &yylval.identifier) std::string(yytext);
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::term_operator);
|
||
|
}
|
||
|
(\*|\/) {
|
||
|
new((void *) &yylval.identifier) std::string(yytext);
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::factor_operator);
|
||
|
}
|
||
|
:= {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::assignment);
|
||
|
}
|
||
|
: {
|
||
|
yylval.nil = nullptr;
|
||
|
|
||
|
return static_cast<int>(elna::source::token::type::colon);
|
||
|
}
|
||
|
. {
|
||
|
return -1;
|
||
|
}
|
||
|
%%
|
||
|
namespace elna::source
|
||
|
{
|
||
|
|
||
|
result<lexer> tokenize(const std::filesystem::path& path)
|
||
|
{
|
||
|
int yytoken;
|
||
|
std::vector<token> 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<lexer>(unexpected_character{ std::string{ yytext[0] }, path, token_position });
|
||
|
}
|
||
|
tokens.emplace_back(static_cast<token::type>(yytoken), std::move(yylval), token_position);
|
||
|
}
|
||
|
while (yytoken != 0);
|
||
|
|
||
|
return result<lexer>(std::in_place, std::move(tokens), position{ line_no, column_no }, path);
|
||
|
}
|
||
|
|
||
|
}
|