/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

%{

#include <setjmp.h>
#include <stdarg.h>
static jmp_buf env;
#define exit(a)    jumpexit(a)
#define fprintf    jumpprtf

static void jumpexit(int n)
{
	longjmp(env,1);
}

static void jumpprtf(FILE *f,char *fmt,...)
{
	va_list list;
	char buf[1024];
	int len;
	va_start(list,fmt);
	vsprintf(buf, fmt, list);
	va_end(list);

	len = strlen(buf);
	if(len && buf[len-1] == '\n')
		buf[len-1] = 0;

	yyerror(buf);
}

#define _k(x) (keyword(yytext),(x))
#define _w(x) (plainword(yytext),(x))

static void kword(char *p)
{
    char buf[10];
    int i = 0;

    while(*p)
    {
        switch(*p)
        {
        case ' ':
        case '\t':
            buf[i] = 0;
            if(i) keyword(buf);
            buf[0] = *p;
            buf[1] = 0;
            space(buf);
            i = 0;
            break;

        case '\n':
            buf[i] = 0;
            if(i) keyword(buf);
            cr(buf);
            i = 0;
            break;

        default:
            buf[i++] = *p;
            break;
        }
        p++;
    }
    buf[i] = 0;
    keyword(buf);
}
%}

IDENT   [_A-Za-z]+[_0-9A-Za-z]*
NUMB    [0-9]+[\.]*[0-9]*
EXP     [eE][+\-]*[0-9]+ 

TIME1   [0-9][0-9]:[0-9][0-9]
TIME2   [0-9][0-9]:[0-9][0-9]:[0-9][0-9]
TIME    {TIME1}{TIME2}

DATE1   [0-9][0-9]-[0-9][0-9]-[0-9][0-9]
DATE2   [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]
DATE3   [0-9][0-9]-[0-9][0-9][0-9]
DATE4   [0-9][0-9][0-9][0-9]-[0-9][0-9][0-9]
DATE    {DATE1}{DATE2}


%s SOURCE

%%

<SOURCE>end[ \t]+inline[ \t]* { BEGIN INITIAL; kword(yytext); return ENDINLINE;}
<SOURCE>[ \t]+          space(yytext);
<SOURCE>.               inlineword(yytext);
<SOURCE>\n              cr(yytext);

<INITIAL>if        return _k(IF);
<INITIAL>then      return _k(THEN);
<INITIAL>else      return _k(ELSE);
<INITIAL>and       return _k(AND);
<INITIAL>not       return _k(NOT);
<INITIAL>or        return _k(OR);
<INITIAL>function  return _k(FUNCTION);
<INITIAL>return    return _k(RETURN);
<INITIAL>end       return _k(END);
<INITIAL>while     return _k(WHILE);
<INITIAL>global    return _k(GLOBAL);
<INITIAL>do        return _k(DO);
<INITIAL>on        return _k(ON);
<INITIAL>for       return _k(FOR);
<INITIAL>to        return _k(TO);
<INITIAL>by        return _k(BY);
<INITIAL>in        return _k(IN);
<INITIAL>of        return _k(OF);
<INITIAL>case      return _k(CASE);
<INITIAL>otherwise return _k(OTHERWISE);
<INITIAL>repeat    return _k(REPEAT);
<INITIAL>until     return _k(UNTIL);
<INITIAL>loop      return _k(LOOP);
<INITIAL>when      return _k(WHEN);
<INITIAL>include   return _k(INCLUDE);
<INITIAL>extern    return _k(EXTERN);
<INITIAL>tell      return _k(TELL);
<INITIAL>task      return _k(TASK);
<INITIAL>nil       return _k(NIL);
<INITIAL>object    return _k(OBJECT);
<INITIAL>import    return _k(IMPORT);
<INITIAL>export    return _k(EXPORT);
<INITIAL>inline[ \t]*\n  { BEGIN SOURCE; kword(yytext);return INLINE;}


<INITIAL>"->"       return _w(ARROW);
<INITIAL>"<>"       return _w(NE);
<INITIAL>">="       return _w(GE);
<INITIAL>"<="       return _w(LE);
<INITIAL>"\*\*"     return _w('^');

<INITIAL>\#.*\n     { yytext[yyleng-1] = 0; comment(yytext);}
<INITIAL>\#.*       comment(yytext);

<INITIAL>\"|\'      { 
					   int c,q = yytext[0]; 

					   yyleng = 1;

					   while((c = input()) && c != q && c != '\n') 
					   {
						   if(c == '\\') {
								yytext[yyleng++] = c;
								yytext[yyleng++] = input();
							} else yytext[yyleng++] =  c;
					   }

					   yytext[yyleng++] = c;
					   yytext[yyleng++] = 0;
					   return _w(STRING);
					 }

<INITIAL>{DATE}      return _w(DATE);
<INITIAL>{TIME}      return _w(TIME);
<INITIAL>{IDENT}     return _w(WORD); 
<INITIAL>{NUMB}{EXP} return _w(NUMBER); 
<INITIAL>{NUMB}      return _w(NUMBER); 

<INITIAL>^[ \t]*     leading(yytext);
<INITIAL>[ \t]*      space(yytext);
<INITIAL>\n          cr(yytext);
<INITIAL>.           return _w(*yytext); 
%%

int beau_parse()
{
	if(setjmp(env)) return 1;
	return yyparse();
}
