From ba6f7b36679e9bb509b217b3a658998a97a8b4df Mon Sep 17 00:00:00 2001 From: Ron Pinkas Date: Mon, 18 Sep 2000 07:04:53 +0000 Subject: [PATCH] 2000-09-17 23:45 UTC+0800 Ron Pinkas * source/compiler/harbour.l ! Corrected definition of _PROCREQ_() * tests/testdecl.prg - Removed 1 line of unspported syntax. * source/macro/macro.slx * source/compiler/harbour.slx % Greatly optimized, much simplified, smaller, and faster. ! Converted all "non conventional" macros to functions. * source/compiler/simplex.c % Greatly optimized, now as fast as Flex based lexer. ! Converted all "non conventional" macros to functions. + Added support for predefind match pattern, {WS} (White Space), in KEYWORDS and WORDS. + source/compiler/harbour.sly * Same as harbour.y, excluding un-needed support for reserved words used as identifiers. /* Harbour.slx works with either harbour.y or harbour.sly, but harbour.sly creates smaller harbour.exe. */ * hb_slex.bc * Modified to use harbour.sly --- harbour/ChangeLog | 24 + harbour/hb_slex.bc | 2 +- harbour/source/compiler/harbour.l | 2 +- harbour/source/compiler/harbour.slx | 1813 +++++++++++------------- harbour/source/compiler/harbour.sly | 2048 +++++++++++++++++++++++++++ harbour/source/compiler/simplex.c | 1788 +++++++++++------------ harbour/source/macro/macro.slx | 541 ++++--- harbour/tests/testdecl.prg | 2 +- 8 files changed, 4035 insertions(+), 2185 deletions(-) create mode 100644 harbour/source/compiler/harbour.sly diff --git a/harbour/ChangeLog b/harbour/ChangeLog index bcfb48364c..9628bc1f23 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,27 @@ +2000-09-17 23:45 UTC+0800 Ron Pinkas + * source/compiler/harbour.l + ! Corrected definition of _PROCREQ_() + + * tests/testdecl.prg + - Removed 1 line of unspported syntax. + + * source/macro/macro.slx + * source/compiler/harbour.slx + % Greatly optimized, much simplified, smaller, and faster. + ! Converted all "non conventional" macros to functions. + + * source/compiler/simplex.c + % Greatly optimized, now as fast as Flex based lexer. + ! Converted all "non conventional" macros to functions. + + Added support for predefind match pattern, {WS} (White Space), in KEYWORDS and WORDS. + + + source/compiler/harbour.sly + * Same as harbour.y, exclusing un-needed support for reserved words used as identifiers. + /* Harbour.slx works with either harbour.y or harbour.sly, but harbour.sly creates smaller harbour.exe. */ + + * hb_slex.bc + * Modified to use harbour.sly + 2000-09-15 17:45 UTC-0400 David G. Holm * include/hbver.h diff --git a/harbour/hb_slex.bc b/harbour/hb_slex.bc index eaa4557021..f08528c0fa 100644 --- a/harbour/hb_slex.bc +++ b/harbour/hb_slex.bc @@ -730,7 +730,7 @@ $(HARBOUR_EXE) : $(HARBOUR_EXE_OBJS) $(OBJ_DIR)\harbour.obj : $(COMPILER_DIR)\harbour.c $(CC) $(CLIBFLAGS) -o$@ $** -$(OBJ_DIR)\harboury.c : $(COMPILER_DIR)\harbour.y +$(OBJ_DIR)\harboury.c : $(COMPILER_DIR)\harbour.sly bison -d $** -o$@ #$(OBJ_DIR)\harbourl.c : $(COMPILER_DIR)\harbour.l diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index 82c97c3f50..55557f7483 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -456,7 +456,7 @@ Separator {SpaceTab} %{ /* ************************************************************************ */ %} -"_procreq_" { +"_procreq_(" { yylval.string = hb_compIdentifierNew( "_PROCREQ_", TRUE ); hb_comp_iState =IDENTIFIER; return PROCREQ; diff --git a/harbour/source/compiler/harbour.slx b/harbour/source/compiler/harbour.slx index 1ca94c1897..f6d221219e 100644 --- a/harbour/source/compiler/harbour.slx +++ b/harbour/source/compiler/harbour.slx @@ -42,19 +42,404 @@ #define DEBUG_INFO(x) x #endif -#undef LEX_ABBREVIATE_KEYS - #define LEX_ABBREVIATE_KEYS 4 +#undef LEX_ABBREVIATE + #define LEX_ABBREVIATE 4 -#undef LEX_ABBREVIATE_WORDS - #define LEX_ABBREVIATE_WORDS 4 +#undef YY_BUF_SIZE + #define YY_BUF_SIZE HB_PP_STR_SIZE + +static int iTexts = 0, iCloseSquare = 0, iWantsEOL, iWantsEXP, iWantsID, iWantsVAR; +static char * aTexts[ NUMERALS_PER_LINE ]; +static unsigned char iIdentifier = 0; +static char* sIdOnHold; + +long hb_comp_SLX_Hex2L( char* sHex ); +static void hb_comp_SLX_ConvertNumber(void); +static void hb_comp_SLX_EelemntToken(void); + +/* ----------------------------------------------------- Language Definitions. ---------------------------------------------------- */ + +/* Delimiters. */ +ACCEPT_TOKEN_AND_DROP_DELIMITER_IF_ONE_OF_THESE( " \t" ); + +ACCEPT_TOKEN_AND_RETURN_DELIMITERS { + LEX_DELIMITER( ',' ) AS_TOKEN( ',' ), + LEX_DELIMITER( '(' ) AS_TOKEN( '(' ), + LEX_DELIMITER( ')' ) AS_TOKEN( ')' ), + LEX_DELIMITER( '[' ) AS_TOKEN( '[' ), + LEX_DELIMITER( ']' ) AS_TOKEN( ']' + DONT_REDUCE ), + LEX_DELIMITER( '}' ) AS_TOKEN( '}' + DONT_REDUCE ), + LEX_DELIMITER( ':' ) AS_TOKEN( ':' ), + LEX_DELIMITER( '=' ) AS_TOKEN( '=' ), + LEX_DELIMITER( '#' ) AS_TOKEN( NE1 ), + LEX_DELIMITER( '@' ) AS_TOKEN( '@' ), + LEX_DELIMITER( '<' ) AS_TOKEN( '<' + DONT_REDUCE ), + LEX_DELIMITER( '>' ) AS_TOKEN( '>' + DONT_REDUCE ), + LEX_DELIMITER( '!' ) AS_TOKEN( NOT + DONT_REDUCE ), + LEX_DELIMITER( '{' ) AS_TOKEN( '{' + DONT_REDUCE ), + LEX_DELIMITER( '|' ) AS_TOKEN( '|' + DONT_REDUCE ), + LEX_DELIMITER( '^' ) AS_TOKEN( POWER + DONT_REDUCE ), + LEX_DELIMITER( '%' ) AS_TOKEN( '%' + DONT_REDUCE ), + LEX_DELIMITER( '*' ) AS_TOKEN( '*' + DONT_REDUCE ), + LEX_DELIMITER( '/' ) AS_TOKEN( '/' + DONT_REDUCE ), + LEX_DELIMITER( '+' ) AS_TOKEN( '+' + DONT_REDUCE ), + LEX_DELIMITER( '-' ) AS_TOKEN( '-' + DONT_REDUCE ), + LEX_DELIMITER( '$' ) AS_TOKEN( '$' + DONT_REDUCE ) + }; + +/* Custom Intermediate Token needed to be expanded. */ +#define HB_LIT_ACT LEX_CUSTOM_ACTION - 1 +#define HB_NESTED_LIT LEX_CUSTOM_ACTION - 2 +#define HB_QOUT_ACT LEX_CUSTOM_ACTION - 3 +#define HB_RET_QOUT_LIT LEX_CUSTOM_ACTION - 4 + +/* Stream Pairs. */ +DEFINE_STREAM_AS_ONE_OF_THESE { + START_WITH("\"") END_WITH("\"" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_LIT_ACT), + START_WITH("'") END_WITH("'") STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_LIT_ACT), + START_WITH("QOUT([") END_WITH("])\n") STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_QOUT_ACT), + START_WITH("[") END_WITH("]" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(TRUE ) AS_PAIR_TOKEN(HB_LIT_ACT), + START_WITH("[\"") END_WITH("\"]" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_NESTED_LIT), + START_WITH("['") END_WITH("\']" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_NESTED_LIT), + START_WITH("[[") END_WITH("]]" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_NESTED_LIT) + }; + +START_NEW_LINE_IF_ONE_OF_THESE( "\n;" ); + +#define HB_SELF LEX_CUSTOM_ACTION - 5 + +SELF_CONTAINED_WORDS_ARE { + LEX_WORD( ".AND." ) AS_TOKEN( AND + DONT_REDUCE ), + LEX_WORD( ".NOT." ) AS_TOKEN( NOT + DONT_REDUCE ), + LEX_WORD( ".OR." ) AS_TOKEN( OR + DONT_REDUCE ), + LEX_WORD( ":=" ) AS_TOKEN( INASSIGN ), + LEX_WORD( "::" ) AS_TOKEN( HB_SELF ), + LEX_WORD( "==" ) AS_TOKEN( EQ + DONT_REDUCE ), + LEX_WORD( "<>" ) AS_TOKEN( NE2 + DONT_REDUCE ), + LEX_WORD( "<=" ) AS_TOKEN( LE + DONT_REDUCE ), + LEX_WORD( ">=" ) AS_TOKEN( GE + DONT_REDUCE ), + LEX_WORD( "!=" ) AS_TOKEN( NE2 + DONT_REDUCE ), + LEX_WORD( "++" ) AS_TOKEN( INC ), + LEX_WORD( "+=" ) AS_TOKEN( PLUSEQ ), + LEX_WORD( "--" ) AS_TOKEN( DEC ), + LEX_WORD( "-=" ) AS_TOKEN( MINUSEQ ), + LEX_WORD( "->" ) AS_TOKEN( ALIASOP ), + LEX_WORD( "*=" ) AS_TOKEN( MULTEQ ), + LEX_WORD( "**" ) AS_TOKEN( POWER + DONT_REDUCE ), + LEX_WORD( "/=" ) AS_TOKEN( DIVEQ ), + LEX_WORD( "^=" ) AS_TOKEN( EXPEQ ), + LEX_WORD( "%=" ) AS_TOKEN( MODEQ ) + }; + +/* Intermediate Key Words when ambigious. */ +#define DO_WHILE 701 +#define DO_WHILE_WITH 702 + +#define WANTS_EOL 703 +#define WANTS_EXP 704 +#define WANTS_ID 705 +#define WANTS_VAR 706 +#define REJECT_OP 707 + +/* When 2 identifiers are correct syntax like in class declaration, we have to temporarily store the 2nd identifier. */ +#define HB_ID_ON_HOLD LEX_CUSTOM_ACTION - 6 + +#define HB_MACRO_ERR LEX_CUSTOM_ACTION - 7 + +#define HB_INIT_PROC LEX_CUSTOM_ACTION - 8 +#define HB_INIT_FUNC LEX_CUSTOM_ACTION - 9 +#define HB_EXIT_PROC LEX_CUSTOM_ACTION - 10 +#define HB_EXIT_FUNC LEX_CUSTOM_ACTION - 11 +#define HB_STATIC_PROC LEX_CUSTOM_ACTION - 12 +#define HB_STATIC_FUNC LEX_CUSTOM_ACTION - 13 + +#define HB_DO_CASE_ID LEX_CUSTOM_ACTION - 14 + +#define HB_DO_WHILE_ID LEX_CUSTOM_ACTION - 15 +#define HB_DO_WHILE_WITH LEX_CUSTOM_ACTION - 16 + +#define _WITH_ID_CR LEX_CUSTOM_ACTION - 17 +#define _WITH_ID_SEMI LEX_CUSTOM_ACTION - 18 + +#define HB_IN LEX_CUSTOM_ACTION - 19 +#define HB_STEP LEX_CUSTOM_ACTION - 20 +#define HB_TO LEX_CUSTOM_ACTION - 21 +#define HB_WITH LEX_CUSTOM_ACTION - 22 + +#define HB_IDENTIFIER LEX_CUSTOM_ACTION - 23 /* When reservered words are used as Identifier. */ + +#define HB_WANTS_VAR LEX_CUSTOM_ACTION - 512 +#define HB_WANTS_ID LEX_CUSTOM_ACTION - 1024 +#define HB_WANTS_EOL LEX_CUSTOM_ACTION - 1536 +#define HB_WANTS_EXP LEX_CUSTOM_ACTION - 2048 + +/* Wants EOL: ELSE, END, ENDCASE, ENDDO, ENDIF, EXIT, LOOP, NEXT, OTHERWISE, RECOVER */ + +/* Wants Expression: BREAK, CASE, ELSEIF, IF, RETURN, WHILE */ + +/* Wants Identifier: ANNOUNCE, EXTERN, FIELD, FUNCTION, LOCAL, MEMVAR, PARAMETERS, PROCEDURE, STATIC */ + +/* Wants Variable (including Macros): DO, FOR, PRIVATE, PUBLIC */ + +#define USE_KEYWORDS + +/* Key Words. */ +LANGUAGE_KEY_WORDS_ARE { + LEX_WORD( "ANNOUNCE" ) AS_TOKEN( HB_WANTS_ID - ANNOUNCE ), + LEX_WORD( "BEGIN{WS}SEQUENCE" ) AS_TOKEN( BEGINSEQ ), + LEX_WORD( "BREAK" ) AS_TOKEN( HB_WANTS_EXP - BREAK ), + LEX_WORD( "CASE" ) AS_TOKEN( HB_WANTS_EXP - CASE ), + LEX_WORD( "DECLARE" ) AS_TOKEN( DECLARE ), + LEX_WORD( "DO" ) AS_TOKEN( HB_WANTS_VAR - DO ), + LEX_WORD( "DO{WS}CASE" ) AS_TOKEN( DOCASE ), + LEX_WORD( "DO{WS}WHILE" ) AS_TOKEN( DO_WHILE ), + LEX_WORD( "DO{WS}WHILE{WS}WITH" ) AS_TOKEN( DO_WHILE_WITH ), + LEX_WORD( "ELSE" ) AS_TOKEN( HB_WANTS_EOL - ELSE ), + LEX_WORD( "ELSEIF" ) AS_TOKEN( HB_WANTS_EXP - ELSEIF ), + LEX_WORD( "END" ) AS_TOKEN( HB_WANTS_EOL - END ), + LEX_WORD( "ENDCASE" ) AS_TOKEN( HB_WANTS_EOL - ENDCASE ), + LEX_WORD( "ENDDO" ) AS_TOKEN( HB_WANTS_EOL - ENDDO ), + LEX_WORD( "ENDIF" ) AS_TOKEN( HB_WANTS_EOL - ENDIF ), + LEX_WORD( "EXIT" ) AS_TOKEN( HB_WANTS_EOL - EXIT ), + LEX_WORD( "EXIT{WS}FUNCTION" ) AS_TOKEN( HB_EXIT_FUNC ), + LEX_WORD( "EXIT{WS}PROCEDURE" ) AS_TOKEN( HB_EXIT_PROC ), + LEX_WORD( "EXTERNAL" ) AS_TOKEN( HB_WANTS_ID - EXTERN ), + LEX_WORD( "FIELD" ) AS_TOKEN( HB_WANTS_ID - FIELD ), + LEX_WORD( "FOR" ) AS_TOKEN( HB_WANTS_VAR - FOR ), + LEX_WORD( "FUNCTION" ) AS_TOKEN( HB_WANTS_ID - FUNCTION ), + LEX_WORD( "IF" ) AS_TOKEN( HB_WANTS_EXP - IF ), + LEX_WORD( "INIT{WS}FUNCTION" ) AS_TOKEN( HB_INIT_FUNC ), + LEX_WORD( "INIT{WS}PROCEDURE" ) AS_TOKEN( HB_INIT_PROC ), + LEX_WORD( "LOCAL" ) AS_TOKEN( HB_WANTS_ID - LOCAL ), + LEX_WORD( "LOOP" ) AS_TOKEN( HB_WANTS_EOL - LOOP ), + LEX_WORD( "MEMVAR" ) AS_TOKEN( HB_WANTS_ID - MEMVAR ), + LEX_WORD( "NEXT" ) AS_TOKEN( HB_WANTS_EOL - NEXT ), + LEX_WORD( "OTHERWISE" ) AS_TOKEN( HB_WANTS_EOL - OTHERWISE ), + LEX_WORD( "PARAMETERS" ) AS_TOKEN( HB_WANTS_ID - PARAMETERS ), + LEX_WORD( "PRIVATE" ) AS_TOKEN( HB_WANTS_VAR - PRIVATE ), + LEX_WORD( "PROCEDURE" ) AS_TOKEN( HB_WANTS_ID - PROCEDURE ), + LEX_WORD( "PUBLIC" ) AS_TOKEN( HB_WANTS_VAR - PUBLIC ), + LEX_WORD( "RECOVER" ) AS_TOKEN( HB_WANTS_EOL - RECOVER ), + LEX_WORD( "RECOVER{WS}USING" ) AS_TOKEN( RECOVERUSING ), + LEX_WORD( "RETURN" ) AS_TOKEN( HB_WANTS_EXP - RETURN ), + LEX_WORD( "STATIC" ) AS_TOKEN( HB_WANTS_ID - STATIC ), + LEX_WORD( "STATIC{WS}FUNCTION" ) AS_TOKEN( HB_STATIC_FUNC ), + LEX_WORD( "STATIC{WS}PROCEDURE" ) AS_TOKEN( HB_STATIC_PROC ), + LEX_WORD( "WHILE" ) AS_TOKEN( HB_WANTS_EXP - WHILE ), + LEX_WORD( "_HB_CLASS" ) AS_TOKEN( DECLARE_CLASS ), + LEX_WORD( "_HB_MEMBER" ) AS_TOKEN( DECLARE_MEMBER ), + LEX_WORD( "_PROCREQ_" ) AS_TOKEN( PROCREQ ) + }; + +/* Intermediate Words when ambigious. */ +#define QSELF 801 +#define _LINE_ 802 + +/* Words. */ +LANGUAGE_WORDS_ARE { + LEX_WORD( ".F." ) AS_TOKEN( FALSEVALUE + DONT_REDUCE ), + LEX_WORD( ".N." ) AS_TOKEN( FALSEVALUE + DONT_REDUCE ), + LEX_WORD( ".T." ) AS_TOKEN( TRUEVALUE + DONT_REDUCE ), + LEX_WORD( ".Y." ) AS_TOKEN( TRUEVALUE + DONT_REDUCE ), + + LEX_WORD( "AS{WS}ANYTYPE" ) AS_TOKEN( AS_VARIANT + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY" ) AS_TOKEN( AS_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY{WS}OF{WS}ANYTYPE" ) AS_TOKEN( AS_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY{WS}OF{WS}ARRAY" ) AS_TOKEN( AS_ARRAY_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY{WS}OF{WS}CHARACTER" ) AS_TOKEN( AS_CHARACTER_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY{WS}OF{WS}CLASS" ) AS_TOKEN( AS_CLASS_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY{WS}OF{WS}CODEBLOCK" ) AS_TOKEN( AS_BLOCK_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY{WS}OF{WS}DATE" ) AS_TOKEN( AS_DATE_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY{WS}OF{WS}LOGICAL" ) AS_TOKEN( AS_LOGICAL_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY{WS}OF{WS}NUMERIC" ) AS_TOKEN( AS_NUMERIC_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY{WS}OF{WS}OBJECT" ) AS_TOKEN( AS_OBJECT_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY{WS}OF{WS}STRING" ) AS_TOKEN( AS_CHARACTER_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}ARRAY{WS}OF{WS}USUAL" ) AS_TOKEN( AS_CHARACTER_ARRAY + DONT_REDUCE ), + LEX_WORD( "AS{WS}CHARACTER" ) AS_TOKEN( AS_CHARACTER + DONT_REDUCE ), + LEX_WORD( "AS{WS}CLASS" ) AS_TOKEN( AS_CLASS + DONT_REDUCE ), + LEX_WORD( "AS{WS}CODEBLOCK" ) AS_TOKEN( AS_BLOCK + DONT_REDUCE ), + LEX_WORD( "AS{WS}DATE" ) AS_TOKEN( AS_DATE + DONT_REDUCE ), + LEX_WORD( "AS{WS}LOGICAL" ) AS_TOKEN( AS_LOGICAL + DONT_REDUCE ), + LEX_WORD( "AS{WS}NUMERIC" ) AS_TOKEN( AS_NUMERIC + DONT_REDUCE ), + LEX_WORD( "AS{WS}OBJECT" ) AS_TOKEN( AS_OBJECT + DONT_REDUCE ), + LEX_WORD( "AS{WS}STRING" ) AS_TOKEN( AS_CHARACTER + DONT_REDUCE ), + LEX_WORD( "AS{WS}USUAL" ) AS_TOKEN( AS_CHARACTER + DONT_REDUCE ), + + LEX_WORD( "FIELD" ) AS_TOKEN( FIELD ), + LEX_WORD( "IF" ) AS_TOKEN( IIF ), + LEX_WORD( "IIF" ) AS_TOKEN( IIF ), + LEX_WORD( "IN" ) AS_TOKEN( HB_IN ), + LEX_WORD( "LINE" ) AS_TOKEN( _LINE_ ), + LEX_WORD( "NIL" ) AS_TOKEN( NIL + DONT_REDUCE ), + LEX_WORD( "OPTIONAL" ) AS_TOKEN( OPTIONAL ), + LEX_WORD( "QSELF" ) AS_TOKEN( QSELF ), + LEX_WORD( "SELF" ) AS_TOKEN( SELF ), + LEX_WORD( "STEP" ) AS_TOKEN( HB_STEP ), + LEX_WORD( "TO" ) AS_TOKEN( HB_TO ), + LEX_WORD( "WITH" ) AS_TOKEN( HB_WITH ), + LEX_WORD( "_FIELD" ) AS_TOKEN( FIELD ) + }; + +/* Intermediate Reductions when still ambigious or need further reductions. */ +#define _ID_ARRAY 901 +#define _ID_COMMA 902 +#define _ID_CR 903 +#define _ID_SEMI 904 +#define _ID_ASSIGN 905 +#define _WHL_ID_CR 906 +#define _WHL_ID_SEMI 907 +#define _QOUT_LIT 908 + +/* When 2 identifiers are correct syntax like in class declaration, we have to temporarily store the 2nd identifier. */ +#define _ID_ON_HOLD 913 + +LANGUAGE_RULES_ARE { + /* Wants any Var. */ + IF_SEQUENCE_IS( WANTS_VAR , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( WANTS_VAR , MACROVAR , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( WANTS_VAR , MACROTEXT , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( WANTS_VAR , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + + /* Wants Identifier. */ + IF_SEQUENCE_IS( WANTS_ID , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( WANTS_ID , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + + /* Wants EOL */ + IF_SEQUENCE_IS( WANTS_EOL , '\n' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( WANTS_EOL , ';' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( WANTS_EOL , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + + /* Wants Expression ( DOESN'T WANT OPERATORS ) - At BOL, if followed by operator (other than logicals .t., .f., !) than Identifier else COMMAND. */ + IF_SEQUENCE_IS( REJECT_OP , INC , '\n' , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , INC , ';' , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , DEC , '\n' , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , DEC , ';' , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , INASSIGN , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , ALIASOP , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , PLUSEQ , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , MINUSEQ , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , MULTEQ , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , DIVEQ , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , EXPEQ , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , MODEQ , 0 , 0 ) PASS_THROUGH(), + /* IF_SEQUENCE_IS( REJECT_OP , '(' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , '[' , 0 , 0 ) PASS_THROUGH(), DONT uncomment!!!*/ + IF_SEQUENCE_IS( REJECT_OP , '=' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , ':' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( REJECT_OP , 0 , 0 , 0 ) REDUCE_TO( WANTS_EXP + DONT_REDUCE , 0 ), + + IF_SEQUENCE_IS( REJECT_OP , OPTIONAL , 0 , 0 ) REDUCE_TO( WANTS_EXP + DONT_REDUCE , HB_IDENTIFIER ), + IF_SEQUENCE_IS( REJECT_OP , WANTS_ID , 0 , 0 ) REDUCE_TO( WANTS_EXP + DONT_REDUCE , HB_IDENTIFIER ), + IF_SEQUENCE_IS( REJECT_OP , WANTS_EXP , 0 , 0 ) REDUCE_TO( WANTS_EXP + DONT_REDUCE , HB_IDENTIFIER ), + IF_SEQUENCE_IS( REJECT_OP , WANTS_VAR , 0 , 0 ) REDUCE_TO( WANTS_EXP + DONT_REDUCE , HB_IDENTIFIER ), + + + /* Complex */ + + IF_SEQUENCE_IS( DOCASE , '\n' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( DOCASE , ';' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( DOCASE , 0 , 0 , 0 ) REDUCE_TO( HB_DO_CASE_ID , 0 ), + + IF_SEQUENCE_IS( DO_WHILE_WITH, '\n' , 0 , 0 ) REDUCE_TO( WHILE + DONT_REDUCE, _WITH_ID_CR ), + IF_SEQUENCE_IS( DO_WHILE_WITH, ';' , 0 , 0 ) REDUCE_TO( WHILE + DONT_REDUCE, _WITH_ID_SEMI), + IF_SEQUENCE_IS( DO_WHILE_WITH, 0 , 0 , 0 ) REDUCE_TO( HB_DO_WHILE_WITH , 0 ), + + IF_SEQUENCE_IS( DO_WHILE , '\n' , 0 , 0 ) REDUCE_TO( HB_DO_WHILE_ID , '\n' + DONT_REDUCE ), + IF_SEQUENCE_IS( DO_WHILE , ';' , 0 , 0 ) REDUCE_TO( HB_DO_WHILE_ID , ';' + DONT_REDUCE ), + IF_SEQUENCE_IS( DO_WHILE , 0 , 0 , 0 ) REDUCE_TO( WHILE + DONT_REDUCE, 0 ), + + + /* DECLARE as PRIVATE. */ + IF_SEQUENCE_IS( DECLARE , IDENTIFIER , '[' , 0 ) REDUCE_TO( PRIVATE + DONT_REDUCE , _ID_ARRAY ), + IF_SEQUENCE_IS( DECLARE , IDENTIFIER , ',' , 0 ) REDUCE_TO( PRIVATE + DONT_REDUCE , _ID_COMMA ), + IF_SEQUENCE_IS( DECLARE , IDENTIFIER , '\n' , 0 ) REDUCE_TO( PRIVATE + DONT_REDUCE , _ID_CR ), + IF_SEQUENCE_IS( DECLARE , IDENTIFIER , ';' , 0 ) REDUCE_TO( PRIVATE + DONT_REDUCE , _ID_SEMI ), + IF_SEQUENCE_IS( DECLARE , IDENTIFIER ,INASSIGN, 0 ) REDUCE_TO( PRIVATE + DONT_REDUCE , _ID_ASSIGN ), + IF_SEQUENCE_IS( DECLARE , MACROVAR , 0 , 0 ) REDUCE_TO( PRIVATE + DONT_REDUCE , MACROVAR ), + IF_SEQUENCE_IS( DECLARE , MACROTEXT , 0 , 0 ) REDUCE_TO( PRIVATE + DONT_REDUCE , MACROTEXT ), + + /* Any other DECLARE IDENTIFIER, must be Strong Type DECLARE. */ + IF_SEQUENCE_IS( DECLARE , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), + + IF_SEQUENCE_IS( _ID_ON_HOLD , 0 , 0 , 0 ) REDUCE_TO( HB_ID_ON_HOLD , ), + + /* Any other DECLARE must be Identifier. */ + IF_SEQUENCE_IS( DECLARE , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ), + + /* Expnasions from DECLARE ...*/ + IF_SEQUENCE_IS( _ID_ARRAY , 0 , 0 , 0 ) REDUCE_TO( IDENTIFIER + DONT_REDUCE , '[' + DONT_REDUCE ), + IF_SEQUENCE_IS( _ID_COMMA , 0 , 0 , 0 ) REDUCE_TO( IDENTIFIER + DONT_REDUCE , ',' + DONT_REDUCE ), + IF_SEQUENCE_IS( _ID_CR , 0 , 0 , 0 ) REDUCE_TO( IDENTIFIER + DONT_REDUCE , '\n' + DONT_REDUCE ), + IF_SEQUENCE_IS( _ID_SEMI , 0 , 0 , 0 ) REDUCE_TO( IDENTIFIER + DONT_REDUCE , ';' + DONT_REDUCE ), + IF_SEQUENCE_IS( _ID_ASSIGN , 0 , 0 , 0 ) REDUCE_TO( IDENTIFIER + DONT_REDUCE , INASSIGN + DONT_REDUCE ), + + + /* This FIELD is NOT at BOL wants only ->. */ + IF_SEQUENCE_IS( FIELD , ALIASOP , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( FIELD , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + + + IF_SEQUENCE_IS( SELF , ':' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( SELF , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + + IF_SEQUENCE_IS( QSELF , '(' , ')' , 0 ) REDUCE_TO( SELF + DONT_REDUCE, 0 ), + IF_SEQUENCE_IS( QSELF , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + + IF_SEQUENCE_IS( IIF , '(' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( IIF , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + + IF_SEQUENCE_IS( OPTIONAL , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( OPTIONAL , '@' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( OPTIONAL , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + + IF_SEQUENCE_IS( PROCREQ , '(' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( PROCREQ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + + IF_SEQUENCE_IS( NE1 , _LINE_ , 0 , 0 ) REDUCE_TO( LINE + DONT_REDUCE, 0 ), + IF_SEQUENCE_IS( _LINE_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + + IF_SEQUENCE_IS( '&' , '\'' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ), + IF_SEQUENCE_IS( '&' , '"' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ), + IF_SEQUENCE_IS( '&' , '[' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ), + + IF_SEQUENCE_IS( _QOUT_LIT , 0 , 0 , 0 ) REDUCE_TO( HB_RET_QOUT_LIT , 0 ) + }; + +/* ------------------------------------------------- End of Language Definitions. ------------------------------------------------ */ + +/* SimpLex Macros. */ + +#undef LEX_CASE + #define LEX_CASE(x) ( ( ( iRet = (x) ) > 96 && iRet < 123 ) ? iRet - 32 : iRet ) + +#undef NEW_LINE_ACTION + #define NEW_LINE_ACTION() \ + while( iTexts ) \ + { \ + DEBUG_INFO( printf( "Releasing short term Text: %i = %s At: %i\n", iTexts, aTexts[iTexts - 1], aTexts[iTexts - 1] ) ); \ + iTexts--; \ + hb_xfree( aTexts[iTexts] ); \ + }\ + \ + if( ( hb_comp_iLine % 100 ) == 0 && hb_comp_bQuiet == FALSE ) \ + { \ + printf( "\r%i", hb_comp_iLine ); \ + fflush( stdout ); \ + } + +#undef INTERCEPT_ACTION + #define INTERCEPT_ACTION(x) hb_comp_SLX_InterceptAction() + +#undef ELEMENT_TOKEN + #define ELEMENT_TOKEN(x,y) hb_compElementToken() #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 ); -#undef YY_BUF_SIZE - #define YY_BUF_SIZE HB_PP_STR_SIZE +#undef CUSTOM_ACTION + #define CUSTOM_ACTION(x) x = hb_lex_CustomAction( x, aiHold, &iHold, &bIgnoreWords, iLastToken, (char*) sToken ) #undef STREAM_EXCEPTION #define STREAM_EXCEPTION( sPair, cChar ) \ @@ -62,20 +447,20 @@ { \ szBuffer -= ( ( strlen( sPair ) - iCloseSquare ) + 1 ); \ sPair[ iCloseSquare - 1 ] = '\0'; \ - aiReturn[ iReturn++ ] = HB_LIT_ACT; \ + aiHold[ iHold++ ] = HB_LIT_ACT; \ } \ else \ { \ hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_STRING_TERMINATOR, sPair, NULL ); \ - aiReturn[ iReturn++ ] = '\n'; \ + aiHold[ iHold++ ] = '\n'; \ yylval.string = hb_compIdentifierNew( sPair, TRUE ); \ - aiReturn[ iReturn++ ] = LITERAL; \ + aiHold[ iHold++ ] = LITERAL + DONT_REDUCE ; \ } \ #undef STREAM_APPEND #define STREAM_APPEND(x) \ - if( iPairLen == 0 && sStart[1] ) sPair[ iPairLen++ ] = sStart[1]; \ - if( x == ']' && ! iCloseSquare ) iCloseSquare = iPairLen + 1; sPair[ iPairLen++ ] = x + if( iPairLen == 0 && sStart[1] ) { sPair[ iPairLen++ ] = sStart[1]; } \ + if( x == ']' && iCloseSquare == 0 ) { iCloseSquare = iPairLen + 1; } sPair[ iPairLen++ ] = x; #undef STREAM_OPEN #define STREAM_OPEN( sStarter ) \ @@ -89,907 +474,254 @@ } \ if( bTmp ) -#undef KEYWORD_ACTION - #define KEYWORD_ACTION() strncpy( (char*) sWordAsString, (char*) sToken, iWordLen ); sWordAsString[iWordLen] = '\0'; - -#undef WORD_ACTION - #define WORD_ACTION() strncpy( (char*) sWordAsString, (char*) sToken, iWordLen ); sWordAsString[iWordLen] = '\0'; - -static int iTexts = 0, iCloseSquare = 0; -static char * aTexts[ NUMERALS_PER_LINE ]; - -static unsigned char iIdentifier = 0; -static char* sIdOnHold; -static char sWordAsString[11]; - -long hb_lex_Hex2L( char* sHex ); - -/* ----------------------------------------------------- Language Definitions. ---------------------------------------------------- */ - -/* Delimiters. */ -ACCEPT_TOKEN_AND_DROP_DELIMITER_IF_ONE_OF_THESE( " \t" ); -ACCEPT_TOKEN_AND_RETURN_DELIMITER_IF_ONE_OF_THESE( "|,()[]{}^%*/+-:=!<>#@$" ); -DELIMITER_BELONGS_TO_TOKEN_IF_ONE_OF_THESE( "" ); - -/* Custom Action can be requested by setting reduction to LEX_CUSTOM_ACTION or lower. */ - -/* Intermediate Token needed to be expanded. */ -#define HB_LIT_ACT -1001 -#define HB_NESTED_LIT -1002 -#define HB_QOUT_ACT -1003 -#define HB_RET_QOUT_LIT -1004 - -/* Stream Pairs. */ -DEFINE_STREAM_AS_ONE_OF_THESE { - START_WITH("\'") END_WITH("\'") STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_LIT_ACT), - START_WITH("\"") END_WITH("\"" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_LIT_ACT), - START_WITH("[") END_WITH("]" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(TRUE ) AS_PAIR_TOKEN(HB_LIT_ACT), - START_WITH("[\'") END_WITH("\']" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_NESTED_LIT), - START_WITH("[\"") END_WITH("\"]" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_NESTED_LIT), - START_WITH("[[") END_WITH("]]" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_NESTED_LIT), - START_WITH("QOUT([") END_WITH("])\n") STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_QOUT_ACT) - }; - -START_NEW_LINE_IF_ONE_OF_THESE( "\n;" ); - -/* Intermediate Token neede to be expanded. */ -#define _DOT_DOT_ 1001 - -SELF_CONTAINED_WORDS_ARE { - LEX_WORD( ".NOT." ) AS_TOKEN( NOT ), - LEX_WORD( ".AND." ) AS_TOKEN( AND ), - LEX_WORD( ".OR." ) AS_TOKEN( OR ), - LEX_WORD( ":=" ) AS_TOKEN( INASSIGN ), - LEX_WORD( "==" ) AS_TOKEN( EQ ), - LEX_WORD( "<>" ) AS_TOKEN( NE2 ), - LEX_WORD( "!=" ) AS_TOKEN( NE2 ), - LEX_WORD( "++" ) AS_TOKEN( INC ), - LEX_WORD( "--" ) AS_TOKEN( DEC ), - LEX_WORD( "->" ) AS_TOKEN( ALIASOP ), - LEX_WORD( "<=" ) AS_TOKEN( LE ), - LEX_WORD( ">=" ) AS_TOKEN( GE ), - LEX_WORD( "+=" ) AS_TOKEN( PLUSEQ ), - LEX_WORD( "-=" ) AS_TOKEN( MINUSEQ ), - LEX_WORD( "*=" ) AS_TOKEN( MULTEQ ), - LEX_WORD( "/=" ) AS_TOKEN( DIVEQ ), - LEX_WORD( "**" ) AS_TOKEN( POWER ), - LEX_WORD( "^=" ) AS_TOKEN( EXPEQ ), - LEX_WORD( "%=" ) AS_TOKEN( MODEQ ), - LEX_WORD( "::" ) AS_TOKEN( _DOT_DOT_ ) - }; - -/* Intermediate Key Words when ambigious. */ -#define EXIT_ 1002 -#define BEGIN_ 1003 -#define PROCREQ_ 1004 -#define FIELD_ 1005 -#define PRIVATE_ 1006 - -/* When 2 identifiers are correct syntax like in class declaration, we have to temporarily store the 2nd identifier. */ -#define HB_ID_ON_HOLD -1005 - -#define HB_MACRO_ERR -1006 - -#define HB_CHK_NEXT -1007 -#define HB_CHK_EXIT -1008 -#define HB_CHK_LOOP -1009 -#define HB_CHK_IN -1010 - -#define HB_INIT_PROC -1011 -#define HB_EXIT_PROC -1012 -#define HB_INIT_FUNC -1013 -#define HB_EXIT_FUNC -1014 - -#define HB_RET_FUNID -1015 - -/* Key Words. */ -LANGUAGE_KEY_WORDS_ARE { - LEX_WORD( "ANNOUNCE" ) AS_TOKEN( ANNOUNCE ), - LEX_WORD( "BEGIN" ) AS_TOKEN( BEGIN_ ), - LEX_WORD( "BREAK" ) AS_TOKEN( BREAK ), - LEX_WORD( "CASE" ) AS_TOKEN( CASE ), - LEX_WORD( "DECLARE" ) AS_TOKEN( DECLARE + SUSPEND_WORDS ), - LEX_WORD( "DO" ) AS_TOKEN( DO ), - LEX_WORD( "ELSE" ) AS_TOKEN( ELSE ), - LEX_WORD( "ELSEIF" ) AS_TOKEN( ELSEIF ), - LEX_WORD( "END" ) AS_TOKEN( END ), - LEX_WORD( "ENDCASE" ) AS_TOKEN( ENDCASE ), - LEX_WORD( "ENDDO" ) AS_TOKEN( ENDDO ), - LEX_WORD( "ENDIF" ) AS_TOKEN( ENDIF ), - LEX_WORD( "EXIT" ) AS_TOKEN( EXIT_ ), - LEX_WORD( "EXTERNAL" ) AS_TOKEN( EXTERN + SUSPEND_WORDS ), - LEX_WORD( "FIELD" ) AS_TOKEN( FIELD_ + SUSPEND_WORDS ), - LEX_WORD( "FOR" ) AS_TOKEN( FOR + SUSPEND_WORDS ), - LEX_WORD( "FUNCTION" ) AS_TOKEN( FUNCTION + SUSPEND_WORDS ), - LEX_WORD( "IF" ) AS_TOKEN( IF ), - LEX_WORD( "INIT" ) AS_TOKEN( INIT ), - LEX_WORD( "LOCAL" ) AS_TOKEN( LOCAL + SUSPEND_WORDS ), - LEX_WORD( "LOOP" ) AS_TOKEN( LOOP ), - LEX_WORD( "MEMVAR" ) AS_TOKEN( MEMVAR + SUSPEND_WORDS ), - LEX_WORD( "NEXT" ) AS_TOKEN( NEXT ), - LEX_WORD( "OTHERWISE" ) AS_TOKEN( OTHERWISE ), - LEX_WORD( "PARAMETERS" ) AS_TOKEN( PARAMETERS + SUSPEND_WORDS ), - LEX_WORD( "PRIVATE" ) AS_TOKEN( PRIVATE + SUSPEND_WORDS ), - LEX_WORD( "PROCEDURE" ) AS_TOKEN( PROCEDURE + SUSPEND_WORDS ), - LEX_WORD( "PUBLIC" ) AS_TOKEN( PUBLIC + SUSPEND_WORDS ), - LEX_WORD( "RECOVER" ) AS_TOKEN( RECOVER ), - LEX_WORD( "RETURN" ) AS_TOKEN( RETURN ), - LEX_WORD( "STATIC" ) AS_TOKEN( STATIC ), - LEX_WORD( "WHILE" ) AS_TOKEN( WHILE ), - LEX_WORD( "_PROCREQ_" ) AS_TOKEN( PROCREQ_ ), - LEX_WORD( "_HB_CLASS" ) AS_TOKEN( DECLARE_CLASS + SUSPEND_WORDS ), - LEX_WORD( "_HB_MEMBER" ) AS_TOKEN( DECLARE_MEMBER + SUSPEND_WORDS ) - }; - -/* Intermediate Words when ambigious. */ -#define _FUNC_ 2001 -#define _PROC_ 2002 -#define _IF_ 2003 -#define _USING_ 2004 -#define _SEQUENCE_ 2005 -#define _OF_ 2006 -#define QSELF 2007 -#define _LINE_ 2008 -#define _AS_ 2009 -#define _ARRAY_ 2010 -#define _BLOCK_ 2011 -#define _STRING_ 2012 -#define _CLASS_ 2013 -#define _DATE_ 2014 -#define _LOGICAL_ 2015 -#define _NUMERIC_ 2016 -#define _OBJECT_ 2017 -#define _VARIANT_ 2018 -#define _FIELD_ 2019 -#define _FIELD 2020 -#define _CASE_ 2021 -#define _WHILE_ 2022 -#define _WITH_ 2023 -#define _SELF_ 2024 -#define _CHARACTER_ 2025 - -/* Words. */ -LANGUAGE_WORDS_ARE { - LEX_WORD( "ANYTYPE" ) AS_TOKEN( _VARIANT_ ), - LEX_WORD( "ARRAY" ) AS_TOKEN( _ARRAY_ ), - LEX_WORD( "AS" ) AS_TOKEN( _AS_ ), - LEX_WORD( "CASE" ) AS_TOKEN( _CASE_ ), - LEX_WORD( "CHARACTER" ) AS_TOKEN( _CHARACTER_ ), - LEX_WORD( "CLASS" ) AS_TOKEN( _CLASS_ ), - LEX_WORD( "CODEBLOCK" ) AS_TOKEN( _BLOCK_ ), - LEX_WORD( "DATE" ) AS_TOKEN( _DATE_ ), - LEX_WORD( "FIELD" ) AS_TOKEN( _FIELD_ ), - LEX_WORD( "FUNCTION" ) AS_TOKEN( _FUNC_ ), - LEX_WORD( "IF" ) AS_TOKEN( _IF_ ), - LEX_WORD( "IIF" ) AS_TOKEN( IIF ), - LEX_WORD( "IN" ) AS_TOKEN( HB_CHK_IN ), - LEX_WORD( "LINE" ) AS_TOKEN( _LINE_ ), - LEX_WORD( "LOGICAL" ) AS_TOKEN( _LOGICAL_ ), - LEX_WORD( "NIL" ) AS_TOKEN( NIL ), - LEX_WORD( "NUMERIC" ) AS_TOKEN( _NUMERIC_ ), - LEX_WORD( "OBJECT" ) AS_TOKEN( _OBJECT_ ), - LEX_WORD( "OF" ) AS_TOKEN( _OF_ ), - LEX_WORD( "OPTIONAL" ) AS_TOKEN( OPTIONAL + SUSPEND_WORDS ), - LEX_WORD( "PROCEDURE" ) AS_TOKEN( _PROC_ ), - LEX_WORD( "QSELF" ) AS_TOKEN( QSELF ), - LEX_WORD( "SELF" ) AS_TOKEN( _SELF_ ), - LEX_WORD( "SEQUENCE" ) AS_TOKEN( _SEQUENCE_ ), - LEX_WORD( "STEP" ) AS_TOKEN( STEP ), - LEX_WORD( "STRING" ) AS_TOKEN( _STRING_ ), - LEX_WORD( "TO" ) AS_TOKEN( TO ), - LEX_WORD( "USING" ) AS_TOKEN( _USING_ ), - LEX_WORD( "WHILE" ) AS_TOKEN( _WHILE_ ), - LEX_WORD( "WITH" ) AS_TOKEN( _WITH_ ), - LEX_WORD( "_FIELD" ) AS_TOKEN( _FIELD ), - LEX_WORD( ".F." ) AS_TOKEN( FALSEVALUE ), - LEX_WORD( ".N." ) AS_TOKEN( FALSEVALUE ), - LEX_WORD( ".T." ) AS_TOKEN( TRUEVALUE ), - LEX_WORD( ".Y." ) AS_TOKEN( TRUEVALUE ) - }; - -/* When reservered words are used as Identifier. */ -#define HB_IDENTIFIER -2001 -#define HB_SELF_ID -2002 - -/* Intermediate Reductions when still ambigious or need further reductions. */ -#define _WHILE_WITH 3001 -#define _ID_ARRAY 3002 -#define _ID_COMMA 3003 -#define _ID_CR 3004 -#define _ID_SEMI 3005 -#define _ID_ASSIGN 3006 -#define _ID_AS 3007 -#define _CASE_WITH 3008 -#define _WHL_ID_CR 3009 -#define _WHL_ID_SEMI 3010 -#define _VAR_ARRAY 3011 -#define _TEXT_ARRAY 3012 -#define _INC_CR 3013 -#define _INC_SEMI 3014 -#define _DEC_CR 3015 -#define _DEC_SEMI 3016 - -#define HB_QOUT_LIT 3017 - -LANGUAGE_RULES_ARE { - IF_SEQUENCE_IS( '^' , 0 , 0 , 0 ) REDUCE_TO( POWER , 0 ), - IF_SEQUENCE_IS( '!' , 0 , 0 , 0 ) REDUCE_TO( NOT , 0 ), - - IF_SEQUENCE_IS( _AS_ , _ARRAY_ , 0 , 0 ) REDUCE_TO( AS_ARRAY , 0 ), - IF_SEQUENCE_IS( _AS_ , _BLOCK_ , 0 , 0 ) REDUCE_TO( AS_BLOCK , 0 ), - IF_SEQUENCE_IS( _AS_ , _CHARACTER_ , 0 , 0 ) REDUCE_TO( AS_CHARACTER , 0 ), - IF_SEQUENCE_IS( _AS_ , _STRING_ , 0 , 0 ) REDUCE_TO( AS_CHARACTER , 0 ), - IF_SEQUENCE_IS( _AS_ , _CLASS_ , 0 , 0 ) REDUCE_TO( AS_CLASS , 0 ), - IF_SEQUENCE_IS( _AS_ , _DATE_ , 0 , 0 ) REDUCE_TO( AS_DATE , 0 ), - IF_SEQUENCE_IS( _AS_ , _LOGICAL_ , 0 , 0 ) REDUCE_TO( AS_LOGICAL , 0 ), - IF_SEQUENCE_IS( _AS_ , _NUMERIC_ , 0 , 0 ) REDUCE_TO( AS_NUMERIC , 0 ), - IF_SEQUENCE_IS( _AS_ , _OBJECT_ , 0 , 0 ) REDUCE_TO( AS_OBJECT , 0 ), - IF_SEQUENCE_IS( _AS_ , _VARIANT_ , 0 , 0 ) REDUCE_TO( AS_VARIANT , 0 ), - - IF_SEQUENCE_IS( _AS_ , _ARRAY_ , _OF_ , _ARRAY_ ) REDUCE_TO( AS_ARRAY_ARRAY , 0 ), - IF_SEQUENCE_IS( _AS_ , _ARRAY_ , _OF_ , _VARIANT_ ) REDUCE_TO( AS_ARRAY_ARRAY , 0 ), - IF_SEQUENCE_IS( _AS_ , _ARRAY_ , _OF_ , _BLOCK_ ) REDUCE_TO( AS_BLOCK_ARRAY , 0 ), - IF_SEQUENCE_IS( _AS_ , _ARRAY_ , _OF_ , _STRING_ ) REDUCE_TO( AS_CHARACTER_ARRAY, 0 ), - IF_SEQUENCE_IS( _AS_ , _ARRAY_ , _OF_ , _CHARACTER_) REDUCE_TO( AS_CHARACTER_ARRAY, 0 ), - IF_SEQUENCE_IS( _AS_ , _ARRAY_ , _OF_ , _CLASS_ ) REDUCE_TO( AS_CLASS_ARRAY , 0 ), - IF_SEQUENCE_IS( _AS_ , _ARRAY_ , _OF_ , _DATE_ ) REDUCE_TO( AS_DATE_ARRAY , 0 ), - IF_SEQUENCE_IS( _AS_ , _ARRAY_ , _OF_ , _LOGICAL_ ) REDUCE_TO( AS_LOGICAL_ARRAY , 0 ), - IF_SEQUENCE_IS( _AS_ , _ARRAY_ , _OF_ , _NUMERIC_ ) REDUCE_TO( AS_NUMERIC_ARRAY , 0 ), - IF_SEQUENCE_IS( _AS_ , _ARRAY_ , _OF_ , _OBJECT_ ) REDUCE_TO( AS_OBJECT_ARRAY , 0 ), - - /* Treat as Identifiers when not qualified with the AS qualifier. */ - IF_SEQUENCE_IS( _AS_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _OF_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _ARRAY_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _VARIANT_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _BLOCK_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _STRING_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _CHARACTER_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _CLASS_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _DATE_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _LOGICAL_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _NUMERIC_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _OBJECT_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( FUNCTION , IDENTIFIER , 0 , 0 ) REDUCE_TO( HB_RET_FUNID , 0 ), - IF_SEQUENCE_IS( FUNCTION , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( FUNCTION , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( PROCEDURE , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( PROCEDURE , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( PROCEDURE , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( EXTERN , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( EXTERN , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( EXTERN , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( END , INASSIGN , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INASSIGN ), - IF_SEQUENCE_IS( END , INC , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INC ), - IF_SEQUENCE_IS( END , DEC , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DEC ), - IF_SEQUENCE_IS( END , ALIASOP , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ALIASOP ), - IF_SEQUENCE_IS( END , PLUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , PLUSEQ ), - IF_SEQUENCE_IS( END , MINUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MINUSEQ ), - IF_SEQUENCE_IS( END , MULTEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MULTEQ ), - IF_SEQUENCE_IS( END , DIVEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DIVEQ ), - IF_SEQUENCE_IS( END , EXPEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , EXPEQ ), - IF_SEQUENCE_IS( END , MODEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MODEQ ), - IF_SEQUENCE_IS( END , '(' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '(' ), - IF_SEQUENCE_IS( END , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( END , '=' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '=' ), - IF_SEQUENCE_IS( END , ':' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ':' ), - IF_SEQUENCE_IS( END , _SEQUENCE_ , 0 , 0 ) REDUCE_TO( END , 0 ), - IF_SEQUENCE_IS( END , 0 , 0 , 0 ) PASS_THROUGH(), - - /* DECLARE as PRIVATE. */ - IF_SEQUENCE_IS( DECLARE , IDENTIFIER , '[' , 0 ) REDUCE_TO( PRIVATE , _ID_ARRAY ), - IF_SEQUENCE_IS( DECLARE , IDENTIFIER , ',' , 0 ) REDUCE_TO( PRIVATE , _ID_COMMA ), - IF_SEQUENCE_IS( DECLARE , IDENTIFIER , '\n' , 0 ) REDUCE_TO( PRIVATE , _ID_CR ), - IF_SEQUENCE_IS( DECLARE , IDENTIFIER , ';' , 0 ) REDUCE_TO( PRIVATE , _ID_SEMI ), - IF_SEQUENCE_IS( DECLARE , IDENTIFIER ,INASSIGN, 0 ) REDUCE_TO( PRIVATE , _ID_ASSIGN ), - IF_SEQUENCE_IS( DECLARE , IDENTIFIER ,_AS_ , 0 ) REDUCE_TO( PRIVATE , _ID_AS ), - IF_SEQUENCE_IS( DECLARE , MACROVAR , 0 , 0 ) REDUCE_TO( PRIVATE , MACROVAR ), - IF_SEQUENCE_IS( DECLARE , MACROTEXT , 0 , 0 ) REDUCE_TO( PRIVATE , MACROTEXT ), - IF_SEQUENCE_IS( _ID_ARRAY , 0 , 0 , 0 ) REDUCE_TO( IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _ID_COMMA , 0 , 0 , 0 ) REDUCE_TO( IDENTIFIER , ',' ), - IF_SEQUENCE_IS( _ID_CR , 0 , 0 , 0 ) REDUCE_TO( IDENTIFIER , '\n' ), - IF_SEQUENCE_IS( _ID_SEMI , 0 , 0 , 0 ) REDUCE_TO( IDENTIFIER , ';' ), - IF_SEQUENCE_IS( _ID_ASSIGN , 0 , 0 , 0 ) REDUCE_TO( IDENTIFIER , INASSIGN ), - IF_SEQUENCE_IS( _ID_AS , 0 , 0 , 0 ) REDUCE_TO( IDENTIFIER , _AS_ ), - - /* Anything DECLARE IDENTIFIER, must be Strong Type DECLARE. */ - IF_SEQUENCE_IS( DECLARE , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), - - /* Anthing else, DECLARE as Identifier. */ - IF_SEQUENCE_IS( DECLARE , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( DECLARE , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ), - - IF_SEQUENCE_IS( PUBLIC , IDENTIFIER , '[' , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( PUBLIC , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( PUBLIC , MACROVAR , '[' , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( PUBLIC , MACROVAR , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( PUBLIC , MACROTEXT , '[' , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( PUBLIC , MACROTEXT , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( PUBLIC , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( PUBLIC , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( PRIVATE_ , IDENTIFIER , '[' , 0 ) REDUCE_TO( PRIVATE , _ID_ARRAY ), - IF_SEQUENCE_IS( PRIVATE_ , IDENTIFIER , 0 , 0 ) REDUCE_TO( PRIVATE , IDENTIFIER ), - IF_SEQUENCE_IS( PRIVATE_ , MACROVAR , '[' , 0 ) REDUCE_TO( PRIVATE , _VAR_ARRAY ), - IF_SEQUENCE_IS( PRIVATE_ , MACROVAR , 0 , 0 ) REDUCE_TO( PRIVATE , MACROVAR ), - IF_SEQUENCE_IS( PRIVATE_ , MACROTEXT , '[' , 0 ) REDUCE_TO( PRIVATE , _TEXT_ARRAY ), - IF_SEQUENCE_IS( PRIVATE_ , MACROTEXT , 0 , 0 ) REDUCE_TO( PRIVATE , MACROTEXT ), - IF_SEQUENCE_IS( PRIVATE_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( PRIVATE_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _VAR_ARRAY , 0 , 0 , 0 ) REDUCE_TO( MACROVAR , '[' ), - IF_SEQUENCE_IS( _TEXT_ARRAY , 0 , 0 , 0 ) REDUCE_TO( MACROTEXT , '[' ), - - IF_SEQUENCE_IS( LOCAL , IDENTIFIER , '[' , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( LOCAL , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( LOCAL , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( LOCAL , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - /* STATIC Func/Proc. */ - IF_SEQUENCE_IS( STATIC , _PROC_ , 0 , 0 ) REDUCE_TO( STATIC , PROCEDURE ), - IF_SEQUENCE_IS( STATIC , _FUNC_ , 0 , 0 ) REDUCE_TO( STATIC , FUNCTION ), - - /* STATIC IDENTIFIER - Exclusion works best here because we may also have STATIC Func/Proc (above). */ - IF_SEQUENCE_IS( STATIC , INASSIGN , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INASSIGN ), - IF_SEQUENCE_IS( STATIC , INC , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INC ), - IF_SEQUENCE_IS( STATIC , DEC , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DEC ), - IF_SEQUENCE_IS( STATIC , ALIASOP , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ALIASOP ), - IF_SEQUENCE_IS( STATIC , PLUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , PLUSEQ ), - IF_SEQUENCE_IS( STATIC , MINUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MINUSEQ ), - IF_SEQUENCE_IS( STATIC , MULTEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MULTEQ ), - IF_SEQUENCE_IS( STATIC , DIVEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DIVEQ ), - IF_SEQUENCE_IS( STATIC , EXPEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , EXPEQ ), - IF_SEQUENCE_IS( STATIC , MODEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MODEQ ), - IF_SEQUENCE_IS( STATIC , '(' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '(' ), - IF_SEQUENCE_IS( STATIC , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( STATIC , '=' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '=' ), - IF_SEQUENCE_IS( STATIC , ':' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ':' ), - IF_SEQUENCE_IS( STATIC , ';' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ';' ), - IF_SEQUENCE_IS( STATIC , 0 , 0 , 0 ) PASS_THROUGH(), - - IF_SEQUENCE_IS( MEMVAR , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( MEMVAR , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( MEMVAR , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( FIELD_ , IDENTIFIER , 0 , 0 ) REDUCE_TO( FIELD , IDENTIFIER ), - IF_SEQUENCE_IS( FIELD_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( FIELD_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( PARAMETERS , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( PARAMETERS , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( PARAMETERS , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - /* This _FIELD_ is FIELD NOT at BOL wants only ->. */ - IF_SEQUENCE_IS( _FIELD_ , ALIASOP , 0 , 0 ) REDUCE_TO( FIELD , ALIASOP ), - IF_SEQUENCE_IS( _FIELD_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _FIELD_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - /* This _FIELD is _FIELD NOT at BOL wants only ->. */ - IF_SEQUENCE_IS( _FIELD , ALIASOP , 0 , 0 ) REDUCE_TO( FIELD , ALIASOP ), - IF_SEQUENCE_IS( _FIELD , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _FIELD , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( OTHERWISE , '\n' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( OTHERWISE , ';' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( OTHERWISE , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( OTHERWISE , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( RETURN , INASSIGN , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INASSIGN ), - IF_SEQUENCE_IS( RETURN , INC , '\n' , 0 ) REDUCE_TO( HB_IDENTIFIER , _INC_CR ), - IF_SEQUENCE_IS( RETURN , INC , ';' , 0 ) REDUCE_TO( HB_IDENTIFIER , _INC_SEMI ), - IF_SEQUENCE_IS( RETURN , DEC , '\n' , 0 ) REDUCE_TO( HB_IDENTIFIER , _DEC_CR ), - IF_SEQUENCE_IS( RETURN , DEC , ';' , 0 ) REDUCE_TO( HB_IDENTIFIER , _DEC_SEMI ), - IF_SEQUENCE_IS( RETURN , ALIASOP , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ALIASOP ), - IF_SEQUENCE_IS( RETURN , PLUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , PLUSEQ ), - IF_SEQUENCE_IS( RETURN , MINUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MINUSEQ ), - IF_SEQUENCE_IS( RETURN , MULTEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MULTEQ ), - IF_SEQUENCE_IS( RETURN , DIVEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DIVEQ ), - IF_SEQUENCE_IS( RETURN , EXPEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , EXPEQ ), - IF_SEQUENCE_IS( RETURN , MODEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MODEQ ), - /* IF_SEQUENCE_IS( RETURN , '(' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '(' ), - IF_SEQUENCE_IS( RETURN , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), */ - IF_SEQUENCE_IS( RETURN , '=' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '=' ), - IF_SEQUENCE_IS( RETURN , ':' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ':' ), - IF_SEQUENCE_IS( RETURN , 0 , 0 , 0 ) PASS_THROUGH(), - - IF_SEQUENCE_IS( FOR , IDENTIFIER , '[' , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( FOR , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( FOR , MACROVAR , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( FOR , MACROTEXT , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( FOR , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( FOR , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( NEXT , '\n' , 0 , 0 ) REDUCE_TO( HB_CHK_NEXT , '\n' ), - IF_SEQUENCE_IS( NEXT , ';' , 0 , 0 ) REDUCE_TO( HB_CHK_NEXT , ';' ), - IF_SEQUENCE_IS( NEXT , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( NEXT , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( EXIT_ , '\n' , 0 , 0 ) REDUCE_TO( HB_CHK_EXIT , '\n' ), - IF_SEQUENCE_IS( EXIT_ , ';' , 0 , 0 ) REDUCE_TO( HB_CHK_EXIT , ';' ), - - IF_SEQUENCE_IS( INIT , _PROC_ , 0 , 0 ) REDUCE_TO( HB_INIT_PROC , 0 ), - IF_SEQUENCE_IS( INIT , _FUNC_ , 0 , 0 ) REDUCE_TO( HB_INIT_FUNC , 0 ), - IF_SEQUENCE_IS( INIT , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( INIT , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( EXIT_ , _PROC_ , 0 , 0 ) REDUCE_TO( HB_EXIT_PROC , 0 ), - IF_SEQUENCE_IS( EXIT_ , _FUNC_ , 0 , 0 ) REDUCE_TO( HB_EXIT_FUNC , 0 ), - IF_SEQUENCE_IS( EXIT_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( EXIT_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - /* LOOP at BOL if followed by anything other the NEW LINE than Identifier else LOOP. */ - IF_SEQUENCE_IS( LOOP , '\n' , 0 , 0 ) REDUCE_TO( HB_CHK_LOOP , '\n' ), - IF_SEQUENCE_IS( LOOP , ';' , 0 , 0 ) REDUCE_TO( HB_CHK_LOOP , ';' ), - IF_SEQUENCE_IS( LOOP , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( LOOP , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - /* --------------------------- BEGIN SEQUENCE ; BREAK ; RECOVER ; RECOVER USING --------------------------- */ - IF_SEQUENCE_IS( BEGIN_ , _SEQUENCE_ , 0 , 0 ) REDUCE_TO( BEGINSEQ , 0 ), - IF_SEQUENCE_IS( BEGIN_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( BEGIN_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _SEQUENCE_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( BREAK , INASSIGN , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INASSIGN ), - IF_SEQUENCE_IS( BREAK , INC , '\n' , 0 ) REDUCE_TO( HB_IDENTIFIER , _INC_CR ), - IF_SEQUENCE_IS( BREAK , INC , ';' , 0 ) REDUCE_TO( HB_IDENTIFIER , _INC_SEMI ), - IF_SEQUENCE_IS( BREAK , DEC , '\n' , 0 ) REDUCE_TO( HB_IDENTIFIER , _DEC_CR ), - IF_SEQUENCE_IS( BREAK , DEC , ';' , 0 ) REDUCE_TO( HB_IDENTIFIER , _DEC_SEMI ), - IF_SEQUENCE_IS( BREAK , ALIASOP , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ALIASOP ), - IF_SEQUENCE_IS( BREAK , PLUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , PLUSEQ ), - IF_SEQUENCE_IS( BREAK , MINUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MINUSEQ ), - IF_SEQUENCE_IS( BREAK , MULTEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MULTEQ ), - IF_SEQUENCE_IS( BREAK , DIVEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DIVEQ ), - IF_SEQUENCE_IS( BREAK , EXPEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , EXPEQ ), - IF_SEQUENCE_IS( BREAK , MODEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MODEQ ), - /* IF_SEQUENCE_IS( BREAK , '(' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '(' ), - IF_SEQUENCE_IS( BREAK , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), */ - IF_SEQUENCE_IS( BREAK , '=' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '=' ), - IF_SEQUENCE_IS( BREAK , ':' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ':' ), - IF_SEQUENCE_IS( BREAK , 0 , 0 , 0 ) PASS_THROUGH(), - - IF_SEQUENCE_IS( RECOVER , _USING_ , 0 , 0 ) REDUCE_TO( RECOVERUSING , 0 ), - IF_SEQUENCE_IS( RECOVER , '\n' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( RECOVER , ';' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( RECOVER , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( RECOVER , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - IF_SEQUENCE_IS( _USING_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _USING_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - /* -------------------------- DO WHILE; WHILE ; DO CASE ; CASE; DO ... ; DO ... WITH ----------------------- */ - IF_SEQUENCE_IS( DO , _WHILE_ , _WITH_ , 0 ) REDUCE_TO( DO , _WHILE_WITH ), - IF_SEQUENCE_IS( DO , _CASE_ , _WITH_ , 0 ) REDUCE_TO( DO , _CASE_WITH ), - IF_SEQUENCE_IS( DO , _WHILE_ , '\n' , 0 ) REDUCE_TO( DO , _WHL_ID_CR ), - IF_SEQUENCE_IS( DO , _WHILE_ , ';' , 0 ) REDUCE_TO( DO , _WHL_ID_SEMI ), - IF_SEQUENCE_IS( DO , _WITH_ , 0 , 0 ) REDUCE_TO( DO , HB_IDENTIFIER ), - IF_SEQUENCE_IS( DO , OPTIONAL , 0 , 0 ) REDUCE_TO( DO , HB_IDENTIFIER ), - IF_SEQUENCE_IS( DO , IN , 0 , 0 ) REDUCE_TO( DO , HB_IDENTIFIER ), - IF_SEQUENCE_IS( DO , _WHILE_ , 0 , 0 ) REDUCE_TO( WHILE , 0 ), - IF_SEQUENCE_IS( _WHILE_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _WHILE_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( _WHILE_WITH , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , WITH ), - IF_SEQUENCE_IS( _CASE_WITH , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , WITH ), - IF_SEQUENCE_IS( _WHL_ID_CR , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '\n' ), - IF_SEQUENCE_IS( _WHL_ID_SEMI, 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ';' ), - - /* This WHILE is only at BOL if followed by operator (other than logicals .t., .f., !) than Identifier else CASE. */ - IF_SEQUENCE_IS( WHILE , INASSIGN , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INASSIGN ), - IF_SEQUENCE_IS( WHILE , INC , '\n' , 0 ) REDUCE_TO( HB_IDENTIFIER , _INC_CR ), - IF_SEQUENCE_IS( WHILE , INC , ';' , 0 ) REDUCE_TO( HB_IDENTIFIER , _INC_SEMI ), - IF_SEQUENCE_IS( WHILE , DEC , '\n' , 0 ) REDUCE_TO( HB_IDENTIFIER , _DEC_CR ), - IF_SEQUENCE_IS( WHILE , DEC , ';' , 0 ) REDUCE_TO( HB_IDENTIFIER , _DEC_SEMI ), - IF_SEQUENCE_IS( WHILE , ALIASOP , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ALIASOP ), - IF_SEQUENCE_IS( WHILE , PLUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , PLUSEQ ), - IF_SEQUENCE_IS( WHILE , MINUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MINUSEQ ), - IF_SEQUENCE_IS( WHILE , MULTEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MULTEQ ), - IF_SEQUENCE_IS( WHILE , DIVEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DIVEQ ), - IF_SEQUENCE_IS( WHILE , EXPEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , EXPEQ ), - IF_SEQUENCE_IS( WHILE , MODEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MODEQ ), - /* IF_SEQUENCE_IS( WHILE , '(' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '(' ), - IF_SEQUENCE_IS( WHILE , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), */ - IF_SEQUENCE_IS( WHILE , '=' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '=' ), - IF_SEQUENCE_IS( WHILE , ':' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ':' ), - IF_SEQUENCE_IS( WHILE , 0 , 0 , 0 ) PASS_THROUGH(), - - IF_SEQUENCE_IS( DO , _CASE_ , 0 , 0 ) REDUCE_TO( DOCASE , 0 ), - IF_SEQUENCE_IS( _CASE_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _CASE_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - /* This CASE is only at BOL if followed by operator (other than logicals .t., .f., !) than Identifier else CASE. */ - IF_SEQUENCE_IS( CASE , INASSIGN , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INASSIGN ), - IF_SEQUENCE_IS( CASE , INC , '\n' , 0 ) REDUCE_TO( HB_IDENTIFIER , _INC_CR ), - IF_SEQUENCE_IS( CASE , INC , ';' , 0 ) REDUCE_TO( HB_IDENTIFIER , _INC_SEMI ), - IF_SEQUENCE_IS( CASE , DEC , '\n' , 0 ) REDUCE_TO( HB_IDENTIFIER , _DEC_CR ), - IF_SEQUENCE_IS( CASE , DEC , ';' , 0 ) REDUCE_TO( HB_IDENTIFIER , _DEC_SEMI ), - IF_SEQUENCE_IS( CASE , ALIASOP , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ALIASOP ), - IF_SEQUENCE_IS( CASE , PLUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , PLUSEQ ), - IF_SEQUENCE_IS( CASE , MINUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MINUSEQ ), - IF_SEQUENCE_IS( CASE , MULTEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MULTEQ ), - IF_SEQUENCE_IS( CASE , DIVEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DIVEQ ), - IF_SEQUENCE_IS( CASE , EXPEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , EXPEQ ), - IF_SEQUENCE_IS( CASE , MODEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MODEQ ), - /* IF_SEQUENCE_IS( CASE , '(' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '(' ), - IF_SEQUENCE_IS( CASE , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), */ - IF_SEQUENCE_IS( CASE , '=' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '=' ), - IF_SEQUENCE_IS( CASE , ':' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ':' ), - IF_SEQUENCE_IS( CASE , 0 , 0 , 0 ) PASS_THROUGH(), - - IF_SEQUENCE_IS( _INC_CR , 0 , 0 , 0 ) REDUCE_TO( INC , '\n' ), - IF_SEQUENCE_IS( _INC_SEMI , 0 , 0 , 0 ) REDUCE_TO( INC , ';' ), - IF_SEQUENCE_IS( _DEC_CR , 0 , 0 , 0 ) REDUCE_TO( DEC , '\n' ), - IF_SEQUENCE_IS( _DEC_SEMI , 0 , 0 , 0 ) REDUCE_TO( DEC , ';' ), - - /* This _WITH_ is not at BOL. */ - IF_SEQUENCE_IS( IDENTIFIER , _WITH_ , 0 , 0 ) REDUCE_TO( IDENTIFIER , WITH ), - IF_SEQUENCE_IS( MACROVAR , _WITH_ , 0 , 0 ) REDUCE_TO( MACROVAR , WITH ), - IF_SEQUENCE_IS( MACROTEXT , _WITH_ , 0 , 0 ) REDUCE_TO( MACROTEXT , WITH ), - IF_SEQUENCE_IS( ')' , _WITH_ , 0 , 0 ) REDUCE_TO( ')' , WITH ), - IF_SEQUENCE_IS( _WITH_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _WITH_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( DO , INASSIGN , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INASSIGN ), - IF_SEQUENCE_IS( DO , INC , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INC ), - IF_SEQUENCE_IS( DO , DEC , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DEC ), - IF_SEQUENCE_IS( DO , ALIASOP , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ALIASOP ), - IF_SEQUENCE_IS( DO , PLUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , PLUSEQ ), - IF_SEQUENCE_IS( DO , MINUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MINUSEQ ), - IF_SEQUENCE_IS( DO , MULTEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MULTEQ ), - IF_SEQUENCE_IS( DO , DIVEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DIVEQ ), - IF_SEQUENCE_IS( DO , EXPEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , EXPEQ ), - IF_SEQUENCE_IS( DO , MODEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MODEQ ), - IF_SEQUENCE_IS( DO , '(' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '(' ), - IF_SEQUENCE_IS( DO , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( DO , '=' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '=' ), - IF_SEQUENCE_IS( DO , ':' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ':' ), - IF_SEQUENCE_IS( DO , ';' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ';' ), - IF_SEQUENCE_IS( DO , 0 , 0 , 0 ) PASS_THROUGH(), - /* ---------------------- End of: DO WHILE; WHILE ; DO CASE ; CASE; DO ... ; DO ... WITH ------------------- */ - - /* This IF is only at BOL if followed by operator (other than logicals .t., .f., !) than Identifier else IF. */ - IF_SEQUENCE_IS( IF , INASSIGN , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INASSIGN ), - IF_SEQUENCE_IS( IF , INC , '\n' , 0 ) REDUCE_TO( HB_IDENTIFIER , _INC_CR ), - IF_SEQUENCE_IS( IF , INC , ';' , 0 ) REDUCE_TO( HB_IDENTIFIER , _INC_SEMI ), - IF_SEQUENCE_IS( IF , DEC , '\n' , 0 ) REDUCE_TO( HB_IDENTIFIER , _DEC_CR ), - IF_SEQUENCE_IS( IF , DEC , ';' , 0 ) REDUCE_TO( HB_IDENTIFIER , _DEC_SEMI ), - IF_SEQUENCE_IS( IF , ALIASOP , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ALIASOP ), - IF_SEQUENCE_IS( IF , PLUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , PLUSEQ ), - IF_SEQUENCE_IS( IF , MINUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MINUSEQ ), - IF_SEQUENCE_IS( IF , MULTEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MULTEQ ), - IF_SEQUENCE_IS( IF , DIVEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DIVEQ ), - IF_SEQUENCE_IS( IF , EXPEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , EXPEQ ), - IF_SEQUENCE_IS( IF , MODEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MODEQ ), - /* IF_SEQUENCE_IS( IF , '(' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '(' ), - IF_SEQUENCE_IS( IF , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), */ - IF_SEQUENCE_IS( IF , '=' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '=' ), - IF_SEQUENCE_IS( IF , ':' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ':' ), - IF_SEQUENCE_IS( IF , 0 , 0 , 0 ) PASS_THROUGH(), - - IF_SEQUENCE_IS( PROCREQ_ , '(' , 0 , 0 ) REDUCE_TO( PROCREQ , 0 ), - IF_SEQUENCE_IS( PROCREQ_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( PROCREQ_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - /* Left Associate '[' to seperate from string delimiter. */ - IF_SEQUENCE_IS( IDENTIFIER , '[' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( MACROVAR , '[' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( MACROTEXT , '[' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( ')' , '[' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( ']' , '[' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( '}' , '[' , 0 , 0 ) PASS_THROUGH(), - - IF_SEQUENCE_IS( _DOT_DOT_ , 0 , 0 , 0 ) REDUCE_TO( HB_SELF_ID , ':' ), - - IF_SEQUENCE_IS( _SELF_ , ':' , 0 , 0 ) REDUCE_TO( SELF , ':' ), - IF_SEQUENCE_IS( _SELF_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _SELF_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( QSELF , '(' , ')' , 0 ) REDUCE_TO( SELF , 0 ), - IF_SEQUENCE_IS( QSELF , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( QSELF , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( '#' , _LINE_ , 0 , 0 ) REDUCE_TO( LINE , 0 ), - IF_SEQUENCE_IS( '#' , 0 , 0 , 0 ) REDUCE_TO( NE1 , 0 ), - IF_SEQUENCE_IS( _LINE_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _LINE_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( _IF_ , '(' , 0 , 0 ) REDUCE_TO( IIF , '(' ), - IF_SEQUENCE_IS( _IF_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _IF_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( IIF , '(' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( IIF , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( IIF , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( OPTIONAL , IDENTIFIER , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( OPTIONAL , '@' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( OPTIONAL , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( '&' , '\'' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ), - IF_SEQUENCE_IS( '&' , '"' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ), - IF_SEQUENCE_IS( '&' , '[' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ), - - IF_SEQUENCE_IS( HB_QOUT_LIT , 0 , 0 , 0 ) REDUCE_TO( HB_RET_QOUT_LIT , 0 ) - }; - -/* ------------------------------------------------- End of Language Definitions. ------------------------------------------------ */ - -/* SimpLex Macros. */ - -#undef LEX_CASE - #define LEX_CASE(x) toupper(x) - -#undef NEW_LINE_ACTION - #define NEW_LINE_ACTION() \ - while( iTexts ) \ - { \ - DEBUG_INFO( printf( "Releasing short term Text: %i = %s At: %i\n", iTexts, aTexts[iTexts - 1], aTexts[iTexts - 1] ) ); \ - iTexts--; \ - hb_xfree( aTexts[iTexts] ); \ - }\ - \ - if( ! hb_comp_bQuiet && ( hb_comp_iLine % 100 ) == 0 ) \ - { \ - printf( "\r%i", hb_comp_iLine ); \ - fflush( stdout ); \ - } - -#ifdef SHOW_LEX_TOKENS - #undef INTERCEPT_ACTION - #define INTERCEPT_ACTION(x) \ - \ - yytext = sToken; \ - if( x == IDENTIFIER ) \ - { \ - if( iIdentifier == 0 ) \ - printf( "harbour.slx - Internal Error, iIdentifier underflow!\n" ); \ - else \ - iIdentifier--; \ - } \ - \ - if( x == IDENTIFIER ) \ - printf( " IDENTIFIER = \"%s\"\n", yylval.string ); \ - else if( x == LITERAL ) \ - printf( " LITERAL = \"%s\"\n", yylval.string ); \ - else if( x == MACROVAR ) \ - printf( " MACROVAR = \"%s\"\n", yylval.string ); \ - else if( x == MACROTEXT ) \ - printf( " MACROTEXT = \"%s\"\n", yylval.string ); \ - else if( x == NUM_INTEGER ) \ - printf( " INTEGER = %i\n", yylval.valInteger.iNumber ); \ - else if( x == NUM_LONG ) \ - printf( " INTEGER = %il\n", yylval.valLong.lNumber ); \ - else if( x == NUM_DOUBLE ) \ - printf( " DOUBLE = %f\n", yylval.valDouble.dNumber ); \ - else if( x < 256 ) \ - { \ - yytext[0] = x; \ - yytext[1] = '\0'; \ - \ - if( x == '\n' || x == ';' ) \ - printf( " NEW LINE %i\n", hb_comp_iLine - 1 ); \ - else \ - printf( " DELIMITER = \"%c\"\n", x ); \ - } \ - else \ - printf( " TOKEN = %i\n", x ); -#else - #undef INTERCEPT_ACTION - #define INTERCEPT_ACTION(x) \ - \ - yytext = sToken; \ - if( x == IDENTIFIER ) \ - { \ - if( iIdentifier == 0 ) \ - printf( "harbour.slx - Internal Error, iIdentifier underflow!\n" ); \ - else \ - iIdentifier--; \ - } \ - \ - if( x < 256 ) \ - { \ - yytext[0] = x; \ - yytext[1] = '\0'; \ - } -#endif - -/* Support Functions implemented as macros for speed. */ - -#undef ELEMENT_TOKEN - #define ELEMENT_TOKEN(x)\ -\ - if( x == NULL || *x == '\0' )\ - {\ - printf( "Invalid Token passed to ELEMENT_TOKEN()\n" );\ - iRet = 0;\ - }\ - else\ - {\ - yytext = x;\ - yyleng = iLen;\ -\ - if( *yytext == '_' || *yytext == '&' || isalpha( (int) *yytext ) )\ - {\ - /* Macro. */\ - if( ( tmpPtr = strrchr( yytext, '&' ) ) != NULL ) /* Right Search. */\ - {\ - /* Is '&' the first char? - Since its was right search that would be the only '&'. */\ - if( tmpPtr == yytext )\ - {\ - /* Maybe just the Macro Operator. */\ - if( yyleng == 1 )\ - {\ - iRet = '&';\ - }\ - /* No '.' so Simple Macro. */ \ - else if( ( tmpPtr = strchr( yytext, '.' ) ) == NULL ) /* Left Search. */ \ - {\ - /* Remove the '&'. */ \ - yytext++;\ - yyleng--;\ -\ - yylval.string = hb_compIdentifierNew( yytext, TRUE );\ - iRet = MACROVAR;\ - }\ - else if( tmpPtr == yytext + yyleng - 1 )\ - {\ - /* The only '.' is last char, so Simple Macro. */ \ -\ - /* Remove the '&' and the '.' */ \ - yytext++;\ - yyleng -= 2;\ - yytext[yyleng] = '\0';\ -\ - yylval.string = hb_compIdentifierNew( yytext, TRUE );\ - iRet = MACROVAR;\ - }\ - else\ - {\ - yytext = hb_compIdentifierNew( yytext, TRUE );\ -\ - yylval.string = yytext;\ - iRet = MACROTEXT;\ - }\ - }\ - else\ - {\ - yytext = hb_compIdentifierNew( yytext, TRUE );\ -\ - yylval.string = yytext;\ - iRet = MACROTEXT;\ - }\ - }\ - else\ - {\ - DEBUG_INFO( printf( "Element \"%s\" is IDENTIFIER\n", yytext ) );\ -\ - if( iLen > HB_SYMBOL_NAME_LEN )\ - {\ - yytext[ HB_SYMBOL_NAME_LEN ] = '\0';\ - yyleng = HB_SYMBOL_NAME_LEN;\ - }\ - \ - if( iIdentifier )\ - {\ - DEBUG_INFO( printf( "*** iDentifier = %i - Holding %s\n", iIdentifier, yytext ) );\ - sIdOnHold = hb_compIdentifierNew( yytext, TRUE );\ - iRet = HB_ID_ON_HOLD;\ - }\ - else \ - {\ - iIdentifier++; \ - DEBUG_INFO( printf( "Primary Identifier %s Increased to: %i\n", yytext, iIdentifier ) );\ - yylval.string = hb_compIdentifierNew( yytext, TRUE );\ - iRet = IDENTIFIER;\ - }\ - }\ - }\ - else\ - {\ - DEBUG_INFO( printf( "Passing Element \"%s\" to CONVERT_NUMBER()\n", sToken ) );\ -\ - /* "Returns" Token in iRet. (yylval.string already allocated). */\ - yylval.string = (char*) hb_xgrab( TOKEN_SIZE );\ - yylval.string[0] = 0;\ - aTexts[iTexts++] = yylval.string;\ - /* printf( "Text %i At: %i for Converted %s\n", iTexts, aTexts[iTexts - 1], sToken ); */\ -\ - CONVERT_NUMBER();\ -\ - DEBUG_INFO( printf( "Element \"%s\" is %i\n", sToken, iRet ) );\ - }\ - }\ - -#define CONVERT_NUMBER()\ -\ - if( yytext == NULL || *yytext == '\0' )\ - {\ - printf( "Invalid Token passed to CONVERT_NUMBER()\n" );\ - iRet = 0;\ - }\ - /* Hex Number */\ - else if( yytext[0] == '0' && yytext[1] == 'X' )\ - {\ - long lNumber = hb_lex_Hex2L( yytext + 2 );\ -\ - if( ( double ) SHRT_MIN <= lNumber && lNumber <= ( double ) SHRT_MAX )\ - {\ - yylval.valInteger.iNumber = lNumber;\ - yylval.valInteger.szValue = yytext;\ - iRet = NUM_INTEGER;\ - }\ - else if( ( double ) LONG_MIN <= lNumber && lNumber <= ( double ) LONG_MAX )\ - {\ - yylval.valLong.lNumber = lNumber;\ - yylval.valLong.szValue = yytext;\ - iRet = NUM_LONG;\ - }\ - else\ - {\ - /* NOTE: This will never happen */\ - yylval.valDouble.dNumber = lNumber;\ - yylval.valDouble.bWidth = HB_DEFAULT_WIDTH;\ - yylval.valDouble.bDec = 0;\ - yylval.valDouble.szValue = yytext;\ - iRet = NUM_DOUBLE;\ - }\ - }\ - else\ - {\ - yylval.valDouble.dNumber = atof( yytext );\ - tmpPtr = strchr( yytext, '.' );\ -\ - if( tmpPtr )\ - {\ - yylval.valDouble.bDec = strlen( tmpPtr + 1 );\ - yylval.valDouble.bWidth = iLen - yylval.valDouble.bDec;\ - if( yylval.valDouble.bDec )\ - {\ - yylval.valDouble.bWidth--;\ - }\ - yylval.valDouble.szValue = yytext;\ - iRet = NUM_DOUBLE;\ - }\ - else\ - {\ - if( ( double )SHRT_MIN <= yylval.valDouble.dNumber && yylval.valDouble.dNumber <= ( double )SHRT_MAX )\ - {\ - yylval.valInteger.iNumber = ( int ) yylval.valDouble.dNumber;\ - yylval.valInteger.szValue = yytext;\ - iRet = NUM_INTEGER;\ - }\ - else if( ( double )LONG_MIN <= yylval.valDouble.dNumber && yylval.valDouble.dNumber <= ( double )LONG_MAX )\ - {\ - yylval.valLong.lNumber = ( long ) yylval.valDouble.dNumber;\ - yylval.valLong.szValue = yytext;\ - iRet = NUM_LONG;\ - }\ - else\ - {\ - yylval.valDouble.bWidth = iLen + 1;\ - yylval.valDouble.bDec = 0;\ - yylval.valDouble.szValue = yytext;\ - iRet = NUM_DOUBLE;\ - }\ - }\ +#undef IF_BELONG_LEFT + #define IF_BELONG_LEFT(chr) if( iLastToken == IDENTIFIER || iLastToken == ']' || iLastToken == MACROVAR || iLastToken == MACROTEXT || iLastToken == ')' || iLastToken == '}' || iLastToken == WANTS_EOL || iLastToken == WANTS_ID || iLastToken == WANTS_VAR || iLastToken == DECLARE || iLastToken == FIELD || iLastToken == SELF || iLastToken == QSELF || iLastToken == IIF || iLastToken == PROCREQ ) + +/* Support Functions. */ +void hb_comp_SLX_InterceptAction(void) +{ + extern char *yytext, sToken[TOKEN_SIZE]; + extern int iRet; + + if( iRet < 256 ) + { + yytext[0] = iRet; + yytext[1] = '\0'; + } + else if( iRet < 512 ) + { + yytext = (char*) sToken; + + if( iRet == IDENTIFIER ) + { + if( iIdentifier > 0 ) + { + iIdentifier--; + } + } + } + else + { + yytext = (char*) sToken; + + if( iRet == WANTS_EXP ) + { iRet = iWantsEXP; } + else if( iRet == WANTS_EOL ) + { iRet = iWantsEOL; } + else if( iRet == WANTS_ID ) + { iRet = iWantsID; } + else if( iRet == WANTS_VAR ) + { iRet = iWantsVAR; } + else if( iRet == REJECT_OP ) + { yylval.string = hb_compIdentifierNew( (char*) sToken, TRUE ); iRet = IDENTIFIER; } + else + printf( "ERROR! [harbour.slx] - Missing Handler.\n" ); } -#undef CUSTOM_ACTION - #define CUSTOM_ACTION(x) x = hb_lex_CustomAction(x, aiHold, &iHold, iLastToken, aiReturn, &iReturn ) - -#undef INIT_ACTION - #define INIT_ACTION() ; - -int yy_lex_input( char *buffer, int iBufferSize ) -{ - HB_SYMBOL_UNUSED( buffer ); - HB_SYMBOL_UNUSED( iBufferSize ); - - return hb_pp_Internal( hb_comp_bPPO ? hb_comp_yyppo : NULL, buffer ); + #ifdef SHOW_LEX_TOKENS + if( iRet == IDENTIFIER ) + printf( " IDENTIFIER = \"%s\"\n", yylval.string ); + else if( iRet == LITERAL ) + printf( " LITERAL = \"%s\"\n", yylval.string ); + else if( iRet == MACROVAR ) + printf( " MACROVAR = \"%s\"\n", yylval.string ); + else if( iRet == MACROTEXT ) + printf( " MACROTEXT = \"%s\"\n", yylval.string ); + else if( iRet == NUM_INTEGER ) + printf( " INTEGER = %i\n", yylval.valInteger.iNumber ); + else if( iRet == NUM_LONG ) + printf( " INTEGER = %il\n", yylval.valLong.lNumber ); + else if( iRet == NUM_DOUBLE ) + printf( " DOUBLE = %f\n", yylval.valDouble.dNumber ); + else if( iRet < 256 ) + { + if( iRet == '\n' || iRet == ';' ) + printf( "***NEW LINE %i\n", hb_comp_iLine - 1 ); + else + printf( " DELIMITER = \"%c\"\n", iRet ); + } + else + printf( " TOKEN = %i\n", iRet ); + #endif } -long hb_lex_Hex2L( char* sHex ) +static void hb_compElementToken( void ) +{ + extern char *tmpPtr, *yytext, sToken[TOKEN_SIZE]; + extern int yyleng, iRet; + extern unsigned int iLen; + + yytext = (char*) sToken; + yyleng = iLen; + + if( ( *yytext > 64 && *yytext < 91 ) || *yytext == '&' || *yytext == '_' ) + { + /* Macro. */ + if( ( tmpPtr = strrchr( yytext, '&' ) ) != NULL ) /* Right Search. */ + { + /* Is '&' the first char? - Since its was right search that would be the only '&'. */ + if( tmpPtr == yytext ) + { + /* Maybe just the Macro Operator. */ + if( yyleng == 1 ) + { + iRet = '&'; + } + /* No '.' so Simple Macro. */ + else if( ( tmpPtr = strchr( yytext, '.' ) ) == NULL ) /* Left Search. */ + { + /* Remove the '&'. */ + yytext++; + yyleng--; + + yylval.string = hb_compIdentifierNew( yytext, TRUE ); + iRet = MACROVAR; + } + else if( tmpPtr == yytext + yyleng - 1 ) + { + /* The only '.' is last char, so Simple Macro. */ + + /* Remove the '&' and the '.' */ + yytext++; + yyleng -= 2; + yytext[yyleng] = '\0'; + + yylval.string = hb_compIdentifierNew( yytext, TRUE ); + iRet = MACROVAR; + } + else + { + yytext = hb_compIdentifierNew( yytext, TRUE ); + + yylval.string = yytext; + iRet = MACROTEXT; + } + } + else + { + yytext = hb_compIdentifierNew( yytext, TRUE ); + + yylval.string = yytext; + iRet = MACROTEXT; + } + } + else + { + DEBUG_INFO( printf( "Element \"%s\" is IDENTIFIER\n", yytext ) ); + + if( yyleng > HB_SYMBOL_NAME_LEN ) + { + yytext[ HB_SYMBOL_NAME_LEN ] = '\0'; + yyleng = HB_SYMBOL_NAME_LEN; + } + + if( iIdentifier ) + { + DEBUG_INFO( printf( "*** iDentifier = %i - Holding %s\n", iIdentifier, yytext ) ); + sIdOnHold = hb_compIdentifierNew( yytext, TRUE ); + iRet = _ID_ON_HOLD; + } + else + { + iIdentifier++; + DEBUG_INFO( printf( "Primary Identifier %s Increased to: %i\n", yytext, iIdentifier ) ); + yylval.string = hb_compIdentifierNew( yytext, TRUE ); + iRet = IDENTIFIER; + } + } + } + else + { + DEBUG_INFO( printf( "Passing Element \"%s\" to CONVERT_NUMBER()\n", sToken ) ); + + /* "Returns" Token in iRet. (yylval.string already allocated). */ + yylval.string = (char*) hb_xgrab( TOKEN_SIZE ); + yylval.string[0] = 0; + aTexts[iTexts++] = yylval.string; + + /* "Paramters" yytext & yyleng, "returns" result in iRet. */ + hb_comp_SLX_ConvertNumber(); + + DEBUG_INFO( printf( "Element \"%s\" is %i\n", sToken, iRet ) ); + } +} + +static void hb_comp_SLX_ConvertNumber(void) +{ + extern int iRet, yyleng; + extern char *tmpPtr, *yytext; + + /* Hex Number */ + if( yytext[0] == '0' && yytext[1] == 'X' ) + { + long lNumber = hb_comp_SLX_Hex2L( yytext + 2 ); + + if( ( double ) SHRT_MIN <= lNumber && lNumber <= ( double ) SHRT_MAX ) + { + yylval.valInteger.iNumber = lNumber; + yylval.valInteger.szValue = yytext; + iRet = NUM_INTEGER; + } + else if( ( double ) LONG_MIN <= lNumber && lNumber <= ( double ) LONG_MAX ) + { + yylval.valLong.lNumber = lNumber; + yylval.valLong.szValue = yytext; + iRet = NUM_LONG; + } + else + { + /* NOTE: This will never happen */ + yylval.valDouble.dNumber = lNumber; + yylval.valDouble.bWidth = HB_DEFAULT_WIDTH; + yylval.valDouble.bDec = 0; + yylval.valDouble.szValue = yytext; + iRet = NUM_DOUBLE; + } + } + else + { + yylval.valDouble.dNumber = atof( yytext ); + tmpPtr = strchr( yytext, '.' ); + + if( tmpPtr ) + { + yylval.valDouble.bDec = strlen( tmpPtr + 1 ); + yylval.valDouble.bWidth = yyleng - yylval.valDouble.bDec; + if( yylval.valDouble.bDec ) + { + yylval.valDouble.bWidth--; + } + yylval.valDouble.szValue = yytext; + iRet = NUM_DOUBLE; + } + else + { + if( ( double )SHRT_MIN <= yylval.valDouble.dNumber && yylval.valDouble.dNumber <= ( double )SHRT_MAX ) + { + yylval.valInteger.iNumber = ( int ) yylval.valDouble.dNumber; + yylval.valInteger.szValue = yytext; + iRet = NUM_INTEGER; + } + else if( ( double )LONG_MIN <= yylval.valDouble.dNumber && yylval.valDouble.dNumber <= ( double )LONG_MAX ) + { + yylval.valLong.lNumber = ( long ) yylval.valDouble.dNumber; + yylval.valLong.szValue = yytext; + iRet = NUM_LONG; + } + else + { + yylval.valDouble.bWidth = yyleng + 1; + yylval.valDouble.bDec = 0; + yylval.valDouble.szValue = yytext; + iRet = NUM_DOUBLE; + } + } + } + + iRet += DONT_REDUCE; +} + +long hb_comp_SLX_Hex2L( char* sHex ) { int i, iExp = 0, iLen = strlen( sHex ) - 1; long lVal, lSum = 0; @@ -999,7 +731,7 @@ long hb_lex_Hex2L( char* sHex ) { cChar = sHex[ iLen-- ]; - if( isalpha( (int) cChar ) ) + if( cChar > 64 && cChar < 91 ) { lVal = cChar - 55; } @@ -1025,144 +757,205 @@ long hb_lex_Hex2L( char* sHex ) return lSum; } -int hb_lex_CustomAction( int x, int aiHold[], int *ptr_iHold, int iLastToken, int aiReturn[], int *ptr_iReturn ) +int hb_lex_CustomAction( int x, int aiHold[], int *ptr_iHold, BOOL *ptr_bIgnoreWords, int iLastToken, char *sToken ) { - BOOL bRestored = FALSE; - DEBUG_INFO( printf( "Custom Action for %i\n", x ) ); + if( x < HB_WANTS_EXP ) + { + *ptr_bIgnoreWords = FALSE; + iWantsEXP = (-x) + (HB_WANTS_EXP) ; + return REJECT_OP; + } + else if( x < HB_WANTS_EOL ) + { + iWantsEOL = (-x) + (HB_WANTS_EOL) ; + return WANTS_EOL; + } + else if( x < HB_WANTS_ID ) + { + iWantsID = (-x) + (HB_WANTS_ID) ; + return WANTS_ID; + } + else if( x < HB_WANTS_VAR ) + { + iWantsVAR = (-x) + (HB_WANTS_VAR) ; + return WANTS_VAR; + } + switch ( x ) { + case HB_IDENTIFIER : + yylval.string = hb_compIdentifierNew( (char*) sToken, TRUE ); + iIdentifier++; + DEBUG_INFO( printf( "Primary Identifier %s Increased to: %i\n", (char*) sToken, iIdentifier ) ); + return IDENTIFIER + DONT_REDUCE; + + case HB_SELF : + aiHold[ (*ptr_iHold)++ ] = ':' + DONT_REDUCE ; + yylval.string = hb_compIdentifierNew( "SELF", TRUE ); + iIdentifier++; + DEBUG_INFO( printf( "HB_SELF, Primary Identifier %s Increased to: %i\n", "SELF", iIdentifier ) ); + return IDENTIFIER; + case HB_LIT_ACT : yylval.string = hb_compIdentifierNew( sPair, TRUE ); - x = LITERAL; - break; + return LITERAL + DONT_REDUCE ; + + case HB_INIT_PROC : + aiHold[ (*ptr_iHold)++ ] = PROCEDURE + DONT_REDUCE; + return INIT + DONT_REDUCE; + + case HB_INIT_FUNC : + aiHold[ (*ptr_iHold)++ ] = FUNCTION + DONT_REDUCE; + return INIT + DONT_REDUCE; + + case HB_EXIT_PROC : + aiHold[ (*ptr_iHold)++ ] = PROCEDURE + DONT_REDUCE; + return EXIT + DONT_REDUCE; + + case HB_EXIT_FUNC : + aiHold[ (*ptr_iHold)++ ] = FUNCTION + DONT_REDUCE; + return EXIT + DONT_REDUCE; + + case HB_STATIC_PROC : + aiHold[ (*ptr_iHold)++ ] = PROCEDURE + DONT_REDUCE; + return STATIC + DONT_REDUCE; + + case HB_STATIC_FUNC : + aiHold[ (*ptr_iHold)++ ] = FUNCTION + DONT_REDUCE; + return STATIC + DONT_REDUCE; + + case HB_IN : + *ptr_bIgnoreWords = FALSE; + if( iLastToken == IDENTIFIER ) + { return IN + DONT_REDUCE; } + else + { + yylval.string = hb_compIdentifierNew( "IN", TRUE ); + iIdentifier++; + DEBUG_INFO( printf( "HB_IN, Primary Identifier %s Increased to: %i\n", "IN", iIdentifier ) ); + return IDENTIFIER; + } + + case HB_STEP : + *ptr_bIgnoreWords = FALSE; + if( iLastToken == NUM_INTEGER || iLastToken == IDENTIFIER || iLastToken == MACROVAR || iLastToken == MACROTEXT || iLastToken == ')' || iLastToken == ']' ) + { return STEP + DONT_REDUCE; } + else + { + yylval.string = hb_compIdentifierNew( "STEP", TRUE ); + iIdentifier++; + DEBUG_INFO( printf( "HB_STEP, Primary Identifier %s Increased to: %i\n", "STEP", iIdentifier ) ); + return IDENTIFIER; + } + + case HB_TO : + *ptr_bIgnoreWords = FALSE; + if( iLastToken == NUM_INTEGER || iLastToken == IDENTIFIER || iLastToken == MACROVAR || iLastToken == MACROTEXT || iLastToken == ')' || iLastToken == ']' ) + { return TO + DONT_REDUCE; } + else + { + yylval.string = hb_compIdentifierNew( "TO", TRUE ); + iIdentifier++; + DEBUG_INFO( printf( "HB_TO, Primary Identifier %s Increased to: %i\n", "IN", iIdentifier ) ); + return IDENTIFIER; + } + + case HB_WITH : + *ptr_bIgnoreWords = FALSE; + if( iLastToken == IDENTIFIER || iLastToken == MACROVAR || iLastToken == MACROTEXT ) + { return WITH + DONT_REDUCE; } + else + { + yylval.string = hb_compIdentifierNew( "WITH", TRUE ); + iIdentifier++; + DEBUG_INFO( printf( "HB_WITH, Primary Identifier %s Increased to: %i\n", "WITH", iIdentifier ) ); + return IDENTIFIER; + } + + case _WITH_ID_CR : + aiHold[ (*ptr_iHold)++ ] = '\n' + DONT_REDUCE; + yylval.string = hb_compIdentifierNew( "WITH", TRUE ); + iIdentifier++; + DEBUG_INFO( printf( "_WITH_ID_CR, Primary Identifier %s Increased to: %i\n", "WITH", iIdentifier ) ); + return IDENTIFIER + DONT_REDUCE; + + case _WITH_ID_SEMI : + aiHold[ (*ptr_iHold)++ ] = ';' + DONT_REDUCE; + yylval.string = hb_compIdentifierNew( "WITH", TRUE ); + iIdentifier++; + DEBUG_INFO( printf( "_WITH_ID_SEMI, Primary Identifier %s Increased to: %i\n", "WITH", iIdentifier ) ); + return IDENTIFIER + DONT_REDUCE; case HB_NESTED_LIT : { int iPairLen = strlen( sPair ); + sPair[ iPairLen ] = sTerm[0]; sPair[ iPairLen + 1 ] = '\0'; yylval.string = hb_compIdentifierNew( sPair, TRUE ); - x = LITERAL; - break; + return LITERAL + DONT_REDUCE ; } + case HB_QOUT_ACT : iIdentifier++; DEBUG_INFO( printf( "HB_QOUT_ACT, Primary Identifier %s Increased to: %i\n", "QOUT", iIdentifier ) ); yylval.string = hb_compIdentifierNew( "QOUT", TRUE ); - aiReturn[ (*ptr_iReturn)++ ] = '('; - aiReturn[ (*ptr_iReturn)++ ] = IDENTIFIER; - x = HB_QOUT_LIT; - break; + aiHold[ (*ptr_iHold)++ ] = '(' + DONT_REDUCE; + aiHold[ (*ptr_iHold)++ ] = IDENTIFIER + DONT_REDUCE; + return _QOUT_LIT; case HB_RET_QOUT_LIT : yylval.string = hb_compIdentifierNew( sPair, TRUE ); - aiReturn[ (*ptr_iReturn)++ ] = '\n'; - aiReturn[ (*ptr_iReturn)++ ] = ')'; - aiReturn[ (*ptr_iReturn)++ ] = LITERAL; - x = 0; - break; + aiHold[ (*ptr_iHold)++ ] = '\n' + DONT_REDUCE; + aiHold[ (*ptr_iHold)++ ] = ')' + DONT_REDUCE; + return LITERAL + DONT_REDUCE ; - case HB_CHK_NEXT : - if( hb_comp_wForCounter == 0 ) - hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_NEXTFOR, NULL, NULL ); - x = NEXT; - break; + case HB_DO_WHILE_ID : + iIdentifier++; + DEBUG_INFO( printf( "HB_DO_WHILE_ID, Primary Identifier %s Increased to: %i\n", "WHILE", iIdentifier ) ); + yylval.string = hb_compIdentifierNew( "WHILE", TRUE ); + aiHold[ (*ptr_iHold)++ ] = IDENTIFIER + DONT_REDUCE; + return DO + DONT_REDUCE; - case HB_CHK_EXIT : - if( hb_comp_wForCounter == 0 && hb_comp_wWhileCounter == 0 ) - hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_UNMATCHED_EXIT, "EXIT", NULL ); - x = EXIT; - break; + case HB_DO_WHILE_WITH : + aiHold[ (*ptr_iHold)++ ] = WITH + DONT_REDUCE; + yylval.string = hb_compIdentifierNew( "WHILE", TRUE ); + iIdentifier++; + DEBUG_INFO( printf( "HB_DO_WHILE_WITH, Primary Identifier %s Increased to: %i\n", "WHILE", iIdentifier ) ); + aiHold[ (*ptr_iHold)++ ] = IDENTIFIER + DONT_REDUCE; + return DO + DONT_REDUCE; - case HB_CHK_LOOP : - if( hb_comp_wForCounter == 0 && hb_comp_wWhileCounter == 0 ) - hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_UNMATCHED_EXIT, "LOOP", NULL ); - x = LOOP; - break; - - case HB_CHK_IN : - if( iLastToken == IDENTIFIER ) - { - x = IN; - } - else - { - strcpy( (char*) sWordAsString, "IN" ); - x = IDENTIFIER; - } - break; - - case HB_INIT_PROC : - aiReturn[ (*ptr_iReturn)++ ] = PROCEDURE; - aiReturn[ (*ptr_iReturn)++ ] = INIT; - x = 0; - break; - - case HB_INIT_FUNC : - aiReturn[ (*ptr_iReturn)++ ] = FUNCTION; - aiReturn[ (*ptr_iReturn)++ ] = INIT; - x = 0; - break; - - case HB_EXIT_PROC : - aiReturn[ (*ptr_iReturn)++ ] = PROCEDURE; - aiReturn[ (*ptr_iReturn)++ ] = EXIT; - x = 0; - break; - - case HB_EXIT_FUNC : - aiReturn[ (*ptr_iReturn)++ ] = FUNCTION; - aiReturn[ (*ptr_iReturn)++ ] = EXIT; - x = 0; - break; - - case HB_RET_FUNID : - DEBUG_INFO( printf( "HB_RET_FUNID, Primary Identifier %s preset : %i\n", yylval.string, iIdentifier ) ); - aiReturn[ (*ptr_iReturn)++ ] = IDENTIFIER; - aiReturn[ (*ptr_iReturn)++ ] = FUNCTION; - x = 0; - break; - - case HB_IDENTIFIER : - x = IDENTIFIER; - break; - - case HB_SELF_ID : - sWordAsString[0] = 'S'; - sWordAsString[1] = 'E'; - sWordAsString[2] = 'L'; - sWordAsString[3] = 'F'; - sWordAsString[4] = '\0'; - x = IDENTIFIER; - break; + case HB_DO_CASE_ID : + yylval.string = hb_compIdentifierNew( "CASE", TRUE ); + iIdentifier++; + DEBUG_INFO( printf( "HB_DO_CASE_ID, Primary Identifier %s Increased to: %i\n", "CASE", iIdentifier ) ); + aiHold[ (*ptr_iHold)++ ] = IDENTIFIER + DONT_REDUCE; + return DO + DONT_REDUCE; case HB_MACRO_ERR : hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_SYNTAX, "&", NULL ); - x = 0; - break; + return 0; case HB_ID_ON_HOLD : - bRestored = TRUE; yylval.string = sIdOnHold; iIdentifier++; DEBUG_INFO( printf( "RELEASED ID_ON_HOLD: %s - Increased to: %i\n", sIdOnHold, iIdentifier ) ); - x = IDENTIFIER; - break; + return IDENTIFIER; default: printf( "WARNING! No Handler for Custom Action %i\n", x ); } - if( x == IDENTIFIER && ! bRestored ) - { - yylval.string = hb_compIdentifierNew( (char*) sWordAsString, TRUE ); - iIdentifier++; - DEBUG_INFO( printf( "Primary Identifier %s Increased to: %i\n", (char*) sWordAsString, iIdentifier ) ); - aiHold[ (int)(*ptr_iHold)++ ] = x; - x = 0; - } - return x; } + +int yy_lex_input( char *buffer, int iBufferSize ) +{ + HB_SYMBOL_UNUSED( buffer ); + HB_SYMBOL_UNUSED( iBufferSize ); + + return hb_pp_Internal( hb_comp_bPPO ? hb_comp_yyppo : NULL, buffer ); +} + diff --git a/harbour/source/compiler/harbour.sly b/harbour/source/compiler/harbour.sly new file mode 100644 index 0000000000..fcf97a196a --- /dev/null +++ b/harbour/source/compiler/harbour.sly @@ -0,0 +1,2048 @@ +%{ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Compiler YACC rules and actions + * + * Copyright 1999 Antonio Linares + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +/* TODO list + * 1) Change the pcode generated by ::cVar from Self:cVar to QSELF():cVar + * The major problem to solve is how to support QSELF() inside a codeblock. + * 2) Support this syntax: nPtr := @Hello() + */ + +#include + +#include "hbcomp.h" + +/* Compile using: bison -d -v harbour.y */ + +extern FILE *yyin; /* currently yacc parsed file */ +extern int hb_comp_iLine; /* currently parsed file line number */ +extern char *yytext; + +#ifdef __cplusplus +typedef struct yy_buffer_state *YY_BUFFER_STATE; +extern YY_BUFFER_STATE yy_create_buffer( FILE *, int ); /* yacc functions to manage multiple files */ +extern void yy_switch_to_buffer( YY_BUFFER_STATE ); /* yacc functions to manage multiple files */ +extern void yy_delete_buffer( YY_BUFFER_STATE ); /* yacc functions to manage multiple files */ +#else +extern void * yy_create_buffer( FILE *, int ); /* yacc functions to manage multiple files */ +extern void yy_switch_to_buffer( void * ); /* yacc functions to manage multiple files */ +extern void yy_delete_buffer( void * ); /* yacc functions to manage multiple files */ +#endif + +/* lex & yacc related prototypes */ +extern int yyparse( void ); /* main yacc parsing function */ +extern void yyerror( char * ); /* parsing error management function */ +extern int yylex( void ); /* main lex token function, called by yyparse() */ +#ifdef __cplusplus +extern "C" int yywrap( void ); +#else +extern int yywrap( void ); /* manages the EOF of current processed file */ +#endif + +static void hb_compLoopStart( void ); +static void hb_compLoopEnd( void ); +static void hb_compLoopLoop( void ); +static void hb_compLoopExit( void ); +static void hb_compLoopHere( void ); + +static void * hb_compElseIfGen( void * pFirstElseIf, ULONG ulOffset ); /* generates a support structure for elseifs pcode fixups */ +static void hb_compElseIfFix( void * pIfElseIfs ); /* implements the ElseIfs pcode fixups */ + +static void hb_compRTVariableAdd( HB_EXPR_PTR, BOOL ); +static void hb_compRTVariableGen( char * ); + +static void hb_compVariableDim( char *, HB_EXPR_PTR ); + +#ifdef HARBOUR_YYDEBUG + #define YYDEBUG 1 /* Parser debug information support */ +#endif + +typedef struct __ELSEIF +{ + ULONG ulOffset; + struct __ELSEIF * pNext; +} _ELSEIF, * PELSEIF; /* support structure for else if pcode fixups */ + +typedef struct _LOOPEXIT +{ + ULONG ulOffset; + int iLine; + USHORT wSeqCounter; + struct _LOOPEXIT * pLoopList; + struct _LOOPEXIT * pExitList; + struct _LOOPEXIT * pNext; +} LOOPEXIT, * PTR_LOOPEXIT; /* support structure for EXIT and LOOP statements */ + +typedef struct HB_RTVAR_ +{ + HB_EXPR_PTR pVar; + BOOL bPopValue; + struct HB_RTVAR_ *pNext; + struct HB_RTVAR_ *pPrev; +} HB_RTVAR, *HB_RTVAR_PTR; /* support structure for PUBLIC and PRIVATE statements */ + +USHORT hb_comp_wSeqCounter = 0; +USHORT hb_comp_wForCounter = 0; +USHORT hb_comp_wIfCounter = 0; +USHORT hb_comp_wWhileCounter = 0; +USHORT hb_comp_wCaseCounter = 0; + +char * hb_comp_buffer; /* yacc input buffer */ + +static PTR_LOOPEXIT hb_comp_pLoops = NULL; +static HB_RTVAR_PTR hb_comp_rtvars = NULL; + +char * hb_comp_szAnnounce = NULL; /* ANNOUNCEd procedure */ + +static void hb_compDebugStart( void ) { }; + +%} + +%union /* special structure used by lex and yacc to share info */ +{ + char * string; /* to hold a string returned by lex */ + int iNumber; /* to hold a temporary integer number */ + long lNumber; /* to hold a temporary long number */ + struct + { + int iNumber; /* to hold a number returned by lex */ + char * szValue; + } valInteger; + struct + { + long lNumber; /* to hold a long number returned by lex */ + char * szValue; + } valLong; + struct + { + double dNumber; /* to hold a double number returned by lex */ + /* NOTE: Intentionally using "unsigned char" instead of "BYTE" */ + unsigned char bWidth; /* to hold the width of the value */ + unsigned char bDec; /* to hold the number of decimal points in the value */ + char * szValue; + } valDouble; + HB_EXPR_PTR asExpr; + void * pVoid; /* to hold any memory structure we may need */ +}; + +%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 ANNOUNCE EXTERN INIT EXIT AND OR NOT PUBLIC EQ NE1 NE2 +%token INC DEC ALIASOP DOCASE CASE OTHERWISE ENDCASE ENDDO MEMVAR +%token WHILE LOOP END FOR NEXT TO STEP LE GE FIELD IN PARAMETERS +%token PLUSEQ MINUSEQ MULTEQ DIVEQ POWER EXPEQ MODEQ +%token PRIVATE BEGINSEQ BREAK RECOVER RECOVERUSING DO WITH SELF LINE +%token MACROVAR MACROTEXT +%token AS_ARRAY AS_BLOCK AS_CHARACTER AS_CLASS AS_DATE AS_LOGICAL AS_NUMERIC AS_OBJECT AS_VARIANT DECLARE OPTIONAL DECLARE_CLASS DECLARE_MEMBER +%token AS_ARRAY_ARRAY AS_BLOCK_ARRAY AS_CHARACTER_ARRAY AS_CLASS_ARRAY AS_DATE_ARRAY AS_LOGICAL_ARRAY AS_NUMERIC_ARRAY AS_OBJECT_ARRAY +%token PROCREQ + +/*the lowest precedence*/ +/*postincrement and postdecrement*/ +%left POST +/*assigment - from right to left*/ +%right INASSIGN +%right PLUSEQ MINUSEQ +%right MULTEQ DIVEQ MODEQ +%right EXPEQ +/*logical operators*/ +%right OR +%right AND +%right NOT +/*relational operators*/ +%right '=' '<' '>' EQ NE1 NE2 LE GE '$' +/*mathematical operators*/ +%right '+' '-' +%right '*' '/' '%' +%right POWER +%right UNARY +/*preincrement and predecrement*/ +%right PRE +/*special operators*/ +%right ALIASOP '&' '@' +%right '\n' ';' ',' +/*the highest precedence*/ + +%type IdentName IDENTIFIER LITERAL SendId MACROVAR MACROTEXT CompTimeStr +%type NUM_DOUBLE +%type NUM_INTEGER +%type NUM_LONG +%type FunScope +%type Params ParamList +%type IfBegin VarList ExtVarList +%type FieldList +%type WhileBegin +%type IfElseIf Cases +%type Argument ArgList ElemList BlockExpList BlockVarList BlockNoVar +%type DoName DoProc DoArgument DoArgList +%type PareExpList1 PareExpList2 PareExpList3 PareExpListN +%type ExpList ExpList1 ExpList2 ExpList3 +%type NumValue NumAlias +%type NilValue NilAlias +%type LiteralValue LiteralAlias +%type CodeBlock CodeBlockAlias +%type Logical LogicalAlias +%type SelfValue SelfAlias +%type Array ArrayAlias +%type ArrayAt ArrayAtAlias +%type Variable VarAlias +%type MacroVar MacroVarAlias +%type MacroExpr MacroExprAlias +%type AliasId AliasVar AliasExpr +%type VariableAt VariableAtAlias +%type FunCall FunCallAlias +%type ObjectData ObjectDataAlias +%type ObjectMethod ObjectMethodAlias +%type IfInline IfInlineAlias +%type PareExpList PareExpListAlias +%type Expression SimpleExpression LValue +%type EmptyExpression +%type ExprAssign ExprOperEq ExprPreOp ExprPostOp +%type ExprEqual ExprMath ExprBool ExprRelation ExprUnary +%type ExprPlusEq ExprMinusEq ExprMultEq ExprDivEq ExprModEq ExprExpEq +%type ArrayIndex IndexList +%type DimIndex DimList +%type FieldAlias FieldVarAlias +%type PostOp + +%% + +Main : { hb_compLinePush(); } Source { } + | /* empty file */ + ; + +Source : Crlf + | VarDefs + | FieldsDef + | MemvarDef + | Declaration + | Function + | Statement + | Line + | ProcReq + | error Crlf { yyclearin; } + | Source Crlf + | Source VarDefs + | Source FieldsDef + | Source MemvarDef + | Source Declaration + | Source Function + | Source Statement + | Source Line + | Source ProcReq + | Source error Crlf { yyclearin; } + ; + +Line : LINE NUM_INTEGER LITERAL Crlf + | LINE NUM_INTEGER LITERAL '@' LITERAL Crlf /* Xbase++ style */ + ; + +ProcReq : PROCREQ CompTimeStr ')' Crlf {} + ; + +CompTimeStr: LITERAL { hb_compAutoOpenAdd( $1 ); } + | LITERAL '+' LITERAL { char szFileName[ _POSIX_PATH_MAX ]; sprintf( szFileName, "%s%s", $1, $3 ); hb_compAutoOpenAdd( szFileName ); } + ; + +Function : FunScope FUNCTION IdentName { hb_comp_cVarType = ' '; hb_compFunctionAdd( $3, ( HB_SYMBOLSCOPE ) $1, 0 ); } Params Crlf {} + | FunScope PROCEDURE IdentName { hb_comp_cVarType = ' '; hb_compFunctionAdd( $3, ( HB_SYMBOLSCOPE ) $1, FUN_PROCEDURE ); } Params Crlf {} + ; + +FunScope : { $$ = HB_FS_PUBLIC; } + | STATIC { $$ = HB_FS_STATIC; } + | INIT { $$ = HB_FS_INIT; } + | EXIT { $$ = HB_FS_EXIT; } + ; + +Params : { $$ = 0; } + | '(' ')' { $$ = 0; } + | '(' { hb_comp_iVarScope = VS_PARAMETER; } ParamList ')' { $$ = $3; } + ; + +AsType : /* not specified */ { hb_comp_cVarType = ' '; } + | StrongType + ; + +StrongType : AS_NUMERIC { hb_comp_cVarType = 'N'; } + | AS_CHARACTER { hb_comp_cVarType = 'C'; } + | AS_DATE { hb_comp_cVarType = 'D'; } + | AS_LOGICAL { hb_comp_cVarType = 'L'; } + | AS_BLOCK { hb_comp_cVarType = 'B'; } + | AS_OBJECT { hb_comp_cVarType = 'O'; } + | AS_CLASS IdentName { hb_comp_cVarType = 'S'; hb_comp_szFromClass = $2 } + | AS_VARIANT { hb_comp_cVarType = ' '; } + | AsArray + ; + +AsArray : AS_ARRAY { hb_comp_cVarType = 'A'; } + | AS_NUMERIC_ARRAY { hb_comp_cVarType = 'n'; } + | AS_CHARACTER_ARRAY { hb_comp_cVarType = 'c'; } + | AS_DATE_ARRAY { hb_comp_cVarType = 'd'; } + | AS_LOGICAL_ARRAY { hb_comp_cVarType = 'l'; } + | AS_ARRAY_ARRAY { hb_comp_cVarType = 'a'; } + | AS_BLOCK_ARRAY { hb_comp_cVarType = 'b'; } + | AS_OBJECT_ARRAY { hb_comp_cVarType = 'o'; } + | AS_CLASS_ARRAY IdentName { hb_comp_cVarType = 's'; hb_comp_szFromClass = $2 } + ; + +ParamList : IdentName AsType { hb_compVariableAdd( $1, hb_comp_cVarType ); $$ = 1; } + | ParamList ',' IdentName AsType { hb_compVariableAdd( $3, hb_comp_cVarType ); $$++; } + ; + +/* NOTE: This alllows the use of Expression as a statement. + * The Expression is validated later in reduction phase of + * hb_compExprGenStatement(). With this solution we don't have to + * stop compilation if invalid syntax will be used. + */ +Statement : ExecFlow CrlfStmnt { } + | IfInline CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | FunCall CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | AliasExpr CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | ObjectMethod CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | PareExpList CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | ExprPreOp CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | ExprPostOp CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | ExprOperEq CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | ExprEqual CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | ExprAssign CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | DoProc CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | BREAK CrlfStmnt { hb_compGenBreak(); hb_compGenPCode2( HB_P_DOSHORT, 0, ( BOOL ) 1 ); + hb_comp_functions.pLast->bFlags |= FUN_BREAK_CODE; } + | BREAK { hb_compLinePushIfInside(); } Expression Crlf { hb_compGenBreak(); hb_compExprDelete( hb_compExprGenPush( $3 ) ); + hb_compGenPCode2( HB_P_DOSHORT, 1, ( BOOL ) 1 ); + hb_comp_functions.pLast->bFlags |= FUN_BREAK_CODE; + } + | RETURN CrlfStmnt { + if( hb_comp_wSeqCounter ) + { + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_EXIT_IN_SEQUENCE, "RETURN", NULL ); + } + hb_compGenPCode1( HB_P_ENDPROC ); + if( (hb_comp_functions.pLast->bFlags & FUN_PROCEDURE) == 0 ) + { /* return from a function without a return value */ + hb_compGenWarning( hb_comp_szWarnings, 'W', HB_COMP_WARN_NO_RETURN_VALUE, NULL, NULL ); + } + hb_comp_functions.pLast->bFlags |= FUN_WITH_RETURN; + hb_comp_bDontGenLineNum = TRUE; + hb_comp_functions.pLast->bFlags |= FUN_BREAK_CODE; + } + | RETURN { hb_compLinePushIfInside(); hb_comp_cVarType = ' '; } Expression Crlf { + + hb_comp_cCastType = hb_comp_cVarType; + hb_comp_cVarType = ' '; + + if( hb_comp_wSeqCounter ) + { + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_EXIT_IN_SEQUENCE, "RETURN", NULL ); + } + hb_compExprGenPush( $3 ); /* TODO: check if return value agree with declared value */ + hb_compGenPCode2( HB_P_RETVALUE, HB_P_ENDPROC, ( BOOL ) 1 ); + if( hb_comp_functions.pLast->bFlags & FUN_PROCEDURE ) + { /* procedure returns a value */ + hb_compGenWarning( hb_comp_szWarnings, 'W', HB_COMP_WARN_PROC_RETURN_VALUE, NULL, NULL ); + } + hb_comp_functions.pLast->bFlags |= FUN_WITH_RETURN; + hb_comp_bDontGenLineNum = TRUE; + hb_comp_functions.pLast->bFlags |= FUN_BREAK_CODE; + } + | PUBLIC { hb_compLinePushIfInside(); hb_comp_iVarScope = VS_PUBLIC; } + ExtVarList + { hb_compRTVariableGen( "__MVPUBLIC" ); hb_comp_cVarType = ' '; hb_comp_iVarScope = VS_NONE; } CrlfStmnt + | PRIVATE { hb_compLinePushIfInside(); hb_comp_iVarScope = VS_PRIVATE; } + ExtVarList + { hb_compRTVariableGen( "__MVPRIVATE" ); hb_comp_cVarType = ' '; hb_comp_iVarScope = VS_NONE; } CrlfStmnt + + | EXIT { hb_comp_bDontGenLineNum = TRUE; hb_compLoopExit(); } CrlfStmnt { hb_comp_functions.pLast->bFlags |= FUN_BREAK_CODE; } + | LOOP { hb_comp_bDontGenLineNum = TRUE; hb_compLoopLoop(); } CrlfStmnt { hb_comp_functions.pLast->bFlags |= FUN_BREAK_CODE; } + | EXTERN ExtList Crlf + | ANNOUNCE IdentName { + if( hb_comp_szAnnounce == NULL ) + { + /* check for reserved name + * NOTE: Clipper doesn't check for it + */ + char * szFunction = hb_compReservedName( $2 ); + if( szFunction ) + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_FUNC_RESERVED, szFunction, $2 ); + hb_comp_szAnnounce = $2; + } + else + hb_compGenWarning( hb_comp_szWarnings, 'W', HB_COMP_WARN_DUPL_ANNOUNCE, $2, NULL ); + } Crlf + + ; + +CrlfStmnt : { hb_compLinePushIfInside(); } Crlf + ; + +LineStat : Crlf { $$ = 0; hb_comp_bDontGenLineNum = TRUE; } + | Statement { $$ = 1; } + | Declaration { $$ = 1; } + ; + +Statements : LineStat { $$ = $1; hb_compLinePush(); } + | Statements LineStat { $$ += $2; hb_compLinePush(); } + ; + +ExtList : IdentName { hb_compExternAdd( $1 ); } + | ExtList ',' IdentName { hb_compExternAdd( $3 ); } + ; + +IdentName : IDENTIFIER { $$ = $1; } + ; + +/* Numeric values + */ +NumValue : NUM_DOUBLE { $$ = hb_compExprNewDouble( $1.dNumber, $1.bWidth, $1.bDec ); } + | NUM_INTEGER { $$ = hb_compExprNewLong( $1.iNumber ); } + | NUM_LONG { $$ = hb_compExprNewLong( $1.lNumber ); } + ; + +NumAlias : NUM_INTEGER ALIASOP { $$ = hb_compExprNewLong( $1.iNumber ); } + | NUM_LONG ALIASOP { $$ = hb_compExprNewLong( $1.lNumber ); } + | NUM_DOUBLE ALIASOP { $$ = hb_compErrorAlias( hb_compExprNewDouble( $1.dNumber, $1.bWidth, $1.bDec ) ); } + ; + +/* NIL value + */ +NilValue : NIL { $$ = hb_compExprNewNil(); } +; + +NilAlias : NilValue ALIASOP { $$ = $1; } +; + +/* Literal string value + */ +LiteralValue : LITERAL { $$ = hb_compExprNewString( $1 ); } +; + +LiteralAlias : LiteralValue ALIASOP { $$ = $1; } +; + +/* Codeblock value + */ +CodeBlockAlias : CodeBlock ALIASOP { $$ = $1; } +; + +/* Logical value + */ +Logical : TRUEVALUE { $$ = hb_compExprNewLogical( TRUE ); } + | FALSEVALUE { $$ = hb_compExprNewLogical( FALSE ); } + ; + +LogicalAlias : Logical ALIASOP { $$ = $1; } +; + +/* SELF value and expressions + */ +SelfValue : SELF { $$ = hb_compExprNewSelf(); } +; + +SelfAlias : SelfValue ALIASOP { $$ = $1; } +; + +/* Literal array + */ +Array : '{' ElemList '}' { $$ = hb_compExprNewArray( $2 ); } + ; + +ArrayAlias : Array ALIASOP { $$ = $1; } +; + +/* Literal array access + */ +ArrayAt : Array ArrayIndex { $$ = $2; } +; + +ArrayAtAlias : ArrayAt ALIASOP { $$ = $1; } +; + +/* Variables + */ +Variable : IdentName { $$ = hb_compExprNewVar( $1 ); } +; + +VarAlias : IdentName ALIASOP { $$ = hb_compExprNewAlias( $1 ); } +; + +/* Macro variables + */ +MacroVar : MACROVAR { $$ = hb_compExprNewMacro( NULL, '&', $1 ); } + | MACROTEXT { $$ = hb_compExprNewMacro( NULL, 0, $1 ); } +; + +MacroVarAlias : MacroVar ALIASOP { $$ = $1; } +; + +/* Macro expressions + */ +MacroExpr : '&' PareExpList { $$ = hb_compExprNewMacro( $2, 0, NULL ); } +; + +MacroExprAlias : MacroExpr ALIASOP { $$ = $1; } +; + +/* Aliased variables + */ +/* special case: _FIELD-> and FIELD-> can be nested + */ +FieldAlias : FIELD ALIASOP { $$ = hb_compExprNewAlias( "FIELD" ); } + | FIELD ALIASOP FieldAlias { $$ = $3; } + ; + +/* ignore _FIELD-> or FIELD-> if a real alias is specified + */ +FieldVarAlias : FieldAlias VarAlias { hb_compExprDelete( $1 ); $$ = $2; } + | FieldAlias NumAlias { hb_compExprDelete( $1 ); $$ = $2; } + | FieldAlias PareExpListAlias { hb_compExprDelete( $1 ); $$ = $2; } + | FieldAlias MacroVarAlias { hb_compExprDelete( $1 ); $$ = $2; } + | FieldAlias MacroExprAlias { hb_compExprDelete( $1 ); $$ = $2; } + | FieldAlias NilAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias LiteralAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias LogicalAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias CodeBlockAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias SelfAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias ArrayAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias ArrayAtAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias IfInlineAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + ; + +AliasId : IdentName { $$ = hb_compExprNewVar( $1 ); } + | MacroVar { $$ = $1; } + | MacroExpr { $$ = $1; } + ; + +AliasVar : NumAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | MacroVarAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | MacroExprAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | PareExpListAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | NilAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | LiteralAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | LogicalAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | CodeBlockAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | SelfAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | ArrayAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | ArrayAtAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | VariableAtAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | IfInlineAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | FunCallAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | ObjectDataAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | ObjectMethodAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | VarAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | FieldAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | FieldVarAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + ; + +/* Aliased expressions + */ +/* NOTE: In the case: + * alias->( Expression ) + * alias always selects a workarea at runtime + */ +AliasExpr : NumAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | VarAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | MacroVarAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | MacroExprAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | PareExpListAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | FieldAlias PareExpList { $$ = hb_compErrorAlias( $2 ); } /* QUESTION: Clipper reports error here - we can handle it */ + ; + +/* Array expressions access + */ +VariableAt : NilValue ArrayIndex { $$ = $2; } + | LiteralValue ArrayIndex { $$ = $2; } + | CodeBlock ArrayIndex { $$ = $2; } + | Logical ArrayIndex { $$ = $2; } + | SelfValue ArrayIndex { $$ = $2; } + | Variable ArrayIndex { $$ = $2; } + | AliasVar ArrayIndex { $$ = $2; } + | AliasExpr ArrayIndex { $$ = $2; } + | MacroVar ArrayIndex { $$ = $2; } + | MacroExpr ArrayIndex { $$ = $2; } + | ObjectData ArrayIndex { $$ = $2; } + | ObjectMethod ArrayIndex { $$ = $2; } + | FunCall ArrayIndex { $$ = $2; } + | IfInline ArrayIndex { $$ = $2; } + | PareExpList ArrayIndex { $$ = $2; } + ; + +VariableAtAlias : VariableAt ALIASOP { $$ = $1; } +; + +/* Function call + */ +FunCall : IdentName '(' ArgList ')' { $$ = hb_compExprNewFunCall( hb_compExprNewFunName( $1 ), $3 ); } + | MacroVar '(' ArgList ')' { $$ = hb_compExprNewFunCall( $1, $3 ); } + ; + +ArgList : Argument { $$ = hb_compExprNewArgList( $1 ); } + | ArgList ',' Argument { $$ = hb_compExprAddListExpr( $1, $3 ); } + ; + +Argument : EmptyExpression { $$ = $1; } + | '@' IdentName { $$ = hb_compExprNewVarRef( $2 ); } + | '@' IdentName '(' ')' { $$ = hb_compExprNewFunRef( $2 ); } + ; + +FunCallAlias : FunCall ALIASOP { $$ = $1; } +; + +/* Object's instance variable + */ +SendId : IdentName { $$ = $1; } + | MacroVar { $$ = "&"; hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_INVALID_SEND, "&", NULL); } + ; + +ObjectData : NumValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | NilValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | LiteralValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | CodeBlock ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | Logical ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | SelfValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | Array ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | ArrayAt ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | Variable ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | AliasVar ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | AliasExpr ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | MacroVar ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | MacroExpr ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | FunCall ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | IfInline ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | PareExpList ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | VariableAt ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | ObjectMethod ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | ObjectData ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + ; + +ObjectDataAlias : ObjectData ALIASOP { $$ = $1; } +; + +/* Object's method + */ +ObjectMethod : ObjectData '(' ArgList ')' { $$ = hb_compExprNewMethodCall( $1, $3 ); } + ; + +ObjectMethodAlias : ObjectMethod ALIASOP { $$ = $1; } +; + +/* NOTE: We have to distinguish IdentName here because it is repeated + * in DoArgument (a part of DO WITH .. statement) + * where it generates different action. + */ +SimpleExpression : + NumValue + | NilValue { $$ = $1; } + | LiteralValue { $$ = $1; } + | CodeBlock { $$ = $1; } + | Logical { $$ = $1; } + | SelfValue { $$ = $1; } + | SelfValue {hb_comp_cVarType = ' '} StrongType { $$ = $1; } + | Array { $$ = $1; } + | ArrayAt { $$ = $1; } + | AliasVar { $$ = $1; } + | MacroVar { $$ = $1; } + | MacroExpr { $$ = $1; } + | VariableAt { $$ = $1; } + | FunCall { $$ = $1; } + | FunCall {hb_comp_cVarType = ' '} StrongType { $$ = $1; } + | IfInline { $$ = $1; } + | ObjectData { $$ = $1; } + | ObjectData {hb_comp_cVarType = ' '} StrongType { $$ = $1; } + | ObjectMethod { $$ = $1; } + | ObjectMethod {hb_comp_cVarType = ' '} StrongType { $$ = $1; } + | AliasExpr { $$ = $1; } + | ExprAssign { $$ = $1; } + | ExprOperEq { $$ = $1; } + | ExprPostOp { $$ = $1; } + | ExprPreOp { $$ = $1; } + | ExprUnary { $$ = $1; } + | ExprMath { $$ = $1; } + | ExprBool { $$ = $1; } + | ExprRelation { $$ = $1; } + ; + +Expression : Variable { $$ = $1; } + | SimpleExpression { $$ = $1; } + | PareExpList { $$ = $1; } + | Variable { hb_comp_cVarType = ' ';} StrongType { $$ = $1; } + | PareExpList { hb_comp_cVarType = ' ';} StrongType { $$ = $1; } + ; + +EmptyExpression: /* nothing => nil */ { $$ = hb_compExprNewEmpty(); } + | Expression + ; + +LValue : IdentName { $$ = hb_compExprNewVar( $1 ); } + | AliasVar + | MacroVar + | MacroExpr + | ObjectData + | VariableAt + | PareExpList { $$ = hb_compExprListStrip( $1, NULL ); } + ; + +/* NOTE: PostOp can be used in one context only - it uses $0 rule + * (the rule that stands before PostOp) + */ +PostOp : INC { $$ = hb_compExprNewPostInc( $0 ); } + | DEC { $$ = hb_compExprNewPostDec( $0 ); } + ; + +/* NOTE: The rule: Expression Operator Expression + * that can be used standalone as a statement have to be written + * using all possible left values to resolve shift/reduce conflicts + */ +ExprPostOp : NumValue PostOp %prec POST { $$ = $2; } + | NilValue PostOp %prec POST { $$ = $2; } + | LiteralValue PostOp %prec POST { $$ = $2; } + | CodeBlock PostOp %prec POST { $$ = $2; } + | Logical PostOp %prec POST { $$ = $2; } + | SelfValue PostOp %prec POST { $$ = $2; } + | Array PostOp %prec POST { $$ = $2; } + | ArrayAt PostOp %prec POST { $$ = $2; } + | Variable PostOp %prec POST { $$ = $2; } + | MacroVar PostOp %prec POST { $$ = $2; } + | MacroExpr PostOp %prec POST { $$ = $2; } + | AliasVar PostOp %prec POST { $$ = $2; } + | AliasExpr PostOp %prec POST { $$ = $2; } + | VariableAt PostOp %prec POST { $$ = $2; } + | PareExpList PostOp %prec POST { $$ = $2; } + | IfInline PostOp %prec POST { $$ = $2; } + | FunCall PostOp %prec POST { $$ = $2; } + | ObjectData PostOp %prec POST { $$ = $2; } + | ObjectMethod PostOp %prec POST { $$ = $2; } + ; + +ExprPreOp : INC Expression %prec PRE { $$ = hb_compExprNewPreInc( $2 ); } + | DEC Expression %prec PRE { $$ = hb_compExprNewPreDec( $2 ); } + ; + +ExprUnary : NOT Expression { $$ = hb_compExprNewNot( $2 ); } + | '-' Expression %prec UNARY { $$ = hb_compExprNewNegate( $2 ); } + | '+' Expression %prec UNARY { $$ = $2; } + ; +/* +ExprAssign : Expression INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } +; +*/ + +ExprAssign : NumValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | NilValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | LiteralValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | CodeBlock INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | Logical INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | SelfValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | Array INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | ArrayAt INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | Variable INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); hb_comp_cCastType = hb_comp_cVarType; hb_comp_cVarType = ' ';} + | MacroVar INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | MacroExpr INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | AliasVar INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | AliasExpr INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | VariableAt INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); hb_comp_cCastType = hb_comp_cVarType; hb_comp_cVarType = ' ';} + | PareExpList INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | IfInline INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | FunCall INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | ObjectData INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); hb_comp_cCastType = hb_comp_cVarType; hb_comp_cVarType = ' ';} + | ObjectMethod INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + ; + +ExprEqual : NumValue '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | NilValue '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | LiteralValue '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | CodeBlock '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | Logical '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | SelfValue '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | Array '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | ArrayAt '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | Variable '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | MacroVar '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | MacroExpr '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | AliasVar '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | AliasExpr '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | VariableAt '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | PareExpList '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | IfInline '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | FunCall '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | ObjectData '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + | ObjectMethod '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3 ); } + ; + +ExprPlusEq : NumValue PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | NilValue PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | LiteralValue PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | CodeBlock PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | Logical PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | SelfValue PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | Array PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | ArrayAt PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | Variable PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | MacroVar PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | MacroExpr PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | AliasVar PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | AliasExpr PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | VariableAt PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | PareExpList PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | IfInline PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | FunCall PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | ObjectData PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | ObjectMethod PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + ; + +ExprMinusEq : NumValue MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | NilValue MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | LiteralValue MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | CodeBlock MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | Logical MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | SelfValue MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | Array MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | ArrayAt MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | Variable MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | MacroVar MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | MacroExpr MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | AliasVar MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | AliasExpr MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | VariableAt MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | PareExpList MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | IfInline MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | FunCall MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | ObjectData MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | ObjectMethod MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + ; + +ExprMultEq : NumValue MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | NilValue MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | LiteralValue MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | CodeBlock MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | Logical MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | SelfValue MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | Array MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | ArrayAt MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | Variable MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | MacroVar MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | MacroExpr MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | AliasVar MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | AliasExpr MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | VariableAt MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | PareExpList MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | IfInline MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | FunCall MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | ObjectData MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | ObjectMethod MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + ; + +ExprDivEq : NumValue DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | NilValue DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | LiteralValue DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | CodeBlock DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | Logical DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | SelfValue DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | Array DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | ArrayAt DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | Variable DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | MacroVar DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | MacroExpr DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | AliasVar DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | AliasExpr DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | VariableAt DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | PareExpList DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | IfInline DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | FunCall DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | ObjectData DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | ObjectMethod DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + ; + +ExprModEq : NumValue MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | NilValue MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | LiteralValue MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | CodeBlock MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | Logical MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | SelfValue MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | Array MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | ArrayAt MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | Variable MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | MacroVar MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | MacroExpr MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | AliasVar MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | AliasExpr MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | VariableAt MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | PareExpList MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | IfInline MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | FunCall MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | ObjectData MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | ObjectMethod MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + ; + +ExprExpEq : NumValue EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | NilValue EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | LiteralValue EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | CodeBlock EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | Logical EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | SelfValue EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | Array EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | ArrayAt EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | Variable EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | MacroVar EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | MacroExpr EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | AliasVar EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | AliasExpr EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | VariableAt EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | PareExpList EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | IfInline EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | FunCall EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | ObjectData EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + | ObjectMethod EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + ; + +ExprOperEq : ExprPlusEq { $$ = $1; } + | ExprMinusEq { $$ = $1; } + | ExprMultEq { $$ = $1; } + | ExprDivEq { $$ = $1; } + | ExprModEq { $$ = $1; } + | ExprExpEq { $$ = $1; } + ; + +ExprMath : Expression '+' Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlus( $1 ), $3 ); } + | Expression '-' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinus( $1 ), $3 ); } + | Expression '*' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMult( $1 ), $3 ); } + | Expression '/' Expression { $$ = hb_compExprSetOperand( hb_compExprNewDiv( $1 ), $3 ); } + | Expression '%' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMod( $1 ), $3 ); } + | Expression POWER Expression { $$ = hb_compExprSetOperand( hb_compExprNewPower( $1 ), $3 ); } + ; + +ExprBool : Expression AND Expression { $$ = hb_compExprSetOperand( hb_compExprNewAnd( $1 ), $3 ); } + | Expression OR Expression { $$ = hb_compExprSetOperand( hb_compExprNewOr( $1 ), $3 ); } + ; + +ExprRelation: Expression EQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewEQ( $1 ), $3 ); } + | Expression '<' Expression { $$ = hb_compExprSetOperand( hb_compExprNewLT( $1 ), $3 ); } + | Expression '>' Expression { $$ = hb_compExprSetOperand( hb_compExprNewGT( $1 ), $3 ); } + | Expression LE Expression { $$ = hb_compExprSetOperand( hb_compExprNewLE( $1 ), $3 ); } + | Expression GE Expression { $$ = hb_compExprSetOperand( hb_compExprNewGE( $1 ), $3 ); } + | Expression NE1 Expression { $$ = hb_compExprSetOperand( hb_compExprNewNE( $1 ), $3 ); } + | Expression NE2 Expression { $$ = hb_compExprSetOperand( hb_compExprNewNE( $1 ), $3 ); } + | Expression '$' Expression { $$ = hb_compExprSetOperand( hb_compExprNewIN( $1 ), $3 ); } + | Expression '=' Expression { $$ = hb_compExprSetOperand( hb_compExprNewEqual( $1 ), $3 ); } + ; + +ArrayIndex : IndexList ']' { $$ = $1; } + ; + +/* NOTE: $0 represents the expression before ArrayIndex + * Don't use ArrayIndex in other context than as an array index! + */ +IndexList : '[' Expression { $$ = hb_compExprNewArrayAt( $0, $2 ); } + | IndexList ',' Expression { $$ = hb_compExprNewArrayAt( $1, $3 ); } + | IndexList ']' '[' Expression { $$ = hb_compExprNewArrayAt( $1, $4 ); } + ; + +ElemList : Argument { $$ = hb_compExprNewList( $1 ); } + | ElemList ',' Argument { $$ = hb_compExprAddListExpr( $1, $3 ); } + ; + +CodeBlock : '{' '|' { $$ = hb_compExprNewCodeBlock(); } BlockNoVar + '|' BlockExpList '}' { $$ = $3; } + | '{' '|' { $$ = hb_compExprNewCodeBlock(); } BlockVarList + '|' BlockExpList '}' { $$ = $3; } + ; + +/* NOTE: This uses $-2 then don't use BlockExpList in other context + */ +BlockExpList : Expression { $$ = hb_compExprAddListExpr( $-2, $1 ); } + | BlockExpList ',' Expression { $$ = hb_compExprAddListExpr( $-2, $3 ); } + ; + +/* NOTE: This is really not needed however it allows the use of $-2 item + * in BlockExpList to refer the same rule defined in Codeblock + */ +BlockNoVar : /* empty list */ { $$ = NULL; } +; + +BlockVarList : IdentName AsType { hb_comp_iVarScope = VS_LOCAL; $$ = hb_compExprCBVarAdd( $0, $1, hb_comp_cVarType ); hb_comp_cVarType = ' '; } + | BlockVarList ',' IdentName AsType { hb_comp_iVarScope = VS_LOCAL; $$ = hb_compExprCBVarAdd( $0, $3, hb_comp_cVarType ); hb_comp_cVarType = ' '; } + ; + +/* There is a conflict between the use of IF( Expr1, Expr2, Expr3 ) + * and parenthesized expression ( Expr1, Expr2, Expr3 ) + * To solve this conflict we have to split the definitions into more + * atomic ones. + * Also the generation of pcodes have to be delayed and moved to the + * end of whole parenthesized expression. + */ +PareExpList1: ExpList1 ')' { $$ = $1; } + ; + +PareExpList2: ExpList2 ')' { $$ = $1; } + ; + +PareExpList3: ExpList3 ')' { $$ = $1; } + ; + +PareExpListN: ExpList ')' { $$ = $1; } + ; + +PareExpList : PareExpList1 { $$ = $1; } + | PareExpList2 { $$ = $1; } + | PareExpList3 { $$ = $1; } + | PareExpListN { $$ = $1; } + ; + +PareExpListAlias : PareExpList ALIASOP { $$ = $1; } +; + +ExpList1 : '(' EmptyExpression { $$ = hb_compExprNewList( $2 ); } +; + +ExpList2 : ExpList1 ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } +; + +ExpList3 : ExpList2 ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } +; + +ExpList : ExpList3 ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } + | ExpList ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } + ; + +IfInline : IIF PareExpList3 { $$ = hb_compExprNewIIF( $2 ); } + | IF ExpList1 ',' EmptyExpression ',' + { $$ = hb_compExprAddListExpr( $2, $4 ); } + EmptyExpression ')' + { $$ = hb_compExprNewIIF( hb_compExprAddListExpr( $6, $7 ) ); } + ; + +IfInlineAlias : IfInline ALIASOP { $$ = $1; } +; + +VarDefs : LOCAL { hb_comp_iVarScope = VS_LOCAL; hb_compLinePush(); } VarList Crlf { hb_comp_cVarType = ' '; } + | STATIC { hb_comp_iVarScope = VS_STATIC; hb_compLinePush(); } VarList Crlf { hb_comp_cVarType = ' '; } + | PARAMETERS { if( hb_comp_functions.pLast->bFlags & FUN_USES_LOCAL_PARAMS ) + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_PARAMETERS_NOT_ALLOWED, NULL, NULL ); + else + hb_comp_functions.pLast->wParamNum=0; hb_comp_iVarScope = ( VS_PRIVATE | VS_PARAMETER ); } + MemvarList Crlf { hb_comp_iVarScope = VS_NONE; } + ; + +VarList : VarDef { $$ = 1; } + | VarList ',' VarDef { $$++; } + ; + +ExtVarList : ExtVarDef { $$ = 1; } + | ExtVarList ',' ExtVarDef { $$++; } + ; + +/* NOTE: if STATIC or LOCAL variables are declared and initialized then we can + * assign a value immediately - however for PRIVATE and PUBLIC variables + * initialization have to be delayed because we have to create these variables + * first. + */ +ExtVarDef : VarDef + | MacroVar AsType + { hb_compRTVariableAdd( hb_compExprNewRTVar( NULL, $1 ), FALSE ); } + | MacroVar AsType INASSIGN Expression + { hb_compExprDelete( hb_compExprGenPush( $4 ) ); + hb_compRTVariableAdd( hb_compExprNewRTVar( NULL, $1 ), TRUE ); + } + | MacroVar DimList + { + USHORT uCount = hb_compExprListLen( $2 ); + hb_compExprDelete( hb_compExprGenPush( $2 ) ); + hb_compGenPCode3( HB_P_ARRAYDIM, HB_LOBYTE( uCount ), HB_HIBYTE( uCount ), ( BOOL ) 1 ); + hb_compRTVariableAdd( hb_compExprNewRTVar( NULL, $1 ), TRUE ); + } + | MacroVar DimList AsArray + { + USHORT uCount = hb_compExprListLen( $2 ); + hb_compExprDelete( hb_compExprGenPush( $2 ) ); + hb_compGenPCode3( HB_P_ARRAYDIM, HB_LOBYTE( uCount ), HB_HIBYTE( uCount ), ( BOOL ) 1 ); + hb_compRTVariableAdd( hb_compExprNewRTVar( NULL, $1 ), TRUE ); + } + ; + +VarDef : IdentName AsType { hb_compVariableAdd( $1, hb_comp_cVarType ); } + { + if( hb_comp_iVarScope == VS_STATIC ) + { + hb_compStaticDefStart(); /* switch to statics pcode buffer */ + hb_compStaticDefEnd(); + } + else if( hb_comp_iVarScope == VS_PUBLIC || hb_comp_iVarScope == VS_PRIVATE ) + { + hb_compRTVariableAdd( hb_compExprNewRTVar( $1, NULL ), FALSE ); + } + } + + | IdentName AsType { $$ = hb_comp_iVarScope; + hb_compVariableAdd( $1, hb_comp_cVarType ); + } + INASSIGN {hb_comp_cVarType = ' ';} Expression + { + hb_comp_cCastType = hb_comp_cVarType; + hb_comp_cVarType = ' '; + + hb_comp_iVarScope = $3; + if( hb_comp_iVarScope == VS_STATIC ) + { + hb_compStaticDefStart(); /* switch to statics pcode buffer */ + hb_compExprDelete( hb_compExprGenStatement( hb_compExprAssignStatic( hb_compExprNewVar( $1 ), $6 ) ) ); + hb_compStaticDefEnd(); + } + else if( hb_comp_iVarScope == VS_PUBLIC || hb_comp_iVarScope == VS_PRIVATE ) + { + hb_compExprDelete( hb_compExprGenPush( $6 ) ); + hb_compRTVariableAdd( hb_compExprNewRTVar( $1, NULL ), TRUE ); + } + else + { + hb_compExprDelete( hb_compExprGenStatement( hb_compExprAssign( hb_compExprNewVar( $1 ), $6 ) ) ); + } + hb_comp_iVarScope = $3; + } + + | IdentName DimList { hb_compVariableDim( $1, $2 ); } + | IdentName DimList AsArray { hb_compVariableDim( $1, $2 ); } + ; + +/* NOTE: DimList and DimIndex is the same as ArrayIndex and IndexList + * however we are using quite different actions here + */ +DimList : DimIndex ']' { $$ = $1; } + ; + +DimIndex : '[' Expression { $$ = hb_compExprNewArgList( $2 ); } + | DimIndex ',' Expression { $$ = hb_compExprAddListExpr( $1, $3 ); } + | DimIndex ']' '[' Expression { $$ = hb_compExprAddListExpr( $1, $4 ); } + ; + + +FieldsDef : FIELD { hb_comp_iVarScope = VS_FIELD; } FieldList Crlf { hb_comp_cVarType = ' '; } + ; + +FieldList : IdentName AsType { $$=hb_compFieldsCount(); hb_compVariableAdd( $1, hb_comp_cVarType ); } + | FieldList ',' IdentName AsType { hb_compVariableAdd( $3, hb_comp_cVarType ); } + | FieldList IN IdentName { hb_compFieldSetAlias( $3, $1 ); } + ; + +MemvarDef : MEMVAR { hb_comp_iVarScope = VS_MEMVAR; } MemvarList Crlf { hb_comp_cVarType = ' '; } + ; + +MemvarList : IdentName AsType { hb_compVariableAdd( $1, hb_comp_cVarType ); } + | MemvarList ',' IdentName AsType { hb_compVariableAdd( $3, hb_comp_cVarType ); } + ; + +Declaration: DECLARE IdentName '(' { hb_compDeclaredAdd( $2 ); hb_comp_szDeclaredFun = $2; } DecList ')' AsType Crlf + { + if( hb_comp_pLastDeclared ) + { + hb_comp_pLastDeclared->cType = hb_comp_cVarType; + + if ( toupper( hb_comp_cVarType ) == 'S' ) + { + hb_comp_pLastDeclared->pClass = hb_compClassFind( hb_comp_szFromClass ); + if( ! hb_comp_pLastDeclared->pClass ) + { + hb_compGenWarning( hb_comp_szWarnings, 'W', HB_COMP_WARN_CLASS_NOT_FOUND, hb_comp_szFromClass, hb_comp_pLastDeclared->szName ); + hb_comp_pLastDeclared->cType = ( isupper( ( int ) hb_comp_cVarType ) ? 'O' : 'o' ); + } + + /* Resetting */ + hb_comp_szFromClass = NULL; + } + } + hb_comp_szDeclaredFun = NULL; + hb_comp_cVarType = ' '; + hb_comp_iVarScope = VS_NONE; + } + | DECLARE IdentName { hb_comp_pLastClass = hb_compClassAdd( $2 ); } ClassInfo Crlf { hb_comp_iVarScope = VS_NONE; } + | DECLARE_CLASS IdentName Crlf { hb_comp_pLastClass = hb_compClassAdd( $2 ); hb_comp_iVarScope = VS_NONE; } + | DECLARE_MEMBER DecMethod Crlf { hb_comp_iVarScope = VS_NONE; } + | DECLARE_MEMBER '{' AsType { hb_comp_cDataListType = hb_comp_cVarType; } DecDataList '}' Crlf { hb_comp_cDataListType = NULL; hb_comp_iVarScope = VS_NONE; } + ; + +DecDataList: DecData + | DecDataList ',' DecData + ; + +ClassInfo : DecMethod + | ClassInfo DecMethod + | DecData + | ClassInfo DecData + ; + +DecMethod : IdentName '(' { hb_comp_pLastMethod = hb_compMethodAdd( hb_comp_pLastClass, $1 ); } DecList ')' AsType + { + if( hb_comp_pLastMethod ) + { + hb_comp_pLastMethod->cType = hb_comp_cVarType; + if ( toupper( hb_comp_cVarType ) == 'S' ) + { + hb_comp_pLastMethod->pClass = hb_compClassFind( hb_comp_szFromClass ); + if( ! hb_comp_pLastMethod->pClass ) + { + hb_compGenWarning( hb_comp_szWarnings, 'W', HB_COMP_WARN_CLASS_NOT_FOUND, hb_comp_szFromClass, hb_comp_pLastMethod->szName ); + hb_comp_pLastMethod->cType = ( isupper( ( int ) hb_comp_cVarType ) ? 'O' : 'o' ); + } + + hb_comp_szFromClass = NULL; + } + } + hb_comp_pLastMethod = NULL; + hb_comp_cVarType = ' '; + } + ; + +DecData : IdentName { hb_comp_pLastMethod = hb_compMethodAdd( hb_comp_pLastClass, $1 ); } AsType + { + if( hb_comp_pLastMethod ) + { + PCOMCLASS pClass; + char * szSetData = ( char * ) hb_xgrab( strlen( $1 ) + 2 ); + + /* List Type overrides if exists. */ + if( hb_comp_cDataListType ) hb_comp_cVarType = hb_comp_cDataListType; + + hb_comp_pLastMethod->cType = hb_comp_cVarType; + if ( toupper( hb_comp_cVarType ) == 'S' ) + { + pClass = hb_compClassFind( hb_comp_szFromClass ); + hb_comp_pLastMethod->pClass = pClass; + if( ! hb_comp_pLastMethod->pClass ) + { + hb_compGenWarning( hb_comp_szWarnings, 'W', HB_COMP_WARN_CLASS_NOT_FOUND, hb_comp_szFromClass, hb_comp_pLastMethod->szName ); + hb_comp_pLastMethod->cType = ( isupper( ( int ) hb_comp_cVarType ) ? 'O' :'o' ); + } + } + else + pClass = NULL; + + sprintf( szSetData, "_%s", $1 ); + + hb_comp_pLastMethod = hb_compMethodAdd( hb_comp_pLastClass, szSetData ); + hb_comp_pLastMethod->cType = hb_comp_cVarType; + hb_comp_pLastMethod->iParamCount = 1; + + hb_comp_pLastMethod->cParamTypes = ( BYTE * ) hb_xgrab( 1 ); + hb_comp_pLastMethod->cParamTypes[0] = hb_comp_cVarType; + + hb_comp_pLastMethod->pParamClasses = ( PCOMCLASS * ) hb_xgrab( sizeof( COMCLASS ) ); + hb_comp_pLastMethod->pParamClasses[0] = pClass; + + if ( toupper( hb_comp_cVarType ) == 'S' ) + { + hb_comp_pLastMethod->pClass = pClass; + hb_comp_szFromClass = NULL; + } + } + + hb_comp_pLastMethod = NULL; + hb_comp_cVarType = ' '; + } + ; + +DecList : /* Nothing */ {} + | FormalList + | OptList + | FormalList ',' OptList + ; + +FormalList : IdentName AsType { hb_compDeclaredParameterAdd( $1, hb_comp_cVarType ); } + | '@' IdentName AsType { hb_compDeclaredParameterAdd( $2, hb_comp_cVarType + VT_OFFSET_BYREF ); } + | '@' IdentName '(' ')' { hb_compDeclaredParameterAdd( $2, 'F' ); } + | FormalList ',' IdentName AsType { hb_compDeclaredParameterAdd( $3, hb_comp_cVarType ); } + | FormalList ',' '@' IdentName AsType { hb_compDeclaredParameterAdd( $4, hb_comp_cVarType + VT_OFFSET_BYREF ); } + | FormalList ',' '@' IdentName '(' ')'{ hb_compDeclaredParameterAdd( $4, 'F' ); } + ; + +OptList : OPTIONAL IdentName AsType { hb_compDeclaredParameterAdd( $2, hb_comp_cVarType + VT_OFFSET_OPTIONAL ); } + | OPTIONAL '@' IdentName AsType { hb_compDeclaredParameterAdd( $3, hb_comp_cVarType + VT_OFFSET_OPTIONAL + VT_OFFSET_BYREF ); } + | OPTIONAL '@' IdentName '(' ')' { hb_compDeclaredParameterAdd( $3, hb_comp_cVarType + VT_OFFSET_OPTIONAL + VT_OFFSET_BYREF ); } + | OptList ',' OPTIONAL IdentName AsType { hb_compDeclaredParameterAdd( $4, hb_comp_cVarType + VT_OFFSET_OPTIONAL ); } + | OptList ',' OPTIONAL '@' IdentName AsType { hb_compDeclaredParameterAdd( $5, hb_comp_cVarType + VT_OFFSET_OPTIONAL + VT_OFFSET_BYREF ); } + | OptList ',' OPTIONAL '@' IdentName '(' ')'{ hb_compDeclaredParameterAdd( $5, hb_comp_cVarType + VT_OFFSET_OPTIONAL + VT_OFFSET_BYREF ); } + ; + +ExecFlow : IfEndif + | DoCase + | DoWhile + | ForNext + | BeginSeq + ; + +IfEndif : IfBegin EndIf { hb_compGenJumpHere( $1 ); } + | IfBegin IfElse EndIf { hb_compGenJumpHere( $1 ); } + | IfBegin IfElseIf EndIf { hb_compGenJumpHere( $1 ); hb_compElseIfFix( $2 ); } + | IfBegin IfElseIf IfElse EndIf { hb_compGenJumpHere( $1 ); hb_compElseIfFix( $2 ); } + ; + +EmptyStatements : LineStat { $$ = $1; } + | EmptyStatements { hb_compLinePush(); } LineStat { $$ += $3; } + ; + +EmptyStats : /* empty */ { hb_comp_bDontGenLineNum = TRUE; $$ = 0; } + | EmptyStatements { $$ = $1; } + ; + +IfBegin : IF SimpleExpression { ++hb_comp_wIfCounter; hb_compLinePush(); } Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); } + EmptyStats + { $$ = hb_compGenJump( 0 ); hb_compGenJumpHere( $5 ); } + + | IF Variable { ++hb_comp_wIfCounter; hb_compLinePush(); } Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); } + EmptyStats + { $$ = hb_compGenJump( 0 ); hb_compGenJumpHere( $5 ); } + + | IF PareExpList1 { ++hb_comp_wIfCounter; hb_compLinePush(); } Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); } + EmptyStats + { $$ = hb_compGenJump( 0 ); hb_compGenJumpHere( $5 ); } + + | IF PareExpList2 { ++hb_comp_wIfCounter; hb_compLinePush(); } Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); } + EmptyStats + { $$ = hb_compGenJump( 0 ); hb_compGenJumpHere( $5 ); } + + | IF PareExpListN { ++hb_comp_wIfCounter; hb_compLinePush(); } Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); } + EmptyStats + { $$ = hb_compGenJump( 0 ); hb_compGenJumpHere( $5 ); } + ; + +IfElse : ELSE Crlf { hb_comp_functions.pLast->bFlags &= ~ FUN_BREAK_CODE; } + EmptyStats + ; + +IfElseIf : ELSEIF { hb_compLinePush(); } Expression Crlf + { hb_comp_functions.pLast->bFlags &= ~ FUN_BREAK_CODE; + hb_compExprDelete( hb_compExprGenPush( $3 ) ); + $$ = hb_compGenJumpFalse( 0 ); + } + EmptyStats + { $$ = hb_compElseIfGen( NULL, hb_compGenJump( 0 ) ); + hb_compGenJumpHere( $5 ); + } + + | IfElseIf ELSEIF { hb_compLinePush(); } Expression Crlf + { hb_comp_functions.pLast->bFlags &= ~ FUN_BREAK_CODE; + hb_compExprDelete( hb_compExprGenPush( $4 ) ); + $$ = hb_compGenJumpFalse( 0 ); + } + EmptyStats + { $$ = hb_compElseIfGen( $1, hb_compGenJump( 0 ) ); + hb_compGenJumpHere( $6 ); + } + ; + +EndIf : ENDIF { --hb_comp_wIfCounter; hb_comp_functions.pLast->bFlags &= ~ ( FUN_WITH_RETURN | FUN_BREAK_CODE ); } + | END { --hb_comp_wIfCounter; hb_comp_functions.pLast->bFlags &= ~ ( FUN_WITH_RETURN | FUN_BREAK_CODE ); } + ; + +DoCase : DoCaseBegin + Cases + EndCase { hb_compElseIfFix( $2 ); } + + | DoCaseBegin + Otherwise + EndCase + + | DoCaseBegin + EndCase + + | DoCaseBegin + Cases + Otherwise + EndCase { hb_compElseIfFix( $2 ); } + ; + +EndCase : ENDCASE + { --hb_comp_wCaseCounter; + hb_comp_functions.pLast->bFlags &= ~ ( FUN_WITH_RETURN | FUN_BREAK_CODE ); + } + | END + { --hb_comp_wCaseCounter; + hb_comp_functions.pLast->bFlags &= ~ ( FUN_WITH_RETURN | FUN_BREAK_CODE ); + } + ; + +DoCaseStart : DOCASE { ++hb_comp_wCaseCounter; } Crlf + ; + +DoCaseBegin : DoCaseStart { } + | DoCaseStart Statements { + if( $2 > 0 ) + { + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_MAYHEM_IN_CASE, NULL, NULL ); + } + } + ; + +Cases : CASE { hb_compLinePush(); } Expression Crlf + { + hb_compExprDelete( hb_compExprGenPush( $3 ) ); + $$ = hb_compGenJumpFalse( 0 ); + } + EmptyStats + { + hb_comp_functions.pLast->bFlags &= ~ FUN_BREAK_CODE; + $$ = hb_compElseIfGen( 0, hb_compGenJump( 0 ) ); + hb_compGenJumpHere( $5 ); + } + + | Cases CASE { hb_compLinePush(); } Expression Crlf + { + hb_compExprDelete( hb_compExprGenPush( $4 ) ); + $$ = hb_compGenJumpFalse( 0 ); + } + EmptyStats + { + hb_comp_functions.pLast->bFlags &= ~ FUN_BREAK_CODE; + $$ = hb_compElseIfGen( $1, hb_compGenJump( 0 ) ); + hb_compGenJumpHere( $6 ); + } + ; + +Otherwise : OTHERWISE Crlf { hb_comp_functions.pLast->bFlags &= ~ FUN_BREAK_CODE; } + EmptyStats + | Otherwise OTHERWISE { hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_MAYHEM_IN_CASE, NULL, NULL ); } Crlf + EmptyStats + ; + +DoWhile : WhileBegin Expression Crlf + { + hb_compExprDelete( hb_compExprGenPush( $2 ) ); + $$ = hb_compGenJumpFalse( 0 ); + } + EmptyStats + { + hb_compLoopHere(); + hb_compGenJump( $1 - hb_comp_functions.pLast->lPCodePos ); + } + EndWhile + { + hb_compGenJumpHere( $4 ); --hb_comp_wWhileCounter; + hb_compLoopEnd(); + hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; + } + ; + +WhileBegin : WHILE { $$ = hb_comp_functions.pLast->lPCodePos; hb_compLinePushIfInside(); ++hb_comp_wWhileCounter; hb_compLoopStart(); } + ; + +EndWhile : END + | ENDDO + ; + +ForNext : FOR LValue ForAssign Expression /* 1 2 3 4 */ + { + hb_compLinePush(); + hb_compDebugStart(); + ++hb_comp_wForCounter; /* 5 */ + $$ = hb_compExprGenStatement( hb_compExprAssign( $2, $4 ) ); + } + TO Expression StepExpr /* 6 7 8 */ + { + hb_compLoopStart(); + $$ = hb_comp_functions.pLast->lPCodePos; /* 9 */ + hb_compExprGenPush( $2 ); /* counter */ + hb_compExprGenPush( $7 ); /* end */ + if( $8 ) + hb_compExprGenPush( $8 ); /* step */ + } + Crlf /* 10 */ + { + if( $8 ) + hb_compGenPCode1( HB_P_FORTEST ); + else + hb_compGenPCode1( HB_P_LESSEQUAL ); + $$ = hb_compGenJumpFalse( 0 ); /* 11 */ + } + ForStatements /* 12 */ + { + hb_compLoopHere(); + if( $8 ) + hb_compExprClear( hb_compExprGenStatement( hb_compExprSetOperand( hb_compExprNewPlusEq( $2 ), $8 ) ) ); + else + hb_compExprClear( hb_compExprGenStatement( hb_compExprNewPreInc( $2 ) ) ); + hb_compGenJump( $9 - hb_comp_functions.pLast->lPCodePos ); + hb_compGenJumpHere( $11 ); + hb_compLoopEnd(); + hb_compExprDelete( $7 ); + hb_compExprDelete( $5 ); /* deletes $5, $2, $4 */ + if( $8 ) + hb_compExprDelete( $8 ); + hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; + } + ; + +ForAssign : '=' + | INASSIGN + ; + +StepExpr : /* default step expression */ { $$ = NULL; } + | STEP Expression { $$ = $2; } + ; + +ForStatements : EmptyStats NEXT { --hb_comp_wForCounter; } + | EmptyStats NEXT IdentName { --hb_comp_wForCounter; } + | EmptyStats END { --hb_comp_wForCounter; } + | EmptyStats END IdentName { --hb_comp_wForCounter; } + ; + +BeginSeq : BEGINSEQ { ++hb_comp_wSeqCounter; $$ = hb_compSequenceBegin(); } Crlf + EmptyStats + { + /* Set jump address for HB_P_SEQBEGIN opcode - this address + * will be used in BREAK code if there is no RECOVER clause + */ + hb_compGenJumpHere( $2 ); + $$ = hb_compSequenceEnd(); + } + RecoverSeq + { + /* Replace END address with RECOVER address in + * HB_P_SEQBEGIN opcode if there is RECOVER clause + */ + if( $6 ) + hb_compGenJumpThere( $2, $6 ); + } + END + { + /* Fix END address + * There is no line number after HB_P_SEQEND in case no + * RECOVER clause is used + */ + hb_compGenJumpThere( $5, hb_comp_functions.pLast->lPCodePos ); + if( !$6 ) /* only if there is no RECOVER clause */ + --hb_comp_wSeqCounter; /* RECOVER is also considered as end of sequence */ + hb_compSequenceFinish( $2, $4 ); + hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; + } + ; + +RecoverSeq : /* no recover */ { $$ = 0; } + | RecoverEmpty Crlf { $$ = $1; } EmptyStats + | RecoverUsing Crlf { $$ = $1; } EmptyStats + ; + +RecoverEmpty : RECOVER + { + hb_comp_functions.pLast->bFlags &= ~ FUN_BREAK_CODE; + $$ = hb_comp_functions.pLast->lPCodePos; + --hb_comp_wSeqCounter; + hb_compGenPCode2( HB_P_SEQRECOVER, HB_P_POP, ( BOOL ) 1 ); + } + ; + +RecoverUsing : RECOVERUSING IdentName + { + hb_comp_functions.pLast->bFlags &= ~ FUN_BREAK_CODE; + $$ = hb_comp_functions.pLast->lPCodePos; + --hb_comp_wSeqCounter; + hb_compGenPCode1( HB_P_SEQRECOVER ); + hb_compLinePush(); + hb_compGenPopVar( $2 ); + } + ; + +/* NOTE: In Clipper all variables used in DO .. WITH are passed by reference + * however if they are part of an expression then they are passed by value + * for example: + * DO .. WITH ++variable + * will pass the value of variable not a reference + */ +DoName : IdentName { $$ = hb_compExprNewFunName( $1 ); hb_compAutoOpenAdd( $1 ); } + | MacroVar { $$ = $1; } + | MacroExpr { $$ = $1; } + ; + +DoProc : DO DoName + { $$ = hb_compExprNewFunCall( $2, NULL ); } + | DO DoName WITH DoArgList + { $$ = hb_compExprNewFunCall( $2, $4 ); } + | WHILE WITH DoArgList + { hb_compAutoOpenAdd( "WHILE" ); $$ = hb_compExprNewFunCall( hb_compExprNewFunName( hb_compIdentifierNew("WHILE", TRUE) ), $3 ); } + ; + +DoArgList : ',' { $$ = hb_compExprAddListExpr( hb_compExprNewArgList( hb_compExprNewNil() ), hb_compExprNewNil() ); } + | ',' DoArgument { $$ = hb_compExprAddListExpr( hb_compExprNewArgList( hb_compExprNewNil() ), $2 ); } + | DoArgument { $$ = hb_compExprNewArgList( $1 ); } + | DoArgList ',' { $$ = hb_compExprAddListExpr( $1, hb_compExprNewNil() ); } + | DoArgList ',' DoArgument { $$ = hb_compExprAddListExpr( $1, $3 ); } + ; + +DoArgument : IdentName { $$ = hb_compExprNewVarRef( $1 ); } + | '@' IdentName '(' ')' { $$ = hb_compExprNewFunRef( $2 ); } + | SimpleExpression { $$ = $1; } + | PareExpList { $$ = $1; } + ; + +Crlf : '\n' { hb_comp_bError = FALSE; } + | ';' { hb_comp_bDontGenLineNum = TRUE; } + ; + +%% + +/* + ** ------------------------------------------------------------------------ ** + */ + +#if 0 +int hb_compYACCMain( char * szName ) +{ + /* Generate the starting procedure frame */ + if( hb_comp_bStartProc ) + hb_compFunctionAdd( hb_strupr( hb_strdup( szName ) ), HB_FS_PUBLIC, FUN_PROCEDURE ); + else + /* Don't pass the name of module if the code for starting procedure + * will be not generated. The name cannot be placed as first symbol + * because this symbol can be used as function call or memvar's name. + */ + hb_compFunctionAdd( hb_strupr( hb_strdup( "" ) ), HB_FS_PUBLIC, FUN_PROCEDURE ); + + yyparse(); + + /* fix all previous function returns offsets */ + hb_compFinalizeFunction(); + + hb_compExternGen(); /* generates EXTERN symbols names */ + + if( hb_comp_pInitFunc ) + { + PCOMSYMBOL pSym; + + /* Fix the number of static variables */ + hb_comp_pInitFunc->pCode[ 3 ] = HB_LOBYTE( hb_comp_iStaticCnt ); + hb_comp_pInitFunc->pCode[ 4 ] = HB_HIBYTE( hb_comp_iStaticCnt ); + hb_comp_pInitFunc->iStaticsBase = hb_comp_iStaticCnt; + + pSym = hb_compSymbolAdd( hb_comp_pInitFunc->szName, NULL ); + pSym->cScope |= hb_comp_pInitFunc->cScope; + hb_comp_functions.pLast->pNext = hb_comp_pInitFunc; + hb_comp_functions.pLast = hb_comp_pInitFunc; + hb_compGenPCode1( HB_P_ENDPROC ); + ++hb_comp_functions.iCount; + } + + if( hb_comp_szAnnounce ) + hb_compAnnounce( hb_comp_szAnnounce ); + + /* Close processed file (it is opened in hb_compInclude() function ) + */ + fclose( yyin ); + + while( hb_comp_files.pLast ) + { + PFILE pFile = hb_comp_files.pLast; + if( pFile->pBuffer ) + hb_xfree( (void *) pFile->pBuffer ); + hb_xfree( (void *) pFile->szFileName ); + hb_comp_files.pLast = pFile->pPrev; + hb_xfree( pFile ); + } + hb_comp_files.pLast = NULL; + + return 0; +} +#endif + +/* ------------------------------------------------------------------------ */ + +void yyerror( char * s ) +{ + if( yytext[ 0 ] == '\n' ) + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_YACC, s, "" ); + else + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_YACC, s, yytext ); +} + + +BOOL hb_compInclude( char * szFileName, PATHNAMES * pSearch ) +{ + PFILE pFile; + + yyin = fopen( szFileName, "r" ); + if( ! yyin ) + { + if( pSearch ) + { + PHB_FNAME pFileName = hb_fsFNameSplit( szFileName ); + + while( pSearch && !yyin ) + { + char szFName[ _POSIX_PATH_MAX ]; /* filename to parse */ + + pFileName->szPath = pSearch->szPath; + hb_fsFNameMerge( szFName, pFileName ); + yyin = fopen( szFName, "r" ); + if( ! yyin ) + { + pSearch = pSearch->pNext; + if( ! pSearch ) + return FALSE; + } + } + + hb_xfree( ( void * ) pFileName ); + } + else + return FALSE; + } + + pFile = ( PFILE ) hb_xgrab( sizeof( _FILE ) ); + pFile->handle = yyin; + pFile->pBuffer = hb_xgrab( HB_PP_BUFF_SIZE ); + pFile->iBuffer = pFile->lenBuffer = 10; + pFile->szFileName = szFileName; + pFile->iLine = 0; + pFile->pPrev = hb_comp_files.pLast; + + hb_comp_files.pLast = pFile; + +#ifdef __cplusplus + yy_switch_to_buffer( ( YY_BUFFER_STATE ) ( hb_comp_buffer = ( char * ) yy_create_buffer( yyin, 8192 * 2 ) ) ); +#else + yy_switch_to_buffer( hb_comp_buffer = yy_create_buffer( yyin, 8192 * 2 ) ); +#endif + hb_comp_files.iFiles++; + + return TRUE; +} + +int yywrap( void ) /* handles the EOF of the currently processed file */ +{ + if( hb_comp_files.iFiles == 1 ) + { + hb_xfree( hb_comp_files.pLast->pBuffer ); + hb_comp_files.pLast->pBuffer = NULL; + return 1; /* we have reached the main EOF */ + } + + return 0; +} + +/* ************************************************************************* */ + +/* + * This function stores the position in pcode buffer where the FOR/WHILE + * loop starts. It will be used to fix any LOOP/EXIT statements + */ +static void hb_compLoopStart( void ) +{ + PTR_LOOPEXIT pLoop = ( PTR_LOOPEXIT ) hb_xgrab( sizeof( LOOPEXIT ) ); + + if( hb_comp_pLoops ) + { + PTR_LOOPEXIT pLast = hb_comp_pLoops; + + while( pLast->pNext ) + pLast = pLast->pNext; + pLast->pNext = pLoop; + } + else + hb_comp_pLoops = pLoop; + + pLoop->pNext = NULL; + pLoop->pExitList = NULL; + pLoop->pLoopList = NULL; + pLoop->ulOffset = hb_comp_functions.pLast->lPCodePos; /* store the start position */ + pLoop->iLine = hb_comp_iLine; + pLoop->wSeqCounter = hb_comp_wSeqCounter; /* store current SEQUENCE counter */ +} + +/* + * Stores the position of LOOP statement to fix it later at the end of loop + */ +static void hb_compLoopLoop( void ) +{ + if( ! hb_comp_pLoops ) + { + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_UNMATCHED_EXIT, "LOOP", NULL ); + } + else + { + PTR_LOOPEXIT pLast, pLoop; + + pLoop = ( PTR_LOOPEXIT ) hb_xgrab( sizeof( LOOPEXIT ) ); + + pLoop->pLoopList = NULL; + pLoop->ulOffset = hb_comp_functions.pLast->lPCodePos; /* store the position to fix */ + + pLast = hb_comp_pLoops; + while( pLast->pNext ) + pLast = pLast->pNext; + + if( pLast->wSeqCounter != hb_comp_wSeqCounter ) + { + /* Attempt to LOOP from BEGIN/END sequence + * Current SEQUENCE counter is different then at the beginning of loop + * Notice that LOOP is allowed in RECOVER code. + */ + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_EXIT_IN_SEQUENCE, "LOOP", NULL ); + } + else + { + while( pLast->pLoopList ) + pLast = pLast->pLoopList; + + pLast->pLoopList = pLoop; + + hb_compGenJump( 0 ); + } + } +} + +/* + * Stores the position of EXIT statement to fix it later at the end of loop + */ +static void hb_compLoopExit( void ) +{ + if( ! hb_comp_pLoops ) + { + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_UNMATCHED_EXIT, "EXIT", NULL ); + } + else + { + PTR_LOOPEXIT pLast, pLoop; + + pLoop = ( PTR_LOOPEXIT ) hb_xgrab( sizeof( LOOPEXIT ) ); + + pLoop->pExitList = NULL; + pLoop->ulOffset = hb_comp_functions.pLast->lPCodePos; /* store the position to fix */ + + pLast = hb_comp_pLoops; + while( pLast->pNext ) + pLast = pLast->pNext; + + if( pLast->wSeqCounter != hb_comp_wSeqCounter ) + { + /* Attempt to LOOP from BEGIN/END sequence + * Current SEQUENCE counter is different then at the beginning of loop + * Notice that LOOP is allowed in RECOVER code. + */ + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_EXIT_IN_SEQUENCE, "EXIT", NULL ); + } + else + { + while( pLast->pExitList ) + pLast = pLast->pExitList; + + pLast->pExitList = pLoop; + + hb_compGenJump( 0 ); + } + } +} + +/* + * Fixes the LOOP statement + */ +static void hb_compLoopHere( void ) +{ + PTR_LOOPEXIT pLoop = hb_comp_pLoops, pFree; + + if( pLoop ) + { + while( pLoop->pNext ) + pLoop = pLoop->pNext; + + pLoop = pLoop->pLoopList; + while( pLoop ) + { + hb_compGenJumpHere( pLoop->ulOffset + 1 ); + pFree = pLoop; + pLoop = pLoop->pLoopList; + hb_xfree( ( void * ) pFree ); + } + } +} + +/* + * Fixes the EXIT statements and releases memory allocated for current loop + */ +static void hb_compLoopEnd( void ) +{ + PTR_LOOPEXIT pExit, pLoop = hb_comp_pLoops, pLast = hb_comp_pLoops, pFree; + + if( pLoop ) + { + while( pLoop->pNext ) + { + pLast = pLoop; + pLoop = pLoop->pNext; + } + + pExit = pLoop->pExitList; + while( pExit ) + { + hb_compGenJumpHere( pExit->ulOffset + 1 ); + pFree = pExit; + pExit = pExit->pExitList; + hb_xfree( ( void * ) pFree ); + } + + pLast->pNext = NULL; + if( pLoop == hb_comp_pLoops ) + hb_comp_pLoops = NULL; + hb_xfree( ( void * ) pLoop ); + } +} + +static void * hb_compElseIfGen( void * pFirst, ULONG ulOffset ) +{ + PELSEIF pElseIf = ( PELSEIF ) hb_xgrab( sizeof( _ELSEIF ) ), pLast; + + pElseIf->ulOffset = ulOffset; + pElseIf->pNext = 0; + + if( ! pFirst ) + pFirst = pElseIf; + else + { + pLast = ( PELSEIF ) pFirst; + while( pLast->pNext ) + pLast = pLast->pNext; + pLast->pNext = pElseIf; + } + return pFirst; +} + + +static void hb_compElseIfFix( void * pFixElseIfs ) +{ + PELSEIF pFix = ( PELSEIF ) pFixElseIfs; + + while( pFix ) + { + hb_compGenJumpHere( pFix->ulOffset ); + pFix = pFix->pNext; + } +} + +static void hb_compRTVariableAdd( HB_EXPR_PTR pVar, BOOL bPopInitValue ) +{ + HB_RTVAR_PTR pRTvar = ( HB_RTVAR_PTR ) hb_xgrab( sizeof( HB_RTVAR ) ); + + pRTvar->pVar = pVar; + pRTvar->bPopValue = bPopInitValue; + pRTvar->pNext = NULL; + pRTvar->pPrev = NULL; + + if( hb_comp_rtvars ) + { + HB_RTVAR_PTR pLast = hb_comp_rtvars; + while( pLast->pNext ) + pLast = pLast->pNext; + pLast->pNext = pRTvar; + pRTvar->pPrev = pLast; + } + else + hb_comp_rtvars = pRTvar; +} + +static void hb_compRTVariableGen( char * szCreateFun ) +{ + USHORT usCount = 0; + HB_RTVAR_PTR pVar = hb_comp_rtvars; + HB_RTVAR_PTR pDel; + + /* generate the function call frame */ + hb_compGenPushSymbol( hb_strdup( szCreateFun ), 1); + hb_compGenPushNil(); + + /* push variable names to create */ + while( pVar->pNext ) + { + hb_compExprGenPush( pVar->pVar ); + pVar = pVar->pNext; + ++usCount; + } + hb_compExprGenPush( pVar->pVar ); + ++usCount; + + /* call function that will create either PUBLIC or PRIVATE variables */ + if( usCount > 255 ) + hb_compGenPCode3( HB_P_DO, HB_LOBYTE( usCount ), HB_HIBYTE( usCount ), ( BOOL ) 1 ); + else + hb_compGenPCode2( HB_P_DOSHORT, ( BYTE ) usCount, ( BOOL ) 1 ); + + /* pop initial values */ + while( pVar ) + { + if( pVar->bPopValue ) + hb_compExprDelete( hb_compExprGenPop( pVar->pVar ) ); + else + hb_compExprDelete( pVar->pVar ); + pDel = pVar; + pVar = pVar->pPrev; + hb_xfree( pDel ); + } + hb_comp_rtvars = NULL; +} + +static void hb_compVariableDim( char * szName, HB_EXPR_PTR pInitValue ) +{ + if( hb_comp_iVarScope == VS_PUBLIC || hb_comp_iVarScope == VS_PRIVATE ) + { + USHORT uCount = hb_compExprListLen( pInitValue ); + hb_compVariableAdd( szName, 'A' ); + hb_compExprDelete( hb_compExprGenPush( pInitValue ) ); + hb_compGenPCode3( HB_P_ARRAYDIM, HB_LOBYTE( uCount ), HB_HIBYTE( uCount ), ( BOOL ) 1 ); + hb_compRTVariableAdd( hb_compExprNewRTVar( szName, NULL ), TRUE ); + } + else if( hb_comp_iVarScope == VS_STATIC ) + { + USHORT uCount = hb_compExprListLen( pInitValue ); + HB_EXPR_PTR pVar = hb_compExprNewVar( szName ); + HB_EXPR_PTR pAssign; + + /* create a static variable */ + hb_compVariableAdd( szName, 'A' ); + hb_compStaticDefStart(); /* switch to statics pcode buffer */ + /* create an array */ + hb_compExprGenPush( pInitValue ); + hb_compGenPCode3( HB_P_ARRAYDIM, HB_LOBYTE( uCount ), HB_HIBYTE( uCount ), ( BOOL ) 1 ); + /* check if valid initializers were used but don't generate any code */ + pAssign = hb_compExprAssignStatic( pVar, pInitValue ); + /* now pop an array */ + hb_compExprGenPop( pVar ); + /* delete all used expressions */ + hb_compExprDelete( pAssign ); + hb_compStaticDefEnd(); + } + else + { + USHORT uCount = hb_compExprListLen( pInitValue ); + + hb_compVariableAdd( szName, 'A' ); + hb_compExprDelete( hb_compExprGenPush( pInitValue ) ); + hb_compGenPCode3( HB_P_ARRAYDIM, HB_LOBYTE( uCount ), HB_HIBYTE( uCount ), ( BOOL ) 1 ); + hb_compExprDelete( hb_compExprGenPop( hb_compExprNewVar( szName ) ) ); + } +} + diff --git a/harbour/source/compiler/simplex.c b/harbour/source/compiler/simplex.c index 93883eb7c7..1e25f0f7f1 100644 --- a/harbour/source/compiler/simplex.c +++ b/harbour/source/compiler/simplex.c @@ -45,12 +45,13 @@ #define LANGUAGE_WORDS_ARE LEX_WORD const aWords[] = #define LANGUAGE_RULES_ARE int const aiRules[][ MAX_MATCH + 2 ] = #define ACCEPT_TOKEN_AND_DROP_DELIMITER_IF_ONE_OF_THESE(x) char const * szOmmit = x -#define ACCEPT_TOKEN_AND_RETURN_DELIMITER_IF_ONE_OF_THESE(x) char const * szReturn = x +#define ACCEPT_TOKEN_AND_RETURN_DELIMITERS LEX_DELIMITER const aDelimiters[] = #define DELIMITER_BELONGS_TO_TOKEN_IF_ONE_OF_THESE(x) char const * szAppend = x #define START_NEW_LINE_IF_ONE_OF_THESE(x) char const * szNewLine = x #define IF_SEQUENCE_IS(a, b, c, d) {a, b, c, d #define REDUCE_TO(x, y) ,x, y } #define PASS_THROUGH() ,0, 0 } +#define LEX_DELIMITER(x) {x #define LEX_WORD(x) {x #define AS_TOKEN(x) ,x } @@ -94,6 +95,12 @@ static int iPairToken = 0; /* Self Contained Words. */ static char sSelf[ TOKEN_SIZE ]; +typedef struct _LEX_DELIMITER +{ + char cDelimiter; + int iToken; +} LEX_DELIMITER; /* support structure for KEYS and WORDS. */ + typedef struct _LEX_WORD { char sWord[ TOKEN_SIZE ]; @@ -118,16 +125,19 @@ typedef struct _LEX_PAIR /* --------------------------------------------------------------------------------- */ /* Overidables. */ -#define LEX_CUSTOM_ACTION -65 -#define SUSPEND_WORDS 8192 +#define LEX_CUSTOM_ACTION -65 +#define DONT_REDUCE 1024 #define YY_BUF_SIZE 16384 + #define YY_INPUT( a, b, c ) +/* Optional User Macros. */ +#define LEX_USER_SETUP() #define INIT_ACTION() #define INTERCEPT_ACTION(x) #define CUSTOM_ACTION(x) #define NEW_LINE_ACTION() -#define ELEMENT_TOKEN(x) -1 +#define ELEMENT_TOKEN(x,y) -1 #define DEBUG_INFO(x) #define LEX_CASE(x) #define STREAM_OPEN(x) @@ -149,8 +159,6 @@ extern void yyerror( char * ); /* parsing error management function */ extern int yywrap( void ); /* manages the EOF of current processed file */ #endif -extern YYSTYPE yylval; - /* Use prototypes in function declarations. */ #define YY_USE_PROTOS @@ -162,9 +170,10 @@ extern YYSTYPE yylval; /* ---------------------------------------------------------------------------------------------- */ -#define LEX_RULE_SIZE ( sizeof( (int) iRet ) * ( MAX_MATCH + 2 ) ) -#define LEX_WORD_SIZE ( sizeof( LEX_WORD ) ) -#define LEX_PAIR_SIZE ( sizeof( LEX_PAIR ) ) +#define LEX_RULE_SIZE ( sizeof( (int) iRet ) * ( MAX_MATCH + 2 ) ) +#define LEX_WORD_SIZE ( sizeof( LEX_WORD ) ) +#define LEX_PAIR_SIZE ( sizeof( LEX_PAIR ) ) +#define LEX_DELIMITER_SIZE ( sizeof( LEX_DELIMITER ) ) /* Using statics when we could use locals to eliminate Allocations and Deallocations each time yylex is called and returns. */ @@ -176,28 +185,17 @@ static int aiHold[4]; static int iReturn = 0; static int aiReturn[4]; -/* Rules Support */ -static int aiMatched[ MAX_MATCH ]; -static unsigned int iMatched = 0; -static int aiTentative[2] = { 0, 0 }; -static unsigned int iTentative = 0; -static int aiProspects[ 256 ]; -static unsigned int iProspects = 0; -static unsigned int iFound = 0; -static int iReduce = 0; - /* yylex */ static char * tmpPtr; static char sToken[TOKEN_SIZE]; -static int iLen = 0; +static unsigned int iLen = 0; static char chr, cPrev = 0; -static unsigned int iMatch, iRemove, iWordLen, iPush, iLastToken = 0; +static unsigned int iLastToken = 0; static char szLexBuffer[ YY_BUF_SIZE ]; static char * s_szBuffer; -static int iSize = 0; +static unsigned int iSize = 0; static int iRet; -static BOOL bTmp; -static BOOL bIgnoreWords = FALSE; +static BOOL bTmp, bIgnoreWords = FALSE, bRecursive = FALSE; /* Lex emulation */ char * yytext; @@ -206,23 +204,35 @@ int yyleng; /* NewLine Support. */ static BOOL bNewLine = TRUE, bStart = TRUE; -static unsigned int iSelfs = (int) ( sizeof( aSelfs ) / LEX_WORD_SIZE ); -static unsigned int iKeys = (int) ( sizeof( aKeys ) / LEX_WORD_SIZE ); -static unsigned int iWords = (int) ( sizeof( aWords ) / LEX_WORD_SIZE ); -static unsigned int iRules = (int) ( sizeof( aiRules ) / LEX_RULE_SIZE ); -static unsigned int iPairs = (int) ( sizeof( aPairs ) / LEX_PAIR_SIZE ); +#ifdef USE_KEYWORDS + static unsigned int iKeys = (int) ( sizeof( aKeys ) / LEX_WORD_SIZE ); +#endif + +static unsigned int iWords = (int) ( sizeof( aWords ) / LEX_WORD_SIZE ); +static unsigned int iSelfs = (int) ( sizeof( aSelfs ) / LEX_WORD_SIZE ); +static unsigned int iPairs = (int) ( sizeof( aPairs ) / LEX_PAIR_SIZE ); +static unsigned int iDelimiters = (int) ( sizeof( aDelimiters ) / LEX_DELIMITER_SIZE ); +static unsigned int iRules = (int) ( sizeof( aiRules ) / LEX_RULE_SIZE ); typedef struct _TREE_NODE { - unsigned int iMin; - unsigned int iMax; + int iMin; + int iMax; } TREE_NODE; /* support structure for Streams (Pairs). */ -TREE_NODE aKeyNodes[256], aWordNodes[256]; +/* Indexing System. */ +static TREE_NODE aPairNodes[256], aSelfNodes[256], aKeyNodes[256], aWordNodes[256], aRuleNodes[1024]; +static char acOmmit[256], acNewLine[256]; +static int acReturn[256]; -int Reduce( int iToken, BOOL bReal ); +static int Reduce( int iToken ); +int SimpLex_GetNextToken( void ); +int SimpLex_CheckToken( void ); +void SimpLex_CheckWords( void ); +/* Indexing System. */ static void GenTrees( void ); +static int rulecmp( const void * pLeft, const void * pRight ); /* --------------------------------------------------------------------------------- */ @@ -234,83 +244,52 @@ static void GenTrees( void ); #define LEX_PAIR_SIZE ( sizeof( LEX_PAIR ) ) #define IF_TOKEN_READY() if( iReturn ) #define IF_TOKEN_ON_HOLD() if( iHold ) -#define REDUCE( x ) Reduce( (x), TRUE ) -#define RESET_LEX() { iLen = 0; iMatched = 0; iProspects = 0; iHold = 0; iReturn = 0; bNewLine = TRUE; bStart = TRUE; } -#define FORCE_REDUCE() Reduce( 0, TRUE ) +#define RESET_LEX() { iLen = 0; iHold = 0; iReturn = 0; bNewLine = TRUE; bStart = TRUE; } +#define FORCE_REDUCE() Reduce( 0 ) -#define HOLD_TOKEN(x) \ - /* Last In, First Out */ \ - { iRet = x ; aiHold[ iHold++ ] = iRet; \ - DEBUG_INFO( printf("Now Holding %i Tokens: %i %i %i %i\n", iHold, aiHold[0], aiHold[1], aiHold[2], aiHold[3] ) ); \ - } - -#define RETURN_TOKEN(x) \ - \ - iRet = (x); \ - if( (iRet) ) \ - { \ - LEX_RETURN(iRet); \ - } \ - else \ - { \ - goto Start; \ - } - -#define IF_NEWLINE(chr) \ - \ - tmpPtr = (char*) szNewLine; \ - while ( *tmpPtr && chr != *tmpPtr ) \ - { \ - tmpPtr++; \ - } \ - /* NewLine Found?. */\ - if( *tmpPtr ) +#define HOLD_TOKEN(x) PUSH_TOKEN(x) #define IF_BEGIN_PAIR(chr) \ - {\ - register unsigned int iPair = 0, iStartLen; \ + if( aPairNodes[chr].iMin == -1 ) \ + { \ + bTmp = FALSE; \ + } \ + else \ + { \ + register unsigned int i = aPairNodes[chr].iMin, iMax = aPairNodes[chr].iMax + 1, iStartLen; \ register unsigned char chrStart; \ unsigned int iLastPair = 0, iLastLen = 0; \ \ DEBUG_INFO( printf( "Checking %i Streams for %c At: >%s<\n", iPairs, chr, szBuffer - 1 ) ); \ \ - while( iPair < iPairs ) \ + while( i < iMax ) \ { \ - chrStart = LEX_CASE(chr);\ + iStartLen = 1; \ \ - if( chrStart == aPairs[iPair].sStart[0] ) \ + chrStart = LEX_CASE( *szBuffer ); \ + \ + while( aPairs[i].sStart[iStartLen] ) \ { \ - iStartLen = 1; \ - \ - if( aPairs[iPair].sStart[1] ) \ + if( chrStart != aPairs[i].sStart[iStartLen] ) \ { \ - chrStart = LEX_CASE( *szBuffer ); \ - \ - while( aPairs[iPair].sStart[iStartLen] ) \ - { \ - if( chrStart != aPairs[iPair].sStart[iStartLen] ) \ - { \ - break; \ - } \ - \ - iStartLen++; \ - \ - /* Peek at Next Character. */ \ - chrStart = LEX_CASE( *( szBuffer + iStartLen - 1 ) ); \ - } \ + break; \ } \ \ - /* Match */ \ - if( aPairs[iPair].sStart[iStartLen] == '\0' ) \ + iStartLen++; \ + \ + chrStart = LEX_CASE( *( szBuffer + iStartLen - 1 ) ); \ + } \ + \ + /* Match */ \ + if( aPairs[i].sStart[iStartLen] == '\0' ) \ + { \ + if( iStartLen > iLastLen ) \ { \ - if( iStartLen > iLastLen ) \ - { \ - iLastPair = iPair + 1; \ - iLastLen = iStartLen; \ - } \ + iLastPair = i + 1; \ + iLastLen = iStartLen; \ } \ } \ - iPair++; \ + i++; \ } \ \ bTmp = FALSE; \ @@ -323,12 +302,11 @@ static void GenTrees( void ); bTmp = TRUE; \ \ /* Last charcter read. */\ - chr = chrStart; \ + if( iStartLen > 1 ) chr = chrStart; \ \ /* Moving to next postion after the Stream Start position. */ \ szBuffer += ( iLastLen - 1 ); \ \ - /* Terminator to look for. */ \ sStart = (char *) aPairs[iLastPair].sStart; \ sTerm = (char *) aPairs[iLastPair].sTerm; \ sExclude = (char *) aPairs[iLastPair].sExclude; \ @@ -343,98 +321,78 @@ static void GenTrees( void ); if( bTmp ) #define CHECK_SELF_CONTAINED(chr) \ + if( aSelfNodes[chr].iMin != -1 ) \ + { \ + register unsigned int i = aSelfNodes[chr].iMin, iMax = aSelfNodes[chr].iMax + 1, iSelfLen; \ + register unsigned char chrSelf; \ \ DEBUG_INFO( printf( "Checking %i Selfs for %c At: >%s<\n", iSelfs, chr, szBuffer - 1 ) ); \ \ - {\ - register unsigned int iSelf = 0, iSelfLen; \ - register unsigned char chrSelf; \ - \ - while( iSelf < iSelfs ) \ + while( i < iMax ) \ { \ - chrSelf = LEX_CASE(chr);\ + sSelf[0] = chr; \ + iSelfLen = 1; \ + chrSelf = LEX_CASE( *szBuffer ); \ \ - if( chrSelf == aSelfs[iSelf].sWord[0] ) \ + while( aSelfs[i].sWord[iSelfLen] ) \ { \ - sSelf[0] = chrSelf; \ - iSelfLen = 1; \ - chrSelf = LEX_CASE( *szBuffer ); \ - \ - while( aSelfs[iSelf].sWord[iSelfLen] ) \ + if( aSelfs[i].sWord[iSelfLen] == chrSelf ) \ { \ - if( chrSelf == aSelfs[iSelf].sWord[iSelfLen] ) \ - { \ - sSelf[ iSelfLen ] = chrSelf; \ - } \ - else \ - { \ - break; \ - } \ - \ - iSelfLen++; \ - \ - /* TODO: worry about End of Buffer. */ \ - \ - /* Peek at Next Character. */ \ - chrSelf = LEX_CASE( *( szBuffer + iSelfLen - 1 ) ); \ + sSelf[ iSelfLen ] = chrSelf; \ + } \ + else \ + { \ + break; \ } \ \ - /* Match */ \ - if( aSelfs[iSelf].sWord[iSelfLen] == '\0' ) \ + iSelfLen++; \ + \ + chrSelf = LEX_CASE( *( szBuffer + iSelfLen - 1 ) ); \ + } \ + \ + /* Match */ \ + if( aSelfs[i].sWord[iSelfLen] == '\0' ) \ + { \ + /* Moving to next postion after the Self Contained Word. */ \ + szBuffer += ( iSelfLen - 1 ); \ + s_szBuffer = szBuffer; \ + \ + sSelf[ iSelfLen ] = '\0'; \ + iRet = aSelfs[i].iToken; \ + \ + if( iLen ) \ { \ - /* Moving to next postion after the Self Contained Word. */ \ - szBuffer += ( iSelfLen - 1 ); \ + DEBUG_INFO( printf( "Holding Self >%s<\n", sSelf ) ); \ \ - sSelf[ iSelfLen ] = '\0'; \ + HOLD_TOKEN( iRet ); \ \ - if( iLen ) \ - { \ - DEBUG_INFO( printf( "Holding Self >%s<\n", sSelf ) ); \ - \ - HOLD_TOKEN( aSelfs[iSelf].iToken ); \ - \ - /* Terminate current token and check it. */ \ - sToken[ iLen ] = '\0'; \ - \ - /* Last charcter read. */\ - chr = chrSelf;\ - \ - goto CheckToken; \ - } \ - else \ - { \ - DEBUG_INFO( printf( "Reducing Self >%s<\n", sSelf ) ); \ - \ - bIgnoreWords = FALSE;\ - \ - if( bNewLine )\ - {\ - bNewLine = FALSE;\ - NEW_LINE_ACTION();\ - }\ - \ - if( aSelfs[iSelf].iToken < LEX_CUSTOM_ACTION ) \ - { \ - iRet = aSelfs[iSelf].iToken; \ - iRet = CUSTOM_ACTION( iRet ); \ - if( iRet ) \ - { \ - RETURN_TOKEN( REDUCE( iRet ) ); \ - } \ - else \ - { \ - goto Start; \ - } \ - } \ - else \ - { \ - RETURN_TOKEN( REDUCE( aSelfs[iSelf].iToken ) ); \ - } \ - } \ + /* Terminate current token and check it. */ \ + sToken[ iLen ] = '\0'; \ + \ + /* Last charcter read. */\ + chr = chrSelf;\ + \ + return SimpLex_CheckToken(); \ + } \ + else \ + { \ + DEBUG_INFO( printf( "Reducing Self >%s<\n", sSelf ) ); \ + bIgnoreWords = FALSE;\ + \ + if( bNewLine )\ + {\ + bNewLine = FALSE;\ + NEW_LINE_ACTION();\ + }\ + \ + /* Last charcter read. */\ + if( iSelfLen > 1 ) chr = chrSelf;\ + \ + return iRet; \ } \ } \ \ - iSelf++; \ + i++; \ } \ } @@ -448,450 +406,85 @@ static void GenTrees( void ); /* Exception. */ \ if( *tmpPtr ) -#define IF_OMMIT(chr) \ - /* Delimiter to Ommit? */ \ - tmpPtr = (char*) szOmmit; \ - while ( *tmpPtr && chr != *tmpPtr ) \ - { \ - tmpPtr++; \ - } \ - \ - /* Delimiter to Ommit found. */ \ - if ( *tmpPtr ) - #define IF_APPEND_DELIMITER(chr) \ - /* Delimiter to Append? */ \ + /* Delimiter to Append? */ \ tmpPtr = (char*) szAppend; \ - while ( *tmpPtr && chr != *tmpPtr ) \ - { \ - tmpPtr++; \ - } \ + while ( *tmpPtr && chr != *tmpPtr ) tmpPtr++; \ \ /* Delimiter to Append found. */ \ if( *tmpPtr ) -#define IF_RETURN_DELIMITER(chr) \ - /* Returnable Delimiter? */ \ - tmpPtr = (char*) szReturn; \ - while ( *tmpPtr && chr != *tmpPtr ) \ - { \ - tmpPtr++; \ - } \ - \ - /* Returnable Delimiter found. */ \ - if( *tmpPtr ) - -#define IF_BELONG_LEFT(chr) \ +#ifndef IF_BELONG_LEFT + #define IF_BELONG_LEFT(chr) \ /* Give precedence to associate rules */ \ DEBUG_INFO( printf( "Checking Left for: '%c' cPrev: '%c'\n", chr, cPrev ) ); \ \ - if( iMatched && Reduce( chr, FALSE ) ) + if( 0 ) +#endif #define RETURN_READY_TOKEN() \ \ - /* Ready from previous call. */ \ iReturn--; \ iRet = aiReturn[iReturn]; \ \ DEBUG_INFO( printf( "Returning Ready: %i\n", iRet ) ); \ \ - LEX_RETURN(iRet); + INTERCEPT_ACTION(iRet); \ + return iRet; \ #define RELEASE_TOKEN() \ \ - /* Ready from previous call. */ \ /* Last in First Out. */ \ iHold--; \ iRet = aiHold[iHold]; \ \ DEBUG_INFO( printf( "Released %i Now Holding %i Tokens: %i %i %i %i\n", iRet, iHold, aiHold[0], aiHold[1], aiHold[2], aiHold[3] ) ); \ + bIgnoreWords = FALSE;\ \ - if( iRet == -1 && iMatched ) \ + if( iRet < 256 ) \ { \ - DEBUG_INFO( printf( "Reducing Held: \n" ) ); \ - \ - /* Returning Pending Rule Match Tokens without further tests. */ \ - iMatch = 0; \ - while( iMatch < iMatched ) \ - { \ - DEBUG_INFO( printf( "Returning Pending Match Tokens at: \n" ) ); \ - \ - aiReturn[ iReturn++ ] = aiMatched[ iMatch ]; \ - iMatch++; \ - } \ - /* Resetting */ \ - iLen = 0; iMatched = 0; iProspects = 0; iHold = 0; bNewLine = TRUE; bStart = TRUE; \ - goto Start;\ + if( acNewLine[iRet] ) bNewLine = TRUE; \ } \ - else if( iRet == -1 ) \ - { \ - RESET_LEX();\ - DEBUG_INFO( printf( "Returning: \n" ) ); \ - return -1; \ - }\ - else if( iRet < 256 )\ - {\ - IF_NEWLINE( (char) iRet )\ - {\ - bNewLine = TRUE;\ - }\ - }\ \ DEBUG_INFO( printf( "Reducing Held: %i Pos: %i\n", iRet, iHold ) ); \ - \ - RETURN_TOKEN( REDUCE( iRet ) ); + LEX_RETURN( Reduce( iRet ) ); #define LEX_RETURN(x) \ \ - if( x < LEX_CUSTOM_ACTION ) \ + iRet = x;\ + \ + if( iRet < LEX_CUSTOM_ACTION ) \ { \ - CUSTOM_ACTION(x); \ - \ - if( x ) \ - { \ - INTERCEPT_ACTION(x)\ - \ - s_szBuffer = szBuffer;\ - \ - return x; \ - } \ - else \ - { \ - goto Start; \ - } \ + iRet = CUSTOM_ACTION(iRet); \ + } \ + \ + if( iRet ) \ + { \ + INTERCEPT_ACTION(iRet); \ + DEBUG_INFO( printf( "Returning: %i\n", iRet ) ); \ + return iRet; \ } \ else \ { \ - DEBUG_INFO( printf( "Returning: %i\n", x ) ); \ - \ - INTERCEPT_ACTION(x)\ - \ - s_szBuffer = szBuffer;\ - \ - return x; \ + goto Start; \ } -#define ACCEPT_TOKEN()\ -{\ - DEBUG_INFO( printf( "Accepting Token %i After Tokens: %i %i %i\n", iToken, aiMatched[0], aiMatched[1], aiMatched[2] ) );\ - \ - if( iMatched == MAX_MATCH )\ - {\ - printf( "Maximum depth reached! Multiple Rules for same Tokens: %i %i %i %i - Please correct the rules.\n", aiMatched[0], aiMatched[1], aiMatched[2], aiMatched[3] );\ - \ - GIVE_UP();\ - }\ - else\ - {\ - aiMatched[ iMatched++ ] = iToken;\ - }\ -} - -#define FIND_MATCH()\ -{\ - if( iProspects )\ - {\ - SCAN_PROSPECTS();\ - }\ - else\ - {\ - SCAN_RULES();\ - }\ -} - -#define SCAN_PROSPECTS()\ -{\ - register unsigned int iScan = 0;\ - \ - DEBUG_INFO( printf( "Scaning %i Prospects for %i at Pos: %i\n", iProspects, iToken, iMatched ) ); \ - \ - iFound = 0;\ - while( iScan < iProspects )\ - {\ - if( aiRules[ aiProspects[iScan] ][ iMatched ] == iToken )\ - {\ - /* No more Tokens - Rule Match. */\ - if( iMatched == MAX_MATCH - 1 || aiRules[ aiProspects[iScan] ][ iMatched + 1 ] == 0 )\ - {\ - iFound++;\ - iReduce = aiProspects[iScan];\ - }\ - else\ - {\ - /* Already in prospect list - still a prospect, do nothing. */\ - }\ - }\ - else\ - {\ - if( bReal )\ - {\ - /* No longer a prospect. */\ - REMOVE_PROSPECT(iScan);\ -\ - /* Has to continue without increasing the counter, because of side effect of REMOVE_PROSPECT(). */\ - continue;\ - }\ - else\ - {\ - iRemoved++;\ - }\ - }\ -\ - iScan++;\ - }\ -\ - if( iProspects == 1 && iFound )\ - {\ - /* Already counted as a FOUND. */\ - if( bReal )\ - {\ - iProspects = 0;\ - }\ - }\ -} - -#define SCAN_RULES()\ -{\ - register unsigned int iScan = 0;\ - \ - DEBUG_INFO( printf( "Scaning %i Rules for %i at Pos: %i\n", iRules, iToken, iMatched ) ); \ - \ - iFound = 0;\ - iProspects = 0;\ - while( iScan < iRules )\ - {\ - /* No prospects means we only search 1st Token of Rules. */\ - if( aiRules[iScan][0] == iToken )\ - {\ - /* No more Tokens - Rule Match. */\ - if( aiRules[iScan][1] == 0 )\ - {\ - iReduce = iScan;\ - iFound++;\ - }\ - else\ - {\ - /* Adding this Rule to the Prospects List. */\ - ADD_PROSPECT(iScan);\ - }\ - }\ -\ - iScan++;\ - }\ -} - -#define ADD_PROSPECT(iScan)\ -{\ - aiProspects[ iProspects++ ] = iScan;\ -} - -#define REMOVE_PROSPECT(iScan)\ -{\ - DEBUG_INFO( printf( "Removing Prospect: %i Of: %i\n", iScan, iProspects ) );\ -\ - aiProspects[iProspects--] = 0;\ - iRemove = iScan;\ - while( iRemove < iProspects )\ - {\ - /* iProspectNo is already Zero Based. */\ - aiProspects[ iRemove ] = aiProspects[ iRemove + 1 ];\ - iRemove++;\ - }\ -} - -#define REVERT_OR_GIVEUP()\ -{\ - DEBUG_INFO( printf( "Revert Or Giveup for %i After %i %i %i\n", iToken, aiMatched[0], aiMatched[1], aiMatched[2] ) );\ -\ - /* Have to push the unmatched Token first, so it will Pop LAST after the Left Shift of reverted Tokens. */\ - /* Avoid infinite loop, don't push if this is the only Token, it will be returned instead. */\ - /* iToken maybe ZERO indicating REDUCTION to be FORCED. */\ - if( iMatched && iToken )\ - {\ - PUSH_TOKEN( iToken );\ - }\ -\ - if( iTentative )\ - {\ - if( iMatched > iTentative )\ - {\ - /* Unused Tokens must be pushed before the reduction, so the Reductions will be Poped First. */\ -\ - DEBUG_INFO( printf( "Reverting from %i to %i Shifting to Reductions: %i %i\n", iMatched, iTentative, aiTentative[0], aiTentative[1] ) );\ -\ - /* iTentative is Zero Based, iMatched is 1 Based, but iMatched not increased yet for the unmatched Token. */\ - /* Shift unused Token[s] Left. */\ - PUSH_UN_MATCHED( iMatched - iTentative );\ - }\ -\ - /* Will put the Reductions back into the Hold Stack to support Recursive Rules. */\ - REDUCE_TENTATIVE();\ - CLEAN_UP();\ - }\ - else\ - {\ - /* Will get rid of the 1st (Left) Token and will shift the unmatched Tokens 1 position to the left.\ - So we will start again with the First unmatched Token. */\ - GIVE_UP();\ - }\ -} - -#define REDUCE_TENTATIVE()\ -{\ - /* If Associate Left than don't reduce. */\ - if( aiTentative[0] )\ - {\ - DEBUG_INFO( printf( "Reducing Tentative for %i Matches to %i %i\n", iTentative, aiTentative[0], aiTentative[1] ) );\ -\ - /* Have to push from Right to Left so Last pushed will be First poped. */\ - if( aiTentative[1] )\ - {\ - PUSH_TOKEN( aiTentative[1] );\ - aiTentative[1] = 0;\ - }\ -\ - PUSH_TOKEN( aiTentative[0] );\ - aiTentative[0] = 0;\ - }\ - else\ - {\ - DEBUG_INFO( printf( "Returning Tentative for %i Matches, Associate Left of %i %i %i\n", iTentative, aiMatched[0], aiMatched[1], aiMatched[2] ) );\ -\ - /* Can't have the last Item becuase we just failed a rule. */ \ - if( aiMatched[ 2 ] )\ - {\ - aiReturn[ iReturn++ ] = aiMatched[ 2 ];\ - }\ - if( aiMatched[ 1 ] )\ - {\ - aiReturn[ iReturn++ ] = aiMatched[ 1 ];\ - }\ - aiReturn[ iReturn++ ] = aiMatched[ 0 ];\ - }\ -} - -#define PUSH_UN_MATCHED( iHowMany ) /* Shift Left. */\ -{\ - iPush = iHowMany;\ - while( iPush )\ - {\ - iPush--;\ - iMatched--;\ - PUSH_TOKEN( aiMatched[ iMatched ] );\ - aiMatched[iMatched] = 0;\ - }\ -} - #define PUSH_TOKEN( iPushToken )\ {\ aiHold[ iHold++ ] = iPushToken;\ -\ - /* We don't know what was the text value of this Token any more. */\ DEBUG_INFO( printf("Now Holding %i Tokens: %i %i %i %i\n", iHold, aiHold[0], aiHold[1], aiHold[2], aiHold[3] ) ); \ } -#define SAVE_TENTATIVE()\ -{\ - iTentative = iMatched;\ - aiTentative[1] = aiRules[ iReduce ][ MAX_MATCH + 1 ];\ - aiTentative[0] = aiRules[ iReduce ][ MAX_MATCH ];\ - DEBUG_INFO( printf( "Saved Tentative for: %i\n", iTentative ) ); \ -} - -#define GIVE_UP()\ -{\ - /* We may have Tokens to shift Left. */\ - if( iMatched == 0)\ - {\ - CLEAN_UP();\ -\ - return iToken;\ - }\ - else if( iMatched == 1 )\ - {\ - iRet = aiMatched[0];\ -\ - CLEAN_UP();\ -\ - return iRet;\ - }\ - else\ - {\ - DEBUG_INFO( printf( "Shifting Left %i Tokens\n", iMatched - 1 ) );\ -\ - if( iMatched > 1 )\ - {\ - PUSH_UN_MATCHED( iMatched - 1 );\ - }\ -\ - iRet = aiMatched[0];\ -\ - CLEAN_UP();\ -\ - return iRet;\ - }\ -} - -#define CLEAN_UP()\ -{\ - iMatched = 0;\ - iTentative = 0;\ - aiMatched[0] = 0;\ - aiMatched[1] = 0;\ - aiMatched[2] = 0;\ - aiMatched[3] = 0;\ -} - -#define REDUCE_RULE()\ -{\ - /* If Associate Left than don't push reduce, pass through. */\ - if( aiRules[ iReduce ][ MAX_MATCH ] )\ - {\ - DEBUG_INFO( printf( "Reducing: %i %i %i %i Shifting To: %i %i\n", aiMatched[0], aiMatched[1], aiMatched[2], aiMatched[3], aiRules[ iReduce ][ MAX_MATCH ], aiRules[ iReduce ][ MAX_MATCH + 1 ] ) );\ -\ - /* Have to push from Right to Left so Last pushed will be First poped. */\ - if( aiRules[ iReduce ][ MAX_MATCH + 1 ] )\ - {\ - PUSH_TOKEN( aiRules[ iReduce ][ MAX_MATCH + 1 ] );\ - }\ - PUSH_TOKEN( aiRules[ iReduce ][ MAX_MATCH ] );\ -\ - /* Dispose of tokens and reset. */ \ - CLEAN_UP();\ - }\ - else\ - {\ - DEBUG_INFO( printf( "Associating Left: %i %i %i %i Shifting To: New Token %i\n", aiMatched[0], aiMatched[1], aiMatched[2], aiMatched[3], iToken ) );\ -\ - /* Have to push from Right to Left so Last pushed will be First poped. */\ - if( aiMatched[ 3 ] )\ - {\ - aiReturn[ iReturn++ ] = aiMatched[ 3 ];\ - }\ - if( aiMatched[ 2 ] )\ - {\ - aiReturn[ iReturn++ ] = aiMatched[ 2 ];\ - }\ - if( aiMatched[ 1 ] )\ - {\ - aiReturn[ iReturn++ ] = aiMatched[ 1 ];\ - }\ - aiReturn[ iReturn++ ] = aiMatched[ 0 ];\ -\ - /* Dispose of tokens and reset. */ \ - CLEAN_UP();\ - }\ -} - #ifndef YY_DECL #define YY_DECL int yylex YY_PROTO(( void )) #endif YY_DECL { - register char * szBuffer = s_szBuffer; - Start: + LEX_USER_SETUP(); + + Start : IF_TOKEN_READY() { RETURN_READY_TOKEN(); @@ -919,7 +512,7 @@ YY_DECL if( bStart ) { bStart = FALSE; - GenTrees() + GenTrees(); INIT_ACTION(); } @@ -927,60 +520,59 @@ YY_DECL if( iSize ) { - szBuffer = (char*) szLexBuffer; - - DEBUG_INFO( printf( "New Buffer: >%s<\n", szBuffer ) ); + s_szBuffer = (char*) szLexBuffer; + DEBUG_INFO( printf( "New Buffer: >%s<\n", szLexBuffer ) ); } else { - if( iMatched ) - { - /* Returning Pending Rule Match Tokens without further tests. */ - iMatch = 0; - while( iMatch < iMatched ) - { - DEBUG_INFO( printf( "Returning Pending Match Tokens at: \n" ) ); - - aiReturn[ iReturn++ ] = aiMatched[ iMatch ]; - iMatch++; - } - /* Resetting */ - iLen = 0; iMatched = 0; iProspects = 0; iHold = 0; bNewLine = TRUE; bStart = TRUE; - goto Start; - } - RESET_LEX(); DEBUG_INFO( printf( "Returning: \n" ) ); - return -1; + return -1; \ } } + LEX_RETURN( Reduce( SimpLex_GetNextToken() ) ) +} + +int SimpLex_GetNextToken( void ) +{ + register char * szBuffer = s_szBuffer; + iLen = 0; - yyleng = 0; while ( 1 ) { if ( iSize && *szBuffer ) { if( iPairToken ) + { goto ProcessStream; + } cPrev = chr; /* Get next character. */ iSize--; - chr = LEX_CASE(*szBuffer++) ; + chr = (*szBuffer++); - IF_OMMIT(chr) + /* Not using LEX_CASE() yet (white space)!!! */ + + if( acOmmit[chr] ) { + while( acOmmit[*szBuffer] ) + { + iSize--; szBuffer++; + } + if ( iLen ) { /* Terminate current token and check it. */ sToken[ iLen ] = '\0'; - DEBUG_INFO( printf( "Token: \"%s\" Ommited: \'%c\'\n", sToken, chr ) ); + s_szBuffer = szBuffer; - goto CheckToken; + DEBUG_INFO( printf( "Token: \"%s\" Ommited: \'%c\'\n", sToken, chr ) ); + return SimpLex_CheckToken(); } else { @@ -988,6 +580,8 @@ YY_DECL } } + chr = LEX_CASE(chr); + CHECK_SELF_CONTAINED(chr); /* New Pair ? */ @@ -1000,9 +594,10 @@ YY_DECL /* Terminate and Check Token to the left. */ sToken[ iLen ] = '\0'; - DEBUG_INFO( printf( "Token: \"%s\" before New Pair at: \'%c\'\n", sToken, chr ) ); + s_szBuffer = szBuffer; - goto CheckToken ; + DEBUG_INFO( printf( "Token: \"%s\" before New Pair at: \'%c\'\n", sToken, chr ) ); + return SimpLex_CheckToken(); } ProcessStream : @@ -1013,9 +608,13 @@ YY_DECL { IF_BELONG_LEFT( chr ) { - DEBUG_INFO( printf( "Reducing Left '%c'\n", chr ) ); + /* Resetting. */ iPairToken = 0; - RETURN_TOKEN( REDUCE( (int) chr ) ); + + s_szBuffer = szBuffer; + + DEBUG_INFO( printf( "Reducing Left '%c'\n", chr ) ); + return (int) chr ; } } @@ -1035,7 +634,7 @@ YY_DECL if( sTerm[1] ) { - register char chrTerm = LEX_CASE( *szBuffer ); + register char chrTerm = *szBuffer; /* Not using LEX_CASE() here !!! */ while( sTerm[iTermLen] ) { @@ -1048,8 +647,7 @@ YY_DECL iTermLen++; - /* Peek at Next Character. */ \ - chrTerm = LEX_CASE( *( szBuffer + iTermLen - 1 ) ); + chrTerm = *( szBuffer + iTermLen - 1 ); /* Not using LEX_CASE() here !!! */ } } @@ -1061,34 +659,21 @@ YY_DECL sPair[ iPairLen ] = '\0'; - DEBUG_INFO( printf( "Returning Pair = >%s<\n", sPair ) ); - if( bNewLine ) { bNewLine = FALSE; NEW_LINE_ACTION(); } - /* Resetting. */ iRet = iPairToken; + + /* Resetting. */ iPairToken = 0; - if( iRet < LEX_CUSTOM_ACTION ) - { - iRet = CUSTOM_ACTION( iRet ); - if( iRet ) - { - RETURN_TOKEN( REDUCE( iRet ) ); - } - else - { - goto Start; - } - } - else - { - RETURN_TOKEN( REDUCE( iRet ) ); - } + s_szBuffer = szBuffer; + + DEBUG_INFO( printf( "Returning Pair = >%s<\n", sPair ) ); + return iRet; } } @@ -1097,15 +682,17 @@ YY_DECL { sPair[ iPairLen ] = '\0'; - STREAM_EXCEPTION( sPair, chrPair); - /* Resetting. */ iPairToken = 0; /* Last charcter read. */ chr = chrPair; - goto Start; + STREAM_EXCEPTION( sPair, chrPair ); + + s_szBuffer = szBuffer; + + return iPairToken; } else { @@ -1114,68 +701,79 @@ YY_DECL } } - /* EOF */ - STREAM_EXCEPTION( sPair, NULL ); - /* Resetting. */ iPairToken = 0; - goto Start; + /* EOF */ + STREAM_EXCEPTION( sPair, NULL ); + + s_szBuffer = szBuffer; + + return iPairToken; } /* End Pairs. */ /* NewLine ? */ - IF_NEWLINE( chr ) + if( acNewLine[chr] ) { + while( acNewLine[*szBuffer] ) + { + iSize--; szBuffer++; + } + s_szBuffer = szBuffer; + + if( iLen ) + { + /* Will return NewLine on next call. */ + HOLD_TOKEN( chr ); + + /* Terminate current token and check it. */ + sToken[ iLen ] = '\0'; + + DEBUG_INFO( printf( "Token: \"%s\" at Holding: \'%c\'\n", sToken, chr ) ); + return SimpLex_CheckToken(); + } + else + { + DEBUG_INFO( printf( "Reducing NewLine '%c'\n", chr ) ); + bIgnoreWords = FALSE; + bNewLine = TRUE; + return (int) chr; + } + } + + #ifdef USE_BELONGS + IF_APPEND_DELIMITER( chr ) + { + /* Append and Terminate current token and check it. */ + sToken[ iLen++ ] = chr; + sToken[ iLen ] = '\0'; + + s_szBuffer = szBuffer; + + DEBUG_INFO( printf( "Token: \"%s\" Appended: \'%c\'\n", sToken, chr ) ); + return SimpLex_CheckToken(); + } + #endif + + if( acReturn[chr] ) + { + s_szBuffer = szBuffer; + if( iLen ) { - /* Will return NewLine on next call. */ - HOLD_TOKEN( chr ); + /* Will be returned on next cycle. */ + + HOLD_TOKEN( acReturn[chr] ); /* Terminate current token and check it. */ sToken[ iLen ] = '\0'; - DEBUG_INFO( printf( "Token: \"%s\" at Holding: \'%c\'\n", sToken, chr ) ); - goto CheckToken; + DEBUG_INFO( printf( "Token: \"%s\" Holding: \'%c\' As: %i \n", sToken, chr, iRet ) ); + return SimpLex_CheckToken(); } else { - DEBUG_INFO( printf( "Reducing NewLine '%c'\n", chr ) ); - bIgnoreWords = FALSE; - bNewLine = TRUE; - RETURN_TOKEN( REDUCE( (int) chr ) ); - } - } - - IF_APPEND_DELIMITER( chr ) - { - /* Append and Terminate current token and check it. */ - sToken[ iLen++ ] = chr; - sToken[ iLen ] = '\0'; - - DEBUG_INFO( printf( "Token: \"%s\" Appended: \'%c\'\n", sToken, chr ) ); - - goto CheckToken; - } - - IF_RETURN_DELIMITER( chr ) - { - if( iLen ) - { - /* Will be rturned on next cycle. */ - HOLD_TOKEN( chr ); - - /* Terminate current token and check it. */ - sToken[ iLen ] = '\0'; - - DEBUG_INFO( printf( "Token: \"%s\" Holding: \'%c\'\n", sToken, chr ) ); - - goto CheckToken; - } - else - { - DEBUG_INFO( printf( "Reducing Delimiter: '%c'\n", chr ) ); - bIgnoreWords = FALSE; if( bNewLine ) @@ -1184,7 +782,8 @@ YY_DECL NEW_LINE_ACTION(); } - RETURN_TOKEN( REDUCE( (int) chr ) ); + DEBUG_INFO( printf( "Reducing Delimiter: '%c' As: %i\n", chr, iRet ) ); + return acReturn[chr]; } } @@ -1204,6 +803,7 @@ YY_DECL } else { + if( iLen ) { /* */ @@ -1212,244 +812,556 @@ YY_DECL /* Terminate current token and check it. */ sToken[ iLen ] = '\0'; - DEBUG_INFO( printf( "Token: \"%s\" at: \'\'\n", sToken ) ); + s_szBuffer = szBuffer; - goto CheckToken; + DEBUG_INFO( printf( "Token: \"%s\" at: \'\'\n", sToken ) ); + return SimpLex_CheckToken(); } else { - goto Start; + s_szBuffer = szBuffer; + DEBUG_INFO( printf( "Returning: \n", iRet ) ); \ + return -1; \ } } } - - CheckToken: - { - unsigned int i, iMax; - - if( bNewLine ) - { - bIgnoreWords = FALSE; - - #ifdef LEX_ABBREVIATE_KEYS - iWordLen = iLen; - - if( iWordLen < LEX_ABBREVIATE_KEYS ) - { - iWordLen = LEX_ABBREVIATE_KEYS; - } - #endif - - i = aKeyNodes[ (int) sToken[0] ].iMin; - iMax = aKeyNodes[ (int) sToken[0] ].iMax + 1; - DEBUG_INFO( printf( "Scanning Keys for Token: %s at Positions: %i-%i\n", (char*) sToken, i, iMax -1 ) ); - - while ( i < iMax ) - { - #ifdef LEX_ABBREVIATE_KEYS - if( strncmp( (char*) sToken, (char*)( aKeys[ i++ ].sWord ), iWordLen ) == 0 ) - #else - if( strcmp( (char*) sToken, (char*) ( aKeys[ i++ ].sWord ) ) == 0 ) - #endif - { - DEBUG_INFO( printf( "Reducing Key Word: %s\n", (char*) sToken ) ); - - bNewLine = FALSE; - NEW_LINE_ACTION(); - - KEYWORD_ACTION() - - if( aKeys[ i - 1 ].iToken < LEX_CUSTOM_ACTION ) - { - iRet = aKeys[ i - 1 ].iToken; - iRet = CUSTOM_ACTION( iRet ); - if( iRet ) - { - RETURN_TOKEN( REDUCE( iRet ) ); - } - else - { - goto Start; - } - } - else - { - iRet = aKeys[ i - 1 ].iToken; - if( iRet > SUSPEND_WORDS ) - { - iRet -= SUSPEND_WORDS; - bIgnoreWords = TRUE; - } - - RETURN_TOKEN( REDUCE( iRet ) ); - } - } - } - - if( bNewLine ) - { - bNewLine = FALSE; - NEW_LINE_ACTION(); - } - } - - if( bIgnoreWords ) - { - DEBUG_INFO( printf( "Skiped Words for Word: %s\n", (char*) sToken ) ); - bIgnoreWords = FALSE; - } - else - { - #ifdef LEX_ABBREVIATE_WORDS - iWordLen = iLen; - - if( iWordLen < LEX_ABBREVIATE_WORDS ) - { - iWordLen = LEX_ABBREVIATE_WORDS; - } - #endif - - i = aWordNodes[ (int) sToken[0] ].iMin; - iMax = aWordNodes[ (int) sToken[0] ].iMax + 1; - DEBUG_INFO( printf( "Scanning Words for Token: %s at Positions: %i-%i\n", (char*) sToken, i, iMax - 1 ) ); - - while ( i < iMax ) - { - #ifdef LEX_ABBREVIATE_WORDS - if( strncmp( (char*) sToken, (char*) ( aWords[ i++ ].sWord ), iWordLen ) == 0 ) - #else - if( strcmp( (char*) sToken, (char*) ( aWords[ i++ ].sWord ) ) == 0 ) - #endif - { - DEBUG_INFO( printf( "Reducing Word: %s\n", (char*) sToken ) ); - - WORD_ACTION() - - if( aWords[ i - 1 ].iToken < LEX_CUSTOM_ACTION ) - { - iRet = aWords[ i - 1 ].iToken; - iRet = CUSTOM_ACTION( iRet ); - if( iRet ) - { - RETURN_TOKEN( REDUCE( iRet ) ); - } - else - { - goto Start; - } - } - else - { - iRet = aWords[ i - 1 ].iToken; - if( iRet > SUSPEND_WORDS ) - { - iRet -= SUSPEND_WORDS; - bIgnoreWords = TRUE; - } - - RETURN_TOKEN( REDUCE( iRet ) ); - } - } - } - } - - DEBUG_INFO( printf( "Reducing Element: \"%s\"\n", (char*) sToken ) ); - - /* "Returns" the Token as iRet. */ - ELEMENT_TOKEN( sToken ) - - RETURN_TOKEN( REDUCE( iRet ) ); - } } } -int Reduce( int iToken, BOOL bReal ) +int SimpLex_CheckToken( void ) { - int iRemoved = 0; /* Simulted Removed Prospects if bReal is FALSE. */ + if( bRecursive ) + { + return 0; + } + else + { + bRecursive = TRUE; + } - /* The search rutine will "return" the number of Matches in iFound, number of Prospects in iProspects, and the last - (and hopefuly only) Matched Rule No in iReduce. */ + if( bNewLine ) + { + bIgnoreWords = FALSE; - if( iToken ) + NEW_LINE_ACTION(); + + #ifdef USE_KEYWORDS + SimpLex_CheckWords(); + if( iRet ) + { + bRecursive = FALSE; + /* bIgnoreWords and bNewLine were handled by SimpLex_CheckWords(). */ + return iRet; + } + #endif + } + + if( bIgnoreWords ) + { + DEBUG_INFO( printf( "Skiped Words for Word: %s\n", (char*) sToken ) ); + bIgnoreWords = FALSE; + } + else + { + SimpLex_CheckWords(); + if( iRet ) + { + bRecursive = FALSE; + return iRet; + } + } + + DEBUG_INFO( printf( "Reducing Element: \"%s\"\n", (char*) sToken ) ); + + /* "Returns" result in iRet. */ + ELEMENT_TOKEN( sToken, iLen ); + + bRecursive = FALSE; + return iRet; +} + +int Reduce( int iToken ) +{ + BeginReduce : + + if( iToken < LEX_CUSTOM_ACTION ) { - iLastToken = iToken; + iToken = CUSTOM_ACTION( iToken ); \ + } - DEBUG_INFO( printf( "Checking Token: %i After %i %i %i at Pos: %i\n", iToken, aiMatched[0], aiMatched[1], aiMatched[2], iMatched ) ); + if( iToken > DONT_REDUCE ) + { + iLastToken = ( iToken - DONT_REDUCE ); + DEBUG_INFO( printf( "Returning Dont Reduce %i\n", iLastToken ) ); + return iLastToken; + } + else if( iToken == 0 ) + { + DEBUG_INFO( printf( "Returning 0\n" ) ); + return 0; + } - FIND_MATCH(); + iLastToken = iToken; + + if( aRuleNodes[ iToken ].iMin == -1 ) + { + DEBUG_INFO( printf( "Passing through: %i\n", iToken ) ); + return iToken; } else { - DEBUG_INFO( printf( "Reduced Forced After %i %i %i at Pos: %i\n", aiMatched[0], aiMatched[1], aiMatched[2], iMatched ) ); + register unsigned int i = (unsigned int)(aRuleNodes[ iToken ].iMin), iMax = (unsigned int)(aRuleNodes[ iToken ].iMax); + register unsigned int iTentative = 0, iMatched = 1; - /* Force Reduce was requested. */ - iFound = 0; - iProspects = 0; + DEBUG_INFO( printf( "Scaning Prospects %i-%i at Pos: 0 for Token: %i\n", i, iMax -1, iToken ) ); + + { + FoundProspect : + + DEBUG_INFO( printf( "Prospect of %i Tokens - Testing Token: %i\n", iMatched, iToken ) ); + + if( iMatched == MAX_MATCH || aiRules[i][iMatched] == 0 ) + { + DEBUG_INFO( printf( "Saving Tentative %i - Found match of %i Tokens at Token: %i\n", i, iMatched, iToken ) ); + iTentative = i; + } + else + { + DEBUG_INFO( printf( "Partial Match - Get next Token after Token: %i\n", iToken ) ); + + /* Partial Match, try more...*/ + if( iHold ) + { + iHold--; + iToken = aiHold[ iHold ]; + bIgnoreWords = FALSE; + if( iToken < 256 ) + { + if( acNewLine[iToken] ) bNewLine = TRUE; + } + } + else + { + iToken = SimpLex_GetNextToken(); + } + + if( iToken < LEX_CUSTOM_ACTION ) + { + iToken = CUSTOM_ACTION( iToken ); \ + } + + if( iToken > DONT_REDUCE ) + { + DEBUG_INFO( printf( "Reduce Forced for Token: %i\n", iToken - DONT_REDUCE ) ); + aiHold[iHold++] = iToken; + goto AfterScanRules; + } + else + { + iLastToken = iToken; + } + + if( aiRules[i][iMatched] == iToken ) + { + /* Continue... Still a prospect. */ + DEBUG_INFO( printf( "Accepted Token: %i - Continue with this Rule...\n", iToken ) ); + iMatched++; + goto FoundProspect; + } + else if( aiRules[i][iMatched] > iToken ) + { + DEBUG_INFO( printf( "Rejected Token: %i - Giving up...\n", iToken ) ); + aiHold[iHold++] = iToken; + goto AfterScanRules; + } + else + { + DEBUG_INFO( printf( "Rejected Token: %i - Continue with next Rule...\n", iToken ) ); + aiHold[iHold++] = iToken; + } + } + + if( i < iMax ) + { + register unsigned int j = 1; + + DEBUG_INFO( printf( "Checking if next rule is extension of last Rule\n" ) ); + + while( j < iMatched ) + { + if( aiRules[i][j] != aiRules[i+1][j] ) + { + break; + } + j++; + } + if( j < iMatched ) + { + DEBUG_INFO( printf( "Rejected Rule - Not an extension or previous - Giving up...\n" ) ); + } + else + { + DEBUG_INFO( printf( "Accepted Next Rule...\n" ) ); + i++; + goto FoundProspect; + } + } + else + { + DEBUG_INFO( printf( "No More prospects...\n" ) ); + } + } + + AfterScanRules : + + if( iTentative ) + { + DEBUG_INFO( printf( "Processing Tentative: %i\n", iTentative ) ); + + if( aiRules[iTentative][MAX_MATCH] ) + { + DEBUG_INFO( printf( "Reducing Rule: %i Found %i Tokens\n", iTentative, iMatched ) ); + + if( aiRules[iTentative][MAX_MATCH + 1] ) + { + DEBUG_INFO( printf( "Pushing Reduction: %i\n", aiRules[iTentative][MAX_MATCH + 1] ) ); + aiHold[iHold++] = aiRules[iTentative][MAX_MATCH + 1]; + } + + DEBUG_INFO( printf( "Recycling Reduction: %i\n", aiRules[iTentative][MAX_MATCH] ) ); + iToken = aiRules[iTentative][MAX_MATCH]; + goto BeginReduce; + } + else + { + DEBUG_INFO( printf( "Passing Through %i Tokens\n", iMatched ) ); + while( iMatched > 1 ) + { + iMatched--; + DEBUG_INFO( printf( "Stacking Return: %i\n", aiRules[iTentative][iMatched] ) ); + aiReturn[iReturn++] = aiRules[iTentative][iMatched]; + } + DEBUG_INFO( printf( "Returning: %i\n", aiRules[iTentative][0] ) ); + return aiRules[iTentative][0]; + } + } + else + { + while( iMatched > 1 ) + { + iMatched--; + DEBUG_INFO( printf( "Pushing: %i\n", aiRules[i][iMatched] ) ); + aiHold[iHold++] = aiRules[i][iMatched]; + } + + DEBUG_INFO( printf( "Returning Shifted Left: %i\n", aiRules[i][0] ) ); + return aiRules[i][0]; + } + } +} + +void SimpLex_CheckWords( void ) +{ + int iTentative = -1, iCompare; + unsigned int i, iMax, iLenMatched, iBaseSize, iKeyLen; + char *pNextSpacer, *sKeys2Match = NULL, *szBaseBuffer = s_szBuffer, cSpacer = chr; + LEX_WORD *aCheck; + + #ifdef DEBUG_LEX + char sKeyDesc[] = "Key", sWordDesc[] = "Word", *sDesc; + #endif + #ifdef LEX_ABBREVIATE + unsigned int iLen2Match; + #endif + + #ifdef USE_KEYWORDS + if( bNewLine ) + { + i = aKeyNodes[ sToken[0] ].iMin; + iMax = aKeyNodes[ sToken[0] ].iMax + 1; + aCheck = (LEX_WORD*) ( &(aKeys[0]) ); + #ifdef DEBUG_LEX + sDesc = (char*) sKeyDesc; + #endif + } + else + #endif + { + i = aWordNodes[ sToken[0] ].iMin; + iMax = aWordNodes[ sToken[0] ].iMax + 1; + aCheck = (LEX_WORD*) ( &( aWords[0] ) ); + #ifdef DEBUG_LEX + sDesc = (char*) sWordDesc; + #endif } - if( ! bReal ) + bNewLine = FALSE; + + DEBUG_INFO( printf( "Pre-Scaning %ss for Token: %s at Positions: %i-%i\n", sDesc, (char*) sToken, i, iMax -1 ) ); + + while( i < iMax ) { - return ( iFound || ( iProspects - iRemoved ) ); + if( sToken[1] < aCheck[i].sWord[1] ) + { + DEBUG_INFO( printf( "Gave-Up! Token [%s] < Pattern [%s]\n", sToken, aCheck[i].sWord ) ); + iRet = 0; + return; + } + else if( sToken[1] > aCheck[i].sWord[1] ) + { + DEBUG_INFO( printf( "Skip... %s [%s] < [%s]\n", sDesc, aCheck[i].sWord, sToken ) ); + i++; + DEBUG_INFO( printf( "Continue with larger: [%s]\n", aCheck[i].sWord ) ); + continue; + } + else + { + break; + } } - DEBUG_INFO( printf( "Found %i Rules and %i Prospects for Token %i After %i %i %i\n", iFound, iProspects, iToken, aiMatched[0], aiMatched[1], aiMatched[2] ) ); - - /* Pass through. */ - if( iMatched == 0 && iFound == 0 && iProspects == 0 ) + while( i < iMax ) { - DEBUG_INFO( printf( "Passed Through Token %i After %i %i %i\n", iToken, aiMatched[0], aiMatched[1], aiMatched[2] ) ); - return iToken; + if( sKeys2Match ) + { + pNextSpacer = strstr( sKeys2Match, "{WS}" ); + } + else + { + sKeys2Match = aCheck[ i ].sWord; + pNextSpacer = strstr( sKeys2Match, "{WS}" ); + } + + if( sToken[0] < sKeys2Match[0] ) + { + DEBUG_INFO( printf( "Gave-Up! Token [%s] < Pattern [%s]\n", sToken, sKeys2Match ) ); + break; + } + else if( sToken[0] > sKeys2Match[0] ) + { + DEBUG_INFO( printf( "Skip... %s [%s] < [%s]\n", sDesc, sKeys2Match, sToken ) ); + i++; + if( ( iLenMatched = ( sKeys2Match - aCheck[i - 1].sWord ) ) == 0 ) + { + sKeys2Match = NULL; + DEBUG_INFO( printf( "Continue with larger: [%s]\n", aCheck[i].sWord ) ); + continue; + } + + /* Is there a next potential Pattern. */ + if( i < iMax && strncmp( aCheck[i - 1].sWord, aCheck[i].sWord, iLenMatched ) == 0 ) + { + /* Same relative position, in the next Pattern. */ + sKeys2Match = aCheck[i].sWord + iLenMatched; + DEBUG_INFO( printf( "Continue with larger: [%s] at: [%s]\n", aCheck[i].sWord, sKeys2Match ) ); + continue; + } + else + { + DEBUG_INFO( printf( "Gave-Up! %i !< %i or Pattern [%s] not compatible with last match\n", i, iMax, aCheck[i].sWord ) ); + break; + } + } + + if( pNextSpacer ) + { + /* Token not followed by white space - can't match this [or any latter] pattern! */ + if( ! acOmmit[cSpacer] ) + { + DEBUG_INFO( printf( "Skip... Pattern [%s] requires {WS}, cSpacer: %c\n", sKeys2Match, cSpacer ) ); + + i++; + if( ( iLenMatched = ( sKeys2Match - aCheck[i - 1].sWord ) ) == 0 ) + { + sKeys2Match = NULL; + DEBUG_INFO( printf( "Continue with: [%s]\n", aCheck[i].sWord ) ); + continue; + } + + /* Is there a next potential Pattern. */ + if( i < iMax && strncmp( aCheck[i - 1].sWord, aCheck[i].sWord, iLenMatched ) == 0 ) + { + /* Same relative position, in the next Pattern. */ + sKeys2Match = aCheck[i].sWord + iLenMatched; + DEBUG_INFO( printf( "Continue with: [%s] at: [%s]\n", aCheck[i].sWord, sKeys2Match ) ); + continue; + } + else + { + DEBUG_INFO( printf( "Gave-Up! %i !< %i or Pattern [%s] not compatible with last match\n", i, iMax, aCheck[i].sWord ) ); + break; + } + } + + iKeyLen = pNextSpacer - sKeys2Match; + } + else + { + iKeyLen = strlen( sKeys2Match ); + } + + #ifdef LEX_ABBREVIATE + iLen2Match = iLen; + if( iLen2Match < LEX_ABBREVIATE && iLen2Match < iKeyLen ) + { + iLen2Match = ( LEX_ABBREVIATE < iKeyLen ) ? LEX_ABBREVIATE : iKeyLen ; + } + + if( iLen2Match > iKeyLen && i < iMax - 1 ) + { + DEBUG_INFO( printf( "Trying Next... length mismatch - iKeyLen: %i iLen2Match: %i comparing: [%s] with: [%s]\n", iKeyLen, iLen2Match, sToken, sKeys2Match ) ); + i++; + + if( ( iLenMatched = ( sKeys2Match - aCheck[i - 1].sWord ) ) == 0 ) + { + sKeys2Match = NULL; + DEBUG_INFO( printf( "Continue with: [%s]\n", aCheck[i].sWord ) ); + continue; + } + + /* Is there a next potential Pattern. */ + if( i < iMax && strncmp( aCheck[i - 1].sWord, aCheck[i].sWord, iLenMatched ) == 0 ) + { + /* Same relative position, in the next Pattern. */ + sKeys2Match = aCheck[i].sWord + iLenMatched; + DEBUG_INFO( printf( "Continue with: [%s] at: [%s]\n", aCheck[i].sWord, sKeys2Match ) ); + continue; + } + else + { + DEBUG_INFO( printf( "Gave-Up! %i !< %i or Pattern [%s] not compatible with last match\n", i, iMax, aCheck[i].sWord ) ); + break; + } + } + + DEBUG_INFO( printf( "iKeyLen: %i iLen2Match: %i comparing: [%s] with: [%s]\n", iKeyLen, iLen2Match, sToken, sKeys2Match ) ); + + iCompare = strncmp( (char*) sToken, sKeys2Match, iLen2Match ); + #else + iCompare = strcmp( (char*) sToken, sKeys2Match ); + #endif + + if( iCompare == 0 ) /* Match found */ + { + if( pNextSpacer == NULL ) /* Full Match! */ + { + DEBUG_INFO( printf( "Saving Tentative %s [%s] == [%s]\n", sDesc, sToken, sKeys2Match ) ); + + iTentative = i; + iLenMatched = strlen( aCheck[i].sWord ); + + /* Saving this pointer of the input stream, we might have to get here again. */ + szBaseBuffer = s_szBuffer; iBaseSize = iSize; + DEBUG_INFO( printf( "Saved Buffer Postion: %i at: [%s]\n", iBaseSize, szBaseBuffer ) ); + + /* No White Space after last Token! */ + if( iHold || iPairToken ) + { + DEBUG_INFO( printf( "No White space after [%s] Holding: %i\n", sToken, aiHold[0] ) ); + break; + } + + IsExtendedMatch : + i++; + + /* Is there a next potential Pattern, that is an extended version of the current Pattern. */ + if( i < iMax && strncmp( aCheck[i - 1].sWord, aCheck[i].sWord, iLenMatched ) == 0 ) + { + if( strlen( aCheck[i].sWord ) > ( iLenMatched + 4 ) && ( pNextSpacer = strstr( aCheck[i].sWord + iLenMatched, "{WS}" ) ) != NULL ) + { + /* Same relative position, in the next Pattern. */ + sKeys2Match = pNextSpacer + 4; + DEBUG_INFO( printf( "Continue with: [%s] at: [%s]\n", aCheck[i].sWord, sKeys2Match ) ); + } + else + { + DEBUG_INFO( printf( "Skip... - Not Extended: [%s]\n", aCheck[i].sWord ) ); + goto IsExtendedMatch; + } + } + else + { + DEBUG_INFO( printf( "Gave-Up! %i !< %i or Pattern [%s] not extension of Pattern [%s]\n", i, iMax, aCheck[i].sWord, aCheck[iTentative].sWord ) ); + break; + } + } + else + { + sKeys2Match = pNextSpacer + 4; + DEBUG_INFO( printf( "Partial %s Match! [%s] == [%s] - Looking for: [%s]\n", sDesc, sToken, aCheck[i].sWord, sKeys2Match ) ); + + /* Saving this pointer of the input stream, we might have to get here again. */ + szBaseBuffer = s_szBuffer; iBaseSize = iSize; + DEBUG_INFO( printf( "Saved Buffer Postion: %i at: [%s]\n", iBaseSize, szBaseBuffer ) ); + } + + /* i may have been increased above - don't want to read next token if it won't get used! */ + if( i < iMax ) + { + bRecursive = TRUE; + cSpacer = chr; + + DEBUG_INFO( printf( "Getting next Token...\n" ) ); + SimpLex_GetNextToken(); + continue; + } + } + else if( iCompare > 0 ) + { + DEBUG_INFO( printf( "Trying Next %s Pattern... [%s] > [%s]\n", sDesc, sToken, sKeys2Match ) ); + i++; + + if( ( iLenMatched = ( sKeys2Match - aCheck[i - 1].sWord ) ) == 0 ) + { + sKeys2Match = NULL; + DEBUG_INFO( printf( "Continue with: [%s]\n", aCheck[i].sWord ) ); + continue; + } + + /* Is there a next potential Pattern. */ + if( i < iMax && strncmp( aCheck[i - 1].sWord, aCheck[i].sWord, iLenMatched ) == 0 ) + { + /* Same relative position, in the next Pattern. */ + sKeys2Match = aCheck[i].sWord + iLenMatched; + DEBUG_INFO( printf( "Continue with: [%s] at: [%s]\n", aCheck[i].sWord, sKeys2Match ) ); + continue; + } + else + { + DEBUG_INFO( printf( "Gave-Up! %i !< %i or Pattern [%s] not compatible with previous match.\n", i, iMax, aCheck[i].sWord ) ); + break; + } + } + else + { + DEBUG_INFO( printf( "Gave-Up! [%s] < [%s]\n", sToken, sKeys2Match ) ); + break; + } } - if( iFound || iProspects ) + if( s_szBuffer != szBaseBuffer ) { - /* Adding to Matched List. */ - ACCEPT_TOKEN(); + s_szBuffer = szBaseBuffer; iSize = iBaseSize; iHold = 0; iReturn = 0; + DEBUG_INFO( printf( "Partial Match - Restored position: %i at: [%s]\n", iSize, s_szBuffer ) ); } - switch( iFound ) + if( iTentative > -1 ) { - /* Match Failed. */ - case 0 : - if( iProspects ) - { - /* Can't reduce yet, can't "bookmark" possible reduction either, must continue checking. */ - return 0; - } - else - { - REVERT_OR_GIVEUP(); - return 0; - } + DEBUG_INFO( printf( "Reducing %s Pattern: %i [%s]\n", sDesc, iTentative, aCheck[iTentative].sWord ) ); - case 1 : - if( iProspects ) - { - /* Can't reduce yet, "bookmark" possible reduction here, and continue checking. */ - SAVE_TENTATIVE(); + bIgnoreWords = TRUE; - return 0; - } - else - { - /* One Match and no additional Prospects - we can reduce. */ - REDUCE_RULE(); + KEYWORD_ACTION() - return 0; - } - - default : - if( iProspects ) - { - /* Can't reduce yet, and can't "bookmark" possible reduction either, must continue checking. */ - return 0; - } - else - { - printf( "Multiple Rules for same Tokens: %i %i %i %i - Please correct the rules.\n", aiMatched[0], aiMatched[1], aiMatched[2], aiMatched[3] ); - - return 0; - } + iRet = aCheck[ iTentative ].iToken; + if( iRet < LEX_CUSTOM_ACTION ) + { + iRet = CUSTOM_ACTION( iRet ); + } + } + else + { + iRet = 0; } } @@ -1500,7 +1412,7 @@ void * yy_bytes_buffer( char * pBuffer, int iBufSize ) if( bStart ) { bStart = FALSE; - GenTrees() + GenTrees(); INIT_ACTION(); } @@ -1510,45 +1422,143 @@ void * yy_bytes_buffer( char * pBuffer, int iBufSize ) static void GenTrees( void ) { register unsigned int i; - register unsigned char cIndex; + register unsigned int iIndex; i = 0; while( i < 256 ) { - aKeyNodes[i].iMin = 0; - aKeyNodes[i].iMax = 0; - aWordNodes[i].iMin = 0; - aWordNodes[i].iMax = 0; + acOmmit[i] = 0; + acNewLine[i] = 0; + acReturn[i] = 0; + aPairNodes[i].iMin = -1; + aPairNodes[i].iMax = -1; + aSelfNodes[i].iMin = -1; + aSelfNodes[i].iMax = -1; + aKeyNodes[i].iMin = -1; + aKeyNodes[i].iMax = -1; + aWordNodes[i].iMin = -1; + aWordNodes[i].iMax = -1; + aRuleNodes[i].iMin = -1; + aRuleNodes[i].iMax = -1; + i++; + } + + while( i < 1024 ) + { + aRuleNodes[i].iMin = -1; + aRuleNodes[i].iMax = -1; i++; } i = 0; - while ( i < iKeys ) + while ( szOmmit[i] ) { - cIndex = aKeys[i].sWord[0]; - - if( aKeyNodes[ cIndex ].iMin == 0 ) - { - aKeyNodes[ cIndex ].iMin = i; - } - - aKeyNodes[ cIndex ].iMax = i; - + acOmmit[ szOmmit[i] ] = 1; i++; } + i = 0; + while ( szNewLine[i] ) + { + acNewLine[ szNewLine[i] ] = 1; + i++; + } + + i = 0; + while ( i < iDelimiters ) + { + acReturn[ aDelimiters[i].cDelimiter ] = aDelimiters[i].iToken; + i++; + } + + i = 0; + while ( i < iPairs ) + { + iIndex = aPairs[i].sStart[0]; + if( aPairNodes[ iIndex ].iMin == -1 ) + { + aPairNodes[ iIndex ].iMin = i; + } + aPairNodes[ iIndex ].iMax = i; + i++; + } + + i = 0; + while ( i < iSelfs ) + { + iIndex = aSelfs[i].sWord[0]; + if( aSelfNodes[ iIndex ].iMin == -1 ) + { + aSelfNodes[ iIndex ].iMin = i; + } + aSelfNodes[ iIndex ].iMax = i; + i++; + } + + #ifdef USE_KEYWORDS + i = 0; + while ( i < iKeys ) + { + iIndex = aKeys[i].sWord[0]; + if( aKeyNodes[ iIndex ].iMin == -1 ) + { + aKeyNodes[ iIndex ].iMin = i; + } + aKeyNodes[ iIndex ].iMax = i; + i++; + } + #endif + i = 0; while ( i < iWords ) { - cIndex = aWords[i].sWord[0]; - - if( aWordNodes[ cIndex ].iMin == 0 ) + iIndex = aWords[i].sWord[0]; + if( aWordNodes[ iIndex ].iMin == -1 ) { - aWordNodes[ cIndex ].iMin = i; + aWordNodes[ iIndex ].iMin = i; } + aWordNodes[ iIndex ].iMax = i; + i++; + } - aWordNodes[ cIndex ].iMax = i; + /* Reduce logic excpects the Rules to be sorted. */ + qsort( ( void * ) aiRules, iRules, LEX_RULE_SIZE, rulecmp ); + i = 0; + while ( i < iRules ) + { + iIndex = (unsigned int) aiRules[i][0]; + if( iIndex > 1023 ) + { + printf( "ERROR! Primary Token: %i out of range.\n", (int) iIndex ); + exit( EXIT_FAILURE ); + } + if( aRuleNodes[ iIndex ].iMin == -1 ) + { + aRuleNodes[ iIndex ].iMin = i; + } + aRuleNodes[ iIndex ].iMax = i; i++; } } + +static int rulecmp( const void * pLeft, const void * pRight ) +{ + int *iLeftRule = (int*)( pLeft ); + int *iRightRule = (int*)( pRight ); + register unsigned int i = 0; + + while( iLeftRule[i] == iRightRule[i] ) + { + i++; + } + + if( iLeftRule[i] < iRightRule[i] ) + { + return -1; + } + else + { + return 1; + } +} diff --git a/harbour/source/macro/macro.slx b/harbour/source/macro/macro.slx index 410c3c6aec..088d7a4f71 100644 --- a/harbour/source/macro/macro.slx +++ b/harbour/source/macro/macro.slx @@ -40,17 +40,18 @@ #define DEBUG_INFO(x) x #endif -#undef LEX_ABBREVIATE_WORDS - #define LEX_ABBREVIATE_WORDS 4 +#undef LEX_ABBREVIATE + #define LEX_ABBREVIATE 4 #undef YY_BUF_SIZE #define YY_BUF_SIZE 1 /* Not needed because using the pMacro->String as input buffer. */ /* declaration of yylex function - * NOTE: yylval is paassed automaticaly by bison if %pure_parser is used - */ + * NOTE: yylval_ptr is passed automaticaly by bison if %pure_parser is used +*/ #undef YY_DECL -#define YY_DECL int yylex( YYSTYPE *yylval_ptr, HB_MACRO_PTR pMacro ) + #define YY_DECL int yylex( YYSTYPE *yylval_ptr ) + #define YYLEX_PARAM pMacro #undef YY_INPUT @@ -58,19 +59,18 @@ #undef STREAM_EXCEPTION #define STREAM_EXCEPTION( sPair, cChar ) \ - hb_macroError( EG_SYNTAX, YYLEX_PARAM ); \ - aiReturn[ iReturn++ ] = '\n'; \ - aiReturn[ iReturn++ ] = LITERAL; + hb_macroError( EG_SYNTAX, YYLEX_PARAM ); -#undef KEYWORD_ACTION - #define KEYWORD_ACTION() strncpy( (char*) sWordAsString, (char*) sToken, iWordLen ); sWordAsString[iWordLen] = '\0'; +#undef IF_BELONG_LEFT + #define IF_BELONG_LEFT(chr) if( iLastToken == IDENTIFIER || iLastToken == ']' || iLastToken == MACROVAR || iLastToken == MACROTEXT || iLastToken == ')' || iLastToken == '}' || iLastToken == FIELD || iLastToken == SELF || iLastToken == QSELF || iLastToken == IIF ) -#undef WORD_ACTION - #define WORD_ACTION() strncpy( (char*) sWordAsString, (char*) sToken, iWordLen ); sWordAsString[iWordLen] = '\0'; +static HB_MACRO_PTR pMacro; +static YYSTYPE *pYYLVAL; -static char sWordAsString[11]; - -long hb_lex_Hex2L( char* sHex ); +static int hb_macro_SLX_CustomAction( int x, int aiHold[], int *ptr_iHold, char *sToken ); +static void hb_macro_SLX_EelemntToken(void); +static void hb_macro_SLX_ConvertNumber(void); +long hb_macro_SLX_Hex2L( char* sHex ); void * yy_bytes_buffer( char * pBuffer, int iBufSize ); @@ -78,162 +78,130 @@ void * yy_bytes_buffer( char * pBuffer, int iBufSize ); /* Delimiters. */ ACCEPT_TOKEN_AND_DROP_DELIMITER_IF_ONE_OF_THESE( " \t" ); -ACCEPT_TOKEN_AND_RETURN_DELIMITER_IF_ONE_OF_THESE( "|,()[]{}^%*/+-:=!<>#@$" ); -DELIMITER_BELONGS_TO_TOKEN_IF_ONE_OF_THESE( "" ); + +ACCEPT_TOKEN_AND_RETURN_DELIMITERS { + LEX_DELIMITER( ',' ) AS_TOKEN( ',' + DONT_REDUCE ), + LEX_DELIMITER( '(' ) AS_TOKEN( '(' ), + LEX_DELIMITER( ')' ) AS_TOKEN( ')' ), + LEX_DELIMITER( '[' ) AS_TOKEN( '[' ), + LEX_DELIMITER( ']' ) AS_TOKEN( ']' + DONT_REDUCE ), + LEX_DELIMITER( '}' ) AS_TOKEN( '}' + DONT_REDUCE ), + LEX_DELIMITER( ':' ) AS_TOKEN( ':' ), + LEX_DELIMITER( '=' ) AS_TOKEN( '=' + DONT_REDUCE ), + LEX_DELIMITER( '#' ) AS_TOKEN( NE1 + DONT_REDUCE ), + LEX_DELIMITER( '@' ) AS_TOKEN( '@' + DONT_REDUCE ), + LEX_DELIMITER( '<' ) AS_TOKEN( '<' + DONT_REDUCE ), + LEX_DELIMITER( '>' ) AS_TOKEN( '>' + DONT_REDUCE ), + LEX_DELIMITER( '!' ) AS_TOKEN( NOT + DONT_REDUCE ), + LEX_DELIMITER( '{' ) AS_TOKEN( '{' + DONT_REDUCE ), + LEX_DELIMITER( '|' ) AS_TOKEN( '|' + DONT_REDUCE ), + LEX_DELIMITER( '^' ) AS_TOKEN( POWER + DONT_REDUCE ), + LEX_DELIMITER( '%' ) AS_TOKEN( '%' + DONT_REDUCE ), + LEX_DELIMITER( '*' ) AS_TOKEN( '*' + DONT_REDUCE ), + LEX_DELIMITER( '/' ) AS_TOKEN( '/' + DONT_REDUCE ), + LEX_DELIMITER( '+' ) AS_TOKEN( '+' + DONT_REDUCE ), + LEX_DELIMITER( '-' ) AS_TOKEN( '-' + DONT_REDUCE ), + LEX_DELIMITER( '$' ) AS_TOKEN( '$' + DONT_REDUCE ) + }; /* Intermediate Token, needs CustomAction. */ -#define HB_LIT_ACT -1000 +#define HB_LIT_ACT LEX_CUSTOM_ACTION - 1 /* Stream Pairs. */ DEFINE_STREAM_AS_ONE_OF_THESE { - START_WITH("\'") END_WITH("\'") STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_LIT_ACT), START_WITH("\"") END_WITH("\"" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_LIT_ACT), + START_WITH("'") END_WITH("'") STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(FALSE) AS_PAIR_TOKEN(HB_LIT_ACT), START_WITH("[") END_WITH("]" ) STOP_IF_ONE_OF_THESE("\n") TEST_LEFT(TRUE ) AS_PAIR_TOKEN(HB_LIT_ACT) }; START_NEW_LINE_IF_ONE_OF_THESE( "\n;" ); -/* Intermediate Token neede to be expanded. */ -#define _DOT_DOT_ -1001 +#define HB_SELF LEX_CUSTOM_ACTION - 2 SELF_CONTAINED_WORDS_ARE { - LEX_WORD( ".NOT." ) AS_TOKEN( NOT ), - LEX_WORD( ".AND." ) AS_TOKEN( AND ), - LEX_WORD( ".OR." ) AS_TOKEN( OR ), - LEX_WORD( ":=" ) AS_TOKEN( INASSIGN ), - LEX_WORD( "==" ) AS_TOKEN( EQ ), - LEX_WORD( "<>" ) AS_TOKEN( NE2 ), - LEX_WORD( "!=" ) AS_TOKEN( NE2 ), - LEX_WORD( "++" ) AS_TOKEN( INC ), - LEX_WORD( "--" ) AS_TOKEN( DEC ), + LEX_WORD( ".AND." ) AS_TOKEN( AND + DONT_REDUCE ), + LEX_WORD( ".NOT." ) AS_TOKEN( NOT + DONT_REDUCE ), + LEX_WORD( ".OR." ) AS_TOKEN( OR + DONT_REDUCE ), + LEX_WORD( ":=" ) AS_TOKEN( INASSIGN + DONT_REDUCE ), + LEX_WORD( "::" ) AS_TOKEN( HB_SELF ), + LEX_WORD( "==" ) AS_TOKEN( EQ + DONT_REDUCE ), + LEX_WORD( "<>" ) AS_TOKEN( NE2 + DONT_REDUCE ), + LEX_WORD( "<=" ) AS_TOKEN( LE + DONT_REDUCE ), + LEX_WORD( ">=" ) AS_TOKEN( GE + DONT_REDUCE ), + LEX_WORD( "!=" ) AS_TOKEN( NE2 + DONT_REDUCE ), + LEX_WORD( "++" ) AS_TOKEN( INC + DONT_REDUCE ), + LEX_WORD( "+=" ) AS_TOKEN( PLUSEQ + DONT_REDUCE ), + LEX_WORD( "--" ) AS_TOKEN( DEC + DONT_REDUCE ), + LEX_WORD( "-=" ) AS_TOKEN( MINUSEQ + DONT_REDUCE ), LEX_WORD( "->" ) AS_TOKEN( ALIASOP ), - LEX_WORD( "<=" ) AS_TOKEN( LE ), - LEX_WORD( ">=" ) AS_TOKEN( GE ), - LEX_WORD( "+=" ) AS_TOKEN( PLUSEQ ), - LEX_WORD( "-=" ) AS_TOKEN( MINUSEQ ), - LEX_WORD( "*=" ) AS_TOKEN( MULTEQ ), - LEX_WORD( "/=" ) AS_TOKEN( DIVEQ ), - LEX_WORD( "**" ) AS_TOKEN( POWER ), - LEX_WORD( "^=" ) AS_TOKEN( EXPEQ ), - LEX_WORD( "%=" ) AS_TOKEN( MODEQ ), - LEX_WORD( "::" ) AS_TOKEN( _DOT_DOT_ ) + LEX_WORD( "*=" ) AS_TOKEN( MULTEQ + DONT_REDUCE ), + LEX_WORD( "**" ) AS_TOKEN( POWER + DONT_REDUCE ), + LEX_WORD( "/=" ) AS_TOKEN( DIVEQ + DONT_REDUCE ), + LEX_WORD( "^=" ) AS_TOKEN( EXPEQ + DONT_REDUCE ), + LEX_WORD( "%=" ) AS_TOKEN( MODEQ + DONT_REDUCE ) }; -/* Key Words. */ -LANGUAGE_KEY_WORDS_ARE { - LEX_WORD( "" ) AS_TOKEN( 0 ) - }; - /* Intermediate Words when ambigious. */ -#define _IF_ 2001 -#define QSELF 2002 -#define _FIELD_ 2003 -#define _FIELD 2004 -#define _SELF_ 2005 +#define QSELF 802 /* Words. */ LANGUAGE_WORDS_ARE { - LEX_WORD( "FIELD" ) AS_TOKEN( _FIELD_ ), - LEX_WORD( "IF" ) AS_TOKEN( _IF_ ), + LEX_WORD( ".F." ) AS_TOKEN( FALSEVALUE + DONT_REDUCE ), + LEX_WORD( ".N." ) AS_TOKEN( FALSEVALUE + DONT_REDUCE ), + LEX_WORD( ".T." ) AS_TOKEN( TRUEVALUE + DONT_REDUCE ), + LEX_WORD( ".Y." ) AS_TOKEN( TRUEVALUE + DONT_REDUCE ), + LEX_WORD( "FIELD" ) AS_TOKEN( FIELD ), + LEX_WORD( "IF" ) AS_TOKEN( IIF ), LEX_WORD( "IIF" ) AS_TOKEN( IIF ), - LEX_WORD( "NIL" ) AS_TOKEN( NIL ), + LEX_WORD( "NIL" ) AS_TOKEN( NIL + DONT_REDUCE ), LEX_WORD( "QSELF" ) AS_TOKEN( QSELF ), - LEX_WORD( "SELF" ) AS_TOKEN( _SELF_ ), - LEX_WORD( "_FIELD" ) AS_TOKEN( _FIELD ), - LEX_WORD( ".F." ) AS_TOKEN( FALSEVALUE ), - LEX_WORD( ".N." ) AS_TOKEN( FALSEVALUE ), - LEX_WORD( ".T." ) AS_TOKEN( TRUEVALUE ), - LEX_WORD( ".Y." ) AS_TOKEN( TRUEVALUE ) + LEX_WORD( "SELF" ) AS_TOKEN( SELF ), + LEX_WORD( "_FIELD" ) AS_TOKEN( FIELD ) }; /* When reservered words are used as Identifier. */ -#define HB_IDENTIFIER -1002 -#define HB_SELF_ID -1003 -#define HB_MACRO_ERR -1004 +#define HB_IDENTIFIER LEX_CUSTOM_ACTION - 3 +#define HB_MACRO_ERR LEX_CUSTOM_ACTION - 4 LANGUAGE_RULES_ARE { - IF_SEQUENCE_IS( '^' , 0 , 0 , 0 ) REDUCE_TO( POWER , 0 ), - IF_SEQUENCE_IS( '!' , 0 , 0 , 0 ) REDUCE_TO( NOT , 0 ), + /* This _FIELD_ is NOT at BOL wants only ->. */ + IF_SEQUENCE_IS( FIELD , ALIASOP , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( FIELD , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - /* FIELD ALIASOP was removed because FIELD-> is still FIELD.*/ - IF_SEQUENCE_IS( FIELD , INASSIGN , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INASSIGN ), - IF_SEQUENCE_IS( FIELD , INC , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , INC ), - IF_SEQUENCE_IS( FIELD , DEC , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DEC ), - IF_SEQUENCE_IS( FIELD , PLUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , PLUSEQ ), - IF_SEQUENCE_IS( FIELD , MINUSEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MINUSEQ ), - IF_SEQUENCE_IS( FIELD , MULTEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MULTEQ ), - IF_SEQUENCE_IS( FIELD , DIVEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , DIVEQ ), - IF_SEQUENCE_IS( FIELD , EXPEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , EXPEQ ), - IF_SEQUENCE_IS( FIELD , MODEQ , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , MODEQ ), - IF_SEQUENCE_IS( FIELD , '(' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '(' ), - IF_SEQUENCE_IS( FIELD , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( FIELD , '=' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '=' ), - IF_SEQUENCE_IS( FIELD , ':' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ':' ), - IF_SEQUENCE_IS( FIELD , '\n' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '\n' ), - IF_SEQUENCE_IS( FIELD , ';' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , ';' ), - IF_SEQUENCE_IS( FIELD , 0 , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( SELF , ':' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( SELF , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - /* This _FIELD_ is FIELD NOT at BOL wants only ->. */ - IF_SEQUENCE_IS( _FIELD_ , ALIASOP , 0 , 0 ) REDUCE_TO( FIELD , ALIASOP ), - IF_SEQUENCE_IS( _FIELD_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _FIELD_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + IF_SEQUENCE_IS( QSELF , '(' , ')' , 0 ) REDUCE_TO( SELF + DONT_REDUCE, 0 ), + IF_SEQUENCE_IS( QSELF , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - /* This _FIELD is _FIELD NOT at BOL wants only ->. */ - IF_SEQUENCE_IS( _FIELD , ALIASOP , 0 , 0 ) REDUCE_TO( FIELD , ALIASOP ), - IF_SEQUENCE_IS( _FIELD , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _FIELD , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), + IF_SEQUENCE_IS( IIF , '(' , 0 , 0 ) PASS_THROUGH(), + IF_SEQUENCE_IS( IIF , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - /* Left Associate '[' to seperate from string delimiter. */ - IF_SEQUENCE_IS( IDENTIFIER, '[' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( MACROVAR , '[' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( MACROTEXT , '[' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( ')' , '[' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( ']' , '[' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( '}' , '[' , 0 , 0 ) PASS_THROUGH(), - - IF_SEQUENCE_IS( _DOT_DOT_ , 0 , 0 , 0 ) REDUCE_TO( HB_SELF_ID , ':' ), - - IF_SEQUENCE_IS( _SELF_ , ':' , 0 , 0 ) REDUCE_TO( SELF , ':' ), - IF_SEQUENCE_IS( _SELF_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _SELF_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( QSELF , '(' , ')' , 0 ) REDUCE_TO( SELF , 0 ), - IF_SEQUENCE_IS( QSELF , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( QSELF , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( _IF_ , '(' , 0 , 0 ) REDUCE_TO( IIF , '(' ), - IF_SEQUENCE_IS( _IF_ , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( _IF_ , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( IIF , '(' , 0 , 0 ) PASS_THROUGH(), - IF_SEQUENCE_IS( IIF , '[' , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , '[' ), - IF_SEQUENCE_IS( IIF , 0 , 0 , 0 ) REDUCE_TO( HB_IDENTIFIER , 0 ), - - IF_SEQUENCE_IS( '&' , '\'' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ), - IF_SEQUENCE_IS( '&' , '"' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ), - IF_SEQUENCE_IS( '&' , '[' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ) + IF_SEQUENCE_IS( '&' , '\'' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ), + IF_SEQUENCE_IS( '&' , '"' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ), + IF_SEQUENCE_IS( '&' , '[' , 0 , 0 ) REDUCE_TO( HB_MACRO_ERR , 0 ) }; /* ------------------------------------------------- End of Language Definitions. ------------------------------------------------ */ #undef LEX_CASE - #define LEX_CASE(x) toupper(x) + #define LEX_CASE(x) ( ( ( iRet = (x) ) > 96 && iRet < 123 ) ? iRet - 32 : iRet ) #ifdef SHOW_LEX_TOKENS #undef INTERCEPT_ACTION #define INTERCEPT_ACTION(x) \ if( x == IDENTIFIER ) \ - printf( " IDENTIFIER = \"%s\"\n", yylval_ptr->string ); \ + printf( " IDENTIFIER = \"%s\"\n", pYYLVAL->string ); \ else if( x == LITERAL ) \ - printf( " LITERAL = \"%s\"\n", yylval_ptr->string ); \ + printf( " LITERAL = \"%s\"\n", pYYLVAL->string ); \ else if( x == MACROVAR ) \ - printf( " MACROVAR = \"%s\"\n", yylval_ptr->string ); \ + printf( " MACROVAR = \"%s\"\n", pYYLVAL->string ); \ else if( x == MACROTEXT ) \ - printf( " MACROTEXT = \"%s\"\n", yylval_ptr->string ); \ + printf( " MACROTEXT = \"%s\"\n", pYYLVAL->string ); \ else if( x == NUM_LONG ) \ - printf( " INTEGER = %il\n", yylval_ptr->valLong.lNumber ); \ + printf( " INTEGER = %il\n", pYYLVAL->valLong.lNumber ); \ else if( x == NUM_DOUBLE ) \ - printf( " DOUBLE = %f\n", yylval_ptr->valDouble.dNumber ); \ + printf( " DOUBLE = %f\n", pYYLVAL->valDouble.dNumber ); \ else if( x < 256 ) \ if( x == '\n' || x == ';' ) \ printf( " NEW LINE %i\n", hb_comp_iLine - 1 ); \ @@ -244,137 +212,154 @@ LANGUAGE_RULES_ARE { #endif #undef ELEMENT_TOKEN - #define ELEMENT_TOKEN(x)\ - { yytext = x;\ - yyleng = iLen;\ -\ - if( *yytext == '_' || *yytext == '&' || isalpha( (int) *yytext ) )\ - {\ - /* Macro. */\ - if( ( tmpPtr = strrchr( yytext, '&' ) ) != NULL ) /* Right Search. */\ - {\ - /* Is '&' the first char? - Since its was right search that would be the only '&'. */\ - if( tmpPtr == yytext )\ - {\ - /* Maybe just the Macro Operator. */\ - if( yyleng == 1 )\ - {\ - iRet = '&';\ - }\ - /* No '.' so Simple Macro. */ \ - else if( ( tmpPtr = strchr( yytext, '.' ) ) == NULL ) /* Left Search. */ \ - {\ - /* Remove the '&'. */ \ - yytext++;\ - yyleng--;\ -\ - yylval_ptr->string = hb_strdup( yytext );\ - iRet = MACROVAR;\ - }\ - else if( tmpPtr == yytext + yyleng - 1 )\ - {\ - /* The only '.' is last char, so Simple Macro. */ \ -\ - /* Remove the '&' and the '.' */ \ - yytext++;\ - yyleng -= 2;\ - yytext[yyleng] = '\0';\ -\ - yylval_ptr->string = hb_strdup( yytext );\ - iRet = MACROVAR;\ - }\ - else\ - {\ - yytext = hb_strdup( yytext );\ -\ - yylval_ptr->string = yytext;\ - iRet = MACROTEXT;\ - }\ - }\ - else\ - {\ - yytext = hb_strdup( yytext );\ -\ - yylval_ptr->string = yytext;\ - iRet = MACROTEXT;\ - }\ - }\ - else\ - {\ - if( iLen > YYLEX_PARAM->uiNameLen )\ - {\ - yytext[ YYLEX_PARAM->uiNameLen ] = '\0';\ - yyleng = YYLEX_PARAM->uiNameLen;\ - }\ -\ - yylval_ptr->string = hb_strdup( yytext );\ - iRet = IDENTIFIER;\ - }\ - }\ - else\ - {\ - CONVERT_NUMBER();\ - }\ - } - -#define CONVERT_NUMBER()\ - if( yytext[0] == '0' && yytext[1] == 'X' )\ - {\ - long lNumber = hb_lex_Hex2L( yytext + 2 );\ -\ - if( ( double ) LONG_MIN <= lNumber && lNumber <= ( double ) LONG_MAX )\ - {\ - yylval_ptr->valLong.lNumber = lNumber;\ - yylval_ptr->valLong.szValue = yytext;\ - iRet = NUM_LONG;\ - }\ - else\ - {\ - yylval_ptr->valDouble.dNumber = lNumber;\ - yylval_ptr->valDouble.bWidth = HB_DEFAULT_WIDTH;\ - yylval_ptr->valDouble.bDec = 0;\ - yylval_ptr->valDouble.szValue = yytext;\ - iRet = NUM_DOUBLE;\ - }\ - }\ - else\ - {\ - yylval_ptr->valDouble.dNumber = atof( yytext );\ - tmpPtr = strchr( yytext, '.' );\ -\ - if( tmpPtr )\ - {\ - yylval_ptr->valDouble.bDec = strlen( tmpPtr + 1 );\ - yylval_ptr->valDouble.bWidth = iLen - yylval_ptr->valDouble.bDec;\ - if( yylval_ptr->valDouble.bDec )\ - {\ - yylval_ptr->valDouble.bWidth--;\ - }\ - yylval_ptr->valDouble.szValue = yytext;\ - iRet = NUM_DOUBLE;\ - }\ - else\ - {\ - if( ( double )LONG_MIN <= yylval_ptr->valDouble.dNumber && yylval_ptr->valDouble.dNumber <= ( double )LONG_MAX )\ - {\ - yylval_ptr->valLong.lNumber = ( long ) yylval_ptr->valDouble.dNumber;\ - yylval_ptr->valLong.szValue = yytext;\ - iRet = NUM_LONG;\ - }\ - else\ - {\ - yylval_ptr->valDouble.bWidth = iLen + 1;\ - yylval_ptr->valDouble.bDec = 0;\ - yylval_ptr->valDouble.szValue = yytext;\ - iRet = NUM_DOUBLE;\ - }\ - }\ - } + #define ELEMENT_TOKEN(x,y) hb_macro_SLX_ElementToken() #undef CUSTOM_ACTION - #define CUSTOM_ACTION(x) x = hb_lex_CustomAction( x, aiHold, &iHold, yylval_ptr, pMacro ) + #define CUSTOM_ACTION(x) x = hb_macro_SLX_CustomAction( x, aiHold, &iHold, (char*) sToken ) -long hb_lex_Hex2L( char* sHex ) +#undef LEX_USER_SETUP + #define LEX_USER_SETUP() if( pYYLVAL == NULL ) pYYLVAL = yylval_ptr; + +void hb_macro_SLX_ElementToken(void) +{ + extern char *tmpPtr, *yytext, sToken[TOKEN_SIZE]; + extern int yyleng, iRet; + extern unsigned int iLen; + + yytext = (char*) sToken; + yyleng = iLen; + + if( ( *yytext > 64 && *yytext < 91 ) || *yytext == '&' || *yytext == '_' ) + { + /* Macro. */ + if( ( tmpPtr = strrchr( yytext, '&' ) ) != NULL ) /* Right Search. */ + { + /* Is '&' the first char? - Since its was right search that would be the only '&'. */ + if( tmpPtr == yytext ) + { + /* Maybe just the Macro Operator. */ + if( yyleng == 1 ) + { + iRet = '&'; + } + /* No '.' so Simple Macro. */ + else if( ( tmpPtr = strchr( yytext, '.' ) ) == NULL ) /* Left Search. */ + { + /* Remove the '&'. */ + yytext++; + yyleng--; + + pYYLVAL->string = hb_strdup( yytext ); + iRet = MACROVAR; + } + else if( tmpPtr == yytext + yyleng - 1 ) + { + /* The only '.' is last char, so Simple Macro. */ + + /* Remove the '&' and the '.' */ + yytext++; + yyleng -= 2; + yytext[yyleng] = '\0'; + + pYYLVAL->string = hb_strdup( yytext ); + iRet = MACROVAR; + } + else + { + yytext = hb_strdup( yytext ); + pYYLVAL->string = yytext; + iRet = MACROTEXT; + } + } + else + { + yytext = hb_strdup( yytext ); + pYYLVAL->string = yytext; + iRet = MACROTEXT; + } + } + else + { + if( yyleng > (int) YYLEX_PARAM->uiNameLen ) + { + yytext[ YYLEX_PARAM->uiNameLen ] = '\0'; + yyleng = YYLEX_PARAM->uiNameLen; + } + + pYYLVAL->string = hb_strdup( yytext ); + iRet = IDENTIFIER + DONT_REDUCE; + } + } + else + { + /* "Paramters" yytext & yyleng, "returns" result in iRet. */ + hb_macro_SLX_ConvertNumber(); + + DEBUG_INFO( printf( "Element \"%s\" is %i\n", sToken, iRet ) ); + } +} + +static void hb_macro_SLX_ConvertNumber(void) +{ + extern int iRet, yyleng; + extern char *tmpPtr, *yytext; + + if( yytext[0] == '0' && yytext[1] == 'X' ) + { + long lNumber = hb_macro_SLX_Hex2L( yytext + 2 ); + + if( ( double ) LONG_MIN <= lNumber && lNumber <= ( double ) LONG_MAX ) + { + pYYLVAL->valLong.lNumber = lNumber; + pYYLVAL->valLong.szValue = yytext; + iRet = NUM_LONG; + } + else + { + pYYLVAL->valDouble.dNumber = lNumber; + pYYLVAL->valDouble.bWidth = HB_DEFAULT_WIDTH; + pYYLVAL->valDouble.bDec = 0; + pYYLVAL->valDouble.szValue = yytext; + iRet = NUM_DOUBLE; + } + } + else + { + pYYLVAL->valDouble.dNumber = atof( yytext ); + tmpPtr = strchr( yytext, '.' ); + + if( tmpPtr ) + { + pYYLVAL->valDouble.bDec = strlen( tmpPtr + 1 ); + pYYLVAL->valDouble.bWidth = yyleng - pYYLVAL->valDouble.bDec; + if( pYYLVAL->valDouble.bDec ) + { + pYYLVAL->valDouble.bWidth--; + } + pYYLVAL->valDouble.szValue = yytext; + iRet = NUM_DOUBLE; + } + else + { + if( ( double )LONG_MIN <= pYYLVAL->valDouble.dNumber && pYYLVAL->valDouble.dNumber <= ( double )LONG_MAX ) + { + pYYLVAL->valLong.lNumber = ( long ) pYYLVAL->valDouble.dNumber; + pYYLVAL->valLong.szValue = yytext; + iRet = NUM_LONG; + } + else + { + pYYLVAL->valDouble.bWidth = yyleng + 1; + pYYLVAL->valDouble.bDec = 0; + pYYLVAL->valDouble.szValue = yytext; + iRet = NUM_DOUBLE; + } + } + } + iRet += DONT_REDUCE; +} + +long hb_macro_SLX_Hex2L( char* sHex ) { int i, iExp = 0, iLen = strlen( sHex ) - 1; long lVal, lSum = 0; @@ -384,7 +369,7 @@ long hb_lex_Hex2L( char* sHex ) { cChar = sHex[ iLen-- ]; - if( isalpha( (int) cChar ) ) + if( cChar > 64 && cChar < 91 ) { lVal = cChar - 55; } @@ -393,7 +378,7 @@ long hb_lex_Hex2L( char* sHex ) lVal = cChar - 48; } - if( lVal ) + if( lVal) { i = 0; while( i++ < iExp ) @@ -410,51 +395,41 @@ long hb_lex_Hex2L( char* sHex ) return lSum; } -int hb_lex_CustomAction( int x, int aiHold[], int *ptr_iHold, YYSTYPE *yylval_ptr, HB_MACRO_PTR pMacro ) +int hb_macro_SLX_CustomAction( int x, int aiHold[], int *ptr_iHold, char *sToken ) { switch ( x ) { case HB_LIT_ACT : - yylval_ptr->string = hb_strdup( sPair ); - x = LITERAL; - break; + pYYLVAL->string = hb_strdup( sPair ); + return LITERAL + DONT_REDUCE ; case HB_IDENTIFIER : - x = IDENTIFIER; - break; + pYYLVAL->string = hb_strdup( sToken ); + return IDENTIFIER + DONT_REDUCE; - case HB_SELF_ID : - sWordAsString[0] = 'S'; - sWordAsString[1] = 'E'; - sWordAsString[2] = 'L'; - sWordAsString[3] = 'F'; - sWordAsString[4] = '\0'; - x = IDENTIFIER; - break; + case HB_SELF : + aiHold[ (*ptr_iHold)++ ] = ':' + DONT_REDUCE ; + pYYLVAL->string = hb_strdup( "SELF" ); + return IDENTIFIER + DONT_REDUCE ; case HB_MACRO_ERR : hb_macroError( EG_SYNTAX, YYLEX_PARAM ); - x = 0; - break; + return 0; default: - printf( "No Handler for Custom Action %i\n", x ); + printf( "ERROR! [MACRO.SLX] - No Handler for Custom Action %i\n", x ); + return 0; } - - if( x == IDENTIFIER ) - { - yylval_ptr->string = hb_strdup( sWordAsString ); - aiHold[ (*ptr_iHold)++ ] = x; - x = 0; - } - - return x; } -void * hb_compFlexNew( HB_MACRO_PTR pMacro ) +void * hb_compFlexNew( HB_MACRO_PTR pNewMacro ) { - HB_TRACE(HB_TR_DEBUG, ("hb_compFlexNew(%s, %i)", pMacro->string, pMacro->length)); + HB_TRACE(HB_TR_DEBUG, ("hb_compFlexNew(%s, %i)", pNewMacro->string, pNewMacro->length)); + pYYLVAL = NULL; + pMacro = pNewMacro; + + DEBUG_INFO( printf( "*** New Macro: %s\n", pMacro->string ) ); return yy_bytes_buffer( pMacro->string, pMacro->length ); } diff --git a/harbour/tests/testdecl.prg b/harbour/tests/testdecl.prg index 6b8a9e208c..3a6e366023 100644 --- a/harbour/tests/testdecl.prg +++ b/harbour/tests/testdecl.prg @@ -37,7 +37,7 @@ INIT Function Main() DECLARE aVar[2] DECLARE Var3 := 'Var9', Var4, aVar5[1] DECLARE Var6, Var7:=7, aVar8[8] - DECLARE Var9 AS STRING + DECLARE Var9 DECLARE &var3 DECLARE &Var3. DECLARE &Var3. ; DECLARE &Var3.&Var3