* harbour/include/hbapi.h
* harbour/source/common/hbstr.c
* harbour/source/compiler/harbour.l
* harbour/source/macro/macro.l
* harbour/source/macro/macro.slx
* harbour/source/compiler/harbour.slx
* changed parameters in function: hb_compStrToNum() now the string
size is passed explicitly so it can work with strings which does
not have trailing ASCII NUL character.
* harbour/source/macro/macro.y
* indenting
* harbour/include/hbmacro.h
* harbour/source/common/hbstr.c
* harbour/source/macro/macro.l
* harbour/source/macro/macro.y
* added two new functions for macro compiler: hb_macroLexNew() and
hb_macroLexDelete() to clearly separate lexer from grammar parser.
* harbour/source/compiler/harbour.l
* harbour/source/common/hbstr.c
* harbour/source/pp/ppcore.c
* added error generation for wrong e"..." strings and fixed \" quoting
* removed \q quoting
* harbour/source/pp/ppcore.c
* harbour/source/pp/ppgen.c
* added small description in headers
* harbour/common.mak
* harbour/source/pp/Makefile
* harbour/source/pp/pplib.c
+ harbour/source/pp/pplib2.c
* harbour/include/hbextern.ch
+ added auto destructor for allocated PP context, it's not longer
necessary to execute __PP_FREE() so this function was moved from
the standard .prg API to file with backward compatible functions
* changed __PREPROCESS() to __PP_PROCESS()
* moved setting std rules to separate file so now if user uses PP
with only his own rules we are not forcing linking static tables
which are quite huge (over 100kb)
To include stdandard rules in static binaries user should add
to his code:
REQUEST __PP_STDRULES
+ harbour/source/pp/pplib3.c
* old PP functions for backward compatibility:
__PPADDRULE(), __PREPROCESS(), __PP_FREE()
Please note that using this function is not MT safe. They should
work like with old PP code. Using any of this function automatically
forces linking __PP_STDRULES
390 lines
15 KiB
Plaintext
390 lines
15 KiB
Plaintext
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* Harbour Project source code:
|
|
* Compiler MACRO SimpLex rules
|
|
*
|
|
* Copyright 2000 Ron Pinkas <ronpinkas@profit-master.com>
|
|
* 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, or (at your option)
|
|
* any later version.
|
|
*
|
|
* 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 software; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
|
|
*
|
|
* As a special exception, the Harbour Project gives permission for
|
|
* additional uses of the text contained in its release of Harbour.
|
|
*
|
|
* The exception is that, if you link the Harbour libraries 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 Harbour library code into it.
|
|
*
|
|
* This exception does not however invalidate any other reasons why
|
|
* the executable file might be covered by the GNU General Public License.
|
|
*
|
|
* This exception applies only to the code released by the Harbour
|
|
* Project under the name Harbour. If you copy code from other
|
|
* Harbour Project or Free Software Foundation releases into a copy of
|
|
* Harbour, as the General Public License permits, the exception does
|
|
* not apply to the code that you add in this way. To avoid misleading
|
|
* anyone as to the status of such modified files, you must delete
|
|
* this exception notice from them.
|
|
*
|
|
* If you write modifications of your own for Harbour, it is your choice
|
|
* whether to permit this exception to apply to your modifications.
|
|
* If you do not wish that, delete this exception notice.
|
|
*
|
|
*/
|
|
|
|
//#define SHOW_LEX_TOKENS
|
|
//#define DEBUG_LEX
|
|
|
|
#ifdef DEBUG_LEX
|
|
#undef DEBUG_INFO
|
|
#define DEBUG_INFO(x) x
|
|
#endif
|
|
|
|
#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_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 YYLEX_PARAM pMacro
|
|
|
|
#undef YY_INPUT
|
|
#define YY_INPUT( buf, result, max_size ) result = 0;
|
|
|
|
#undef STREAM_EXCEPTION
|
|
#define STREAM_EXCEPTION( sPair, cChar ) \
|
|
hb_macroError( EG_SYNTAX, YYLEX_PARAM );
|
|
|
|
#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 )
|
|
|
|
static HB_MACRO_PTR pMacro;
|
|
static YYSTYPE *pYYLVAL;
|
|
|
|
static int hb_macro_SLX_CustomAction( int x, int aiHold[], int *ptr_iHold, char *sToken );
|
|
static int hb_macro_SLX_ElementToken( char* szToken, unsigned int iTokenLen );
|
|
static int hb_comp_SLX_Str2Num( char* szNum, HB_LONG * lVal, double * dVal, int * iDec, int * iWidth );
|
|
|
|
void * yy_bytes_buffer( char * pBuffer, int iBufSize );
|
|
|
|
/* ----------------------------------------------------- Language Definitions. ---------------------------------------------------- */
|
|
|
|
/* Delimiters. */
|
|
ACCEPT_TOKEN_AND_DROP_DELIMITER_IF_ONE_OF_THESE( " \t" );
|
|
|
|
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 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(TRUE ) AS_PAIR_TOKEN(HB_LIT_ACT)
|
|
};
|
|
|
|
START_NEW_LINE_IF_ONE_OF_THESE( "\n;" );
|
|
|
|
#define HB_SELF LEX_CUSTOM_ACTION - 2
|
|
|
|
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 + 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( 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 )
|
|
};
|
|
|
|
/* Intermediate Words when ambigious. */
|
|
#define QSELF 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( "FIELD" ) AS_TOKEN( FIELD ),
|
|
LEX_WORD( "IF" ) AS_TOKEN( IIF ),
|
|
LEX_WORD( "IIF" ) AS_TOKEN( IIF ),
|
|
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 )
|
|
};
|
|
|
|
/* When reservered words are used as Identifier. */
|
|
#define HB_IDENTIFIER LEX_CUSTOM_ACTION - 3
|
|
#define HB_MACRO_ERR LEX_CUSTOM_ACTION - 4
|
|
|
|
LANGUAGE_RULES_ARE {
|
|
/* 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( '&' , '\'' , 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) ( ( ( 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", pYYLVAL->string ); \
|
|
else if( x == LITERAL ) \
|
|
printf( " LITERAL = \"%s\"\n", pYYLVAL->string ); \
|
|
else if( x == MACROVAR ) \
|
|
printf( " MACROVAR = \"%s\"\n", pYYLVAL->string ); \
|
|
else if( x == MACROTEXT ) \
|
|
printf( " MACROTEXT = \"%s\"\n", pYYLVAL->string ); \
|
|
else if( x == NUM_LONG ) \
|
|
printf( " INTEGER = %il\n", pYYLVAL->valLong.lNumber ); \
|
|
else if( x == NUM_DOUBLE ) \
|
|
printf( " DOUBLE = %f\n", pYYLVAL->valDouble.dNumber ); \
|
|
else if( x < 256 ) \
|
|
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 );
|
|
#endif
|
|
|
|
#undef ELEMENT_TOKEN
|
|
#define ELEMENT_TOKEN(x,y) hb_macro_SLX_ElementToken(x,y)
|
|
|
|
#undef CUSTOM_ACTION
|
|
#define CUSTOM_ACTION(x) x = hb_macro_SLX_CustomAction( x, aiHold, &iHold, (char*) sToken )
|
|
|
|
#undef LEX_USER_SETUP
|
|
#define LEX_USER_SETUP() if( pYYLVAL == NULL ) pYYLVAL = yylval_ptr;
|
|
|
|
static int hb_macro_SLX_ElementToken( char* szToken, unsigned int iTokenLen )
|
|
{
|
|
extern char *yytext;
|
|
extern int yyleng;
|
|
|
|
char *tmpPtr;
|
|
int iRet;
|
|
|
|
yytext = szToken;
|
|
yyleng = iTokenLen;
|
|
|
|
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;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* ConverNumber */
|
|
|
|
HB_LONG lNumber;
|
|
double dNumber;
|
|
int iDec, iWidth;
|
|
|
|
iRet = hb_comp_SLX_Str2Num( yytext, &lNumber, &dNumber, &iDec, &iWidth );
|
|
|
|
if ( iRet == NUM_DOUBLE )
|
|
{
|
|
pYYLVAL->valDouble.dNumber = dNumber;
|
|
pYYLVAL->valDouble.bDec = iDec;
|
|
pYYLVAL->valDouble.bWidth = iWidth;
|
|
pYYLVAL->valDouble.szValue = yytext;
|
|
}
|
|
else
|
|
{
|
|
pYYLVAL->valLong.lNumber = lNumber;
|
|
pYYLVAL->valLong.szValue = yytext;
|
|
}
|
|
}
|
|
|
|
DEBUG_INFO( printf( "Element \"%s\" is %i\n", sToken, iRet ) );
|
|
return iRet + DONT_REDUCE;
|
|
}
|
|
|
|
static int hb_comp_SLX_Str2Num( char* szNum, HB_LONG * plVal, double * pdVal, int * piDec, int * piWidth )
|
|
{
|
|
BOOL fDbl;
|
|
|
|
fDbl = hb_compStrToNum( szNum, strlen( szNum ), plVal, pdVal, piDec, piWidth );
|
|
return fDbl ? NUM_DOUBLE : NUM_LONG;
|
|
}
|
|
|
|
int hb_macro_SLX_CustomAction( int x, int aiHold[], int *ptr_iHold, char *sToken )
|
|
{
|
|
switch ( x )
|
|
{
|
|
case HB_LIT_ACT :
|
|
pYYLVAL->string = hb_strdup( sPair );
|
|
return LITERAL + DONT_REDUCE ;
|
|
|
|
case HB_IDENTIFIER :
|
|
pYYLVAL->string = hb_strdup( sToken );
|
|
return IDENTIFIER + DONT_REDUCE;
|
|
|
|
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 );
|
|
return 0;
|
|
|
|
default:
|
|
printf( "ERROR! [MACRO.SLX] - No Handler for Custom Action %i\n", x );
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void * hb_compFlexNew( HB_MACRO_PTR pNewMacro )
|
|
{
|
|
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 );
|
|
}
|
|
|
|
void hb_compFlexDelete( void * pBuffer )
|
|
{
|
|
HB_SYMBOL_UNUSED( pBuffer );
|
|
}
|