%option c++
%option yyclass="TestLexer"
%option noyywrap

%{
    #include <iostream>
    #include "TestLexer.h"

    #undef YY_DECL
    #define YY_DECL int TestLexer::yylex()



    enum tokens { COMMENT, INT, IF, ELSE, WHILE, INPUT, OUTPUT,
    OPENPAREN, CLOSEPAREN, OPENBRACE, CLOSEBRACE, COMMA, SEMICOLON,
    ASSIGN, PLUS, MINUS, MULT, DIV, MOD,
    LESS, LESSEQUAL, EQUAL, UNEQUAL, GREATEREQUAL, GREATER,
    NOT, OR, AND,
    NUMBER, STRING, IDENTIFIER, YYEOF };

    //#define TOKEN(X) std::cout << " " << X
    #define TOKEN(X) std::cout << " " << #X
%}


%%

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

"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]+                  { TOKEN(NUMBER) << "(" << yytext << ")"; }
\"[^"]*\"                { TOKEN(STRING) << "(" << yytext << ")"; }
[a-zA-Z_][a-zA-Z0-9_]*  { TOKEN(IDENTIFIER) << "(" << yytext << ")"; }
<<EOF>>                 { TOKEN(YYEOF); return YYEOF; }

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

%%

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