From ee656694b5b045d70fd154af93dd8d5d752bd627 Mon Sep 17 00:00:00 2001 From: Ryszard Glab Date: Thu, 6 May 1999 01:36:45 +0000 Subject: [PATCH] NEXT keywork is now contex sensitive --- harbour/source/compiler/harbour.l | 493 ++++++++++++++++++++++++++++-- 1 file changed, 469 insertions(+), 24 deletions(-) diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index 22aed5d322..b770ccd405 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -1,372 +1,817 @@ %{ -/* - * $Id$ - */ + /* + Harbour lex rules. + Build 21: Spring 99 + Usage: flex -i -oyylex.c harbour.l + You may find flex.exe at www.harbour-project.org + */ + + #include + #include + #include + #include + #include "y_tab.h" + + void yyerror( char * ); + void yyunput( int, char * ); + #undef yywrap /* to implement our own yywrap() funtion to handle EOFs */ + int yywrap( void ); + #undef YY_INPUT /* to implement our own YY_INPUT function to manage PRGs without \n at the end */ + extern FILE * yyin; /* currently yacc parsed file */ + int yy_lex_input( char *, int ); + #define YY_INPUT( buf, result, max_size ) result = yy_lex_input( buf, max_size ); + void GenError( int, char*, char * ); /* generic parsing error management function */ + + #define ERR_NUMERIC_FORMAT 6 + #define ERR_STRING_TERMINATOR 7 + + typedef struct + { + char * szDefine; + char * szValue; + void * pKeys; + void * pNext; + } _DEFINE, * PDEFINE; + + PDEFINE LastDef( PDEFINE pDef ); /* searches for the latest #define */ + void Define( char * szDefine ); /* add a new #define symbol */ + void DefineKey( char * szKey ); /* add a new key to a #define expression */ + void AddDefine( char * szDefine, char * szValue ); /* add a new define from the command line */ + PDEFINE FindDef( char * szText ); /* finds a #define */ + + extern int _iQuiet; + extern int _iRestrictSymbolLength; + + PDEFINE pDefs = 0; /* support for #defines */ + int iLine = 1; + long lNumber = 0; + + +#define LOOKUP 0 + +int _iState = LOOKUP; + + + +/* + +//Separator {SpaceTab}|("/ *".*"* /")|"//".* + +*/ + + + %} + + SpaceTab [ \t]+ + InvalidNumber [0-9]+\. + Number ([0-9]+)|([0-9]*\.[0-9]+) + HexNumber 0x[0-9A-F]+ + Identifier (([a-zA-Z])|([_a-zA-Z][_a-zA-Z0-9]+)) + String (\"(([^\"]*)|([\!]*))\")|(\'(([^\']*)|([\!]*))\') + PseudoFunc {Identifier}"("+.*")"+ + + +Comment1 [\/][\*]([^\*]|[\*][^\/])*[\*][\/] + +Comment2 [\/][\/].* + +Comment ({Comment1}|{Comment2}) + +Separator {SpaceTab}|{Comment} + + + %x COMMENT3 DEFINE DEFINE_PARAMS DEFINE_EXPR + %x IFDEF IFNDEF STRING1 STRING2 +%x _NEXT + + + %% + + ("//".*)|("&&".*) ; + + ^{SpaceTab}*(\*|"NOTE").* ; + \n{SpaceTab}*(\*|"NOTE").* ++iLine; if( ! _iQuiet ) printf( "\rline: %i", iLine ); + + ' BEGIN STRING1; + \" BEGIN STRING2; + + [^'^\n]* GenError( ERR_STRING_TERMINATOR, yytext, NULL ); BEGIN 0; + [^\"^\n]* GenError( ERR_STRING_TERMINATOR, yytext, NULL ); BEGIN 0; + + [^']*' { BEGIN 0; yylval.string = strdup( yytext + 1 ); + yylval.string[ yyleng - 2 ] = 0; return LITERAL; } + [^\"]*\" { BEGIN 0; yylval.string = strdup( yytext + 1 ); + yylval.string[ yyleng - 2 ] = 0; return LITERAL; } + + "/*" BEGIN COMMENT3; + "*/" BEGIN 0; + [^"*/"\n]* ; + [\/\"]+ ; + \n ++iLine; if( ! _iQuiet ) printf( "\rline: %i", iLine ); + + "#"{SpaceTab}*"define" BEGIN DEFINE; + {Identifier}/{SpaceTab}+ Define( yytext ); + {Identifier}/{SpaceTab}*\n Define( yytext ); BEGIN 0; + {SpaceTab} ; + {Identifier} LastDef( pDefs )->szValue = strdup( yytext ); BEGIN 0; + {PseudoFunc} LastDef( pDefs )->szValue = strdup( yytext ); BEGIN 0; + {String} LastDef( pDefs )->szValue = strdup( yytext ); BEGIN 0; + -?{Number} LastDef( pDefs )->szValue = strdup( yytext ); BEGIN 0; + {HexNumber} LastDef( pDefs )->szValue = strdup( yytext ); BEGIN 0; + "/*".*"*/" ; + {Number}{SpaceTab}*[\(] yyerror( "Syntax error in #define" ); + {String}{SpaceTab}*[\(] yyerror( "Syntax error in #define" ); + {Identifier}{SpaceTab}*[\(] Define( yytext ); BEGIN DEFINE_PARAMS; + {SpaceTab} ; + {Identifier} DefineKey( yytext ); + [\,] ; + [\)] BEGIN DEFINE_EXPR; + .*/\n LastDef( pDefs )->szValue = strdup( yytext ); BEGIN 0; + + "#"{SpaceTab}*"ifdef" BEGIN IFDEF; + {Identifier} if( FindDef( yytext ) ) BEGIN 0; + "#"{SpaceTab}*"else"\n ++iLine; BEGIN 0; + "#"{SpaceTab}*"endif"\n ++iLine; BEGIN 0; + \n ++iLine; + [\(\),\"\/\.]* ; + "#"{SpaceTab}*"ifdef" ; + "#"{SpaceTab}*"else" BEGIN 0; + "#"{SpaceTab}*"else" BEGIN IFDEF; + "#"{SpaceTab}*"endif" BEGIN 0; + + "#"{SpaceTab}*"ifndef" BEGIN IFNDEF; + {Identifier} if( ! FindDef( yytext ) ) BEGIN 0; + "#endif"\n ++iLine; BEGIN 0; + \n ++iLine; + + "#"{SpaceTab}*"line".* ; + + {SpaceTab} ; -\n.* yyless( 1 ); ++iLine; if( ! _iQuiet ) printf( "\rline: %i", iLine ); return '\n'; -;\n ++iLine; if( ! _iQuiet ) printf( "\rline: %i", iLine ); + + +\n.* _iState=LOOKUP; yyless( 1 ); ++iLine; if( ! _iQuiet ) printf( "\rline: %i", iLine ); return '\n'; + +;\n _iState=LOOKUP; ++iLine; if( ! _iQuiet ) printf( "\rline: %i", iLine ); + + "begin" return BEGINSEQ; -"break" return BREAK; -"case" return CASE; + +"break" _iState =BREAK; return BREAK; + +"case" _iState =CASE; return CASE; + "do" return DO; + "do"{SpaceTab}+"case" return DOCASE; + ("do"{SpaceTab}+"while")|"while" return WHILE; + "else" return ELSE; -"elseif" return ELSEIF; + +"elseif" _iState =ELSEIF; return ELSEIF; + "end"/[^(] return END; + "endif" return ENDIF; + "endcase" return ENDCASE; + "enddo" return ENDDO; + "exit"/[\n\;] return EXITLOOP; + "exit" return EXIT; -"extern"|"external" return EXTERN; -"field"/[^(] return FIELD; -"for" return FOR; + +"extern"|"external" _iState =EXTERN; return EXTERN; + +"field"/[^(] _iState =FIELD; return FIELD; + +"for" _iState = FOR; return FOR; + "func"|"funct"|"functi"|"functio"|"function"/[^(] return FUNCTION; -("if"|"iif"){SpaceTab}*/[(] return IF; -"if" return IF; + +("if"|"iif"){SpaceTab}*/[(] _iState =IF; return IF; + +"if" _iState =IF; return IF; + "in" return IN; + "include" return INCLUDE; + "init" return INIT; -"local" return LOCAL; + +"local" _iState =LOCAL; return LOCAL; + "loop" return LOOP; -"memvar" return MEMVAR; -"next" return NEXT; + +"memvar" _iState =MEMVAR; return MEMVAR; + +"next" BEGIN _NEXT; + +<_NEXT>{Separator}*[\n\;] { /* at the end of line */ + + BEGIN 0; + + if( _iState == LOOKUP ) + + { /* it is first item in the line */ + + ++iLine; + + return NEXT; + + } + + else + + { /* there is another item in line already */ + + unput( yytext[ yyleng-1 ] ); + + yylval.string = "nExT"; + + return IDENTIFIER; + + } + + } + +<_NEXT>{Separator}*[^_a-zA-Z\n\;] { /* there is no identifier after "next" */ + + BEGIN 0; + + yylval.string = ((yytext[ yyleng-1 ] =='(')?"NEXT":"nExT"); + + unput( yytext[ yyleng-1 ] ); + + _iState =IDENTIFIER; + + return IDENTIFIER; + + } + +<_NEXT>{Separator}*. { /* an identifier follows NEXT statement */ + + BEGIN 0; + + unput( yytext[ yyleng-1 ] ); + + _iState =NEXT; + + return NEXT; + + } + +<_NEXT>. { BEGIN 0; unput( yytext[ yyleng-1 ] ); } + "nil" return NIL; + "otherwise" return OTHERWISE; -"parameters" return PARAMETERS; -"private" return PRIVATE; + +"parameters" _iState =PARAMETERS; return PARAMETERS; + +"private" _iState =PRIVATE; return PRIVATE; + "proc"|"procedure" return PROCEDURE; -"public" return PUBLIC; + +"public" _iState =PUBLIC; return PUBLIC; + "qself"{SpaceTab}*[(]{SpaceTab}*[)] return SELF; -"recover" return RECOVER; -"retu"|"retur"|"return" return RETURN; + +"recover" _iState =RECOVER; return RECOVER; + +"retu"|"retur"|"return" _iState =RETURN; return RETURN; + "sequence" return SEQUENCE; -"static" return STATIC; + +"static" _iState =STATIC; return STATIC; + "step"/[^(] return STEP; + "to" return TO; + "using" return USING; + "with" return WITH; + "#" return NE1; + "<>"|"!=" return NE2; + ":=" return INASSIGN; + "==" return EQ; -"++" return INC; -"--" return DEC; + +"++" _iState =INC; return INC; + +"--" _iState =DEC; return DEC; + "->" return ALIAS; + "<=" return LE; + ">=" return GE; + "+=" return PLUSEQ; + "-=" return MINUSEQ; + "*=" return MULTEQ; + "/=" return DIVEQ; + "^=" return EXPEQ; + "%=" return MODEQ; + "**"|"^" return POWER; + "."[t|y]"." return TRUE; + "."[f|n]"." return FALSE; + ".and." return AND; + ".or." return OR; + "!"|".not." return NOT; + "::" unput( ':' ); unput( 'f' ); unput( 'l' ); unput( 'e' ); unput( 'S' ); + [,\;+\-\*\/\{\}\|\#\&\:\<\>\=\[\]\$\%\(\)\@] return yytext[ 0 ]; + + {InvalidNumber} GenError( ERR_NUMERIC_FORMAT, NULL, NULL ); + + {Number} { yylval.dNumber = atof( yytext ); + if( strchr( yytext, '.' ) ) + return DOUBLE; + else + { + if( ( double )SHRT_MIN <= yylval.dNumber && + yylval.dNumber <= ( double )SHRT_MAX ) + { + yylval.iNumber = ( int ) yylval.dNumber; + return INTEGER; + } + else if( ( double )LONG_MIN <= yylval.dNumber && + yylval.dNumber <= ( double )LONG_MAX ) + { + yylval.lNumber = ( long ) yylval.dNumber; + return INTLONG; + } + else + return DOUBLE; + } + } + + {HexNumber} { sscanf( yytext, "%lxI", &lNumber ); + + if( ( double )SHRT_MIN <= lNumber && + lNumber <= ( double )SHRT_MAX ) + { + yylval.iNumber = lNumber; + return INTEGER; + } + else if( ( double )LONG_MIN <= lNumber && + lNumber <= ( double )LONG_MAX ) + { + yylval.lNumber = lNumber; + return INTLONG; + } + else + { + yylval.dNumber = lNumber; + return DOUBLE; + } + } + + {String} yylval.string = strdup( yytext + 1 ); yylval.string[ yyleng - 2 ] = 0; return LITERAL; + + {Identifier} { + PDEFINE pDef = FindDef( yytext ); + char * szText; int c; + _iState = IDENTIFIER; + if( pDef ) + { + c = strlen( pDef->szValue ) - 1; + szText = pDef->szValue; + while( c >= 0 ) + unput( szText[ c-- ] ); + } + else + { + if( _iRestrictSymbolLength && strlen( yytext ) > 10 ) + { + yytext[ 10 ] = 0; + yyleng = 10; + } + yylval.string = strupr( strdup( yytext ) ); + return IDENTIFIER; + } + } + + %% + + PDEFINE LastDef( PDEFINE pDef ) + { + while( pDef->pNext ) + pDef = pDef->pNext; + + return pDef; + } + + void Define( char * szDefine ) + { + PDEFINE pDef = ( PDEFINE ) malloc( sizeof( _DEFINE ) ); + + if( ! pDefs ) + pDefs = pDef; + else + LastDef( pDefs )->pNext = pDef; + + pDef->szDefine = strdup( szDefine ); + pDef->szValue = 0; + pDef->pKeys = 0; + pDef->pNext = 0; + } + + void DefineKey( char * szKey ) + { + PDEFINE pDef = ( PDEFINE ) malloc( sizeof( _DEFINE ) ); + PDEFINE pLast = LastDef( pDefs ); + + if( pLast->pKeys ) + LastDef( pLast->pKeys )->pNext = pDef; + else + pLast->pKeys = pDef; + + pDef->szDefine = strdup( szKey ); + pDef->szValue = 0; + pDef->pKeys = 0; + pDef->pNext = 0; + } + + PDEFINE FindDef( char * szText ) + { + PDEFINE pDef = pDefs; + + while( pDef ) + { + if( ! strcmp( pDef->szDefine, szText ) ) + return pDef; + else + { + if( pDef->pNext ) + pDef = pDef->pNext; + else + return 0; + } + } + return 0; + } + + void AddDefine( char * szId, char * szValue ) /* adds a new define from command line */ + { + PDEFINE pDefine = FindDef( szId ); /* just incase there are several repited defines */ + + if( pDefine ) + { + if( pDefine->szValue ) + { + free( pDefine->szValue ); + pDefine->szValue = 0; + } + if( szValue ) + pDefine->szValue = strdup( szValue ); + } + else + { + Define( szId ); + if( szValue ) + LastDef( pDefs )->szValue = strdup( szValue ); + } + } + + int yy_lex_input( char *buffer, int iBufferSize ) + { + int i; + static int _ineedLF = 1; /* we want LF as the last character */ + + if( ((i = fread(buffer, 1, iBufferSize, yyin)) == 0) && ferror(yyin) ) + YY_FATAL_ERROR( "input in flex scanner failed" ); + + if( i == iBufferSize ) + _ineedLF =( buffer[i-1] != '\n' ); /* check if last character is LF */ + /* in case it is the last block */ + else if( i < iBufferSize && _ineedLF ) + { + if( i == 0 ) + buffer[ i++ ] ='\n'; + else if( buffer[ i-1 ] != '\n' ) + buffer[ i++ ] ='\n'; + _ineedLF =0; /* OK - no more LF */ + } + return i; + } + \ No newline at end of file