%{

typedef struct _rented_coder rented_coder;


#include "d2c-d2c_gram.h"

#include <ctype.h>
#include <string.h>


/* Tente de libérer autant de mémoire que possible...  */
void free_flex_memory(void) ;


%}

%option noyywrap
%option nounput
%option noinput
%option yylineno
%option stack
%option noyy_top_state


%x comments

%x ins_name try_details ins_details
%x encoding encoding_type encoding_content

%x encoding_bits encoding_bits_size

%x syntax syntax_name syntax_int syntax_ext

%x conv_begin conv_content conv_arg conv_arg_binval

%x arg arg_binval

%x hooks_begin hooks_content

%x rules_begin rules_content rules_cond rules_cond_binval rules_action rules_action_see rules_action_call


%%


[ \t\n]+                            { }

"/*"                                { BEGIN(comments); }
<comments>"*/"                      { BEGIN(INITIAL); }
<comments>[^*\n]                    { }
<comments>"Copyright"[^\n]*         { d2c_lval.string = strdup(yytext); return COPYRIGHT; }
<comments>"*"                       { }
<comments>"\n"                      { }


"@title"                            { BEGIN(ins_name); return TITLE; }

<ins_name>[ ][A-Za-z-]+             { d2c_lval.string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; }
<try_details>[ ,/]                  { BEGIN(ins_details); }
<try_details>[\n]                   { BEGIN(INITIAL); }

<ins_details>[^\n]*                 { d2c_lval.cstring = yytext; return INS_DETAILS; }
<ins_details>[\n]                   { BEGIN(INITIAL); }



"@encoding"                         { BEGIN(encoding); return ENCODING; }

<encoding>[ ]                       { }
<encoding>"("                       { BEGIN(encoding_type); }

<encoding_type>[A-Za-z]             { d2c_lval.string = strdup(yytext); return TYPE; }
<encoding_type>[0-9]+               { d2c_lval.integer = atoi(yytext); return NUMBER; }
<encoding_type>")"                  { BEGIN(encoding); }

<encoding>"{"                       { BEGIN(encoding_content); }
<encoding_content>[ \t\n]+          { }
<encoding_content>"}"               { BEGIN(INITIAL); }



<encoding_content>"@half"           { BEGIN(encoding_bits); return HALF; }
<encoding_content>"@word"           { BEGIN(encoding_bits); return WORD; }

<encoding_bits>" "                  { }
<encoding_bits>"\n"                 { BEGIN(encoding_content); }
<encoding_bits>[A-Za-z][A-Za-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; }

<encoding_bits>"("                  { BEGIN(encoding_bits_size); }
<encoding_bits_size>[0-9]+          { d2c_lval.integer = atoi(yytext); return SIZE; }
<encoding_bits_size>")"             { BEGIN(encoding_bits); }

<encoding_bits>[01]                 { d2c_lval.integer = atoi(yytext); return BIT; }



<encoding_content>"@syntax"         { BEGIN(syntax); return SYNTAX; }

<syntax>[ ]+                        { }
<syntax>"\n"                        { BEGIN(encoding_content); }

<syntax>[\"]                        { BEGIN(syntax_name); }
<syntax_name>[^ \n\"]+              { d2c_lval.string = strdup(yytext); return OPERAND_NAME; }
<syntax_name>[\"]                   { BEGIN(syntax); }

<syntax>"{"                         { BEGIN(syntax_int); }
<syntax_int>[^ \n}]+                { d2c_lval.string = strdup(yytext); return OPERAND_INTERNAL; }
<syntax_int>"}"                     { BEGIN(syntax); }

<syntax>"<"                         { BEGIN(syntax_ext); }
<syntax_ext>[^ \n>]+                { d2c_lval.string = strdup(yytext); return OPERAND_VISIBLE; }
<syntax_ext>">"                     { BEGIN(syntax); }



<encoding_content>"@conv"           { BEGIN(conv_begin); return CONV; }
<conv_begin>[ ]+                    { }
<conv_begin>"{"                     { BEGIN(conv_content); }
<conv_content>"}"                   { BEGIN(encoding_content); }

<conv_content>[ \t\n]+              { }
<conv_content>[A-Za-z_][A-Za-z0-9_]* {
                                      if (strcmp(yytext, "NOT") == 0) return NOT;
                                      else
                                      {
                                          d2c_lval.string = strdup(yytext);
                                          return NAME;
                                      }
                                    }
<conv_content>"="                   { return EQ; }
<conv_content>"("                   { BEGIN(conv_arg); return OP; }




<conv_arg>[A-Za-z][A-Za-z0-9_]*      {
                                      if (strcmp(yytext, "NOT") == 0) return NOT;
                                      else if (strcmp(yytext, "EOR") == 0) return EOR;
                                      else
                                      {
                                          d2c_lval.string = strdup(yytext);
                                          return NAME;
                                      }
                                    }
<conv_arg>[0-9][0-9]*               { d2c_lval.integer = atoi(yytext); return NUMBER; }
<conv_arg>"'"                       { BEGIN(conv_arg_binval); }
<conv_arg_binval>[01][01]*          { d2c_lval.string = strdup(yytext); return BINVAL; }
<conv_arg_binval>"'"                { BEGIN(conv_arg); }
<conv_arg>","                       { return COMMA; }
<conv_arg>":"                       { return COLON; }
<conv_arg>[ ]+                      { }
<conv_arg>")"                       { BEGIN(conv_content); return CP; }









<arg>[A-Za-z][A-Za-z0-9_]*     {
                                   if (strcmp(yytext, "NOT") == 0) return NOT;
                                   else if (strcmp(yytext, "EOR") == 0) return EOR;
                                   else
                                   {
                                       d2c_lval.string = strdup(yytext);
                                       return NAME;
                                   }
                               }
<arg>[0-9][0-9]*               { d2c_lval.integer = atoi(yytext); return NUMBER; }
<arg>"'"                       { BEGIN(arg_binval); }
<arg_binval>[01][01]*          { d2c_lval.string = strdup(yytext); return BINVAL; }
<arg_binval>"'"                { BEGIN(arg); }
<arg>","                       { return COMMA; }
<arg>":"                       { return COLON; }
<arg>[ ]+                      { }
<arg>")"                       { yy_pop_state(); return CP; }




<encoding_content>"@hooks"          { BEGIN(hooks_begin); return HOOKS; }
<hooks_begin>[ ]+                   { }
<hooks_begin>"{"                    { BEGIN(hooks_content); }
<hooks_content>"}"                  { BEGIN(encoding_content); }

<hooks_content>[ \t\n]+             { }
<hooks_content>[a-z_][a-z0-9_]*     { d2c_lval.string = strdup(yytext); return NAME; }
<hooks_content>"="                  { return EQ; }



<encoding_content>"@rules"          { BEGIN(rules_begin); return RULES; }
<rules_content>\/\/[^\n]+           { printf("SKIP '%s'\n", yytext); }
<rules_begin>[ ]+                   { }
<rules_begin>"{"                    { BEGIN(rules_content); }
<rules_content>[ \t\n]+             { }
<rules_content>"}"                  { BEGIN(encoding_content); }

<rules_content>"see "               { BEGIN(rules_action_see); return SEE; }
<rules_content>"unpredictable"      { return UNPREDICTABLE; }
<rules_content>"call"               { BEGIN(rules_action_call); return CALL; }

<rules_content>"if"                 { BEGIN(rules_cond); return IF; }
<rules_cond>[ ]+                    { }
<rules_cond>"("                     { return EXPR_START; }
<rules_cond>[A-Za-z][A-Za-z0-9]*    { d2c_lval.string = strdup(yytext); return NAME; }
<rules_cond>"=="                    { return EQUAL; }
<rules_cond>"'"                     { BEGIN(rules_cond_binval); }
<rules_cond_binval>[01][01]*        { d2c_lval.string = strdup(yytext); return BINVAL; }
<rules_cond_binval>"'"              { BEGIN(rules_cond); }
<rules_cond>[0-9][0-9]*             { d2c_lval.string = strdup(yytext); return IMMVAL; }
<rules_cond>")"                     { return EXPR_END; }
<rules_cond>"&&"                    { return AND; }

<rules_cond>";"                     { BEGIN(rules_action); return THEN; }
<rules_action>[ ]+                  { }

<rules_action>"see "                { BEGIN(rules_action_see); return SEE; }
<rules_action_see>[^\n]*            { d2c_lval.cstring = yytext; BEGIN(rules_content); return INS_DETAILS; }

<rules_action>"unpredictable"       { BEGIN(rules_content); return UNPREDICTABLE; }

<rules_action>"call"                    { BEGIN(rules_action_call); return CALL; }
<rules_action_call>[\t ]+               { }
<rules_action_call>[A-Za-z][A-Za-z0-9]* { d2c_lval.string = strdup(yytext); return NAME; }
<rules_action_call>"("                  { yy_push_state(arg); return OP; }
<rules_action_call>[\n]                 { BEGIN(rules_content); }


%%


/******************************************************************************
*                                                                             *
*  Paramètres  : -                                                            *
*                                                                             *
*  Description : Tente de libérer autant de mémoire que possible...           *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void free_flex_memory(void)
{
    yy_delete_buffer(YY_CURRENT_BUFFER);

}