%option c++
%option yyclass="TestLexer"
%option noyywrap
%{
    #include <iostream>
    #include "TestLexer.h"

    #undef YY_DECL
    #define YY_DECL int TestLexer::yylex(yy::TestParser::semantic_type* lval)



    #define vt100BLUE "\x1b[34m"
    #define TOKEN(X) \
        std::cout << " " << vt100BLUE << #X; \
        return yy::TestParser::token::X;
%}

%%

[ \t\r\n]+              { std::cout << yytext; /* ignore whitespace */ }
\/\/[^\n]*\n            { /* ignore comments */ }

"int"                   { TOKEN(INT); }
"if"                    { TOKEN(IF); }
"else"                  { TOKEN(ELSE); }
"while"                 { TOKEN(WHILE); }
"input"                 { TOKEN(INPUT); }
"output"                { TOKEN(OUTPUT); }

"("                     { TOKEN(OPENPAREN); }
")"                     { TOKEN(CLOSEPAREN); }
"{"                     { TOKEN(OPENBRACE); }
"}"                     { TOKEN(CLOSEBRACE); }
","                     { TOKEN(COMMA); }
";"                     { TOKEN(SEMICOLON); }

"="                     { TOKEN(ASSIGN); }
"+"                     { TOKEN(PLUS); }
"-"                     { TOKEN(MINUS); }
"*"                     { TOKEN(MULT); }
"/"                     { TOKEN(DIV); }
"%"                     { TOKEN(MOD); }

"<"                     { TOKEN(LESS); }
"<="                    { TOKEN(LESSEQUAL); }
"=="                    { TOKEN(EQUAL); }
"!="                    { TOKEN(UNEQUAL); }
">="                    { TOKEN(GREATEREQUAL); }
">"                     { TOKEN(GREATER); }

"!"                     { TOKEN(NOT); }
"||"                    { TOKEN(OR); }
"&&"                    { TOKEN(AND); }

[0-9]+                  { lval->num = std::stoi(yytext); TOKEN(NUMBER); }
\"[^"]\"                { lval->str = new std::string(yytext); TOKEN(STRING); }
[a-zA-Z_][a-zA-Z0-9_]*  { lval->str = new std::string(yytext); TOKEN(IDENTIFIER); }
<<EOF>>                 { TOKEN(YYEOF); }

.                       { std::cerr << " #ERROR#"; /* lexical error */ }

%%

TestLexer::TestLexer(std::istream* is, std::ostream* os)
: yyFlexLexer(is, os)
{
}
