%top{
#include "parser.hpp"

#define YY_DECL yy::parser::symbol_type yylex()
}

%option warn noyywrap nodefault nounput yylineno
%option header-file="lexer.hpp"
%option outfile="lexer.cpp"

%{
#include <iostream>
#include <memory>

static yy::location loc;

// This macro runs before every single action in your lexer
#define YY_USER_ACTION loc.columns(yyleng);
%}

D [0-9]
L [a-z]
W [ \t\r]

%%

%{
  // Reset the "end" of the previous token to be the "start" of this one
  loc.step();
%}

"begin"     { return yy::parser::make_begin(loc); }
"do"        { return yy::parser::make_do(loc); }
"else"      { return yy::parser::make_else(loc); }
"end"       { return yy::parser::make_end(loc); }
"for"       { return yy::parser::make_for(loc); }
"if"        { return yy::parser::make_if(loc); }
"let"       { return yy::parser::make_let(loc); }
"print"     { return yy::parser::make_print(loc); }
"then"      { return yy::parser::make_then(loc); }
"var"       { return yy::parser::make_var(loc); }
"int"       { return yy::parser::make_int(loc); }
"bool"      { return yy::parser::make_bool(loc); }
"true"      { return yy::parser::make_true(loc); }
"false"     { return yy::parser::make_false(loc); }

[\=\+\-\*\/\%\(\)\:\<\>]  { return yy::parser::symbol_type(yytext[0], loc); }

{D}+        { return yy::parser::make_const(atoi(yytext), loc); }
{L}         { return yy::parser::make_id(yytext[0], loc); }
{W}+        { loc.step(); }
\n+         { loc.lines(yyleng); loc.step(); }

'[^\n]*     { /* nothing */ }

.           { std::cerr << "\033[91mIllegal character '" << yytext[0]
                        << "' at line " << loc.begin.line << "\033[0m"
                        << std::endl;
              std::exit(1);
            }

<<EOF>>     { return yy::parser::make_YYEOF(loc); }

%%

