%option stack

%x comment
%x api_entry
%x api_entry2
%x api_entry_param
%x var_type

DIGIT    [0-9]
ID       [a-zA-Z_][a-zA-Z0-9_]*

    #include "spec.h"

   int num_lines = 0;

   VarType *currType = 0;

   ApiEntry apis[128];
   int apiCount = 0;

   int typeNextState;

   void checkPointerType() {
       VarType *baseType = currType;
       int curPtrLevel = 0;
       while (curPtrLevel < baseType->ptrLevel) {
           currType = &apis[apiCount].params[apis[apiCount].paramCount];
           currType->type = 4;
           currType->ptrLevel = curPtrLevel;
           if (currType->ptrLevel > 0) {
              currType->isConst = 1;
           }
           sprintf(currType->typeName, "%s", "size_t");
           switch(baseType->ptrLevel - curPtrLevel) {
           case 1:
              sprintf(currType->name, "%s_length", baseType->name);
              break;
           case 2:
              sprintf(currType->name, "%s_length_length", baseType->name);
              break;
           }
           apis[apiCount].paramCount++;
           curPtrLevel ++;
       }
   }

   int yylex();

%%

"/*"         BEGIN(comment);
<comment>[^*\n]*        /* eat anything that's not a '*' */
<comment>"*"+[^*/\n]*   /* eat up '*'s not followed by '/'s */
<comment>\n             ++num_lines;
<comment>"*"+"/"        BEGIN(INITIAL);

<*>" "   //printf("found ' '\n");
<*>"\t"   //printf("found ' '\n");
<*>"\n"  ++num_lines; //printf("found lf \n");

{ID} {
    memset(&apis[apiCount], 0, sizeof(ApiEntry));
    memcpy(apis[apiCount].name, yytext, yyleng);
    BEGIN(api_entry);
    }

<api_entry>"{" {
    BEGIN(api_entry2);
    }

<api_entry2>"sync" {
    apis[apiCount].sync = 1;
    }

<api_entry2>"handcodeApi" {
    apis[apiCount].handcodeApi = 1;
    }

<api_entry2>"direct" {
    apis[apiCount].direct = 1;
    }

<api_entry2>"nocontext" {
    apis[apiCount].nocontext = 1;
    }

<api_entry2>"ret" {
    currType = &apis[apiCount].ret;
    typeNextState = api_entry2;
    BEGIN(var_type);
    }

<api_entry2>"param" {
    currType = &apis[apiCount].params[apis[apiCount].paramCount];
    apis[apiCount].paramCount++;
    typeNextState = api_entry_param;
    BEGIN(var_type);
    }

<var_type>"const" {
    currType->isConst = 1;
    }

<var_type>"i8" {
    currType->type = 1;
    currType->bits = 8;
    BEGIN(typeNextState);
    }

<var_type>"i16" {
    currType->type = 1;
    currType->bits = 16;
    BEGIN(typeNextState);
    }

<var_type>"i32" {
    currType->type = 1;
    currType->bits = 32;
    BEGIN(typeNextState);
    }

<var_type>"i64" {
    currType->type = 1;
    currType->bits = 64;
    BEGIN(typeNextState);
    }

<var_type>"u8" {
    currType->type = 2;
    currType->bits = 8;
    BEGIN(typeNextState);
    }

<var_type>"u16" {
    currType->type = 2;
    currType->bits = 16;
    BEGIN(typeNextState);
    }

<var_type>"u32" {
    currType->type = 2;
    currType->bits = 32;
    BEGIN(typeNextState);
    }

<var_type>"u64" {
    currType->type = 2;
    currType->bits = 64;
    BEGIN(typeNextState);
    }

<var_type>"f" {
    currType->type = 3;
    currType->bits = 32;
    BEGIN(typeNextState);
    }

<var_type>"d" {
    currType->type = 3;
    currType->bits = 64;
    BEGIN(typeNextState);
    }

<var_type>{ID} {
    currType->type = 4;
    currType->bits = 32;
    memcpy(currType->typeName, yytext, yyleng);
    BEGIN(typeNextState);
    }

<api_entry_param>"*" {
    currType->ptrLevel ++;
    }

<api_entry_param>{ID} {
    memcpy(currType->name, yytext, yyleng);
    checkPointerType();
    BEGIN(api_entry2);
    }

<api_entry2>"*" {
    currType->ptrLevel ++;
    }

<api_entry2>"}" {
    apiCount++;
    BEGIN(INITIAL);
    }

<*>. {
    fprintf(stderr, "error: unexpected character \'%c\' at line %d\n",
            *yytext, num_lines + 1);
    exit(1);
    }

%%


int yywrap()
{
    return 1;
}