%{

/***************************************/

/*
 *		'D' Tokeniser module
 * Version	0.0.0.0 GPL (alpha)
 * Copyright	C.R.Chafer 2002/6/11
 * Author	C.R.Chafer
 * Contact	c.chafer@herts.ac.uk
 * License	GPL v2 (www.fsf.org)
 *		(contact me for versions
 *		 under other licenses)
 *
 */

/***************************************/

/*
 * Notes:	This is not to be assumed
 *		definitive - see
 *		http://www.digitalmars.com
 *		for definitive D spec
 */

/***************************************/

#include "d.h"
#include "y.tab.h"

/***************************************/

#define YY_NO_UNPUT

/***************************************/

static	U32	lineNumberIncrement = 1	;
static	U32	lineNumber = 0		;

/***************************************/

	void	lineInc()		{ ++lineNumberIncrement; return; }
	void	lineUpdate()		{ lineNumber+=lineNumberIncrement; lineNumberIncrement=0; return; }
	U32	getLine()		{ return lineNumber; }
	U32	getLineInc()		{ return lineNumberIncrement; }
	void	setInput( s ) CH*s;	{ if( !(yyin=fopen(s,"rb")) ) printError( "Unable to open input", s, 0 ); return; }
static	char*	convertString( char*s )	{ return s; /* later convert unprintable letters to escapes */ }
static	U32	getInt( char*s, int l )	{ return strtol( s, 0, l ); }
static	F64	getFloat( char*s )	{ return atof( s ); }
static	F64	hexFloat( char*s )	{ return 1.0;	/* later convert */ }
static	int	suffix( char*s )	{ return _I;/* have to extend these later (uUlL/fFiIlL) */ }
static	int	floatSuffix( char*s )	{ while( *s++ ) if( *s=='i' || *s=='I' ) return _J; return _F; }
	int	yywrap( void )		{ return 1; }
	int	yyerror( char*s )	{ printError( s, convertString( yytext ), 0 ); return 0; }

/***************************************/

%}

%%

<<EOF>>					{ return _EOF		;}
[ \t\r]+				{ /* whitespace */	;}
\n					{ lineInc()		;}
"//"[^\n]*				{ /* line comment */	;}
"/*"								{ /* multi line comment #1 */
		S32 c1 = 0, c2 = 0
	;	while( !( c1 == '*' && c2 == '/' ) )
	{	if( c2 == EOF ) printError( "Unexpected end of file within comment", 0, 0 )
	 ;	if( c1 == '[' && c2 == '`' ) printError( "Found comment header '/*' within comment", 0, 0 )
	 ;	if( c1 == '\n' ) lineInc()
	 ;	c1 = c2
	 ;	c2 = input()
	;}							}
"/+"								{ /* multi line comment #2 (nestable) */
		S32 c1 = 0, c2 = 0, c3 = 2
	;	while( -- c3 )
	;	while( !( c1 == '+' && c2 == '/' ) )
	{	if( c2 == EOF ) printError( "Unexpected end of file within comment", 0, 0 )
	 ;	if( c1 == '/' && c2 == '+' ) ++ c3
	 ;	if( c1 == '\n' ) lineInc()
	 ;	c1 = c2
	 ;	c2 = input()
	;}							}
\"([^"\n]|\\\")*\"						{ /* string constant - double quoted */
		CH*s=yytext
	;	while( *s++ )
	;	*(s-2)=0
	;	yylval.s=newString( yytext+1 )
	;	return _S					;}
\'[^'\n]*\'							{ /* string constant - single quoted */
		CH*s=yytext
	;	while( *s++ )
	;	*(s-2)=0
	;	yylval.s=newStringNoEsc( yytext+1 )
	;	return _S					;}
\"([^"\n]|\\["\n])*\n						{ printError( "Unterminated string constant",0,0 ); }
\'[^\n]*\n							{ printError( "Unterminated character constant",0,0 ); }
\\x[0-9a-fA-F][0-9a-fA-F]					{ /* escape sequence */
		yylval.s=newString( yytext )
	;	return _S					;}
\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]			{ /* escape sequence */
		yylval.s=newString( yytext )
	;	return _S					;}
\\[0-7]([0-7][0-7]?)?						{ /* escape sequence */
		yylval.s=newString( yytext )
	;	return _S					;}
\\[abfnrtv'"?]							{ /* escape sequence */
		yylval.s=newString( yytext )
	;	return _S					;}
0[bB][01]+[lLuU]*						{ /* number/binary */
		yylval.i = getInt( yytext+2, 2 )
	;	return suffix( yytext )				;}
0[0-7]+[lLuU]*							{ /* number/octal */
		yylval.i = getInt( yytext, 8 )
	;	return suffix( yytext )				;}
[0-9]+[lLuU]*							{ /* number/decimal */
		yylval.i = getInt( yytext, 10 )
	;	return suffix( yytext )				;}
0[xX][0-9a-fA-F]+[lLuU]*					{ /* number/hexadecimal */
		yylval.i = getInt( yytext+2, 16 )
	;	return suffix( yytext )				;}
[0-9][0-9a-fA-F]*[hH][lLuU]*					{ /* number/hexadecimal */
		yylval.i = getInt( yytext, 16 )
	;	return suffix( yytext )				;}
([0-9][0-9]*\.[0-9]+)([eE][+-]?[0-9]+)?[iIfFlL]*		{ /* number/float */
		yylval.f = getFloat( yytext )
	;	return floatSuffix( yytext )			;}
0[xX][0-9a-fA-F]*(\.[0-9a-fA-F]+)?[pP][+-]?[0-9]+[iIfFlL]*	{ /* number/hex_float */
		yylval.f = hexFloat( yytext )
	;	return floatSuffix( yytext )			;}
"this"			{ return _this		;}
"super"			{ return _super		;}
"assert"		{ return _assert	;}
"null"			{ return _null		;}
"true"			{ return _true		;}
"false"			{ return _false		;}
"cast"			{ return _cast		;}
"new"			{ return _new		;}
"delete"		{ return _delete	;}
"throw"			{ return _throw		;}
"void"			{ return _void		;}
"byte"			{ return _byte		;}
"ubyte"			{ return _ubyte		;}
"short"			{ return _short		;}
"ushort"		{ return _ushort	;}
"int"			{ return _int		;}
"uint"			{ return _uint		;}
"long"			{ return _long		;}
"ulong"			{ return _ulong		;}
"cent"			{ return _cent		;}
"ucent"			{ return _ucent		;}
"float"			{ return _float		;}
"double"		{ return _double	;}
"extended"		{ return _extended	;}
"bit"			{ return _bit		;}
"char"			{ return _char		;}
"wchar"			{ return _wchar		;}
"imaginary"		{ return _imaginary	;}
"complex"		{ return _complex	;}
"if"			{ return _if		;}
"else"			{ return _else		;}
"while"			{ return _while		;}
"for"			{ return _for		;}
"do"			{ return _do		;}
"switch"		{ return _switch	;}
"case"			{ return _case		;}
"default"		{ return _default	;}
"break"			{ return _break		;}
"continue"		{ return _continue	;}
"synchronized"		{ return _synchronized	;}
"return"		{ return _return	;}
"goto"			{ return _goto		;}
"try"			{ return _try		;}
"catch"			{ return _catch		;}
"finally"		{ return _finally	;}
"with"			{ return _with		;}
"struct"		{ return _struct	;}
"class"			{ return _class		;}
"interface"		{ return _interface	;}
"union"			{ return _union		;}
"enum"			{ return _enum		;}
"import"		{ return _import	;}
"static"		{ return _static	;}
"final"			{ return _final		;}
"const"			{ return _const		;}
"typedef"		{ return _typedef	;}
"alias"			{ return _alias		;}
"override"		{ return _override	;}
"abstract"		{ return _abstract	;}
"debug"			{ return _debug		;}
"version"		{ return _version	;}
"deprecated"		{ return _deprecated	;}
"in"			{ return _in		;}
"out"			{ return _out		;}
"inout"			{ return _inout		;}
"align"			{ return _align		;}
"extern"		{ return _extern	;}
"private"		{ return _private	;}
"protected"		{ return _protected	;}
"public"		{ return _public	;}
"export"		{ return _export	;}
"body"			{ return _body		;}
"invariant"		{ return _invariant	;}
"asm"			{ return _asm		;}
"delegate"		{ return _delegate	;}

"/"			{ return '/'		;}
"/="			{ return _DIVE		;}
"."			{ return '.'		;}
".."			{ return _DOT2		;}
"..."			{ return _DOT3		;}
"&"			{ return '&'		;}
"&="			{ return _ANDE		;}
"&&"			{ return _ANDB		;}
"|"			{ return '|'		;}
"|="			{ return _IORE		;}
"||"			{ return _IORB		;}
"-"			{ return '-'		;}
"-="			{ return _SUBE		;}
"--"			{ return _DEC		;}
"+"			{ return '+'		;}
"+="			{ return _ADDE		;}
"++"			{ return _INC		;}
"<"			{ return '<'		;}
"<="			{ return _LEQ		;}
"<<"			{ return _SHL		;}
"<<="			{ return _SHLE		;}
"<>"			{ return _GLS		;}
"<>="			{ return _GLSE		;}
">"			{ return '>'		;}
">="			{ return _GEQ		;}
">>="			{ return _SHRE		;}
">>>="			{ return _SARE		;}
">>"			{ return _SHR		;}
">>>"			{ return _SAR		;}
"!"			{ return '!'		;}
"!="			{ return _NEQU		;}
"!=="			{ return _NEQUR		;}
"!==="			{ return _NEQUV		;}
"!<>"			{ return _NGLS		;}
"!<>="			{ return _NGLSE		;}
"!<"			{ return _NLES		;}
"!<="			{ return _NLEQ		;}
"!>"			{ return _NGRT		;}
"!>="			{ return _NGEQ		;}
"("			{ return '('		;}
")"			{ return ')'		;}
"["			{ return '['		;}
"]"			{ return ']'		;}
"{"			{ return '{'		;}
"}"			{ return '}'		;}
"?"			{ return '?'		;}
","			{ return ','		;}
";"			{ return ';'		;}
":"			{ return ':'		;}
"$"			{ return '$'		;}
"="			{ return '='		;}
"=="			{ return _EQU		;}
"==="			{ return _EQUR		;}
"*"			{ return '*'		;}
"*="			{ return _MULE		;}
"%"			{ return '%'		;}
"%="			{ return _MODE		;}
"^"			{ return '^'		;}
"^="			{ return _XORE		;}
"~"			{ return '~'		;}
"~="			{ return _CAT		;}
[a-zA-Z_][a-zA-Z0-9_]*				{ yylval.s=newSymbol( yytext ); return _V; /* identifier */	}
.						{ printError( "Unexpected symbol", convertString( yytext ), 0 );}

%%


