see ChangeLog: 19990510-01:19

This commit is contained in:
Ryszard Glab
1999-05-10 00:18:28 +00:00
parent 2f8f9a01e9
commit 8cab2ba0bb
4 changed files with 348 additions and 43 deletions

View File

@@ -1,3 +1,14 @@
19990510-01:19 Ryszard Glab <rglab@imid.med.pl>
* 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

View File

@@ -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_;
<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;
}
}
<BREAK_>{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;
}
<BREAK_>. { BEGIN 0; unput( yytext[ yyleng-1 ] ); }
%{
/* ** */
%}
"case" { BEGIN CASE_; }
<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;
}
<CASE_>{Separator}*("+="|"-=") { /* operators */
<CASE_>{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;
}
<CASE_>{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_;
<DO_>{Separator}+"case" { /* DO CASE statement */
BEGIN 0;
yy_lex_count_lf();
_iState =DOCASE;
return DOCASE;
}
<DO_>{Separator}+"while" { /* DO WHILE found -move it to WHILE state */
/* NOTE: we cannot decide here if it is DO WHILE <condition>
* or DO while [WITH <args>]
*/
yy_lex_count_lf();
BEGIN 0;
_iState =DO;
yyless( yyleng-5 );
}
<DO_>{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;
}
}
<DO_>{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;
}
<NEXT_>{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_;
<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;
}
<WHILE_>{Separator}*[\:\=\|\$\%\*\,\/\[\]\)\}] { /* there is an operator after "case" */
yy_lex_count_lf();
BEGIN 0;
yylval.string = strdup( "WHILE" );
unput( yytext[ yyleng-1 ] );
return IDENTIFIER;
}
<WHILE_>{Separator}*("+="|"-="|"->") { /* operators */
yy_lex_count_lf();
BEGIN 0;
yylval.string = strdup( "WHILE" );
unput( yytext[ yyleng-1 ] );
unput( yytext[ yyleng-2 ] );
return IDENTIFIER;
}
<WHILE_>{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_;
<WITH_>{Separator}*\n { /* at the end of line */
yy_lex_count_lf();
--iLine;
BEGIN 0;
unput( '\n' );
yylval.string = strdup( "WITH" );
return IDENTIFIER;
}
<WITH_>{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 <arg> */
_iState =WITH;
return WITH;
}
}
<WITH_>{Separator}*. {
yy_lex_count_lf();
BEGIN 0;
unput( yytext[ yyleng-1 ] );
if( _iState == WHILE || _iState == DO || _iState == IDENTIFIER )
{ /* DO <ident> WITH <arg> */
_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 );

View File

@@ -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 */
}
}

View File

@@ -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