/*
This is a simple parser for html.  It tries to turn the html into something that
can be displayed by a wiki.
 */

%namespace GLScript
%option noparser


%x COMMENT
%x COMMENTSHARP
%x STVARRAY
%x STFUNCTION
%x STUNARY



ALPHA [A-Za-z]
DIGIT [0-9]
NONNEWLINE_WHITE_SPACE_CHAR [\ \r\t\b\012]
WHITE_SPACE_CHAR [\n\r\ \t\b\012]
STRING_TEXT (\\\"|[^\n\"]|\\{WHITE_SPACE_CHAR}+\\)*
COMMENT_TEXT ([^/*\n]|[^*\n]"/"[^*\n]|[^/\n]"*"[^/\n]|"*"[^/\n]|"/"[^*\n])*
COMMENT_TEXT_SHARP ([^\n])*
BLOC_TEXT [^\n\r]*
BLOC_ARRAY ([^\[\];,\(\)])*
BLOC_FUNCTION ([^\[\];,\(\)\"])*
OPERATOR [\+\-\*\/=<>&\|\!\^;]
BLOC_UNARY ([^\[\]\;,\(\)\"\+\-\*\/=<>&\|\!\^])*
VAR ${ALPHA}(({ALPHA}|{DIGIT}|_)*)
VARARRAY ${ALPHA}(({ALPHA}|{DIGIT}|_)*)({WHITE_SPACE_CHAR})*\[
IDENT {ALPHA}(({ALPHA}|{DIGIT}|_)*)
FUNCTION {ALPHA}(({ALPHA}|{DIGIT}|_)*)({WHITE_SPACE_CHAR})*\(


%%

<INITIAL> "!" { isOperator = true; YyLine = yyline; return E_NOT; }
<INITIAL> "," { isOperator = false; YyLine = yyline; return E_COLON; }
<INITIAL> ":" { isOperator = false; YyLine = yyline; return E_DOUBLEDOT; }
<INITIAL> ";" { isOperator = false; YyLine = yyline; return E_SEMICOLON; }
<INITIAL> "(" { isOperator = false; YyLine = yyline; return E_PAR_OPEN; }
<INITIAL> ")" { isOperator = false; YyLine = yyline; return E_PAR_CLOSE; }
<INITIAL> "[" { isOperator = false; YyLine = yyline; return E_BRACKET_OPEN; }
<INITIAL> "]" { isOperator = false; YyLine = yyline; return E_BRACKET_CLOSE; }
/* <INITIAL> "{" { isOperator = false; YyLine = yyline; return 7; } */
/* <INITIAL> "}" { isOperator = false; YyLine = yyline; return 8; } */
<INITIAL> "." { isOperator = true; YyLine = yyline; return E_POINT; }
<INITIAL> "+" {
	if( isOperator ){
		isOperator = true;
		YyLine = yyline; return E_POS;
	}
	else{
		isOperator = true;
		YyLine = yyline; return E_PLUS;
	}
}
<INITIAL> "-" {
	if( isOperator ){
		isOperator = true;
		YyLine = yyline; return E_NEG;
	}
	else{
		isOperator = true;
		YyLine = yyline; return E_MOINS;
	}
}
<INITIAL> "*" { isOperator = true; YyLine = yyline; return E_MULT; }
<INITIAL> "/" { isOperator = true; YyLine = yyline; return E_DIV; }
<INITIAL> "=" { isOperator = true; YyLine = yyline; return E_ASSIGN; }
<INITIAL> "==" { isOperator = true; YyLine = yyline; return E_EQUAL; }
<INITIAL> "<>" { isOperator = true; YyLine = yyline; return E_DIFF; }
<INITIAL> "<"  { isOperator = true; YyLine = yyline; return E_LESS; }
<INITIAL> "<=" { isOperator = true; YyLine = yyline; return E_LESS_EQUAL; }
<INITIAL> ">"  { isOperator = true; YyLine = yyline; return E_MORE; }
<INITIAL> ">=" { isOperator = true; YyLine = yyline; return E_MORE_EQUAL; }
<INITIAL> "&"  { isOperator = true; YyLine = yyline; return E_BOOL_AND; }
<INITIAL> "|"  { isOperator = true; YyLine = yyline; return E_BOOL_OR; }
<INITIAL> "&&"  { isOperator = true; YyLine = yyline; return E_AND; }
<INITIAL> "||"  { isOperator = true; YyLine = yyline; return E_OR; }
<INITIAL> "!=" { isOperator = true; YyLine = yyline; return E_DIFF; }
<INITIAL> "\^" { isOperator = true; YyLine = yyline; return E_POW; }
<INITIAL> "§" { isOperator = false; YyLine = yyline; return 23; }
<INITIAL> [eE][vV][eE][nN][tT]|[sS][uU][bB]|[cC][aA][tT][cC][hH][eE][vV][eE][nN][tT]|[cC][aA][tT][cC][hH][sS][uU][bB] { isOperator = false; YyLine = yyline; return E_BEGIN_FUNCTION; }
<INITIAL> [eE][nN][dD][eE][vV][eE][nN][tT]|[eE][nN][dD][sS][uU][bB]|[eE][nN][dD][cC][aA][tT][cC][hH][eE][vV][eE][nN][tT]|[eE][nN][dD][cC][aA][tT][cC][hH][sS][uU][bB] { isOperator = false; YyLine = yyline; return E_END_FUNCTION; }
<INITIAL> [cC][oO][nN][sS][tT] { isOperator = false; YyLine = yyline; return E_CONST; }
<INITIAL> [bB][rR][eE][aA][kK] { isOperator = false; YyLine = yyline; return E_BREAK; }
<INITIAL> [fF][oO][rR]({WHITE_SPACE_CHAR})*\( { isOperator = false; YyLine = yyline; return E_FOR; }
<INITIAL> [fF][oO][rR][eE][aA][cC][hH]({WHITE_SPACE_CHAR})*\( { isOperator = false; YyLine = yyline; return E_FOREACH; }
<INITIAL> [sS][wW][iI][tT][cC][hH]({WHITE_SPACE_CHAR})*\( { isOperator = false; YyLine = yyline; return E_SWITCH; }
<INITIAL> [cC][aA][sS][eE] { isOperator = false; YyLine = yyline; return E_CASE; }
<INITIAL> [eE][nN][dD][sS][wW][iI][tT][cC][hH] { isOperator = false; YyLine = yyline; return E_ENDSWITCH; }
<INITIAL> [dD][eE][fF][aA][uU][lL][tT] { isOperator = false; YyLine = yyline; return E_DEFAULT; }
<INITIAL> [eE][nN][dD][fF][oO][rR] { isOperator = false; YyLine = yyline; return E_ENDFOR; }
<INITIAL> [eE][nN][dD][fF][oO][rR][eE][aA][cC][hH] { isOperator = false; YyLine = yyline; return E_ENDFOREACH; }
<INITIAL> [iI][nN] { isOperator = false; YyLine = yyline; return E_IN; }
<INITIAL> [wW][hH][iI][lL][eE]({WHITE_SPACE_CHAR})*\( { isOperator = false; YyLine = yyline; return E_WHILE; }
<INITIAL> [eE][nN][dD][wW][hH][iI][lL][eE] { isOperator = false; YyLine = yyline; return E_ENDWHILE; }
<INITIAL> [iI][fF]({WHITE_SPACE_CHAR})*\( { isOperator = false; YyLine = yyline; return E_IF; }
<INITIAL> [tT][hH][eE][nN] { isOperator = false; YyLine = yyline; return E_THEN; }
<INITIAL> [eE][lL][sS][eE] { isOperator = false; YyLine = yyline; return E_ELSE; }
<INITIAL> [eE][nN][dD][iI][fF] { isOperator = false; YyLine = yyline; return E_ENDIF; }
<INITIAL> [gG][lL][oO][bB][aA][lL][vV][aA][rR] { isOperator = false; YyLine = yyline; return E_GLOBALVAR; }
<INITIAL> [lL][aA][nN][gG] { isOperator = false; YyLine = yyline; return E_LANG; }
<INITIAL> [eE][nN][dD][lL][aA][nN][gG] { isOperator = false; YyLine = yyline; return E_ENDLANG; }
/* <INITIAL> [rR][eE][tT][uU][rR][nN] { isOperator = false; YyLine = yyline; return E_YyLine = yyline; return; } */
/* <INITIAL> [pP][lL][aA][yY][eE][rR][vV][aA][rR] { isOperator = false; YyLine = yyline; return E_PLAYERVAR; } */
<INITIAL,STFUNCTION,STVARRAY> {NONNEWLINE_WHITE_SPACE_CHAR}+ { }


<INITIAL> {VARARRAY} {
	BEGIN(STVARRAY);
	brack_count = 1;
	par_count = 0;
	strBloc = yytext;
	args.Clear();
	strParam = "";
	break;
}
<STVARRAY> "[" {
	brack_count += 1;
	strBloc+="[";
    strParam+=yytext;
	break;
}

<STVARRAY> "]" {
	brack_count -= 1;
	strBloc+="]";
	if( brack_count == 0 ){
	    args.Add( strParam.Trim() );
	    BEGIN(INITIAL);
	    isOperator = false; YyLine = yyline; return E_ARVAR;
	}
	else
	    strParam+=yytext;

	break;
}
<STVARRAY> "," {
    strBloc+=yytext;
	if( brack_count == 1 && par_count == 0 ){
	    args.Add( strParam.Trim() );
	    strParam = "";
	}
	else
	    strParam+=yytext;
	break;

}
<STVARRAY> ";" {
	    strBloc+=yytext;
	    BEGIN(INITIAL);
		Utility.assert(par_count >= 0 || brack_count > 0, "'[' not closed");
	    break;
}
<STVARRAY> "(" {
    strBloc+=yytext;
    strParam+=yytext;
	par_count++;
	break;
}
<STVARRAY> ")" {
    strBloc+=yytext;
    strParam+=yytext;
	par_count--;
	break;
}
<STVARRAY> {BLOC_ARRAY} { strBloc+=yytext;strParam+=yytext;break; }


<INITIAL> {FUNCTION} {
	BEGIN(STFUNCTION);
	brack_count = 0;
	par_count = 1;
	strBloc = yytext;
	args.Clear();
	strParam = "";
	myFunc = yytext;
	break;
}
<STFUNCTION> "(" {
	par_count += 1;
	strBloc+=yytext;
    strParam+=yytext;
	break;
}
<STFUNCTION> ")" {
	par_count -= 1;
	strBloc+=yytext;
	if( par_count == 0 ){
	    if( strParam.Trim() != "" )
	    	args.Add( strParam.Trim() );
	    
	    strParam = "";
	    BEGIN(INITIAL);
//	    Console.WriteLine( "end function : " + myFunc + string.Join( ",",(string[])args.ToArray(typeof(string)) ) + ")\n");
	    isOperator = false;
		YyLine = yyline; return E_FUNCTION;
	}
	else
	    strParam+=yytext;

	break;
}
<STFUNCTION> "," {
    strBloc+=yytext;
	if( par_count == 1 && brack_count == 0 ){
	    args.Add( strParam.Trim() );
	    strParam = "";
	}
	else
	    strParam+=yytext;
	break;

}
<STFUNCTION> ";" {
	    strBloc+=yytext;
	    BEGIN(INITIAL);
		Utility.assert(par_count >= 0 || brack_count > 0, "'(' not closed");
	    break;
}
<STFUNCTION> "[" {
    strBloc+=yytext;
    strParam+=yytext;
	brack_count++;
	break;
}
<STFUNCTION> "]" {
    strBloc+=yytext;
    strParam+=yytext;
	brack_count--;
	break;
}
<STFUNCTION> \"{STRING_TEXT}\" {
	{
		string str1 =  yytext.Substring(1,yytext.Length - 2);
	    strBloc+=yytext;
    	strParam+=yytext;
		Utility.assert(str1.Length == yytext.Length - 2, "Error on '\"'");
//		Console.WriteLine( "String " + yytext);
		break;
	}
}
<STFUNCTION> \"{STRING_TEXT} {
//	string str =  yytext.Substring(1,yytext.Length);

	    strBloc+=yytext;
    	strParam+=yytext;

//	Console.WriteLine( "String " + yytext);

//	Utility.error(yyline,Utility.E_UNCLOSEDSTR);
	Utility.assert(false,"Unclosed string");
	break;
//	YyLine = yyline; return 41;
}

<STFUNCTION> {BLOC_FUNCTION} {
	strBloc+=yytext;
	strParam+=yytext;
	break;
}


<INITIAL> "#" { BEGIN(COMMENTSHARP);break; }
<INITIAL> "/*" { BEGIN(COMMENT); comment_count = comment_count + 1;break; }

<COMMENTSHARP> "\n" { BEGIN(INITIAL);break; }

<COMMENT> "/*" { comment_count = comment_count + 1;break; }
<COMMENT> "*/" {
	comment_count = comment_count - 1;
	Utility.assert(comment_count >= 0, "To much ')'");
	if (comment_count == 0) {
    		BEGIN(INITIAL);

	}
	break;
}
<COMMENTSHARP> {COMMENT_TEXT_SHARP} { }
<COMMENT> {COMMENT_TEXT} { }

<INITIAL> \"{STRING_TEXT}\" {
	string str =  yytext.Substring(1,yytext.Length - 2);

	Utility.assert(str.Length == yytext.Length - 2, "Error on '\"'");
//	Console.WriteLine( "String " + yytext);
	isOperator = false; YyLine = yyline; return E_STRING;
}
<INITIAL> \"{STRING_TEXT} {
//	string str =  yytext.Substring(1,yytext.Length);

//	Console.WriteLine( "String " + yytext);

//	Utility.error(yyline,Utility.E_UNCLOSEDSTR);
	Utility.assert(false,"Unclosed string");
	break;
//	YyLine = yyline; return 41;
}
/*<INITIAL> -?({WHITE_SPACE_CHAR})*{DIGIT}+ {*/
<INITIAL> {DIGIT}+ {
	isOperator = false; YyLine = yyline; return E_INTEGER;
}
/*<INITIAL> -?({WHITE_SPACE_CHAR})*{DIGIT}+"."{DIGIT}+ {*/
<INITIAL> {DIGIT}+"."{DIGIT}+ {
	isOperator = false; YyLine = yyline; return E_FLOAT;
}
<INITIAL> {IDENT} {
	isOperator = false; YyLine = yyline; return E_IDENT;
}
<INITIAL> {DIGIT}+"."{DIGIT}+"."{DIGIT}+"."{DIGIT}+ {
	isOperator = false; YyLine = yyline; return E_IP;
}
<INITIAL> {VAR} {
	isOperator = false; YyLine = yyline; return E_VAR;
}
<INITIAL,COMMENT> . {
    System.Console.WriteLine("Illegal character: <" + yytext + "> at line #" + yyline);
	Utility.error(yyline,Utility.E_UNMATCHED);
	break;
}

%%
/* bool comment_sharp = false; */
int comment_count = 0;
int brack_count = 0;
int par_count = 0;
string strParam = "";
public string strBloc = "";
string myFunc = "";
bool isOperator = false;
public int YyLine = 0;
public System.Collections.ArrayList args = new System.Collections.ArrayList();
/*
class Sample {
    public static void Main(string[] argv)  {
        try
        {
            int tok;
            FileStream file = new FileStream("LFSLapper.cfg", FileMode.Open);
            Scanner scnr = new Scanner(file);
             do {
                 tok = scnr.yylex();
                 Console.WriteLine("#"+tok + ": " + scnr.yytext);
             } while (tok > (int)Tokens.EOF);
        }
        catch (System.Exception e)
        {
            Console.WriteLine(e.Message);
        }
                Console.ReadKey();
    }

}
*/
public const int E_END = 0;
public const int E_DOUBLEDOT = 1;
public const int E_SEMICOLON = 2;
public const int E_PAR_OPEN = 3;
public const int E_PAR_CLOSE = 4;
public const int E_BRACKET_OPEN = 5;
public const int E_BRACKET_CLOSE = 6;
public const int E_POINT = 9;
public const int E_PLUS = 10;
public const int E_MOINS = 11;
public const int E_MULT = 12;
public const int E_DIV = 13;
public const int E_EQUAL = 14;
public const int E_DIFF = 15;
public const int E_LESS = 16;
public const int E_LESS_EQUAL = 17;
public const int E_MORE = 18;
public const int E_MORE_EQUAL = 19;
public const int E_AND = 20;
public const int E_OR = 21;
public const int E_POW = 22;
public const int E_COLON = 24;
public const int E_INTEGER = 50;
public const int E_STRING = 40;
public const int E_ASSIGN = 42;
public const int E_IDENT = 43;
public const int E_IP = 45;
public const int E_FLOAT = 46;
public const int E_VAR = 47;
public const int E_BLOC = 48;
public const int E_BEGIN_FUNCTION = 100;
public const int E_END_FUNCTION = 101;
public const int E_IF = 102;
public const int E_THEN = 103;
public const int E_ELSE = 104;
public const int E_ENDIF = 105;
public const int E_GLOBALVAR = 106;
public const int E_PLAYERVAR = 107;
public const int E_WHILE = 108;
public const int E_ENDWHILE = 109;
public const int E_FOR = 110;
public const int E_ENDFOR = 111;
public const int E_BREAK = 112;
public const int E_SWITCH = 113;
public const int E_ENDSWITCH = 114;
public const int E_CASE = 115;
public const int E_DEFAULT = 116;
public const int E_BOOL_AND = 117;
public const int E_BOOL_OR = 118;
public const int E_LANG = 119;
public const int E_ENDLANG = 120;
public const int E_FOREACH = 121;
public const int E_ENDFOREACH = 122;
public const int E_IN = 123;
public const int E_CONST = 124;
public const int E_ARVAR = 125;
public const int E_FUNCTION = 126;
public const int E_NOT = 127;
public const int E_NEG = 128;
public const int E_POS = 129;
class Utility {
  public static void assert( bool expr, string errMsg )
  {
		if (false == expr) {
		  throw (new System.Exception("Error: " + errMsg));
		}
  }
  private static readonly string[] errorMsg =new string[] {
    "Error: Unmatched end-of-comment punctuation.",
    "Error: Unmatched start-of-comment punctuation.",
    "Error: Unclosed string.",
    "Error: Illegal character."
    };

  public const int E_ENDCOMMENT = 0;
  public const int E_STARTCOMMENT = 1;
  public const int E_UNCLOSEDSTR = 2;
  public const int E_UNMATCHED = 3;
  

  public static void error(int yy,int code)
      {
	System.Console.WriteLine(errorMsg[code] + " at line #" + yy);
      }
}


