%{
/*******************************************************************************
 *	Scan.l		BEAM IDL Lexical analyser
 *			T.Barnaby, 	BEAM Ltd,	2/5/03
 *******************************************************************************
 */
#include <stdio.h>
#include <string.h>
#include "bidl.h"
#include "cgram.hh"

extern Node*	yylval;
static void	comment0();
static void	comment1();
static void	preProcess();
static void	nextLine();
static void	count();
static int	typeCheck();

#define	DOECHO	0
%}

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)*

%%
"/*"			{ comment0(); }
"//"			{ comment1(); return(COMMENT); }
"#"			{ preProcess(); }
"\n"			{ nextLine(); }

"module"		{ count(); return(MODULE); }
"interface"		{ count(); return(INTERFACE); }
"bidirectional"		{ count(); return(BIDIRECTIONAL); }
"oneway"		{ count(); return(ONEWAY); }
"struct"		{ count(); return(STRUCT); }
"class"			{ count(); return(CLASS); }
"typeDomain"		{ count(); return(TYPEDOMAIN); }
"apiVersion"		{ count(); return(APIVERSION); }
"apiCmd"		{ count(); return(APICMD); }
"enum"			{ count(); return(ENUM); }

"Error"			{ count(); return(ERROR); }
"Bool"			{ count(); return(BOOL); }
"Int8"			{ count(); return(INT8); }
"UInt8"			{ count(); return(UINT8); }
"Int16"			{ count(); return(INT16); }
"UInt16"		{ count(); return(UINT16); }
"Int32"			{ count(); return(INT32); }
"UInt32"		{ count(); return(UINT32); }
"Int64"			{ count(); return(INT64); }
"UInt64"		{ count(); return(UINT64); }
"Char"			{ count(); return(CHAR); }
"String"		{ count(); return(STRING); }
"Double"		{ count(); return(FLOAT64); }
"Float32"		{ count(); return(FLOAT32); }
"Float64"		{ count(); return(FLOAT64); }

"Id"			{ count(); return(ID); }
"Date"			{ count(); return(DATE); }
"Time"			{ count(); return(TIME); }
"DateTime"		{ count(); return(DATETIME); }
"TimeStamp"		{ count(); return(TIMESTAMP); }
"Complex"		{ count(); return(COMPLEX); }
"Complex32"		{ count(); return(COMPLEX32); }
"Complex64"		{ count(); return(COMPLEX64); }

"List"			{ count(); return(LIST); }
"Array"			{ count(); return(ARRAY); }
"Dict"			{ count(); return(DICT); }

"in"			{ count(); return(IN); }
"inref"			{ count(); return(INREF); }
"out"			{ count(); return(OUT); }
"inout"			{ count(); return(INOUT); }

{L}({L}|{D})*		{ count(); return(typeCheck()); }

0[xX]{H}+{IS}?		{ count(); return(CONSTANT); }
0{D}+{IS}?		{ count(); return(CONSTANT); }
{D}+{IS}?		{ count(); return(CONSTANT); }
'(\\.|[^\\'])+'		{ count(); return(CONSTANT); }

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

\"(\\.|[^\\"])*\"	{ count(); return(STRING_LITERAL); }

";"			{ count(); return(';'); }
"{"			{ count(); return('{'); }
"}"			{ count(); return('}'); }
","			{ count(); return(','); }
":"			{ count(); return(':'); }
"="			{ count(); return('='); }
"("			{ count(); return('('); }
")"			{ count(); return(')'); }
"["			{ count(); return('['); }
"]"			{ count(); return(']'); }
"."			{ count(); return('.'); }
"&"			{ count(); return('&'); }
"!"			{ count(); return('!'); }
"~"			{ count(); return('~'); }
"-"			{ count(); return('-'); }
"+"			{ count(); return('+'); }
"*"			{ count(); return('*'); }
"/"			{ count(); return('/'); }
"%"			{ count(); return('%'); }
"<"			{ count(); return('<'); }
">"			{ count(); return('>'); }
"^"			{ count(); return('^'); }
"|"			{ count(); return('|'); }
"?"			{ count(); return('?'); }

[ \t\v\f]		{ count(); }
.			{ /* ignore bad characters */ }

%%

int	column	= 0;
int	line	= 1;

int yywrap()
{
	return 1;
}

static void comment0(){
	char	c, c1;

#if	DOECHO
loop:
	while ((c = yyinput()) != '*' && c != 0){
		if(c == '\n')
			nextLine();
		putchar(c);
	}

	if ((c1 = yyinput()) != '/' && c != 0)
	{
		unput(c1);
		goto loop;
	}

	if (c != 0)
		putchar(c1);
#else
loop:
	while ((c = yyinput()) != '*' && c != 0){
		if(c == '\n')
			nextLine();
	}

	if ((c1 = yyinput()) != '/' && c != 0) {
		unput(c1);
		goto loop;
	}
#endif
}

static void comment1(){
	char	c;
	BString	comment;

	while((c = yyinput()) != '\n' && c != 0){
		comment = comment + c;
	}

	if(c != 0){
		unput(c);
	}
	yylval = new Node(Node::TCOMMENT, comment);
}

static void preProcess() {
	char	c;
	BString	linestr;
	char	file[256];
	int	lineno;

#if	DOECHO
	ECHO;
	while ((c = yyinput()) != '\n' && c != 0){
		putchar(c);
	if (c == '\n')
		putchar(c);
	}
#else
	while ((c = yyinput()) != '\n' && c != 0)
		linestr = linestr + c;
	file[0] = '\0';
	sscanf(linestr.retStr(), "%d \"%s\"", &lineno, file);
	if(strlen(file))
		file[strlen(file) - 1] = 0;
	line = lineno;
	fileName = file;
#endif

}

static void nextLine(){
	column = 0;
	line++;
#if	DOECHO
	ECHO;
#endif
}

static void count()
{
	int i;

	for (i = 0; yytext[i] != '\0'; i++)
		if (yytext[i] == '\n')
			column = 0;
		else if (yytext[i] == '\t')
			column += 8 - (column % 8);
		else
			column++;

	yylval = new Node(Node::TNONE, yytext);
#if	DOECHO
	ECHO;
#endif
}

/* Check if type exists */
static int typeCheck(){
	if(gtypelist.search(yytext))
		return(TYPE_NAME);
	else
		return(IDENTIFIER);
}
