O                       [0-7]
D                       [0-9]
L                       [a-zA-Z_]
H                       [a-fA-F0-9]
E                       [Ee][+-]?{D}+
FS                      (f|F|l|L)
IS                      (u|U|l|L)
W                       [ \t\f]*
LIT                     \"(\\.|[^\\"])*\"

%{
#include 
#include 
#include 
#include 
#ifndef TESTLEX
#include "tree.h"
#include "token.h"
#include "symtab.h"
#endif
#ifdef __BORLANDC__
#include "ytab.h"
#else
#include "y.tab.h"
#endif

int comment();
int line_num = 1;
char lastid[256];
%}

%%

"/*"                    { comment(); }

^{W}#.*\n               { yyerror("Godiva has no #preprocessor direcives. Are you feeding it C/C++ code?"); }

\n                      { }
[ \t\f]+                { }

"abstract"		{ yylval.node = alcnode(ABSTRACT, 0); return ABSTRACT;}
"bvector"               { return BVECTOR; }
"bigint"                { return BIGINT; }
"boolean"               { return BOOLEAN; }
"break"                 { return BREAK; }
"byte"                  { return BYTE; }
"case"                  { return CASE; }
"catch"                 { return CATCH; }
"char"                  { return CHAR; }
"class"                 { return CLASS; }
"const"                 { return CONST; }
"continue"              { return CONTINUE; }
"default"               { return DEFAULT; }
"do"                    { return DO; }
"double"                { return DOUBLE; }
"else"                  { return ELSE; }
"extends"               { return EXTENDS; }
"final"                 { return FINAL; }
"finally"               { return FINALLY; }
"float"                 { return FLOAT; }
"for"                   { return FOR; }
"goto"                  { return GOTO; }
"if"                    { return IF; }
"implements"            { return IMPLEMENTS; }
"import"                { return IMPORT; }
"instanceof"            { return INSTANCEOF; }
"int"                   { return INT; }
"interface"             { return INTERFACE; }
"list"                  { return LIST; }
"long"                  { return LONG; }
"native"                { return NATIVE; }
"new"                   { return NEW; }
"package"               { return PACKAGE; }
"private"               { return PRIVATE; }
"protected"             { return PROTECTED; }
"public"                { return PUBLIC; }
"return"                { return RETURN; }
"set"                   { return SET; }
"short"                 { return SHORT; }
"static"                { return STATIC; }
"string"                { return STRING;}
"super"                 { return SUPER; }
"suspend"               { return SUSPEND; }
"switch"                { return SWITCH; }
"synchronized"          { return SYNCHRONIZED; }
"table"                 { return TABLE; }
"this"                  { return THIS; }
"throw"                 { return THROW; }
"throws"                { return THROWS; }
"transient"             { return TRANSIENT; }
"try"                   { return TRY; }
"void"                  { return VOID; }
"volatile"              { return VOLATILE; }
"while"                 { return WHILE; }

"null"                  { return NULLLITERAL; }

"true"                  { return BOOLLITERAL; }
"false"                 { return BOOLLITERAL; }
{L}({L}|{D})*           { yylval.node = alcnode(IDENT, 0);
			  yylval.node->u.leaf.symbol =
				insert_globalst(yytext);
			  return IDENT; }

0[xX]{H}+{IS}?          { return INTLITERAL; }
0{O}+{IS}?              { return INTLITERAL; }
{D}+{IS}?               { return INTLITERAL; }

'(\\.|[^\\'])+'         { return CHARLITERAL; }

{D}+{E}{FS}?            { return FLOATLITERAL; }
{D}*"."{D}+({E})?{FS}?  { return FLOATLITERAL; }
{D}+"."{D}*({E})?{FS}?  { return FLOATLITERAL; }

{LIT}                   { return STRINGLITERAL; }

"("                     { return LP; }
")"                     { return RP; }
"{"                     { return LC; }
"}"                     { return RC; }
"["                     { return LB; }
"]"                     { return RB; }
";"                     { return SM; }
","                     { return CM; }
"."                     { return DOT; }


"="                     { return ASN; }
"<"                     { return LT; }
">"                     { return GT; }
"!"                     { return BANG; }
"~"                     { return TILDE; }
"?"                     { return QUEST; }
":"                     { return COLON; }
"=="                    { return EQ; }
"!="                    { return NE; }
"<="                    { return LE; }
">="                    { return GE; }
"&&"                    { return ANDAND; }
"||"                    { return OROR; }
"++"                    { return INC; }
"--"                    { return DEC; }
"+"                     { return PLUS; }
"-"                     { return MINUS; }
"*"                     { return MUL; }
"/"                     { return DIV; }
"&"                     { return AND; }
"|"                     { return OR; }
"^"                     { return CARET; }
"%"                     { return MOD; }
"<<"                    { return SHL; }
">>"                    { return SHR; }
">>>"                   { return LSHR; }
"+="                    { return PLASN; }
"-="                    { return MIASN; }
"*="                    { return MUASN; }
"/="                    { return DIASN; }
"&="                    { return ANDASN; }
"|="                    { return ORASN; }
"^="                    { return CARETASN; }
"%="                    { return MODASN; }
"<<="                   { return SLASN; }
">>="                   { return SRASN; }
">>>="                  { return LSRASN; }

.                       { yyerror("lexical error"); }

%%

char *yyfilename = NULL;
int yychar;
int errors;

yyerror(char *s)
{
   errors++;

   fprintf(stderr, "%s: ", s);

   if (yyfilename)
      fprintf(stderr, "file \"%s\", ", yyfilename );

   fprintf(stderr, "line %d, token = \"%s\"\n", yylineno, yytext);
   exit(1);
}

comment()
{
	
	int splat_seen = 0;

	for(;;) {
	   int ch = input();
	   switch (ch) {
	      default:
		 splat_seen = 0;
					  break;
	      case '*':
		 splat_seen = 1;
		 break;
	      case '/':
		 if(splat_seen)
						  return;
		 else
		    splat_seen = 0;
		 break;
				  case 0: {
		   yychar = BAD_TOKEN;
		   yyerror("Unterminated comment");
		   exit(-(++errors));
	       }
	   }

	}

}

#ifndef yywrap

int yywrap(){
    return 1;
}

#endif


lex_sync()
{
    /* Probably because of its use for interactive line-interpreters
     * like "dc", original yacc uses a "lazy" lookahead, that is to say, it
     * does not fetch a lookahead when the only action is the default
     * reduction. But our scanner-feedback must keep the lookahead in
     * sync. This routine sees to it that the lookahead has been
     * fetched.
     *
     * yychar is the yacc lookahead token. It is -1 when
     * yacc is being "lazy". yylex() is allowed to return -1 (or any
     * negative int) to indicate EOF, but yacc uses 0 to indicate EOF.
     */
    
    if(yychar == -1)
      if((yychar = yylex()) < 0)
	      yychar = 0;
}

#ifdef TESTLEX
void main(int argc, char *argv[])
{
   int t;
   yyin = fopen(argv[1], "r");
   if (yyin == NULL) {
      fprintf(stderr, "can't open %s\n", argv[1]);
      exit(1);
      }

   t = yylex();
   while ( t >= 0 ) { /* while not EOF */
/*      printf("%s\t", yytokenname); */
      switch (t) {
         /* cases which write out appropriate attributes for t, such as */
         case INT:
	    printf("%d", yytext);
	    break;
	 default:
	    printf("TOKEN %d", t);
	    break;
	    }
      printf("\n");
      t = yylex();
      }
}
#endif