Initial commit
This commit is contained in:
204
source/scanner.l
Normal file
204
source/scanner.l
Normal file
@ -0,0 +1,204 @@
|
||||
%{
|
||||
#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);
|
||||
}
|
||||
\^ {
|
||||
yylval.nil = nullptr;
|
||||
|
||||
return static_cast<int>(elna::source::token::type::hat);
|
||||
}
|
||||
@ {
|
||||
yylval.nil = nullptr;
|
||||
|
||||
return static_cast<int>(elna::source::token::type::at);
|
||||
}
|
||||
. {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user