From 8cab2ba0bb161627c4569bda70a4d8c8d6d65827 Mon Sep 17 00:00:00 2001 From: Ryszard Glab Date: Mon, 10 May 1999 00:18:28 +0000 Subject: [PATCH] see ChangeLog: 19990510-01:19 --- harbour/ChangeLog | 11 ++ harbour/source/compiler/harbour.l | 207 +++++++++++++++++++++++++---- harbour/source/compiler/harbour.y | 23 ++-- harbour/tests/working/keywords.prg | 150 ++++++++++++++++++++- 4 files changed, 348 insertions(+), 43 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 07dd834994..a0ca8079ee 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,14 @@ +19990510-01:19 Ryszard Glab + + * source/compiler/harbour.l, source/compiler/harbour.y + - corrected syntax check for: case-> case+= case-= + - DO/WHILE/CASE/WITH is now 100% compatible with Clipper + - there is still problem with comments that ends with **/ + (exactly two asterix and slash) + + * tests/working/keywords.prg + - added code to test DO/WHILE/CASE/WITH + 19900509-23:30 Eddie Runia * source/working/mankala.prg Instructions added diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index 7f73072cd1..c939cabc39 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -52,7 +52,8 @@ PDEFINE pDefs = 0; /* support for #defines */ int iLine = 1; long lNumber = 0; -#define LOOKUP 0 +#define LOOKUP 0 /* scan from the begining of line */ +#define OPERATOR -1 int _iState = LOOKUP; void yy_lex_count_lf( void ) @@ -75,7 +76,7 @@ Identifier (([a-zA-Z])|([_a-zA-Z][_a-zA-Z0-9]+)) String (\"(([^\"]*)|([\!]*))\")|(\'(([^\']*)|([\!]*))\') PseudoFunc {Identifier}"("+.*")"+ -Comment1 "/*"(.*|[\n])"*/" +Comment1 "/*"([^\*]|[\*][^\/])*"*/" Comment2 [\/][\/].* Comment ({Comment1}|{Comment2}) LineCont (;.*\n) @@ -83,7 +84,7 @@ Separator {SpaceTab}|{Comment}|{LineCont} %x COMMENT3 DEFINE DEFINE_PARAMS DEFINE_EXPR %x IFDEF IFNDEF STRING1 STRING2 -%x NEXT_ BREAK_ CASE_ +%x NEXT_ BREAK_ CASE_ DO_ WHILE_ WITH_ %% @@ -153,8 +154,13 @@ Separator {SpaceTab}|{Comment}|{LineCont} ;\n _iState=LOOKUP; ++iLine; if( ! _iQuiet ) printf( "\rline: %i", iLine ); "begin"{Separator}+"sequ"("ence"|"enc"|"en"|"e")? return BEGINSEQ; +%{ +/* ** */ +%} "break" BEGIN BREAK_; {Separator}*\n { /* at the end of line */ + yy_lex_count_lf(); + --iLine; BEGIN 0; unput( yytext[ yyleng-1 ] ); if( _iState == LOOKUP ) @@ -163,14 +169,14 @@ Separator {SpaceTab}|{Comment}|{LineCont} } else { /* there is another item in line already */ - yylval.string = strdup("BrEaK"); + yylval.string = strdup("BREAK"); return IDENTIFIER; } } {Separator}*[^_a-zA-Z] { /* there is no identifier after "break" */ yy_lex_count_lf(); BEGIN 0; - yylval.string = strdup( ((yytext[ yyleng-1 ] =='(')?"BREAK":"BrEaK") ); + yylval.string = strdup( "BREAK" ); _iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; @@ -183,6 +189,9 @@ Separator {SpaceTab}|{Comment}|{LineCont} return BREAK; } . { BEGIN 0; unput( yytext[ yyleng-1 ] ); } +%{ +/* ** */ +%} "case" { BEGIN CASE_; } {Separator}*[\:\=\|\$\%\*\,\/\[\]\)\}] { /* there is an operator after "case" */ yy_lex_count_lf(); @@ -192,13 +201,13 @@ Separator {SpaceTab}|{Comment}|{LineCont} unput( yytext[ yyleng-1 ] ); return IDENTIFIER; } -{Separator}*("+="|"-=") { /* operators */ +{Separator}*("+="|"-="|"->") { /* operators */ yy_lex_count_lf(); BEGIN 0; yylval.string = strdup( "CASE" ); _iState =IDENTIFIER; - unput( yytext[ yyleng-2 ] ); unput( yytext[ yyleng-1 ] ); + unput( yytext[ yyleng-2 ] ); return IDENTIFIER; } {Separator}*(\n|.) { /* not operator */ @@ -218,9 +227,54 @@ Separator {SpaceTab}|{Comment}|{LineCont} return IDENTIFIER; } } -"do" return DO; -"do"{Separator}+"case" { _iState =DOCASE; return DOCASE; } -("do"{SpaceTab}+"while")|"while" { _iState =WHILE; return WHILE; } +%{ +/* ** */ +%} +"do" BEGIN DO_; +{Separator}+"case" { /* DO CASE statement */ + BEGIN 0; + yy_lex_count_lf(); + _iState =DOCASE; + return DOCASE; + } +{Separator}+"while" { /* DO WHILE found -move it to WHILE state */ + /* NOTE: we cannot decide here if it is DO WHILE + * or DO while [WITH ] + */ + yy_lex_count_lf(); + BEGIN 0; + _iState =DO; + yyless( yyleng-5 ); + } +{Separator}+[_a-zA-Z] { /* an identifier DO id WITH */ + yy_lex_count_lf(); + BEGIN 0; + unput( yytext[ yyleng-1 ] ); + if( _iState == LOOKUP ) + { /* it is first item in the line */ + _iState =DO; + return DO; + } + else + { /* there is another item in line already */ + yylval.string = strdup( "DO" ); + _iState =IDENTIFIER; + return IDENTIFIER; + } + } +{Separator}*(.|\n) { /* end of line or any operator */ + yy_lex_count_lf(); + BEGIN 0; + if( yytext[ yyleng-1 ] == '\n' ) + --iLine; + unput( yytext[ yyleng-1 ] ); + yylval.string = strdup( "DO" ); + _iState =IDENTIFIER; + return IDENTIFIER; + } +%{ +/* ** */ +%} "else" return ELSE; "elseif" _iState =ELSEIF; return ELSEIF; "end"/[^(] return END; @@ -248,6 +302,7 @@ Separator {SpaceTab}|{Comment}|{LineCont} if( _iState == LOOKUP ) { /* it is first item in the line */ ++iLine; + _iState =NEXT; return NEXT; } else @@ -262,7 +317,6 @@ Separator {SpaceTab}|{Comment}|{LineCont} BEGIN 0; yylval.string = strdup( ((yytext[ yyleng-1 ] =='(')?"NEXT":"nExT") ); unput( yytext[ yyleng-1 ] ); - _iState =IDENTIFIER; return IDENTIFIER; } {Separator}*. { /* an identifier follows NEXT statement */ @@ -286,30 +340,129 @@ Separator {SpaceTab}|{Comment}|{LineCont} "step"/[^(] return STEP; "to" return TO; "using" return USING; -"with" return WITH; -"#" return NE1; -"<>"|"!=" return NE2; -":=" return INASSIGN; -"==" return EQ; +%{ +/* ** */ +%} +"while" BEGIN WHILE_; +{Separator}*\n { /* end of line */ + yy_lex_count_lf(); + --iLine; + BEGIN 0; + unput( '\n' ); + if( _iState == DO ) + { /* we have DO while - replace it with while() */ + unput( ')' ); unput( '(' ); + } + yylval.string = strdup( "WHILE" ); + return IDENTIFIER; + } +{Separator}*[\:\=\|\$\%\*\,\/\[\]\)\}] { /* there is an operator after "case" */ + yy_lex_count_lf(); + BEGIN 0; + yylval.string = strdup( "WHILE" ); + unput( yytext[ yyleng-1 ] ); + return IDENTIFIER; + } +{Separator}*("+="|"-="|"->") { /* operators */ + yy_lex_count_lf(); + BEGIN 0; + yylval.string = strdup( "WHILE" ); + unput( yytext[ yyleng-1 ] ); + unput( yytext[ yyleng-2 ] ); + return IDENTIFIER; + } +{Separator}*. { /* identifiers and literals */ + yy_lex_count_lf(); + BEGIN 0; + if( _iState == LOOKUP || _iState == DO ) + { /* it is first item in the line or after DO */ + unput( yytext[ yyleng-1 ] ); + _iState =WHILE; + return WHILE; + } + else + { /* there is another item in line already */ + unput( yytext[ yyleng-1 ] ); + yylval.string = strdup( "WHILE" ); + return IDENTIFIER; + } + } +%{ +/* ** */ +%} +"with" BEGIN WITH_; +{Separator}*\n { /* at the end of line */ + yy_lex_count_lf(); + --iLine; + BEGIN 0; + unput( '\n' ); + yylval.string = strdup( "WITH" ); + return IDENTIFIER; + } +{Separator}*"with" { + yy_lex_count_lf(); + BEGIN 0; + yyless( yyleng-4 ); + if( _iState == DO ) + { /* DO with */ + _iState =IDENTIFIER; + yylval.string = strdup( "WITH" ); + return IDENTIFIER; + } + else + { /* DO WITH with */ + _iState =WITH; + return WITH; + } + } +{Separator}*. { + yy_lex_count_lf(); + BEGIN 0; + unput( yytext[ yyleng-1 ] ); + if( _iState == WHILE || _iState == DO || _iState == IDENTIFIER ) + { /* DO WITH */ + _iState =WITH; + return WITH; + } + else + { + yylval.string = strdup( "WITH" ); + return IDENTIFIER; + } + } +%{ +/* ** */ +%} +"#" _iState =NE1; return NE1; +"=" _iState =OPERATOR; return yytext[ 0 ]; +"+" _iState =OPERATOR; return yytext[ 0 ]; +"-" _iState =OPERATOR; return yytext[ 0 ]; +"*" _iState =OPERATOR; return yytext[ 0 ]; +[\/] _iState =OPERATOR; return yytext[ 0 ]; +"%" _iState =OPERATOR; return yytext[ 0 ]; +"$" _iState =OPERATOR; return yytext[ 0 ]; +"<>"|"!=" _iState =NE2; return NE2; +":=" _iState =INASSIGN; return INASSIGN; +"==" _iState =EQ; return EQ; "++" _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; +"->" _iState =ALIAS; return ALIAS; +"<=" _iState =LE; return LE; +">=" _iState =GE; return GE; +"+=" _iState =PLUSEQ; return PLUSEQ; +"-=" _iState =MINUSEQ; return MINUSEQ; +"*=" _iState =MULTEQ; return MULTEQ; +"/=" _iState =DIVEQ; return DIVEQ; +"^=" _iState =EXPEQ; return EXPEQ; +"%=" _iState =MODEQ; return MODEQ; +"**"|"^" _iState =POWER; 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 ]; +[,\;\{\}\|\#\&\:\<\>\[\]\(\)\@] return yytext[ 0 ]; {InvalidNumber} GenError( ERR_NUMERIC_FORMAT, NULL, NULL ); diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index f42082879f..226170eba7 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -298,6 +298,7 @@ static const char * _szReservedFun[] = { "DAY" , "DELETED" , "DEVPOS" , + "DO" , "DOW" , "DTOC" , "DTOS" , @@ -841,6 +842,9 @@ DoCase : DoCaseBegin Otherwise EndCase + | DoCaseBegin + EndCase + | DoCaseBegin Cases Otherwise @@ -927,6 +931,7 @@ RecoverSeq : /* no recover */ DoProc : DO IDENTIFIER { PushSymbol( $2, 1 ); PushNil(); Do( 0 ); } | DO IDENTIFIER { PushSymbol( $2, 1 ); PushNil(); } WITH ArgList { Do( $5 ); } + | WHILE { PushSymbol( "WHILE", 1 ); PushNil(); } WITH ArgList { Do( $4 ); } ; Crlf : '\n' @@ -1518,11 +1523,11 @@ int Include( char * szFileName ) pFile->pPrev = files.pLast; files.pLast = pFile; } -#ifdef __cplusplus - yy_switch_to_buffer( (YY_BUFFER_STATE) (pFile->pBuffer = yy_create_buffer( yyin, 8192 * 2 ) ) ); -#else - yy_switch_to_buffer( (pFile->pBuffer = yy_create_buffer( yyin, 8192 * 2 ) ) ); -#endif +#ifdef __cplusplus + yy_switch_to_buffer( (YY_BUFFER_STATE) pFile->pBuffer = yy_create_buffer( yyin, 8192 * 2 ) ); +#else + yy_switch_to_buffer( pFile->pBuffer = yy_create_buffer( yyin, 8192 * 2 ) ); +#endif files.iFiles++; return 1; } @@ -1540,19 +1545,19 @@ int yywrap( void ) /* handles the EOF of the currently processed file */ files.pLast = ( PFILE ) ( ( PFILE ) files.pLast )->pPrev; iLine = files.pLast->iLine; printf( "\nparsing file %s\n", files.pLast->szFileName ); -#ifdef __cplusplus +#ifdef __cplusplus yy_delete_buffer( (YY_BUFFER_STATE) ( ( PFILE ) pLast )->pBuffer ); #else yy_delete_buffer( ( ( PFILE ) pLast )->pBuffer ); -#endif +#endif free( pLast ); files.iFiles--; yyin = files.pLast->handle; -#ifdef __cplusplus +#ifdef __cplusplus yy_switch_to_buffer( (YY_BUFFER_STATE) files.pLast->pBuffer ); #else yy_switch_to_buffer( files.pLast->pBuffer ); -#endif +#endif return 0; /* we close the currently include file and continue */ } } diff --git a/harbour/tests/working/keywords.prg b/harbour/tests/working/keywords.prg index a70be3315a..4c07fdd0d4 100644 --- a/harbour/tests/working/keywords.prg +++ b/harbour/tests/working/keywords.prg @@ -3,7 +3,7 @@ */ //DO NOT RUN THIS PROGRAM - ITS PURPOSE IS THE SYNTAX CHECK ONLY! -STATIC nExt, bEgin, bReak, cAse +STATIC nExt, bEgin, bReak, cAse, do, wHile, wIth Function Main() @@ -12,7 +12,13 @@ Function Main() RETURN nil ENDIF - NEXT(nExt) //in Clipper: NEXT does not match FOR +// +//DANGER!! +//One line comments that ends with '**/' doesn't work!!! +// +// + +// NEXT(nExt) //in Clipper: NEXT does not match FOR BEGIN( bEgin +';' + ;; //////Clipper doesn't like more then one ';' ";" ; /* ;;;;;Clipper doesn't like this comment after ';' ;;;;;;; */ ) @@ -20,6 +26,10 @@ Function Main() // CASE(case) //it is not possible to call case() in this context case :=CASE( CASE ) //this is valid + //DO is reserved function name in Clipper! + DO_( nExt+bEgin/bReak-do*wHile%cAse $ wIth ) +// WHILE( while ) //it is not possible to call while() in this context + RETURN nil /*================================================================ @@ -53,6 +63,8 @@ Local nExt, nExt7, nExtNEXT nExt[ 1 ] :=nExt //in Clipper: NEXT does not match FOR nExt[ nExt ] := NEXT( nExt[nExt+nExt] * nExt *(nExt+nExt*5) ) + next->next :=next->next + next->next + IF( nExt > nExt+4 ) nExt =nExt +nExt * 5 ELSEIF( nExt > 0 ) @@ -65,7 +77,7 @@ RETURN( nExt * /*next*/ nExt ) /*=================================================================== * Checking for BEGIN -*/ +**/ FUNCTION BEGIN( BEGIN_BEGIN ) LOCAL bEgin LOCAL xbEgin @@ -86,6 +98,8 @@ BEGIN SEQUENCE --bEgin NEXT bEgin + begin->begin :=begin->begin +; /************************/ + begin->begin bEgin :=BEGIN( xbegin +bEgin +bEginBEGIN -bEgin0 * xbEginBEGIN ) +; bEgin[ bEgin ] @@ -101,7 +115,7 @@ RETURN bEgin ^ 2 /*==================================================================== * Test for BREAK and BEGIN/RECOVER sequence -*/ +**/ FUNCTION BREAK_( break_break ) LOCAL bReak:=0 @@ -112,7 +126,7 @@ LOCAL bReak:=0 Break() //in Clipper: syntax error: ')' ENDIF - Break /**** BREAK AGAIN ****/; ;;;;; + Break /*** break ***/ ; ; ////////////////////////////////////////////////// ; //What ; //the @@ -122,8 +136,9 @@ LOCAL bReak:=0 ; //is ; //doing ; //in -; //this -; //place? +; //place +; //like +; //this? ; //Do ; //you ; //use @@ -136,6 +151,7 @@ begin sequence FOR bReak:=1 To 10 QOut( bReak * bReak ) NEXT bReak + break->break :=break->break +break->break BREAK bReak :=IIF( bReak=1, BREAK(0), BREAK(bReak) ) recover USING bReak @@ -186,8 +202,128 @@ case ) CASE( CASE ) case =case != case CASE( CASE ) //new CASE or function call? :) + CASE case->case + case->case :=case->case +1 OTHERWISE case *=case ENDCASE RETURN case + +/*==================================================================== +* Test for DO CASE / DO WHILE / DO / WITH +*/ +FUNCTION DO_( do ) +LOCAL case +LOCAL while +LOCAL with + + do case + case do + case case + endcase + + do/***do***/case/**/ + case do + endcase + + DO CASE + ENDCASE + + while .t. + enddo + + do ; + while do + do :=1 + enddo + + do/***do***/while do/***do do do, da da da***/ + do :=do + enddo + + do :={|do| do} + do while do + do() + do->do :=do() + do++ + do-- + enddo + + do while while + ++do + enddo + + do++ + do +=do + do->do :=do->do +1 + do[ 1 ] :=do + do[ do ] :=do[ do ][ do ] + + DO do WITH do + DO do WITH do() + DO do + + DO while; + while + while :=while() + ENDDO + + while while +// while++ //incomplete statement or unbalanced delimiter +// while-- //incomplete statement or unbalanced delimiter + --while + while +=while + while->while :=while() +while->while + enddo + + while[ 1 ] :=while + while[ while ] :=while[ while ] + while :={|while| while} + while while++ < 10 + enddo + + DO /* **** */; +; +; + while + + DO while WITH + do :=with + while + ENDDO + + do WITH; +; +; + + with() + + DO while WITH while + DO while WITH while() + DO while WITH with + DO do WITH with + DO do WITH with() + + with++ + ++with + with +=with + with->with :=with() +with->with +1 + with :={|with| with} + with[ with ] :=with[ with ][ with ] + with[ with ][ with ] =with[ with ][ with ] + + DO with WITH with + DO with WITH with() + DO with WITH do + DO with WITH while + DO with WITH do() + DO with WITH while() + +RETURN DO + + +FUNCTION WHILE( while ) +RETURN while + +FUNCTION With( with ) +RETURN with