diff --git a/harbour/ChangeLog b/harbour/ChangeLog index c82ee20e1e..49573dd68c 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,12 @@ +19991013-13:46 GMT+8 Ron Pinkas + * harbour.y + + added MACROOP (last session also added MACROALIAS) + + added rules to complete support for PRIVATE/PUBLIC &cVar - it now supports any mix of variables and macros. + * harbour.l + + added rules to support new TOKEN MACROOP and completed support for macro in MODES PRIVATE and PUBLIC_ (Ryszard TODO removed). + * tests/tstmacro.prg + added even more tests to demonstrate working capabilities og macro. + 19991013-17:45 EDT Paul Tucker * source/rtl/oldbox.c * Add parens so cast applies to entire expression diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index acb86958fa..618d78f22e 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -947,13 +947,13 @@ Separator {SpaceTab} "priv"("ate"|"at"|"a")? { BEGIN PRIVATE_; yylval.string = yy_strupr( yy_strdup( yytext ) ); } -{Separator}+[_a-zA-Z] { /* an Identifier after PRIVATE */ +{Separator}+["&"|_a-zA-Z] { /* an Identifier after PRIVATE */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( _iState == LOOKUP ) { /* it is first item in the line */ hb_xfree( (void *) yylval.string ); - _iState =PRIVATE; + _iState = PRIVATE; return PRIVATE; } else @@ -962,11 +962,11 @@ Separator {SpaceTab} return IDENTIFIER; } } -{Separator}*[^a-zA-Z] { /* any character (not identifier) after PRIVATE */ - /* TODO: add support for macro operator */ + +{Separator}*[^a-zA-Z] { /* any character (not identifier or macro operator) after PRIVATE */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =IDENTIFIER; + _iState = IDENTIFIER; return IDENTIFIER; } %{ @@ -979,7 +979,7 @@ Separator {SpaceTab} "publ"("ic"|"i")? { BEGIN PUBLIC_; yylval.string = yy_strupr( yy_strdup( yytext ) ); } -{Separator}+[_a-zA-Z] { /* an identifier after PUBLIC */ +{Separator}+["&"|_a-zA-Z] { /* an identifier after PUBLIC */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( _iState == LOOKUP ) @@ -994,8 +994,7 @@ Separator {SpaceTab} return IDENTIFIER; } } -{Separator}*[^a-zA-Z] { /* any character (not identifier) after PUBLIC */ - /* TODO: add support for macro operator */ +{Separator}*[^a-zA-Z] { /* any character (not identifier or macro) after PUBLIC */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; _iState =IDENTIFIER; @@ -1122,41 +1121,42 @@ Separator {SpaceTab} %{ /* ************************************************************************ */ %} -"#" _iState =OPERATOR; 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 =OPERATOR; return NE2; -":=" _iState =OPERATOR; return INASSIGN; -"==" _iState =OPERATOR; return EQ; -"++" _iState =OPERATOR; return INC; -"--" _iState =OPERATOR; return DEC; -"->" _iState =OPERATOR; return ALIASOP; -"M->&" _iState =OPERATOR; return MACROALIAS; -"MEMVAR->&" _iState =OPERATOR; return MACROALIAS; -"<=" _iState =OPERATOR; return LE; -">=" _iState =OPERATOR; return GE; -"+=" _iState =OPERATOR; return PLUSEQ; -"-=" _iState =OPERATOR; return MINUSEQ; -"*=" _iState =OPERATOR; return MULTEQ; -"/=" _iState =OPERATOR; return DIVEQ; -"^=" _iState =OPERATOR; return EXPEQ; -"%=" _iState =OPERATOR; return MODEQ; -"**"|"^" _iState =OPERATOR; return POWER; -"."[t|y]"." _iState =SEPARATOR; return TRUEVALUE; -"."[f|n]"." _iState =SEPARATOR; return FALSEVALUE; -".and." _iState =OPERATOR; return AND; -".or." _iState =OPERATOR; return OR; -"!"|".not." _iState =OPERATOR; return NOT; -"." _iState =OPERATOR; return DOT; -"::" unput( ':' ); unput( 'f' ); unput( 'l' ); unput( 'e' ); unput( 'S' ); -[,\{\}\|\#\&\:\<\>\[\]\@] _iState =OPERATOR; return yytext[ 0 ]; -[\(] ++_iOpenBracket; _iState =SEPARATOR; return yytext[ 0 ]; -[\)] --_iOpenBracket; _iState =SEPARATOR; return yytext[ 0 ]; +"#" { _iState =OPERATOR; 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 =OPERATOR; return NE2; } +":=" { _iState =OPERATOR; return INASSIGN; } +"==" { _iState =OPERATOR; return EQ; } +"++" { _iState =OPERATOR; return INC; } +"--" { _iState =OPERATOR; return DEC; } +"->" { _iState =OPERATOR; return ALIASOP; } +"M->&" { _iState =OPERATOR; return MACROALIAS; } +"MEMVAR->&" { _iState =OPERATOR; return MACROALIAS; } +"&" { _iState =OPERATOR; return MACROOP; } +"<=" { _iState =OPERATOR; return LE; } +">=" { _iState =OPERATOR; return GE; } +"+=" { _iState =OPERATOR; return PLUSEQ; } +"-=" { _iState =OPERATOR; return MINUSEQ; } +"*=" { _iState =OPERATOR; return MULTEQ; } +"/=" { _iState =OPERATOR; return DIVEQ; } +"^=" { _iState =OPERATOR; return EXPEQ; } +"%=" { _iState =OPERATOR; return MODEQ; } +"**"|"^" { _iState =OPERATOR; return POWER; } +"."[t|y]"." { _iState =SEPARATOR; return TRUEVALUE; } +"."[f|n]"." { _iState =SEPARATOR; return FALSEVALUE; } +".and." { _iState =OPERATOR; return AND; } +".or." { _iState =OPERATOR; return OR; } +"!"|".not." { _iState =OPERATOR; return NOT; } +"." { _iState =OPERATOR; return DOT; } +"::" { unput( ':' ); unput( 'f' ); unput( 'l' ); unput( 'e' ); unput( 'S' ); } +[,\{\}\|\#\&\:\<\>\[\]\@] { _iState =OPERATOR; return yytext[ 0 ]; } +[\(] { ++_iOpenBracket; _iState =SEPARATOR; return yytext[ 0 ]; } +[\)] { --_iOpenBracket; _iState =SEPARATOR; return yytext[ 0 ]; } {InvalidNumber} BEGIN INVALIDNUM_; yylval.string = yy_strupr( yy_strdup( yytext ) ); ("."|{Separator}+) { diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index 3529ec46b5..0d5f3e8900 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -536,12 +536,12 @@ extern int _iState; /* current parser state (defined in harbour.l */ %token FUNCTION PROCEDURE IDENTIFIER RETURN NIL NUM_DOUBLE INASSIGN NUM_INTEGER NUM_LONG %token LOCAL STATIC IIF IF ELSE ELSEIF END ENDIF LITERAL TRUEVALUE FALSEVALUE %token EXTERN INIT EXIT AND OR NOT PUBLIC EQ NE1 NE2 -%token INC DEC ALIASOP MACROALIAS DOCASE CASE OTHERWISE ENDCASE ENDDO MEMVAR +%token INC DEC ALIASOP DOCASE CASE OTHERWISE ENDCASE ENDDO MEMVAR %token WHILE EXIT LOOP END FOR NEXT TO STEP LE GE FIELD IN PARAMETERS %token PLUSEQ MINUSEQ MULTEQ DIVEQ POWER EXPEQ MODEQ EXITLOOP %token PRIVATE BEGINSEQ BREAK RECOVER USING DO WITH SELF LINE %token AS_NUMERIC AS_CHARACTER AS_LOGICAL AS_DATE AS_ARRAY AS_BLOCK AS_OBJECT DECLARE_FUN -%token DOT +%token DOT MACROALIAS MACROOP /*the lowest precedence*/ /*postincrement and postdecrement*/ @@ -565,7 +565,7 @@ extern int _iState; /* current parser state (defined in harbour.l */ /*preincrement and predecrement*/ %left PRE /*special operators*/ -%left ALIASOP '&' '@' ')' +%left ALIASOP MACROOP '@' ')' %right '\n' ';' ',' /*the highest precedence*/ @@ -573,7 +573,7 @@ extern int _iState; /* current parser state (defined in harbour.l */ %type NUM_DOUBLE %type ArgList ElemList PareExpList ExpList FunCall FunScope IncDec %type Params ParamList Logical ArrExpList -%type NUM_INTEGER BlockExpList Argument IfBegin VarList MethParams ObjFunCall +%type NUM_INTEGER BlockExpList Argument IfBegin VarList MethParams ObjFunCall, ExtVarList %type MethCall BlockList FieldList DoArgList VarAt %type NUM_LONG WhileBegin BlockBegin %type IfElseIf Cases @@ -687,10 +687,8 @@ Statement : ExecFlow Crlf {} } functions.pLast->bFlags |= FUN_WITH_RETURN; } Crlf - | PUBLIC { iVarScope = VS_PUBLIC; } VarList Crlf - | PRIVATE { iVarScope = VS_PRIVATE; } VarList Crlf - | PUBLIC { iVarScope = VS_PUBLIC; } VarMacroList Crlf - | PRIVATE { iVarScope = VS_PRIVATE; } VarMacroList Crlf + | PUBLIC { iVarScope = VS_PUBLIC; } ExtVarList Crlf + | PRIVATE { iVarScope = VS_PRIVATE; } ExtVarList Crlf | EXITLOOP Crlf { LoopExit(); } | LOOP Crlf { LoopLoop(); } @@ -698,11 +696,7 @@ Statement : ExecFlow Crlf {} | EXTERN ExtList Crlf ; -VarMacroList : { SetVarMacro(); } VarMacro { Do( 1 ); } - | VarMacroList ',' { SetVarMacro(); } VarMacro { Do( 1 ); } - ; - -VarMacro : '&' IDENTIFIER { PushId( $2 ); } +VarMacro : MACROOP IDENTIFIER { PushId( $2 ); } | MACROALIAS IDENTIFIER { PushId( $2 ); } | Macro | VarMacro DOT IDENTIFIER { PushString( $3 ); GenPlusPCode( HB_P_PLUS ); } @@ -838,8 +832,8 @@ IfInline : IIF PareExpList3 { GenIfInline(); } | IF PareExpList3 { GenIfInline(); } ; -Macro : '&' Variable - | '&' '(' Expression ')' +Macro : MACROOP Variable + | MACROOP '(' Expression ')' | MACROALIAS Variable | MACROALIAS '(' Expression ')' ; @@ -1089,6 +1083,12 @@ VarDefs : LOCAL { iVarScope = VS_LOCAL; Line(); } VarList Crlf { _cVarType = MemvarList Crlf ; +ExtVarList : VarDef { $$ = 1; } + | ExtVarList ',' VarDef { $$++; } + | { SetVarMacro(); } VarMacro { Do( 1 ); } + | ExtVarList ',' { SetVarMacro(); } VarMacro { Do( 1 ); } + ; + VarList : VarDef { $$ = 1; } | VarList ',' VarDef { $$++; } ; diff --git a/harbour/tests/tstmacro.prg b/harbour/tests/tstmacro.prg index 2ae4642f35..b52ec61231 100644 --- a/harbour/tests/tstmacro.prg +++ b/harbour/tests/tstmacro.prg @@ -4,7 +4,7 @@ Function Main( ) LOCAL cStr := 'cVar', cStr_1 := 'cVar_1', aVar := { 'cVar_1' }, oVar - PRIVATE cVar_1, cMainPrivate := 'cVar_1' + PRIVATE cVar_1, cMainPrivate := 'cVar_1', GlobalPrivate := 'BornInRunTimeVar' &cStr_1 = 'Simple ' ? M->cVar_1 @@ -38,6 +38,8 @@ Function Main( ) ? '"cVar_1" = [' + M->cVar_1 + '] AFTER SubFun() PRIVATE' + ? M->NewPublicVar + RETURN NIL FUNCTION TValue @@ -56,7 +58,6 @@ FUNCTION TValue RETURN( oClass:Instance() ) - STATIC FUNCTION New() LOCAL Self := QSelf() @@ -67,7 +68,16 @@ Function SubFun() ? '"cVar_1" = [' + M->cVar_1 + '] BEFORE SubFun() PRIVATE' - PRIVATE M->&cMainPrivate + // Testing conflict with KEY WORD + PRIVATE PRIVATE := 'I am a Var named PRIVATE ', &cMainPrivate, SomeVar, OtherVar := 1, &GlobalPrivate + PUBLIC PUBLIC := 'My Name is PUBLIC', &( 'NewPublicVar' ) + + M->NewPublicVar := 'Still Alive because I am PUBLIC' + + ? M->PRIVATE + PRIVATE + ? PRIVATE + M->PRIVATE + + ? BornInRunTimeVar &cMainPrivate := 'In SubFun()'