/****************************************************************************
**
** Lexical analyzer for meta object compiler
**
** Created : 930417
**
** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA.
**
** This file is part of the TQt GUI Toolkit.
**
** This file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the files LICENSE.GPL2
** and LICENSE.GPL3 included in the packaging of this file.
** Alternatively you may (at your option) use any later version
** of the GNU General Public License if such license has been
** publicly approved by Trolltech ASA (or its successors, if any)
** and the KDE Free TQt Foundation.
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** This file may be used under the terms of the TQ Public License as
** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
** included in the packaging of this file.  Licensees holding valid TQt
** Commercial licenses may use this file in accordance with the TQt
** Commercial License Agreement provided with the Software.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
** herein.
**
*****************************************************************************/

%{
#ifdef TQMOC_YACC_CODE

#ifdef TQMOC_MWERKS_PLUGIN
#ifdef TQ_OS_MAC9
# define isascii(c)   ((int)( (unsigned int) (c) <= (unsigned char)0x7F ))
#endif
const char *buf_buffer = NULL;
long buf_size_total = 0, buf_index = 0;
#define YY_INPUT(buf, result, max_size) \
     { \
          if(buf_index < buf_size_total ) { \
              while(!isascii(buf_buffer[buf_index])) buf_index++; \
              int ms = ((max_size < buf_size_total) ? max_size : buf_size_total); \
              for(result = 0; result < ms; result++) { \
                 char c = buf_buffer[buf_index + result]; \
                 if(!isascii(c)) { \
                    buf_index++; \
                    break; \
                 } \
                 buf[result] = c == '\r' ? '\n' : c; \
              } \
              buf_index += result; \
          } else result = YY_NULL; \
     }
#endif

#include "tqstring.h"


#define input yyinput				// yyinput in C++

#define X if(lexDebug){fprintf(stderr,"LEX (%i) : %s\n",lineNo,yytext);};
#define Y if(lexDebug){fprintf(stderr,"LEX (%i) : %s\n",lineNo,yytext);};
/*
#define Y if(lexDebug){fprintf(stderr,"LEX (%i) : %s updates level to %i\n"\
                                 ,lineNo,yytext,templLevel);};
*/
#define Z if(lexDebug){fprintf(stderr,"LEX (%i) : skipped the string %s\"\n"\
                               ,lineNo,yytext);};
#define BEGIN_INSIDE


#define linput() \
    ( (c = input()) == '\n' ? (lineNo++, c) : (c == EOF) ? 0 : c )

#include <string.h>
#include <stdlib.h>

int classPLevel      = 1;  /* Depth of nested curly braces in IN_CLASS */
int namespacePLevel  = 1;  /* Depth of nested curly braces in IN_NAMESPACE */
int expLevel         = 1;  /* Depth of nested parentheses in IN_EXPR */
int enumLevel         = 1;  /* Depth of nested parentheses in IN_ENUM */
int fctLevel         = 1;  /* Depth of nested parentheses in IN_FCT */
int templLevel       = 1;  /* Depth of levels in IN_TEMPL_ARGS */

int lastState        = 0;  /* Remembers the state when a
                              TQMOC_SKIP_BEGIN is encountered */
int skipLevel        = 0; /* Depth of TQMOC_SKIP_BEGINs */

class TQString;

extern void addExpressionChar( const char );
extern void addExpressionString( const char * );
extern void tqmoc_warn( const char *msg );
%}

%start OUTSIDE TQT_DEF IN_CLASS IN_NAMESPACE IN_ENUM IN_EXPR IN_DEF_ARG IN_FCT IN_TEMPL_ARGS GIMME_SEMICOLON SKIP IN_PROPERTY IN_CLASSINFO

ALMOSTSTRING	\"([^"\n\\]|\\(.|\n))*
STRING		{ALMOSTSTRING}\"

%%

<OUTSIDE>"class"		{ X;
				  BEGIN TQT_DEF;
				  return CLASS; }
<OUTSIDE>"namespace"		{ X;
				  BEGIN TQT_DEF;
				  return NAMESPACE; }
<OUTSIDE>"using"		{ X;
                                  BEGIN TQT_DEF;
				  return USING; }
<OUTSIDE>"template"		{ X;
				  BEGIN TQT_DEF;
				  return TEMPLATE; }
<TQT_DEF>"TQ_OBJECT"		{ X; return TQ_OBJECT; }
<TQT_DEF>"tqsignals"		{ X; return SIGNALS; }
<TQT_DEF>"tqslots"			{ X; return SLOTS; }
<TQT_DEF>"TQ_CLASSINFO"		{ X; return TQ_CLASSINFO; }
<TQT_DEF>"Q_PROPERTY"		{ X; return Q_PROPERTY; }
<TQT_DEF>"TQ_OVERRIDE"		{ X; return TQ_OVERRIDE; }
<TQT_DEF>"TQ_ENUMS"		{ X; return TQ_ENUMS; }
<TQT_DEF>"TQ_SETS"		{ X; return TQ_SETS; }

<IN_FCT>"{"			{ fctLevel++;Y; }
<IN_FCT>"}"			{ fctLevel--;Y;if (fctLevel==0){X;return '}';}}
<IN_CLASS>"{"			{ classPLevel++;Y; }
<IN_CLASS>"}"			{ classPLevel--;Y;if (classPLevel == 0)
                                                      {X;return '}';} }
<IN_CLASS>"public"		{ X;if( classPLevel == 1 ) return PUBLIC; }
<IN_CLASS>"protected"		{ X;if( classPLevel == 1 ) return PROTECTED; }
<IN_CLASS>"private"		{ X;if( classPLevel == 1 ) return PRIVATE; }
<IN_CLASS>"tqsignals"		{ X;if( classPLevel == 1 ) return SIGNALS; }
<IN_CLASS>"tqslots"		{ X;if( classPLevel == 1 ) return SLOTS; }
<IN_CLASS>"TQ_CLASSINFO"		{ X;if( classPLevel == 1 ) return TQ_CLASSINFO; }
<IN_CLASS>"TQ_OBJECT"		{ X;
				  if ( classPLevel == 1 )
				      return TQ_OBJECT;
				  else if ( classPLevel > 1 )
				      tqmoc_warn( "Cannot use TQ_OBJECT in nested class." );
				}
<IN_CLASS>"Q_PROPERTY"		{ X;if( classPLevel == 1 ) return Q_PROPERTY; }
<IN_CLASS>"TQ_OVERRIDE"		{ X;if( classPLevel == 1 ) return TQ_OVERRIDE; }
<IN_CLASS>"TQ_ENUMS"		{ X;if( classPLevel == 1 ) return TQ_ENUMS; }
<IN_CLASS>"TQ_SETS"		{ X;if( classPLevel == 1 ) return TQ_SETS; }

<IN_NAMESPACE>"{"		{ namespacePLevel++;Y; }
<IN_NAMESPACE>"}"		{ namespacePLevel--;Y;if (namespacePLevel == 0)
                                                          {X;return '}';}}
<IN_NAMESPACE>"class" 		{ X;
                                  BEGIN TQT_DEF;
				  return CLASS; }
<IN_NAMESPACE>"template"	{ X;
                                  BEGIN TQT_DEF;
                                  return TEMPLATE; }
<IN_NAMESPACE>"namespace"	{ X;
				  BEGIN TQT_DEF;
				  return NAMESPACE; }
<IN_NAMESPACE>"using"		{ X;
                                  BEGIN TQT_DEF;
				  return USING; }

<IN_PROPERTY>"("		{ X; return '('; }
<IN_PROPERTY>")"		{ X; return ')'; }
<IN_PROPERTY>"READ"		{ X; return READ; }
<IN_PROPERTY>"WRITE"		{ X; return WRITE; }
<IN_PROPERTY>"STORED"		{ X; return STORED; }
<IN_PROPERTY>"RESET"		{ X; return RESET; }
<IN_PROPERTY>"DESIGNABLE"	{ X; return DESIGNABLE; }
<IN_PROPERTY>"SCRIPTABLE"	{ X; return SCRIPTABLE; }


<IN_EXPR>"("			{ expLevel++;X; }
<IN_EXPR>")"			{ expLevel--;Y;if (expLevel == 0)
					{ X; BEGIN TQT_DEF; return ')';} }
<IN_EXPR>"["			{ expLevel++;X; }
<IN_EXPR>"]"			{ expLevel--;X;if (expLevel == 0)
					{ X; BEGIN TQT_DEF; return ']';} }
<IN_EXPR>","			{ if (expLevel == 0)
					{ X; BEGIN TQT_DEF; return ',' ;} }
<IN_EXPR>";"			{ if (expLevel == 0)
					{ X; BEGIN TQT_DEF; return ';' ;} }
<IN_DEF_ARG>"("			{ expLevel++;X; }
<IN_DEF_ARG>")"			{ expLevel--;Y;if (expLevel == 0)
					{ X; BEGIN TQT_DEF; return ')';} }
<IN_DEF_ARG>"["			{ expLevel++;X; }
<IN_DEF_ARG>"]"			{ expLevel--;X;if (expLevel == 0)
					{ X; BEGIN TQT_DEF; return ']';} }
<IN_DEF_ARG>","			{ if (expLevel <= 1)
					{ X; BEGIN TQT_DEF; return ',' ;} }
<IN_DEF_ARG>";"			{ if (expLevel == 0)
					{ X; BEGIN TQT_DEF; return ';' ;} }
<IN_ENUM>"("			{ enumLevel++;X; }
<IN_ENUM>")"			{ enumLevel--;X; }
<IN_ENUM>"["			{ enumLevel++;X; }
<IN_ENUM>"]"			{ enumLevel--;X }
<IN_ENUM>","			{ if (enumLevel == 0)
					{ X; BEGIN TQT_DEF; return ',' ;} }
<IN_ENUM>";"			{ if (enumLevel == 0)
					{ X; BEGIN TQT_DEF; return ';' ;} }
<IN_ENUM>"}"			{ if (enumLevel == 0)
					{ X; BEGIN TQT_DEF; return '}' ;} }
<IN_TEMPL_ARGS>[[(<]		{ templLevel++;
				  Y;
				  addExpressionChar( yytext[0] );
				}
<IN_TEMPL_ARGS>[])>]		{ templLevel--;
				  Y;
				  if ( templLevel == 0 ) {
				      X;
				      BEGIN TQT_DEF;
				      return yytext[0];
				  } else {
				      addExpressionChar( yytext[0] );
				  }
				}
<TQT_DEF>"friend"		{ X;return FRIEND; }
<TQT_DEF>"typedef"		{ X;return TYPEDEF; }
<TQT_DEF>"auto"			{ X;return AUTO; }
<TQT_DEF>"register"		{ X;return REGISTER; }
<TQT_DEF>"static"		{ X;return STATIC; }
<TQT_DEF>"extern"		{ X;return EXTERN; }
<TQT_DEF>"inline"		{ X;return INLINE; }
<TQT_DEF>"__inline__"		{ X;return INLINE; }
<TQT_DEF>"virtual"		{ X;return VIRTUAL; }
<TQT_DEF>"const"			{ X;return CONST; }
<TQT_DEF>"volatile"		{ X;return VOLATILE; }
<TQT_DEF>"char"			{ X;return CHAR; }
<TQT_DEF>"short"			{ X;return SHORT; }
<TQT_DEF>"int"			{ X;return INT; }
<TQT_DEF>"long"			{ X;return LONG; }
<TQT_DEF>"signed"		{ X;return SIGNED; }
<TQT_DEF>"unsigned"		{ X;return UNSIGNED; }
<TQT_DEF>"float"			{ X;return FLOAT; }
<TQT_DEF>"double"		{ X;return DOUBLE; }
<TQT_DEF>"void"			{ X;return VOID; }
<TQT_DEF>"enum"			{ X;return ENUM; }
<TQT_DEF>"class"			{ X;return CLASS; }
<TQT_DEF>"struct"		{ X;return STRUCT; }
<TQT_DEF>"union"			{ X;return UNION; }
<TQT_DEF>"asm"			{ X;return ASM; }
<TQT_DEF>"private"		{ X;return PRIVATE; }
<TQT_DEF>"protected"		{ X;return PROTECTED; }
<TQT_DEF>"public"		{ X;return PUBLIC; }
<TQT_DEF>"operator"		{ X;return OPERATOR; }
<TQT_DEF>"::"			{ X;return DBL_COLON; }
<TQT_DEF>"..."			{ X;return TRIPLE_DOT; }
<TQT_DEF>"template"		{ X;return TEMPLATE; }
<TQT_DEF>"mutable"		{ X;return MUTABLE; }
<TQT_DEF>"throw"			{ X;return THROW; }
<TQT_DEF>"using"		        { X;return USING; }
<TQT_DEF>"namespace"		{ X;return NAMESPACE; }

<TQT_DEF>[_a-zA-Z][_a-zA-Z0-9]* {
			  X;
			  yylval.string = qstrdup(yytext);
			  return IDENTIFIER;
			}

<IN_PROPERTY>[_a-zA-Z][_a-zA-Z0-9]* {
			  X;
			  yylval.string = qstrdup(yytext);
			  return IDENTIFIER;
			}

<IN_CLASSINFO>"(" { X; return '('; }
<IN_CLASSINFO>")" { X; return ')'; }
<IN_CLASSINFO>"," { X; return ','; }

<IN_CLASSINFO>{ALMOSTSTRING} {
			  X;
			  yylval.string = qstrdup( yytext + 1 );
			  input();		/* discard the '"' */
			  return STRING;
			}

<OUTSIDE>[_a-zA-Z][_a-zA-Z0-9]* ;
<IN_CLASS>[_a-zA-Z][_a-zA-Z0-9]* ;
<IN_NAMESPACE>[_a-zA-Z][_a-zA-Z0-9]* ;

<OUTSIDE>{STRING} {				/* discard strings */
			  Z;
			}

<IN_CLASS>{STRING} {				/* discard strings */
			  Z;
			}

<IN_NAMESPACE>{STRING}	{			/* discard strings */
			  Z;
			}

<IN_FCT>{ALMOSTSTRING} {			/* discard strings */
			  Z;
			  addExpressionString( yytext );
			  input();		/* discard the '"' */
			}


<IN_TEMPL_ARGS>{ALMOSTSTRING} {
			  X;
			  addExpressionString( yytext );
			  input();		/* discard the '"' */
			  return STRING;
			}

<TQT_DEF>{ALMOSTSTRING} {
			  X;
			  yylval.string = qstrdup( yytext + 1 );
			  input();		/* discard the '"' */
			  return STRING;
			}

<TQT_DEF>'.'	     { X;
			  yylval.char_val = yytext[1];
			  return CHAR_VAL;
			}

<TQT_DEF>'\\a'	    { X;
			 yylval.char_val = '\a';
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\b'	    { X;
			 yylval.char_val = '\b';
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\f'	    { X;
			 yylval.char_val = '\f';
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\n'	    { X;
			 yylval.char_val = '\n';
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\r'	    { X;
			 yylval.char_val = '\r';
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\t'	    { X;
			 yylval.char_val = '\t';
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\v'	    { X;
			 yylval.char_val = '\v';
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\\\'	    { X;
			 yylval.char_val = '\\';
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\?'	    { X;
			 yylval.char_val = '\?';
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\''	    { X;
			 yylval.char_val = '\'';
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\\"'	    { X;
			 yylval.char_val = '\"';	/* " */
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\0'	    { X;
			 yylval.char_val = '\0';
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\[0-7]+'  { X;
			 yylval.char_val =
			   (char)strtol( &yytext[1], 0, 8 );
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\x[0-9a-fA-F]+' { X;
			 yylval.char_val =
			   (char)strtol( &yytext[2], 0, 16 );
			 return CHAR_VAL;
		       }

<TQT_DEF>'\\.'	    { X;
			 yylval.char_val = ' ';
			 return CHAR_VAL;
		       }

<TQT_DEF>[0-9]+	     { X;
			  yylval.int_val = atoi(yytext);
			  return INT_VAL;
			}

<TQT_DEF>[0-9]+\.[0-9]* { X;
			  yylval.double_val = atof(yytext);
			  return DOUBLE_VAL;
			}

<TQT_DEF>\.[0-9]+     { X;
			  yylval.double_val = atof(yytext);
			  return DOUBLE_VAL;
			}


^#define.*\\$		{ /* skip multi-line macro-definitions */
			  int c, c1;
			  input();   /* Discard the '\n'. */
			  do {
			      c1=' ';
			      while((c = linput()) != '\n' && c != 0) c1=c;
			      if (c == 0) break;
			  } while(c1=='\\');
			  unput(c);  /* put back the '\n' or the EOF */
			}

^[ \t]*#.*		{ /* preprocessor commands are skipped */}
"//"[^\n]*		{ /* C++ comment */
			  TQCString s = yytext;
                          if ( s.contains( "TQMOC_SKIP_BEGIN" ) ) {
                            skipLevel++;
                            if ( skipLevel == 1 ) {
                              lastState = YYSTATE;
                              BEGIN SKIP;
                            }
                          } else
                          if ( s.contains( "TQMOC_SKIP_END" ) ) {
                            if ( skipLevel == 0 ) {
                              tqmoc_warn(" TQMOC_SKIP_END without TQMOC_SKIP_BEGIN");
                            } else {
                              skipLevel--;
                              if ( skipLevel == 0 ) {
                                BEGIN lastState;
                              }
                            }
                          }
                        }
"/*"			{ /* C comment */
			  int c = ' ';
			  do {
			      if ( c!= '*' ) {
				  while((c = linput()) != '*' && c != 0)
				      ;
			      }
			      if (c == 0) break;
			  } while(((c = linput())) != '/' && c != 0);
			  if (c == 0)
			      unput(c);
			}

<IN_TEMPL_ARGS>.	  { addExpressionChar( yytext[0] ); }

<IN_TEMPL_ARGS>[ \t\r\b\f]+	  {
				    /* spaces are important in template args,
				       e.g. Foo<const int> */
				    addExpressionChar( yytext[0] ); }
[ \t\r\b\f]+		;
<IN_CLASS>.		;
<IN_NAMESPACE>.		;
<IN_FCT>.		;
<IN_EXPR>.		  { addExpressionChar( yytext[0] ); }
<IN_DEF_ARG>.		;
<IN_ENUM>.		  { addExpressionChar( yytext[0] ); }
<OUTSIDE>.		;
<SKIP>.		        ;
<TQT_DEF>.		{
			  X;
			  return yytext[0];
			}
<GIMME_SEMICOLON>.	{
			  X;
			  return ';';
			}
\n			{
			  lineNo++;
			}


%%

#endif // TQMOC_YACC_CODE
