%top {

#include "grammar.h"

}


%{

#include "decl.h"

#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>


#define PUSH_STATE(s) yy_push_state(s, yyscanner)
#define POP_STATE     yy_pop_state(yyscanner)

%}


%option bison-bridge reentrant
%option stack
%option nounput
%option noinput
%option noyywrap
%option noyy_top_state
%option yylineno
%option never-interactive


%x regexp
%x comment


str_not_escaped [^\"\\]
str_escaped \\a|\\b|\\t|\\n|\\v|\\f|\\r|\\e|\\\"|\\\\|\\x{hbyte}
str_mixed ({str_not_escaped}|{str_escaped})

hbyte [0-9a-fA-F]{2}

digit         [0-9]
letter        [a-zA-Z]
hexdigit      [a-fA-F0-9]
octdigit      [0-7]


%%


":"                     { return COLON; }
"{"                     { return CURLY_BRACKET_O; }
"}"                     { return CURLY_BRACKET_C; }
"="                     { return EQUAL; }
"("                     { return PAREN_O; }
")"                     { return PAREN_C; }
".."                    { return DOT_DOT; }
","                     { return COMMA; }
"["                     { return BRACKET_O; }
"]"                     { return BRACKET_C; }
"%"                     { return PERCENT; }
"."                     { return DOT; }

"+"                     { return ADD_OP; }
"-"                     { return SUB_OP; }
"*"                     { return MUL_OP; }
"\\"                    { return DIV_OP; }
"^"                     { return EOR_OP; }
"&"                     { return AND_OP; }
"|"                     { return OR_OP; }
"~"                     { return INV_OP; }
"<<"                    { return SHIFT_LEFT_OP; }
">>"                    { return SHIFT_RIGHT_OP; }

"<"                     { return LT; }
">"                     { return GT; }
"<="                    { return LE; }
">="                    { return GE; }
"=="                    { return EQ; }
"!="                    { return NEQ; }

"all"                   { return ALL; }
"and"                   { return AND; }
"any"                   { return ANY; }
"ascii"                 { return ASCII; }
"at"                    { return AT; }
"base64"                { return BASE64; }
"base64wide"            { return BASE64WIDE; }
"condition"             { return CONDITION; }
"contains"              { return CONTAINS; }
"defined"               { return DEFINED; }
"endswith"              { return ENDSWITH; }
"entrypoint"            { return ENTRYPOINT; }
"filesize"              { return FILESIZE; }
"for"                   { return FOR; }
"fullword"              { return FULLWORD; }
"global"                { return GLOBAL; }
"icontains"             { return ICONTAINS; }
"iendswith"             { return IENDSWITH; }
"iequals"               { return IEQUALS; }
"import"                { return IMPORT; }
"in"                    { return IN; }
"include"               { return INCLUDE; }
"istartswith"           { return ISTARTSWITH; }
"matches"               { return MATCHES; }
"meta"                  { return META; }
"nocase"                { return NOCASE; }
"none"                  { return NONE; }
"not"                   { return NOT; }
"of"                    { return OF; }
"or"                    { return OR; }
"private"               { return PRIVATE; }
"rule"                  { return RULE; }
"startswith"            { return STARTSWITH; }
"strings"               { return STRINGS; }
"them"                  { return THEM; }
"wide"                  { return WIDE; }
"xor"                   { return XOR; }

"false"                 { return _FALSE; }
"true"                  { return _TRUE; }


%{ /* Commentaires */ %}

"/*"                    { PUSH_STATE(comment); }
<comment>"*/"           { POP_STATE; }
<comment>(.|\n)         { }

"//"[^\n]*              { }


%{ /* Blocs de texte */ %}

$({letter}|{digit}|_)*"*" {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return STRING_IDENTIFIER_WITH_WILDCARD;

}

$({letter}|{digit}|_)* {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return STRING_IDENTIFIER;

}

#({letter}|{digit}|_)* {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return STRING_COUNT;

}

@({letter}|{digit}|_)* {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return STRING_OFFSET;

}

!({letter}|{digit}|_)* {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return STRING_LENGTH;

}

u?int(8|16|32)(be)? {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return INTEGER_FUNCTION;

}

({letter}|_)({letter}|{digit}|_)* {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return IDENTIFIER;

}

{digit}+(MB|KB){0,1} {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return NUMBER;

}

{digit}+"."{digit}+ {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return DOUBLE;

}

0x{hexdigit}+ {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return NUMBER;

}

0o{octdigit}+ {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return NUMBER;

}

\"{str_mixed}*\" {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return TEXT_STRING;

}

"/" {

    PUSH_STATE(regexp);

}

<regexp>(\\\/|\\.|[^/\n\\])+\/i?s? {

    POP_STATE;

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return REGEXP;

}

\{(({hexdigit}|[ \-|\~\?\[\]\(\)\n\r\t]|\/\*(\/|\**[^*/])*\*+\/)+|\/\/.*\n)+\} {

    yylval->cstring.data = yytext;
    yylval->cstring.len = yyleng;

    return HEX_STRING;

}


%{ /* Actions par défaut */ %}

<*>[ \t\r]+             { }

<*>[\n]+                { }

<*>.                    {
                            char *msg;
                            int ret;
                            ret = asprintf(&msg, "Unhandled token in rule definition: '%s   '", yytext);
                            if (ret == -1)
                                YY_FATAL_ERROR("Unhandled token in undisclosed rule definition");
                            else
                            {
                                YY_FATAL_ERROR(msg);
                                free(msg);
                            }
                        }


%%