%{
#include "ael.tab.h"
#include "ael_structs.h"
static int parencount = 0;
static int commaout = 0;
int my_lineno = 1;
int my_col = 0;
#define YY_NO_INPUT
static int input  (yyscan_t yyscanner);

%}

%x paren semic argg
%option prefix="ael_yy"
%option batch
%option outfile="ael_lex.c"
%option reentrant
%option bison-bridge
%option bison-locations
%option yylineno
%option noyywrap

%%
\{	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return LC;}
\}	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return RC;}
\(	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return LP;}
\)	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return RP;}
\;	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return SEMI;}
\=	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return EQ;}
\,	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return COMMA;}
\:	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return COLON;}
\&	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return AMPER;}
\|	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return BAR;}
\=\>	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return EXTENMARK;}
context	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_CONTEXT;}
macro	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_MACRO;};
globals	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_GLOBALS;}
ignorepat	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_IGNOREPAT;}
switch	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_SWITCH;}
if	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_IF;}
else	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_ELSE;}
goto	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_GOTO;}
return	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_RETURN;}
break	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_BREAK;}
continue	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_CONTINUE;}
for	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_FOR;}
while	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_WHILE;}
case	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_CASE;}
default	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_DEFAULT;}
catch	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_CATCH;}
switches	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_SWITCHES;}
eswitches	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_ESWITCHES;}
includes	{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;return KW_INCLUDES;}

"//".*$		{/* throw away printf("Skipping COMMENT %s\n\n",yytext); */ }
\n		{my_lineno++;}
[ 	]+	{/* nothing */ }

[-a-zA-Z0-9_/.$][-a-zA-Z0-9_/.\{\}$]*	{yylloc->first_line = yylloc->last_line = my_lineno;yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng; /* set up the ptr */yylval->str = strdup(yytext);  /* printf("Got WORD %s\n", yylval->str);*/ return word;}



<paren>[^()]*\)	{yylloc->first_line = yylloc->last_line = my_lineno;yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng; parencount--;if( parencount >= 0){yymore();} else { yylval->str = strdup(yytext); *(yylval->str+strlen(yylval->str)-1)=0;/* printf("Got paren word %s\n", yylval->str); */ unput(')'); BEGIN(0); return word;} }
<paren>[^()]*\(	{yylloc->first_line = yylloc->last_line = my_lineno;yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng; parencount++; yymore();};



<argg>[^(),]*\)	{yylloc->first_line = yylloc->last_line = my_lineno;yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng; parencount--;if( parencount >= 0)
                                   { yymore(); }
                              else { yylval->str = strdup(yytext); 
									 if(yyleng > 1 ) *(yylval->str+yyleng-1)=0;
                                     /* printf("Got argg word '%s'\n", yylval->str);  */
                                     BEGIN(0); 
                                     if( !strcmp(yylval->str,")") ) 
                                         { return RP;  }
                                     else 
                                         {unput(')'); return word;}
                                    } 
                }
<argg>[^(),]*\(	{/* printf("GOT AN LP!!!\n"); */yylloc->first_line = yylloc->last_line = my_lineno;yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng; parencount++; yymore();};
<argg>[^(),]*\,	{yylloc->first_line = yylloc->last_line = my_lineno;  yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;
                  if( parencount != 0)
                  { /* printf("Folding in a comma!\n"); */ 
					yymore();
				  } 
                  else 
                  { /* printf("got a comma!\n\n");  */
                     if( !commaout )
                     { 
						if( !strcmp(yytext,"," ) ) 
							{commaout = 0; return COMMA;} 
						yylval->str = strdup(yytext); /* printf("Got argg2 word %s\n", yylval->str); */ 
						unput(','); 
						commaout = 1; 
						if(yyleng > 1 ) 
							*(yylval->str+yyleng-1)=0;
						return word;
					 }
                     else
                     	{ commaout = 0; return COMMA; }
                   }; }


<semic>[^;]*;	{yylloc->first_line = yylloc->last_line = my_lineno;yylloc->last_column=my_col; yylloc->first_column=my_col-yyleng;  yylval->str = strdup(yytext); if(yyleng > 1 ) *(yylval->str+yyleng-1)=0;/* printf("Got semic word %s\n", yylval->str); */ unput(';'); BEGIN(0); return word; }

%%

void reset_parencount(yyscan_t yyscanner )
{
	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
	parencount = 0;
	BEGIN(paren);
}

void reset_semicount(yyscan_t yyscanner )
{
	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
	BEGIN(semic);
}

void reset_argcount(yyscan_t yyscanner )
{
	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
	parencount = 0;
	commaout = 0;
	BEGIN(argg);
}

void parse_extensions(yyscan_t scanner)
{
    struct yyguts_t * yyg = (struct yyguts_t*)scanner;
	struct pval *yy;
	ael_yyparse((void*)(&yy));
	printf("Done. yy->type is %d\n", yy->type);
}

int main(int argc, char **argv)
{
	struct parse_io *io;
	extern int yydebug;
	FILE *fin;

	// yydebug =1;	

	//yyscan_t scanner;
	//ael_yylex_init(&scanner);
	//parse_extensions(scanner);

        io = calloc(sizeof(struct parse_io),1);

        ael_yylex_init(&io->scanner);

		fin = fopen("/etc/asterisk/extensions.ael","r");
        // ast_yy_scan_string(expr, io->scanner);
		ael_yyset_in (fin , io->scanner);	

        ael_yyparse ((void *) io);

        ael_yylex_destroy(io->scanner);

        free(io);
        return 0;
}

#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
#define yytext_ptr yytext_r
static int input  (yyscan_t yyscanner)
{
    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
	int c;

	*yyg->yy_c_buf_p = yyg->yy_hold_char;

	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
		{
		/* yy_c_buf_p now points to the character we want to return.
		 * If this occurs *before* the EOB characters, then it's a
		 * valid NUL; if not, then we've hit the end of the buffer.
		 */
		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
			/* This was really a NUL. */
			*yyg->yy_c_buf_p = '\0';

		else
			{ /* need more input */
			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
			++yyg->yy_c_buf_p;

			switch ( yy_get_next_buffer( yyscanner ) )
				{
				case EOB_ACT_LAST_MATCH:
					/* This happens because yy_g_n_b()
					 * sees that we've accumulated a
					 * token and flags that we need to
					 * try matching the token before
					 * proceeding.  But for input(),
					 * there's no matching to consider.
					 * So convert the EOB_ACT_LAST_MATCH
					 * to EOB_ACT_END_OF_FILE.
					 */

					/* Reset buffer status. */
					yyrestart(yyin ,yyscanner);

					/*FALLTHROUGH*/

				case EOB_ACT_END_OF_FILE:
					{
					if ( yywrap(yyscanner ) )
						return EOF;

					if ( ! yyg->yy_did_buffer_switch_on_eof )
						YY_NEW_FILE;
					return input(yyscanner);
					}

				case EOB_ACT_CONTINUE_SCAN:
					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
					break;
				}
			}
		}

	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
	yyg->yy_hold_char = *++yyg->yy_c_buf_p;

	if ( c == '\n' )
	    do{ yylineno++;
    	    yycolumn=0;
    	}while(0);
	yycolumn++;
	return c;
}
