/* -*-c++-*- */

%{
// ruri - ruri language compiler
// Copyright 2000 Tom Rothamel <tom-ruri@onegeek.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  

// This is a program that generates another program. As an exemption,
// the output file does not need to be placed under the GPL, provided
// that the following paragraph is placed in the generated output. Please
// note that this is not an authorization to modify this program to cause
// it to output more of itself in order to circumvent my copyright.
//
// 	This program contains code Copyright 2000 Tom Rothamel.
//	It is provided without warranty, and may be redistributed 
//	and used in modified or unmodified form, provided this 
//	copyright notice is retained in the source code.

#include <string>
#include "parse.h"	
#include "parser_core.h"
%}

%option noyywrap
%option yylineno

ISTART [A-Za-z_]
IBODY [A-Za-z0-9_]
DIGIT [0-9]
HEXDIGIT [0-9A-Fa-f]
NEG -

%x str

%%

\/\/.+\n 

emit { return EMIT; }

word { return WORD; }
main { return MAIN; }
method { return METHOD; }

in { return IN; }
const { return CONST; }
out { return OUT; }
return { return RETURN; }

true { return TRUE; }
false { return FALSE; }

if { return IF; }
else { return ELSE; }
while { return WHILE; }
for { return FOR; }

continue { return CONTINUE; }
break { return BREAK; }

halt { return HALT; }
err { return ERR; }

pop { return POP; }
push { return PUSH; }
alloca { return ALLOCA; }

goto { return GOTO; }
asm { return ASM; }

\<\< { return SHL; }
\=\= { return EQUALS; }
\|\| { return LOGOR; }
\&\& { return LOGAND; }


\" { BEGIN(str); }
<str>[^\"]+ { yymore(); } 
<str>\" {
	BEGIN(INITIAL);

	string s;
	char *c = yytext;
	
	while (*c) {
		switch (*c) {
		case '"':
			goto done;
		case '\\':
			c++;
			switch(*c) {
			case 0:
				goto done;
			case 'n':
				s += '\n';
				break;
			case 't':
				s += '\t';
				break;
			case 'b':
				s += '\b';
				break;
			default:
				s += *c;
			}
			break;
		default:
			s += *c;
		}

		c++;
	}

 done:
	yylval.s = new string(s);
	return STRING;
}

0x{HEXDIGIT}+ {
	int n = 0;

	for (int i = 0; i < yyleng; i++) {
		n <<= 4;
		char c = yytext[i];
		
		if ('0' <= c && c <= '9') {
			n += (c - '0');
		}

		if ('A' <= c && c <= 'F') {
			n += 10 + (c - 'A');
		}

		if ('a' <= c && c <= 'f') {
			n += 10 + (c - 'a');
		}
	}

	yylval.i = n;
	return NUMBER;
}

{NEG}?{DIGIT}+ {
	yylval.i = atoi(yytext);
	return NUMBER;
}

'\\n' {
	yylval.i = '\n';
	return NUMBER;
}

'\\t' {
	yylval.i = '\t';
	return NUMBER;
}

'\\b' {
	yylval.i = '\b';
	return NUMBER;
}

'\\\'' {
	yylval.i = '\'';
	return NUMBER;
}

'.' {
	yylval.i = yytext[1];
	return NUMBER;
}

{ISTART}{IBODY}* {
	yylval.s = new string(yytext);
	return NAME;
}

[ \t\r\n]+

. { return yytext[0]; }



%%
