%{

// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#include <stdlib.h>
#include <errno.h>

#include <OB/CORBA.h>
#include <Types.h>
#include <Util.h>
#include <Gram.h>
#include <GramUtil.h>

extern long IdlLineno;

static const char* IntOutOfRange = "integer constant out of range";
static const char* FloatOutOfRange = "floating point constant out of range";

%}

%option noyywrap
%option never-interactive

WS                      [ \t\v\n\r\f]
S			[ \t]
D			[0-9]
L			[a-zA-Z_]
HEX			[a-fA-F0-9]
OCT			[0-7]
EXP			[Ee][+-]?{D}+
FS			[lLfF]
IS			[lLuU]

%%

"#"{S}*{D}+{S}*\n       {
			    IdlLineno++;
			    IdlParseLineAndFile(yytext);
			}

"#"{S}*{D}+{S}+"\""[^\"]*"\"".*\n {
			    IdlLineno++;
			    IdlParseLineAndFile(yytext);
			}

"#"{S}*"line"{S}+{D}+{S}*\n {
			    IdlLineno++;
			    IdlParseLineAndFile(yytext);
			}

"#"{S}*"line"{S}+{D}+{S}+"\""[^\"]*"\"".*\n {
			    IdlLineno++;
			    IdlParseLineAndFile(yytext);
			}

"#"{S}*"pragma".*\n	{
			    IdlLineno++;
			    yylval.string = CORBA_string_dup(yytext);
                            return IDL_PRAGMA;
			}

"#"{S}*{D}+{S}+"$pragma".*\n {
			    IdlLineno++;
			    yylval.string = CORBA_string_dup(yytext);
                            return IDL_PRAGMA;
			}

"//"			{
                            // C++-style comment

                            int c;

                            do
			    {
				c = yyinput();

				if(c == '\n')
				    IdlLineno++;
			    }
			    while(c != '\n' && c != EOF);
                        }

"/*"			{
                            // C-style comment

                            CORBA_String_var doc = CORBA_string_dup("");

                            while(true)
			    {
				int c = yyinput();

				if(c == '\n')
				{
				    IdlLineno++;
				    doc += (char)c;
				}
				else if(c == '*')
				{
				    int next = yyinput();

				    if(next == '/')
					break;
				    else
				    {
					unput(next);
					doc += (char)c;
				    }
				}
				else if(c == EOF)
				{
				    IdlWarning( "EOF in comment" );
				    break;
				}
				else
				    doc += (char)c;
			    }

			    IdlParseComment(doc);
			}

"any"                   { return IDL_ANY; }
"attribute"             { return IDL_ATTRIBUTE; }
"boolean"               { return IDL_BOOLEAN; }
"case"                  { return IDL_CASE; }
"char"                  { return IDL_CHAR; }
"const"                 { return IDL_CONST; }
"context"               { return IDL_CONTEXT; }
"default"               { return IDL_DEFAULT; }
"double"                { return IDL_DOUBLE; }
"enum"                  { return IDL_ENUM; }
"exception"             { return IDL_EXCEPTION; }
"float"                 { return IDL_FLOAT; }
"in"                    { return IDL_IN; }
"inout"                 { return IDL_INOUT; }
"interface"             { return IDL_INTERFACE; }
"long"                  { return IDL_LONG; }
"module"                { return IDL_MODULE; }
"octet"                 { return IDL_OCTET; }
"oneway"                { return IDL_ONEWAY; }
"out"                   { return IDL_OUT; }
"raises"                { return IDL_RAISES; }
"readonly"              { return IDL_READONLY; }
"sequence"              { return IDL_SEQUENCE; }
"short"                 { return IDL_SHORT; }
"string"                { return IDL_STRING; }
"struct"                { return IDL_STRUCT; }
"switch"                { return IDL_SWITCH; }
"typedef"               { return IDL_TYPEDEF; }
"unsigned"              { return IDL_UNSIGNED; }
"union"                 { return IDL_UNION; }
"void"                  { return IDL_VOID; }

"TRUE"                  {
                            yylval.booleanVal = true;
			    return IDL_TRUE;
                        }

"FALSE"                 {
                            yylval.booleanVal = false;
			    return IDL_FALSE;
                        }

{L}({L}|{D})*           {
			    yylval.string = CORBA_string_dup(yytext);
                            return IDL_IDENTIFIER;
		        }

0[xX]{HEX}+{IS}?	{
                            yylval.uLongVal = strtoul(yytext + 2, 0, 16);
			    if(errno == ERANGE)
				IdlWarning(IntOutOfRange);
                            return IDL_INTEGER_LITERAL;
                        }

0{OCT}+{IS}?		{
                            yylval.uLongVal = strtoul(yytext + 1, 0, 8);
			    if(errno == ERANGE)
				IdlWarning(IntOutOfRange);
                            return IDL_INTEGER_LITERAL;
			}

{D}+{IS}?		{
                            yylval.uLongVal = strtoul(yytext, 0, 10);
			    if(errno == ERANGE)
				IdlWarning(IntOutOfRange);
                            return IDL_INTEGER_LITERAL;
			}

"'"\\({OCT}{1,3})"'"	{
                            CORBA_String_var s = CORBA_string_dup(yytext);
			    IdlRemoveEscapes(s.inout(), false);
			    yylval.charVal = s[1];
                            return IDL_CHARACTER_LITERAL;
			}

"'"\\x({HEX}{1,2})"'"	{
                            CORBA_String_var s = CORBA_string_dup(yytext);
			    IdlRemoveEscapes(s.inout(), false);
			    yylval.charVal = s[1];
                            return IDL_CHARACTER_LITERAL;
			}

"'"\\."'"		{
                            CORBA_String_var s = CORBA_string_dup(yytext);
			    IdlRemoveEscapes(s.inout(), false);
			    yylval.charVal = s[1];
                            return IDL_CHARACTER_LITERAL;
			}

"'"."'"			{
			    yylval.charVal = yytext[1];
                            return IDL_CHARACTER_LITERAL;
			}

{D}+{EXP}{FS}?		{
                            yylval.doubleVal = strtod(yytext, 0);
			    if(errno == ERANGE)
				IdlWarning(FloatOutOfRange);
                            return IDL_FLOATING_PT_LITERAL;
			}

{D}*"."{D}+{EXP}?{FS}?  {
                            yylval.doubleVal = strtod(yytext, 0);
			    if(errno == ERANGE)
				IdlWarning(FloatOutOfRange);
                            return IDL_FLOATING_PT_LITERAL;
			}

{D}+"."{D}*{EXP}?{FS}?	{
                            yylval.doubleVal = strtod(yytext, 0);
			    if(errno == ERANGE)
				IdlWarning(FloatOutOfRange);
                            return IDL_FLOATING_PT_LITERAL;
			}

"\""([^\"]|"\\\"")*"\""	{
                            for(int i = 0 ; yytext[i] ; i++)
				if(yytext[i] == '\n')
				    IdlLineno++;

			    yylval.string = CORBA_string_dup(yytext);
	                    return IDL_STRING_LITERAL;
			}

"<<"			{ return IDL_LEFT_SHIFT; }
">>"			{ return IDL_RIGHT_SHIFT; }
"::"			{ return IDL_SCOPE_DELIMITOR; }

{WS}    	      	{
			    // Igore white-space

			    if(yytext[0] == '\n')
				IdlLineno++;
			}

.               	{ return yytext[0]; }

%%
