%{

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "y.tab.h"

int line_nr;
char *tmp_var_name;

typedef enum { 
              probably_in_assignment,
	      in_assignment,
	      out_of_assignment
} state_t;

state_t state;

char *new_string(char *s, int n);
char *new_cstring(char *s, int n);
char *new_var_name(char *s, int n);

%}

interpreter     "#!"[^\n]*
comment		[#][^\n]*
identifier	[A-Za-z_][A-Za-z0-9_]*
integer		[0-9]+
float           [0-9]*[\.]{integer}
string 		["][^"]*["]
perlstring      ['][^']*[']
variable	"$"{identifier}

%%

{interpreter}         { printf("/* perl interpreter was: \"%s\" */", yytext+2); }
{comment}             { printf("/* %s */", yytext+1); }
[ ]+                  { /*skip */ }
"\t"                  { printf("\t"); }
"\n"                  { ++line_nr; state = out_of_assignment; printf("\n"); }
"<"                   { return('<');      }
">"                   { return('>');      }
"="                   { if(state==probably_in_assignment)
                           state=in_assignment;
                        return('=');      }
">="                  { return(GE);       }
"<="                  { return(LE);       }
"!="                  { return(NE);       }
"=="                  { return(EQ);       }
"&&"                  { return(AND);      }
"||"                  { return(OR);       }
"!"                   { return(NOT);      }
"++"                  { return(INCR);     }
"--"                  { return(DECR);     }
for                   { return(FOR);      }
while                 { return(WHILE);    }
if                    { return(IF);       }
else                  { return(ELSE);     }
print                 { return(PRINT);    }
"<STDIN>"             { return(INPUT);    }
{identifier}  	      { yylval.str_value = new_string(yytext, yyleng); 
	                return(IDENTIFIER); }
{integer}             { if(state==in_assignment)
                        {
			  make_var(tmp_var_name, "int");
			  state = out_of_assignment;
			}
                        yylval.str_value = new_string(yytext, yyleng); 
			return(INTEGER);  }
{float}               { if(state==in_assignment)
                        {
			  make_var(tmp_var_name, "float");
			  state = out_of_assignment;
			}
                        yylval.str_value = new_string(yytext, yyleng); 
			return(FLOAT);  }

{string}  	      { if(state==in_assignment)
                        {
			  make_var(tmp_var_name, "char *");
			  state = out_of_assignment;
			}
                        yylval.str_value = new_string(yytext, yyleng); 
			return(STRING);   }
{perlstring}          { yylval.str_value = new_cstring(yytext, yyleng);
			return(STRING);   }
{variable}            { if( state == out_of_assignment )
                        {
			   tmp_var_name = new_var_name(yytext, yyleng);
			   state = probably_in_assignment;
			}
			else if( state == in_assignment )
			{
			   make_var(tmp_var_name, get_type(yytext+1));
			   state = out_of_assignment;
			}
			yylval.str_value = new_string(yytext+1, yyleng-1);
                        return(VARIABLE); }
.		      { return yytext[0]; }

%%

/* no wrap, thanks */
int yywrap(void) { return 1; }

/* allocate a new string of the given length and text */
char *new_string(char *s, int n) {
	char *t = malloc(n+1);
	strncpy(t, s, n);
	t[n]='\0';
	return t;
}

/* allocate a new string of the given length and text
 * repalcing ' with " to have C string format
 */
char *new_cstring(char *s, int n) {
	char *t = malloc(n+1);
	strncpy(t, s, n);
	t[0] = '"';
	t[n-1] = '"';
	t[n]='\0';
	return t;
}

char *new_var_name(char *s, int n) {
	char *t = malloc(n);
	strncpy(t, s+1, n-1);
	t[n-1]='\0';
	return t;
}



syntax highlighted by Code2HTML, v. 0.9.1