* include/hbexprb.c
* src/compiler/complex.c
* src/vm/memvars.c
* src/vm/strapi.c
! fixed compiler warnings emitted by GCC 7+
1458 lines
52 KiB
C
1458 lines
52 KiB
C
/*
|
|
* Compiler lexer which converts PP tokens to the ones which
|
|
* grammar parser generated by bison can understand
|
|
*
|
|
* Copyright 2006 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
|
|
*
|
|
* 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 program; see the file LICENSE.txt. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/).
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#include "hbcomp.h"
|
|
#include "hbpp.h"
|
|
#include "hbdate.h"
|
|
#include "harboury.h"
|
|
|
|
#define HB_PP_LEX_SELF(t) ( HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_SEND && \
|
|
(t)->pNext && (t)->pNext->spaces == 0 && \
|
|
HB_PP_TOKEN_TYPE((t)->pNext->type) == HB_PP_TOKEN_SEND )
|
|
|
|
#define HB_PP_LEX_NEEDLEFT(t) ( HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_ASSIGN || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_PLUSEQ || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_MINUSEQ || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_MULTEQ || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_DIVEQ || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_MODEQ || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_EXPEQ || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_EQUAL || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_EQ || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_ALIAS || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_MULT || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_DIV || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_MOD || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_POWER || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_IN || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_AND || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_OR || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_PIPE || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_RIGHT_PB || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_RIGHT_SB || \
|
|
HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_RIGHT_CB || \
|
|
( HB_PP_TOKEN_TYPE((t)->type) == HB_PP_TOKEN_SEND && \
|
|
(t)->spaces == 0 && ! HB_PP_LEX_SELF(t) ) )
|
|
|
|
#define LOOKUP 0
|
|
#define OPERATOR -2
|
|
#define LSEPARATOR -3
|
|
#define RSEPARATOR -4
|
|
#define LINDEX -5
|
|
#define RINDEX -6
|
|
#define LARRAY -7
|
|
#define RARRAY -8
|
|
#define AS_TYPE -9
|
|
#define DECLARE_TYPE -10
|
|
|
|
|
|
typedef struct
|
|
{
|
|
const char * value; /* keyword name */
|
|
HB_SIZE minlen; /* minimal length */
|
|
HB_SIZE maxlen; /* maximal length */
|
|
int type; /* terminal symbol code */
|
|
}
|
|
HB_LEX_KEY;
|
|
|
|
static const HB_LEX_KEY s_keytable[] =
|
|
{
|
|
{ "ALWAYS", 4, 6, ALWAYS },
|
|
{ "ANNOUNCE", 4, 8, ANNOUNCE },
|
|
{ "AS", 2, 2, AS_TYPE },
|
|
{ "BEGIN", 4, 5, BEGINSEQ },
|
|
{ "BREAK", 4, 5, BREAK },
|
|
{ "CASE", 4, 4, CASE },
|
|
{ "DECLARE", 4, 7, DECLARE },
|
|
{ "DESCEND", 7, 7, DESCEND },
|
|
{ "DO", 2, 2, DO },
|
|
{ "DYNAMIC", 7, 7, DYNAMIC },
|
|
{ "ELSE", 4, 4, ELSE },
|
|
{ "ELSEIF", 5, 6, ELSEIF },
|
|
{ "END", 3, 3, END },
|
|
{ "ENDCASE", 4, 7, ENDCASE },
|
|
{ "ENDDO", 4, 5, ENDDO },
|
|
{ "ENDIF", 4, 5, ENDIF },
|
|
{ "ENDSEQUENCE", 6, 11, ENDSEQ },
|
|
{ "ENDSWITCH", 5, 9, ENDSWITCH },
|
|
{ "ENDWITH", 4, 7, ENDWITH },
|
|
{ "EXIT", 4, 4, EXIT },
|
|
{ "EXTERNAL", 4, 8, EXTERN },
|
|
{ "FIELD", 4, 5, FIELD },
|
|
{ "FOR", 3, 3, FOR },
|
|
{ "FUNCTION", 4, 8, FUNCTION },
|
|
{ "IF", 2, 2, IF },
|
|
{ "IIF", 3, 3, IIF },
|
|
{ "IN", 2, 2, IN },
|
|
{ "INIT", 4, 4, INIT },
|
|
{ "LOCAL", 4, 5, LOCAL },
|
|
{ "LOOP", 4, 4, LOOP },
|
|
{ "MEMVAR", 4, 6, MEMVAR },
|
|
{ "NEXT", 4, 4, NEXT },
|
|
{ "NIL", 3, 3, NIL },
|
|
{ "OPTIONAL", 4, 8, OPTIONAL },
|
|
{ "OTHERWISE", 4, 9, OTHERWISE },
|
|
{ "PARAMETERS", 4, 10, PARAMETERS },
|
|
{ "PRIVATE", 4, 7, PRIVATE },
|
|
{ "PROCEDURE", 4, 9, PROCEDURE },
|
|
{ "PUBLIC", 4, 6, PUBLIC },
|
|
{ "QSELF", 5, 5, SELF },
|
|
{ "RECOVER", 4, 7, RECOVER },
|
|
{ "RETURN", 4, 6, RETURN },
|
|
{ "STATIC", 4, 6, STATIC },
|
|
{ "STEP", 4, 4, STEP },
|
|
{ "SWITCH", 4, 6, DOSWITCH },
|
|
{ "THREAD", 4, 6, THREAD_STATIC },
|
|
{ "TO", 2, 2, TO },
|
|
{ "WHILE", 4, 5, WHILE },
|
|
{ "WITH", 4, 4, WITH },
|
|
{ "_FIELD", 4, 6, FIELD },
|
|
{ "_HB_CLASS", 9, 9, DECLARE_CLASS },
|
|
{ "_HB_MEMBER", 10, 10, DECLARE_MEMBER },
|
|
{ "_PROCREQ_", 9, 9, PROCREQ }
|
|
};
|
|
|
|
#define _AS_ARRAY 1
|
|
#define _AS_BLOCK 2
|
|
#define _AS_CHARACTER 3
|
|
#define _AS_CLASS 4
|
|
#define _AS_DATE 5
|
|
#define _AS_DATETIME 5
|
|
#define _AS_HASH 9
|
|
#define _AS_LOGICAL 6
|
|
#define _AS_NUMERIC 7
|
|
#define _AS_OBJECT 8
|
|
#define _AS_POINTER 9
|
|
#define _AS_SYMBOL 9
|
|
#define _AS_VARIANT 9
|
|
|
|
static const int s_asTypes[] =
|
|
{
|
|
0,
|
|
AS_ARRAY,
|
|
AS_BLOCK,
|
|
AS_CHARACTER,
|
|
AS_CLASS,
|
|
AS_DATE,
|
|
AS_LOGICAL,
|
|
AS_NUMERIC,
|
|
AS_OBJECT,
|
|
AS_VARIANT
|
|
};
|
|
|
|
static const int s_asArrayTypes[] =
|
|
{
|
|
0,
|
|
AS_ARRAY_ARRAY,
|
|
AS_BLOCK_ARRAY,
|
|
AS_CHARACTER_ARRAY,
|
|
AS_CLASS_ARRAY,
|
|
AS_DATE_ARRAY,
|
|
AS_LOGICAL_ARRAY,
|
|
AS_NUMERIC_ARRAY,
|
|
AS_OBJECT_ARRAY,
|
|
AS_ARRAY
|
|
};
|
|
|
|
static const HB_LEX_KEY s_typetable[] =
|
|
{
|
|
{ "ANYTYPE", 4, 7, _AS_VARIANT },
|
|
{ "ARRAY", 4, 5, _AS_ARRAY },
|
|
{ "BLOCK", 4, 5, _AS_BLOCK },
|
|
{ "CHARACTER", 4, 9, _AS_CHARACTER },
|
|
{ "CLASS", 4, 5, _AS_CLASS },
|
|
{ "CODEBLOCK", 4, 9, _AS_BLOCK },
|
|
{ "DATE", 4, 4, _AS_DATE },
|
|
{ "DATETIME", 5, 8, _AS_DATETIME },
|
|
{ "HASH", 4, 4, _AS_HASH },
|
|
{ "LOGICAL", 4, 7, _AS_LOGICAL },
|
|
{ "NUMERIC", 4, 7, _AS_NUMERIC },
|
|
{ "OBJECT", 4, 6, _AS_OBJECT },
|
|
{ "POINTER", 4, 7, _AS_POINTER },
|
|
{ "STRING", 4, 6, _AS_CHARACTER },
|
|
{ "SYMBOL", 4, 6, _AS_SYMBOL },
|
|
{ "TIMESTAMP", 4, 8, _AS_DATETIME },
|
|
{ "USUAL", 4, 5, _AS_VARIANT }
|
|
};
|
|
|
|
static int hb_comp_asType( PHB_PP_TOKEN pToken, HB_BOOL fArray )
|
|
{
|
|
if( pToken && HB_PP_TOKEN_TYPE( pToken->type ) == HB_PP_TOKEN_KEYWORD )
|
|
{
|
|
const HB_LEX_KEY * pKey = s_typetable;
|
|
int i = HB_SIZEOFARRAY( s_typetable );
|
|
|
|
hb_pp_tokenUpper( pToken );
|
|
do
|
|
{
|
|
if( pKey->minlen <= pToken->len && pToken->len <= pKey->maxlen &&
|
|
memcmp( pKey->value, pToken->value, pToken->len ) == 0 )
|
|
return ( fArray ? s_asArrayTypes : s_asTypes )[ pKey->type ];
|
|
++pKey;
|
|
}
|
|
while( --i );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int hb_comp_keywordType( PHB_PP_TOKEN pToken )
|
|
{
|
|
const HB_LEX_KEY * pKey = s_keytable;
|
|
int i = HB_SIZEOFARRAY( s_keytable );
|
|
|
|
do
|
|
{
|
|
if( pKey->minlen <= pToken->len && pToken->len <= pKey->maxlen &&
|
|
memcmp( pKey->value, pToken->value, pToken->len ) == 0 )
|
|
{
|
|
if( HB_PP_TOKEN_ALLOC( pToken->type ) && pToken->len == pKey->maxlen )
|
|
{
|
|
hb_xfree( HB_UNCONST( pToken->value ) );
|
|
pToken->value = pKey->value;
|
|
pToken->type |= HB_PP_TOKEN_STATIC;
|
|
}
|
|
return pKey->type;
|
|
}
|
|
++pKey;
|
|
}
|
|
while( --i );
|
|
return IDENTIFIER;
|
|
}
|
|
|
|
static const char * hb_comp_tokenIdentifer( HB_COMP_DECL, PHB_PP_TOKEN pToken )
|
|
{
|
|
if( HB_PP_TOKEN_ALLOC( pToken->type ) )
|
|
{
|
|
pToken->value = hb_compIdentifierNew( HB_COMP_PARAM, pToken->value, HB_IDENT_FREE );
|
|
pToken->type |= HB_PP_TOKEN_STATIC;
|
|
}
|
|
|
|
return pToken->value;
|
|
}
|
|
|
|
static const char * hb_comp_tokenString( YYSTYPE * yylval_ptr, HB_COMP_DECL, PHB_PP_TOKEN pToken )
|
|
{
|
|
yylval_ptr->valChar.length = pToken->len;
|
|
yylval_ptr->valChar.string = ( char * ) HB_UNCONST( pToken->value );
|
|
yylval_ptr->valChar.dealloc = HB_FALSE;
|
|
if( HB_PP_TOKEN_ALLOC( pToken->type ) )
|
|
{
|
|
yylval_ptr->valChar.dealloc = pToken->len != strlen( pToken->value );
|
|
pToken->value = hb_compIdentifierNew( HB_COMP_PARAM, pToken->value,
|
|
yylval_ptr->valChar.dealloc ? HB_IDENT_COPY : HB_IDENT_FREE );
|
|
if( ! yylval_ptr->valChar.dealloc )
|
|
yylval_ptr->valChar.string = ( char * ) HB_UNCONST( pToken->value );
|
|
pToken->type |= HB_PP_TOKEN_STATIC;
|
|
}
|
|
return pToken->value;
|
|
}
|
|
|
|
#if defined( HB_COMPAT_FOXPRO ) || 1
|
|
static HB_BOOL hb_comp_timeDecode( PHB_PP_TOKEN pTime, long * plTime )
|
|
{
|
|
HB_MAXINT lHour, lMinute, lMilliSec;
|
|
double dNumber;
|
|
int iDec, iWidth;
|
|
|
|
if( ! pTime || HB_PP_TOKEN_TYPE( pTime->type ) != HB_PP_TOKEN_NUMBER ||
|
|
hb_compStrToNum( pTime->value, pTime->len, &lHour, &dNumber,
|
|
&iDec, &iWidth ) || lHour < 0 || lHour >= 24 )
|
|
return HB_FALSE;
|
|
|
|
pTime = pTime->pNext;
|
|
if( ! pTime || HB_PP_TOKEN_TYPE( pTime->type ) != HB_PP_TOKEN_SEND )
|
|
return HB_FALSE;
|
|
|
|
pTime = pTime->pNext;
|
|
if( ! pTime || HB_PP_TOKEN_TYPE( pTime->type ) != HB_PP_TOKEN_NUMBER ||
|
|
hb_compStrToNum( pTime->value, pTime->len, &lMinute, &dNumber,
|
|
&iDec, &iWidth ) || lMinute < 0 || lMinute >= 60 )
|
|
return HB_FALSE;
|
|
|
|
pTime = pTime->pNext;
|
|
if( ! pTime )
|
|
return HB_FALSE;
|
|
|
|
if( HB_PP_TOKEN_TYPE( pTime->type ) == HB_PP_TOKEN_SEND )
|
|
{
|
|
pTime = pTime->pNext;
|
|
if( ! pTime || HB_PP_TOKEN_TYPE( pTime->type ) != HB_PP_TOKEN_NUMBER )
|
|
return HB_FALSE;
|
|
|
|
if( hb_compStrToNum( pTime->value, pTime->len, &lMilliSec, &dNumber,
|
|
&iDec, &iWidth ) )
|
|
{
|
|
if( dNumber < 0.0 || dNumber >= 60.0 )
|
|
return HB_FALSE;
|
|
lMilliSec = ( HB_MAXINT ) ( dNumber * 1000 + 0.05 / HB_MILLISECS_PER_DAY );
|
|
if( lMilliSec == 60000 )
|
|
--lMilliSec;
|
|
}
|
|
else if( lMilliSec < 0 || lMilliSec >= 60 )
|
|
return HB_FALSE;
|
|
else
|
|
lMilliSec *= 1000;
|
|
pTime = pTime->pNext;
|
|
}
|
|
else
|
|
lMilliSec = 0;
|
|
|
|
if( HB_PP_TOKEN_TYPE( pTime->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
lHour > 0 && lHour <= 12 )
|
|
{
|
|
if( ( pTime->len == 1 &&
|
|
( pTime->value[ 0 ] == 'A' || pTime->value[ 0 ] == 'a' ) ) ||
|
|
( pTime->len == 2 && hb_stricmp( pTime->value, "AM" ) == 0 ) )
|
|
{
|
|
if( lHour == 12 )
|
|
lHour = 0;
|
|
pTime = pTime->pNext;
|
|
}
|
|
else if( ( pTime->len == 1 &&
|
|
( pTime->value[ 0 ] == 'P' || pTime->value[ 0 ] == 'p' ) ) ||
|
|
( pTime->len == 2 && hb_stricmp( pTime->value, "PM" ) == 0 ) )
|
|
{
|
|
if( lHour < 12 )
|
|
lHour += 12;
|
|
pTime = pTime->pNext;
|
|
}
|
|
}
|
|
|
|
if( ! pTime || HB_PP_TOKEN_TYPE( pTime->type ) != HB_PP_TOKEN_RIGHT_CB )
|
|
return HB_FALSE;
|
|
|
|
*plTime = ( long ) ( ( lHour * 60 + lMinute ) * 60000 + lMilliSec );
|
|
|
|
return HB_TRUE;
|
|
}
|
|
|
|
static int hb_comp_dayTimeDecode( PHB_COMP_LEX pLex, PHB_PP_TOKEN pToken,
|
|
YYSTYPE * yylval_ptr )
|
|
{
|
|
/* TODO: decode datetime in VFP strict date form:
|
|
* {^YYYY/MM/DD[,][HH[:MM[:SS][.CCC]][A|P]]}
|
|
* VFP accepts slash, dot or hyphen as date delimiter and
|
|
* 12 or 24-hour formatted time,
|
|
* If only hours are included in time part then comma have to
|
|
* be used to separate date and time parts or it's necessary
|
|
* to follow the hours with a colon.
|
|
* { ^ <YEAR> <sep:/.-> <MONTH> <sep:/.-> <DAY> [[<sep2:,>]
|
|
* [ <HOUR> [ : <MIN> [ : <SEC> [ . <FRAQ> ] ] ] [AM|PP] ] }
|
|
*/
|
|
|
|
PHB_PP_TOKEN pYear, pMonth, pDay, pTime = NULL;
|
|
HB_MAXINT lYear = 0, lMonth = 0, lDay = 0;
|
|
long lDate = 0, lTime = 0;
|
|
double dNumber;
|
|
int iDec, iWidth, iType = 0;
|
|
|
|
pYear = pToken->pNext->pNext;
|
|
if( pYear && HB_PP_TOKEN_TYPE( pYear->type ) == HB_PP_TOKEN_NUMBER &&
|
|
pYear->pNext )
|
|
{
|
|
if( ( HB_PP_TOKEN_TYPE( pYear->pNext->type ) == HB_PP_TOKEN_DIV ||
|
|
HB_PP_TOKEN_TYPE( pYear->pNext->type ) == HB_PP_TOKEN_MINUS ) &&
|
|
! hb_compStrToNum( pYear->value, pYear->len, &lYear, &dNumber,
|
|
&iDec, &iWidth ) )
|
|
{
|
|
pMonth = pYear->pNext->pNext;
|
|
if( pMonth && HB_PP_TOKEN_TYPE( pMonth->type ) == HB_PP_TOKEN_NUMBER &&
|
|
pMonth->pNext && HB_PP_TOKEN_TYPE( pYear->pNext->type ) ==
|
|
HB_PP_TOKEN_TYPE( pMonth->pNext->type ) &&
|
|
! hb_compStrToNum( pMonth->value, pMonth->len, &lMonth, &dNumber,
|
|
&iDec, &iWidth ) )
|
|
{
|
|
pDay = pMonth->pNext->pNext;
|
|
if( pDay && HB_PP_TOKEN_TYPE( pDay->type ) == HB_PP_TOKEN_NUMBER &&
|
|
pDay->pNext &&
|
|
! hb_compStrToNum( pDay->value, pDay->len, &lDay, &dNumber,
|
|
&iDec, &iWidth ) )
|
|
{
|
|
pTime = pDay->pNext;
|
|
}
|
|
}
|
|
}
|
|
else if( HB_PP_TOKEN_TYPE( pYear->pNext->type ) == HB_PP_TOKEN_NUMBER &&
|
|
pYear->pNext->pNext )
|
|
{
|
|
if( hb_compStrToNum( pYear->value, pYear->len, &lYear, &dNumber,
|
|
&iDec, &iWidth ) )
|
|
{
|
|
if( iDec == 2 )
|
|
{
|
|
lYear = ( HB_MAXINT ) dNumber;
|
|
lMonth = ( HB_MAXINT ) ( dNumber * 100 + 0.1 ) % 100;
|
|
pDay = pYear->pNext;
|
|
if( hb_compStrToNum( pDay->value, pDay->len, &lDay, &dNumber,
|
|
&iDec, &iWidth ) )
|
|
{
|
|
if( iDec == 2 )
|
|
{
|
|
lDay = ( HB_MAXINT ) ( dNumber * 100 + 0.1 );
|
|
pTime = pDay->pNext;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( pTime )
|
|
{
|
|
lDate = hb_dateEncode( ( int ) lYear, ( int ) lMonth, ( int ) lDay );
|
|
if( lDate != 0 || ( lYear == 0 && lMonth == 0 && lDay == 0 ) )
|
|
{
|
|
iType = NUM_DATE;
|
|
if( HB_PP_TOKEN_TYPE( pTime->type ) != HB_PP_TOKEN_RIGHT_CB )
|
|
{
|
|
if( HB_PP_TOKEN_TYPE( pTime->type ) == HB_PP_TOKEN_COMMA )
|
|
pTime = pTime->pNext;
|
|
iType = hb_comp_timeDecode( pTime, &lTime ) ? TIMESTAMP : 0;
|
|
}
|
|
}
|
|
}
|
|
else if( hb_comp_timeDecode( pYear, &lTime ) )
|
|
iType = TIMESTAMP;
|
|
}
|
|
|
|
if( iType )
|
|
{
|
|
while( HB_PP_TOKEN_TYPE( pToken->type ) != HB_PP_TOKEN_RIGHT_CB )
|
|
pToken = hb_pp_tokenGet( pLex->pPP );
|
|
if( iType == TIMESTAMP )
|
|
{
|
|
yylval_ptr->valTimeStamp.date = lDate;
|
|
yylval_ptr->valTimeStamp.time = lTime;
|
|
}
|
|
else
|
|
yylval_ptr->valLong.lNumber = lDate;
|
|
|
|
pLex->iState = LITERAL;
|
|
}
|
|
|
|
return iType;
|
|
}
|
|
#endif
|
|
|
|
static int hb_comp_funcStart( HB_COMP_DECL, YYSTYPE * yylval_ptr )
|
|
{
|
|
HB_COMP_PARAM->pLex->iClose = HB_COMP_PARAM->functions.pLast->wIfCounter +
|
|
HB_COMP_PARAM->functions.pLast->wForCounter +
|
|
HB_COMP_PARAM->functions.pLast->wWhileCounter +
|
|
HB_COMP_PARAM->functions.pLast->wCaseCounter +
|
|
HB_COMP_PARAM->functions.pLast->wSwitchCounter +
|
|
HB_COMP_PARAM->functions.pLast->wWithObjectCnt +
|
|
HB_COMP_PARAM->functions.pLast->wSeqBegCounter +
|
|
( HB_COMP_PARAM->functions.pLast->funFlags & HB_FUNF_EXTBLOCK ? 1 : 0 );
|
|
if( HB_COMP_PARAM->pLex->iClose > 0 )
|
|
{
|
|
HB_COMP_PARAM->pLex->iClose <<= 1;
|
|
HB_COMP_PARAM->functions.pLast->wIfCounter =
|
|
HB_COMP_PARAM->functions.pLast->wForCounter =
|
|
HB_COMP_PARAM->functions.pLast->wWhileCounter =
|
|
HB_COMP_PARAM->functions.pLast->wCaseCounter =
|
|
HB_COMP_PARAM->functions.pLast->wSwitchCounter =
|
|
HB_COMP_PARAM->functions.pLast->wWithObjectCnt =
|
|
HB_COMP_PARAM->functions.pLast->wSeqBegCounter = 0;
|
|
HB_COMP_PARAM->functions.pLast->wSeqCounter = 0;
|
|
return ENDERR;
|
|
}
|
|
yylval_ptr->iNumber = HB_COMP_PARAM->pLex->iScope;
|
|
return HB_COMP_PARAM->pLex->iState;
|
|
}
|
|
|
|
extern int hb_comp_yylex( YYSTYPE * yylval_ptr, HB_COMP_DECL );
|
|
|
|
int hb_comp_yylex( YYSTYPE * yylval_ptr, HB_COMP_DECL )
|
|
{
|
|
PHB_COMP_LEX pLex = HB_COMP_PARAM->pLex;
|
|
PHB_PP_TOKEN pToken;
|
|
|
|
if( ! HB_COMP_PARAM->fExit )
|
|
{
|
|
if( pLex->iClose < 0 )
|
|
{
|
|
hb_comp_funcStart( HB_COMP_PARAM, yylval_ptr );
|
|
if( pLex->iClose > 0 )
|
|
return ENDERR;
|
|
}
|
|
else if( pLex->iClose > 0 )
|
|
{
|
|
if( --pLex->iClose == 0 )
|
|
{
|
|
yylval_ptr->iNumber = pLex->iScope;
|
|
return pLex->iState;
|
|
}
|
|
if( pLex->iClose == 1 && HB_COMP_PARAM->functions.pLast->funFlags & HB_FUNF_EXTBLOCK )
|
|
{
|
|
pLex->iClose = -1;
|
|
return ';';
|
|
}
|
|
return ( pLex->iClose & 1 ) ? ';' : ( int ) ENDERR;
|
|
}
|
|
}
|
|
|
|
pToken = hb_pp_tokenGet( pLex->pPP );
|
|
|
|
if( pLex->fEol )
|
|
{
|
|
pLex->fEol = HB_FALSE;
|
|
HB_COMP_PARAM->currLine++;
|
|
}
|
|
|
|
if( ! pToken || HB_COMP_PARAM->fExit )
|
|
{
|
|
if( ! HB_COMP_PARAM->fExit )
|
|
{
|
|
hb_comp_funcStart( HB_COMP_PARAM, yylval_ptr );
|
|
if( pLex->iClose > 0 )
|
|
{
|
|
HB_COMP_PARAM->pLex->iScope = HB_COMP_PARAM->pLex->iState = 0;
|
|
return ENDERR;
|
|
}
|
|
}
|
|
pLex->lasttok = NULL;
|
|
return 0;
|
|
}
|
|
|
|
pLex->lasttok = pToken->value;
|
|
|
|
switch( HB_PP_TOKEN_TYPE( pToken->type ) )
|
|
{
|
|
case HB_PP_TOKEN_NUMBER:
|
|
{
|
|
HB_MAXINT lNumber;
|
|
double dNumber;
|
|
int iDec, iWidth;
|
|
|
|
pLex->iState = LITERAL;
|
|
if( hb_compStrToNum( pToken->value, pToken->len, &lNumber, &dNumber, &iDec, &iWidth ) )
|
|
{
|
|
yylval_ptr->valDouble.dNumber = dNumber;
|
|
yylval_ptr->valDouble.bDec = ( HB_UCHAR ) iDec;
|
|
yylval_ptr->valDouble.bWidth = ( HB_UCHAR ) iWidth;
|
|
return NUM_DOUBLE;
|
|
}
|
|
else
|
|
{
|
|
yylval_ptr->valLong.lNumber = lNumber;
|
|
yylval_ptr->valLong.bWidth = ( HB_UCHAR ) iWidth;
|
|
return NUM_LONG;
|
|
}
|
|
}
|
|
case HB_PP_TOKEN_DATE:
|
|
{
|
|
int iYear, iMonth, iDay;
|
|
|
|
pLex->iState = LITERAL;
|
|
if( pToken->value[ 0 ] == '0' &&
|
|
( pToken->value[ 1 ] == 'D' || pToken->value[ 1 ] == 'd' ) )
|
|
{
|
|
if( pToken->len == 10 )
|
|
{
|
|
hb_dateStrGet( pToken->value + 2, &iYear, &iMonth, &iDay );
|
|
}
|
|
else
|
|
{
|
|
iYear = iMonth = iDay = 0;
|
|
if( pToken->len != 3 || pToken->value[ 2 ] != '0' )
|
|
iYear = -1;
|
|
}
|
|
}
|
|
else if( ! hb_timeStampStrGet( pToken->value, &iYear, &iMonth, &iDay, NULL, NULL, NULL, NULL ) )
|
|
iYear = -1;
|
|
yylval_ptr->valLong.lNumber = hb_dateEncode( iYear, iMonth, iDay );
|
|
if( yylval_ptr->valLong.lNumber == 0 &&
|
|
( iYear != 0 || iMonth != 0 || iDay != 0 ) )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_INVALID_DATE, pToken->value, NULL );
|
|
}
|
|
return NUM_DATE;
|
|
}
|
|
case HB_PP_TOKEN_TIMESTAMP:
|
|
pLex->iState = LITERAL;
|
|
if( ! hb_timeStampStrGetDT( pToken->value,
|
|
&yylval_ptr->valTimeStamp.date,
|
|
&yylval_ptr->valTimeStamp.time ) )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_INVALID_TIMESTAMP, pToken->value, NULL );
|
|
}
|
|
return TIMESTAMP;
|
|
|
|
case HB_PP_TOKEN_STRING:
|
|
pLex->iState = LITERAL;
|
|
pLex->lasttok = hb_comp_tokenString( yylval_ptr, HB_COMP_PARAM, pToken );
|
|
return LITERAL;
|
|
|
|
case HB_PP_TOKEN_LOGICAL:
|
|
pLex->iState = LITERAL;
|
|
return pToken->value[ 1 ] == 'T' ? TRUEVALUE : FALSEVALUE;
|
|
|
|
case HB_PP_TOKEN_MACROVAR:
|
|
pLex->iState = MACROVAR;
|
|
hb_pp_tokenUpper( pToken );
|
|
pLex->lasttok = yylval_ptr->string =
|
|
hb_comp_tokenIdentifer( HB_COMP_PARAM, pToken );
|
|
return MACROVAR;
|
|
|
|
case HB_PP_TOKEN_MACROTEXT:
|
|
pLex->iState = MACROTEXT;
|
|
hb_pp_tokenUpper( pToken );
|
|
pLex->lasttok = yylval_ptr->string =
|
|
hb_comp_tokenIdentifer( HB_COMP_PARAM, pToken );
|
|
return MACROTEXT;
|
|
|
|
case HB_PP_TOKEN_LEFT_SB:
|
|
switch( pLex->iState )
|
|
{
|
|
case OPERATOR:
|
|
case LSEPARATOR:
|
|
case LARRAY:
|
|
case IF:
|
|
case ELSEIF:
|
|
case CASE:
|
|
case BREAK:
|
|
case RETURN:
|
|
case IN:
|
|
case WITH:
|
|
case WHILE:
|
|
case DOSWITCH:
|
|
case WITHOBJECT:
|
|
pLex->iState = LITERAL;
|
|
hb_pp_tokenToString( pLex->pPP, pToken );
|
|
pLex->lasttok = hb_comp_tokenString( yylval_ptr, HB_COMP_PARAM,
|
|
pToken );
|
|
return LITERAL;
|
|
|
|
default:
|
|
pLex->iState = LINDEX;
|
|
return '[';
|
|
}
|
|
|
|
case HB_PP_TOKEN_RIGHT_SB:
|
|
pLex->iState = RINDEX;
|
|
return ']';
|
|
|
|
case HB_PP_TOKEN_LEFT_CB:
|
|
if( pToken->pNext )
|
|
{
|
|
if( HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_PIPE )
|
|
{
|
|
yylval_ptr->asCodeblock.string = hb_strdup(
|
|
hb_pp_tokenBlockString( pLex->pPP, pToken,
|
|
&yylval_ptr->asCodeblock.flags,
|
|
&yylval_ptr->asCodeblock.length ) );
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
return CBSTART;
|
|
}
|
|
#if defined( HB_COMPAT_FOXPRO ) || 1
|
|
else if( HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_POWER )
|
|
{
|
|
int iType = hb_comp_dayTimeDecode( pLex, pToken, yylval_ptr );
|
|
if( iType )
|
|
return iType;
|
|
}
|
|
#endif
|
|
}
|
|
pLex->iState = LARRAY;
|
|
return '{';
|
|
|
|
case HB_PP_TOKEN_RIGHT_CB:
|
|
pLex->iState = RARRAY;
|
|
return '}';
|
|
|
|
case HB_PP_TOKEN_LEFT_PB:
|
|
pLex->iState = LSEPARATOR;
|
|
return '(';
|
|
|
|
case HB_PP_TOKEN_RIGHT_PB:
|
|
pLex->iState = RSEPARATOR;
|
|
return ')';
|
|
|
|
case HB_PP_TOKEN_EPSILON:
|
|
pLex->iState = OPERATOR;
|
|
return EPSILON;
|
|
|
|
case HB_PP_TOKEN_HASH:
|
|
case HB_PP_TOKEN_DIRECTIVE:
|
|
if( pLex->iState == LOOKUP && pToken->pNext &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
hb_stricmp( "LINE", pToken->pNext->value ) == 0 )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
return LINE;
|
|
}
|
|
pLex->iState = OPERATOR;
|
|
return NE1;
|
|
|
|
case HB_PP_TOKEN_NE:
|
|
pLex->iState = OPERATOR;
|
|
return NE2;
|
|
|
|
case HB_PP_TOKEN_ASSIGN:
|
|
pLex->iState = OPERATOR;
|
|
return INASSIGN;
|
|
|
|
case HB_PP_TOKEN_EQUAL:
|
|
pLex->iState = OPERATOR;
|
|
return EQ;
|
|
|
|
case HB_PP_TOKEN_INC:
|
|
pLex->iState = OPERATOR;
|
|
return INC;
|
|
|
|
case HB_PP_TOKEN_DEC:
|
|
pLex->iState = OPERATOR;
|
|
return DEC;
|
|
|
|
case HB_PP_TOKEN_ALIAS:
|
|
pLex->iState = OPERATOR;
|
|
return ALIASOP;
|
|
|
|
case HB_PP_TOKEN_LE:
|
|
pLex->iState = OPERATOR;
|
|
return LE;
|
|
|
|
case HB_PP_TOKEN_GE:
|
|
pLex->iState = OPERATOR;
|
|
return GE;
|
|
|
|
case HB_PP_TOKEN_PLUSEQ:
|
|
pLex->iState = OPERATOR;
|
|
return PLUSEQ;
|
|
|
|
case HB_PP_TOKEN_MINUSEQ:
|
|
pLex->iState = OPERATOR;
|
|
return MINUSEQ;
|
|
|
|
case HB_PP_TOKEN_MULTEQ:
|
|
pLex->iState = OPERATOR;
|
|
return MULTEQ;
|
|
|
|
case HB_PP_TOKEN_DIVEQ:
|
|
pLex->iState = OPERATOR;
|
|
return DIVEQ;
|
|
|
|
case HB_PP_TOKEN_MODEQ:
|
|
pLex->iState = OPERATOR;
|
|
return MODEQ;
|
|
|
|
case HB_PP_TOKEN_EXPEQ:
|
|
pLex->iState = OPERATOR;
|
|
return EXPEQ;
|
|
|
|
case HB_PP_TOKEN_POWER:
|
|
pLex->iState = OPERATOR;
|
|
return POWER;
|
|
|
|
case HB_PP_TOKEN_AND:
|
|
pLex->iState = OPERATOR;
|
|
return AND;
|
|
|
|
case HB_PP_TOKEN_OR:
|
|
pLex->iState = OPERATOR;
|
|
return OR;
|
|
|
|
case HB_PP_TOKEN_NOT:
|
|
pLex->iState = OPERATOR;
|
|
return NOT;
|
|
|
|
case HB_PP_TOKEN_SEND:
|
|
if( HB_PP_LEX_SELF( pToken ) )
|
|
{
|
|
pLex->lasttok = yylval_ptr->string = "SELF";
|
|
pLex->iState = IDENTIFIER;
|
|
return IDENTIFIER;
|
|
}
|
|
pLex->iState = OPERATOR;
|
|
return ( HB_UCHAR ) pToken->value[ 0 ];
|
|
|
|
case HB_PP_TOKEN_EQ:
|
|
if( HB_SUPPORT_HARBOUR && pToken->pNext && pToken->pNext->spaces == 0 &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_GT )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
pLex->iState = OPERATOR;
|
|
return HASHOP;
|
|
}
|
|
/* fallthrough */
|
|
case HB_PP_TOKEN_PLUS:
|
|
case HB_PP_TOKEN_MINUS:
|
|
case HB_PP_TOKEN_MULT:
|
|
case HB_PP_TOKEN_DIV:
|
|
case HB_PP_TOKEN_MOD:
|
|
case HB_PP_TOKEN_IN:
|
|
case HB_PP_TOKEN_COMMA:
|
|
case HB_PP_TOKEN_PIPE:
|
|
case HB_PP_TOKEN_AMPERSAND:
|
|
case HB_PP_TOKEN_DOT:
|
|
case HB_PP_TOKEN_LT:
|
|
case HB_PP_TOKEN_GT:
|
|
case HB_PP_TOKEN_REFERENCE:
|
|
pLex->iState = OPERATOR;
|
|
return ( HB_UCHAR ) pToken->value[ 0 ];
|
|
|
|
case HB_PP_TOKEN_EOL:
|
|
pLex->fEol = HB_TRUE;
|
|
/* fallthrough */
|
|
case HB_PP_TOKEN_EOC:
|
|
pLex->iState = LOOKUP;
|
|
return ( HB_UCHAR ) pToken->value[ 0 ];
|
|
|
|
case HB_PP_TOKEN_KEYWORD:
|
|
{
|
|
int iType;
|
|
hb_pp_tokenUpper( pToken );
|
|
iType = hb_comp_keywordType( pToken );
|
|
pLex->lasttok = yylval_ptr->string =
|
|
hb_comp_tokenIdentifer( HB_COMP_PARAM, pToken );
|
|
switch( iType )
|
|
{
|
|
case FUNCTION:
|
|
case PROCEDURE:
|
|
if( ! HB_SUPPORT_HARBOUR ||
|
|
( pLex->iState == LOOKUP && pToken->pNext &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD ) )
|
|
{
|
|
pLex->iScope = HB_FS_PUBLIC;
|
|
pLex->iState = iType;
|
|
return hb_comp_funcStart( HB_COMP_PARAM, yylval_ptr );
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case INIT:
|
|
case EXIT:
|
|
case STATIC:
|
|
if( pLex->iState == LOOKUP && pToken->pNext &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
pToken->pNext->len >= 4 &&
|
|
( hb_strnicmp( "FUNCTION", pToken->pNext->value,
|
|
pToken->pNext->len ) == 0 ||
|
|
hb_strnicmp( "PROCEDURE", pToken->pNext->value,
|
|
pToken->pNext->len ) == 0 ) )
|
|
{
|
|
pLex->iScope = iType == INIT ? HB_FS_INIT :
|
|
( iType == EXIT ? HB_FS_EXIT : HB_FS_STATIC );
|
|
pLex->iState = HB_TOUPPER( pToken->pNext->value[ 0 ] ) == 'F' ?
|
|
FUNCTION : PROCEDURE;
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
return hb_comp_funcStart( HB_COMP_PARAM, yylval_ptr );
|
|
}
|
|
else if( pLex->iState == LOOKUP &&
|
|
( ( iType == EXIT && HB_PP_TOKEN_ISEOC( pToken->pNext ) ) ||
|
|
( iType == STATIC && pToken->pNext &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD ) ) )
|
|
{
|
|
pLex->iState = iType;
|
|
return iType;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case THREAD_STATIC:
|
|
if( pLex->iState == LOOKUP && pToken->pNext &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
pToken->pNext->len >= 4 &&
|
|
hb_strnicmp( "STATIC", pToken->pNext->value,
|
|
pToken->pNext->len ) == 0 )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
pLex->iState = THREAD_STATIC;
|
|
return THREAD_STATIC;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case BEGINSEQ:
|
|
if( pLex->iState == LOOKUP && pToken->pNext &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD )
|
|
{
|
|
if( pToken->pNext->len >= 4 && pToken->pNext->len <= 8 &&
|
|
hb_strnicmp( "SEQUENCE", pToken->pNext->value, pToken->pNext->len ) == 0 )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
pLex->iState = BEGINSEQ;
|
|
return BEGINSEQ;
|
|
}
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case RECOVER:
|
|
if( pLex->iState == LOOKUP )
|
|
{
|
|
if( HB_PP_TOKEN_ISEOC( pToken->pNext ) )
|
|
{
|
|
pLex->iState = RECOVER;
|
|
return RECOVER;
|
|
}
|
|
else if( pToken->pNext &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
pToken->pNext->len >= 4 && pToken->pNext->len <= 5 &&
|
|
hb_strnicmp( "USING", pToken->pNext->value, pToken->pNext->len ) == 0 )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
pLex->iState = RECOVERUSING;
|
|
return RECOVERUSING;
|
|
}
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case END:
|
|
if( pLex->iState == LOOKUP )
|
|
{
|
|
if( HB_PP_TOKEN_ISEOC( pToken->pNext ) )
|
|
{
|
|
pLex->iState = END;
|
|
return END;
|
|
}
|
|
else if( HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
pToken->pNext->len >= 4 && pToken->pNext->len <= 8 &&
|
|
hb_strnicmp( "SEQUENCE", pToken->pNext->value, pToken->pNext->len ) == 0 )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
pLex->iState = ENDSEQ;
|
|
return ENDSEQ;
|
|
}
|
|
if( ! HB_SUPPORT_HARBOUR && HB_COMP_PARAM->iSyntaxCheckOnly < 2 )
|
|
{
|
|
/* Clipper does not like end[], end(), end->, end-- & end++ at
|
|
the beginning of line */
|
|
if( HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_LEFT_PB ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_LEFT_SB ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_INC ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_DEC ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_ALIAS )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E',
|
|
HB_COMP_ERR_ENDIF, NULL, NULL );
|
|
}
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case ELSE:
|
|
if( HB_SUPPORT_HARBOUR &&
|
|
( pLex->iState != LOOKUP ||
|
|
! HB_PP_TOKEN_ISEOC( pToken->pNext ) ) )
|
|
{
|
|
iType = IDENTIFIER;
|
|
break;
|
|
}
|
|
pLex->iState = ELSE;
|
|
return ELSE;
|
|
|
|
case ELSEIF:
|
|
case CASE:
|
|
if( HB_SUPPORT_HARBOUR &&
|
|
( pLex->iState != LOOKUP ||
|
|
HB_PP_TOKEN_ISEOC( pToken->pNext ) ||
|
|
HB_PP_LEX_NEEDLEFT( pToken->pNext ) ) )
|
|
{
|
|
iType = IDENTIFIER;
|
|
break;
|
|
}
|
|
pLex->iState = iType;
|
|
return iType;
|
|
|
|
case ENDIF:
|
|
case ENDCASE:
|
|
case ENDDO:
|
|
if( HB_SUPPORT_HARBOUR &&
|
|
( pLex->iState != LOOKUP ||
|
|
! HB_PP_TOKEN_ISEOC( pToken->pNext ) ) )
|
|
{
|
|
iType = IDENTIFIER;
|
|
break;
|
|
}
|
|
pLex->iState = iType;
|
|
return iType;
|
|
|
|
case OTHERWISE:
|
|
case ENDSEQ:
|
|
case ENDSWITCH:
|
|
case ENDWITH:
|
|
case ALWAYS:
|
|
if( pLex->iState == LOOKUP && HB_PP_TOKEN_ISEOC( pToken->pNext ) )
|
|
{
|
|
pLex->iState = iType;
|
|
return iType;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case FOR:
|
|
if( pLex->iState == LOOKUP &&
|
|
! HB_PP_TOKEN_ISEOC( pToken->pNext ) )
|
|
{
|
|
PHB_PP_TOKEN pNext = pToken->pNext;
|
|
|
|
if( HB_PP_TOKEN_TYPE( pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
pNext->pNext &&
|
|
HB_PP_TOKEN_TYPE( pNext->pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
hb_stricmp( "EACH", pNext->value ) == 0 )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
pLex->iState = FOREACH;
|
|
return FOREACH;
|
|
}
|
|
if( ! hb_pp_tokenNextExp( &pNext ) && pNext &&
|
|
HB_PP_TOKEN_TYPE( pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
hb_stricmp( "TO", pNext->value ) == 0 )
|
|
{
|
|
pLex->iState = FOR;
|
|
return FOR;
|
|
}
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case NEXT:
|
|
if( pLex->iState == LOOKUP )
|
|
{
|
|
if( HB_PP_TOKEN_ISEOC( pToken->pNext ) ||
|
|
( HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
HB_PP_TOKEN_ISEOC( pToken->pNext->pNext ) ) )
|
|
{
|
|
pLex->iState = iType;
|
|
return iType;
|
|
}
|
|
if( ! HB_SUPPORT_HARBOUR && HB_COMP_PARAM->iSyntaxCheckOnly < 2 )
|
|
{
|
|
/* Clipper does not like NEXT[], NEXT(), NEXT->,
|
|
NEXT++ & NEXT-- at the beginning of line */
|
|
if( HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_LEFT_PB ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_LEFT_SB ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_INC ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_DEC ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_ALIAS )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E',
|
|
HB_COMP_ERR_NEXTFOR, NULL, NULL );
|
|
}
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case RETURN:
|
|
case BREAK:
|
|
/* NOTE: Clipper does not like break[] in any context
|
|
* There are no resons to limit this use in Harbour.
|
|
*/
|
|
if( pLex->iState == LOOKUP &&
|
|
( HB_PP_TOKEN_ISEOC( pToken->pNext ) ||
|
|
! HB_PP_LEX_NEEDLEFT( pToken->pNext ) ) )
|
|
{
|
|
pLex->iState = iType;
|
|
return iType;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case WHILE:
|
|
case DOSWITCH:
|
|
if( pLex->iState == LOOKUP &&
|
|
! HB_PP_TOKEN_ISEOC( pToken->pNext ) &&
|
|
! HB_PP_LEX_NEEDLEFT( pToken->pNext ) )
|
|
{
|
|
pLex->iState = iType;
|
|
return iType;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case DECLARE:
|
|
if( pLex->iState == LOOKUP &&
|
|
! HB_PP_TOKEN_ISEOC( pToken->pNext ) )
|
|
{
|
|
if( HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_MACROVAR ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_MACROTEXT ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_AMPERSAND )
|
|
{
|
|
pLex->iState = PRIVATE;
|
|
return PRIVATE;
|
|
}
|
|
else if( HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD )
|
|
{
|
|
if( HB_PP_TOKEN_ISEOC( pToken->pNext->pNext ) ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->pNext->type ) == HB_PP_TOKEN_LEFT_SB ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->pNext->type ) == HB_PP_TOKEN_COMMA ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->pNext->type ) == HB_PP_TOKEN_ASSIGN ||
|
|
( HB_PP_TOKEN_TYPE( pToken->pNext->pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
hb_stricmp( "AS", pToken->pNext->pNext->value ) == 0 ) )
|
|
{
|
|
pLex->iState = PRIVATE;
|
|
return PRIVATE;
|
|
}
|
|
pLex->iState = DECLARE;
|
|
return DECLARE;
|
|
}
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case DO:
|
|
if( pLex->iState == LOOKUP && ! HB_PP_TOKEN_ISEOC( pToken->pNext ) )
|
|
{
|
|
if( HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD )
|
|
{
|
|
if( pToken->pNext->len == 4 &&
|
|
hb_stricmp( "CASE", pToken->pNext->value ) == 0 )
|
|
{
|
|
if( HB_PP_TOKEN_ISEOC( pToken->pNext->pNext ) )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
pLex->iState = DOCASE;
|
|
return DOCASE;
|
|
}
|
|
}
|
|
else if( pToken->pNext->len >= 4 &&
|
|
pToken->pNext->len <= 5 &&
|
|
hb_strnicmp( "WHILE", pToken->pNext->value,
|
|
pToken->pNext->len ) == 0 &&
|
|
/* check if it's not DO while [WITH <args>] */
|
|
! HB_PP_TOKEN_ISEOC( pToken->pNext->pNext ) &&
|
|
( HB_PP_TOKEN_TYPE( pToken->pNext->pNext->type ) != HB_PP_TOKEN_KEYWORD ||
|
|
pToken->pNext->pNext->len != 4 ||
|
|
hb_stricmp( "WITH", pToken->pNext->pNext->value ) != 0 ) )
|
|
{
|
|
/* DO WHILE <exp> */
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
pLex->iState = WHILE;
|
|
return WHILE;
|
|
}
|
|
/* DO identifier [WITH <args>] */
|
|
pToken = hb_pp_tokenGet( pLex->pPP );
|
|
/* do not upper next token for case sensitive file systems */
|
|
#if 0
|
|
hb_pp_tokenUpper( pToken );
|
|
#endif
|
|
pLex->lasttok = yylval_ptr->string =
|
|
hb_comp_tokenIdentifer( HB_COMP_PARAM, pToken );
|
|
pLex->iState = IDENTIFIER;
|
|
return DOIDENT;
|
|
}
|
|
else if( HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_MACROVAR ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_MACROTEXT )
|
|
{
|
|
/* DO &id WITH */
|
|
pLex->iState = DO;
|
|
return DO;
|
|
}
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case WITH:
|
|
if( ! HB_PP_TOKEN_ISEOC( pToken->pNext ) )
|
|
{
|
|
if( pLex->iState == LOOKUP &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
pToken->pNext->len >= 4 &&
|
|
hb_strnicmp( "OBJECT", pToken->pNext->value,
|
|
pToken->pNext->len ) == 0 )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
pLex->iState = WITHOBJECT;
|
|
return WITHOBJECT;
|
|
}
|
|
else if( pLex->iState == MACROVAR ||
|
|
pLex->iState == MACROTEXT ||
|
|
pLex->iState == IDENTIFIER ||
|
|
pLex->iState == BEGINSEQ )
|
|
{
|
|
pLex->iState = WITH;
|
|
return WITH;
|
|
}
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case IIF:
|
|
if( pLex->iState == FUNCTION || pLex->iState == PROCEDURE ||
|
|
( ! HB_SUPPORT_HARBOUR && HB_PP_TOKEN_ISEOC( pToken->pNext ) ) )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E',
|
|
HB_COMP_ERR_SYNTAX, "IIF", NULL );
|
|
else if( pToken->pNext &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_LEFT_PB )
|
|
{
|
|
pLex->iState = IIF;
|
|
return IIF;
|
|
}
|
|
else if( ! HB_SUPPORT_HARBOUR )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E',
|
|
HB_COMP_ERR_SYNTAX, pToken->pNext->value, NULL );
|
|
else
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case IF:
|
|
if( pLex->iState == FUNCTION || pLex->iState == PROCEDURE ||
|
|
( ! HB_SUPPORT_HARBOUR && HB_PP_TOKEN_ISEOC( pToken->pNext ) ) )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E',
|
|
HB_COMP_ERR_SYNTAX, "IF", NULL );
|
|
else if( pToken->pNext &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_LEFT_PB )
|
|
{
|
|
if( pLex->iState == LOOKUP )
|
|
{
|
|
PHB_PP_TOKEN pNext = pToken->pNext->pNext; /* COND EXP */
|
|
|
|
pLex->iState = IF;
|
|
if( hb_pp_tokenNextExp( &pNext ) ) /* TRUE EXP */
|
|
{
|
|
if( hb_pp_tokenNextExp( &pNext ) ) /* FALSE EXP */
|
|
{
|
|
if( ! hb_pp_tokenNextExp( &pNext ) && pNext &&
|
|
HB_PP_TOKEN_TYPE( pNext->type ) == HB_PP_TOKEN_RIGHT_PB )
|
|
pLex->iState = IIF;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
pLex->iState = IIF;
|
|
|
|
return pLex->iState;
|
|
}
|
|
else if( HB_PP_LEX_NEEDLEFT( pToken->pNext ) || pLex->iState != LOOKUP )
|
|
{
|
|
if( ! HB_SUPPORT_HARBOUR )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E',
|
|
HB_COMP_ERR_SYNTAX2, pToken->pNext->value, "IF" );
|
|
}
|
|
else
|
|
{
|
|
pLex->iState = IF;
|
|
return IF;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case PROCREQ:
|
|
if( pLex->iState == LOOKUP && ! HB_PP_TOKEN_ISEOC( pToken->pNext ) &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_LEFT_PB )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
pLex->iState = LSEPARATOR;
|
|
return PROCREQ;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case FIELD:
|
|
if( pToken->pNext &&
|
|
( ( pLex->iState == LOOKUP &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD ) ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_ALIAS ) )
|
|
{
|
|
pLex->iState = FIELD;
|
|
return FIELD;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case SELF:
|
|
if( pToken->pNext && pToken->pNext->pNext &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_LEFT_PB &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->pNext->type ) == HB_PP_TOKEN_RIGHT_PB )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
pLex->iState = RSEPARATOR;
|
|
return SELF;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case AS_TYPE:
|
|
{
|
|
int iAs = hb_comp_asType( pToken->pNext, HB_FALSE );
|
|
if( iAs )
|
|
{
|
|
pLex->iState = DECLARE_TYPE;
|
|
pToken = hb_pp_tokenGet( pLex->pPP );
|
|
if( iAs == AS_ARRAY && pToken->pNext &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD &&
|
|
hb_stricmp( "OF", pToken->pNext->value ) == 0 )
|
|
{
|
|
int iAsArray = hb_comp_asType( pToken->pNext->pNext, HB_TRUE );
|
|
if( iAsArray )
|
|
{
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
hb_pp_tokenGet( pLex->pPP );
|
|
return iAsArray;
|
|
}
|
|
}
|
|
return iAs;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
}
|
|
case DECLARE_CLASS:
|
|
if( pLex->iState == LOOKUP && ! HB_PP_TOKEN_ISEOC( pToken->pNext ) &&
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD )
|
|
{
|
|
pLex->iState = DECLARE_TYPE;
|
|
return DECLARE_CLASS;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
case DECLARE_MEMBER:
|
|
if( pLex->iState == LOOKUP && ! HB_PP_TOKEN_ISEOC( pToken->pNext ) &&
|
|
( HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_KEYWORD ||
|
|
HB_PP_TOKEN_TYPE( pToken->pNext->type ) == HB_PP_TOKEN_LEFT_CB ) )
|
|
{
|
|
pLex->iState = OPERATOR;
|
|
return DECLARE_MEMBER;
|
|
}
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case IN:
|
|
if( pLex->iState == IDENTIFIER )
|
|
{
|
|
pLex->iState = iType;
|
|
return iType;
|
|
}
|
|
break;
|
|
|
|
case NIL:
|
|
if( pLex->iState == DECLARE_TYPE )
|
|
iType = IDENTIFIER;
|
|
break;
|
|
|
|
case LOOP:
|
|
case LOCAL:
|
|
case MEMVAR:
|
|
case PUBLIC:
|
|
case PRIVATE:
|
|
case PARAMETERS:
|
|
case EXTERN:
|
|
case DYNAMIC:
|
|
case ANNOUNCE:
|
|
if( pLex->iState == LOOKUP )
|
|
{
|
|
pLex->iState = iType;
|
|
return iType;
|
|
}
|
|
break;
|
|
|
|
case TO:
|
|
case STEP:
|
|
case OPTIONAL:
|
|
case DESCEND:
|
|
break;
|
|
}
|
|
pLex->iState = IDENTIFIER;
|
|
return iType;
|
|
}
|
|
default:
|
|
return ( HB_UCHAR ) pToken->value[ 0 ];
|
|
}
|
|
}
|
|
|
|
void hb_compParserRun( HB_COMP_DECL )
|
|
{
|
|
YYSTYPE yylval;
|
|
int iToken;
|
|
|
|
while( ! HB_COMP_PARAM->fExit && HB_COMP_PARAM->iErrorCount == 0 )
|
|
{
|
|
if( HB_COMP_PARAM->fSingleModule )
|
|
{
|
|
PHB_PP_TOKEN pToken = hb_pp_tokenGet( HB_COMP_PARAM->pLex->pPP );
|
|
if( ! pToken )
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iToken = hb_comp_yylex( &yylval, HB_COMP_PARAM );
|
|
if( iToken == 0 )
|
|
break;
|
|
if( iToken == DOIDENT )
|
|
hb_compModuleAdd( HB_COMP_PARAM, yylval.string, HB_FALSE );
|
|
else if( iToken == PROCREQ )
|
|
{
|
|
iToken = hb_comp_yylex( &yylval, HB_COMP_PARAM );
|
|
if( iToken == LITERAL )
|
|
{
|
|
const char * szFile, * szExt = NULL;
|
|
|
|
if( yylval.valChar.dealloc )
|
|
szFile = hb_compIdentifierNew( HB_COMP_PARAM, yylval.valChar.string, HB_IDENT_FREE );
|
|
else
|
|
szFile = yylval.valChar.string;
|
|
iToken = hb_comp_yylex( &yylval, HB_COMP_PARAM );
|
|
if( iToken == '+' )
|
|
{
|
|
iToken = hb_comp_yylex( &yylval, HB_COMP_PARAM );
|
|
if( iToken == LITERAL )
|
|
{
|
|
if( yylval.valChar.dealloc )
|
|
szExt = hb_compIdentifierNew( HB_COMP_PARAM, yylval.valChar.string, HB_IDENT_FREE );
|
|
else
|
|
szExt = yylval.valChar.string;
|
|
}
|
|
iToken = hb_comp_yylex( &yylval, HB_COMP_PARAM );
|
|
}
|
|
if( iToken == ')' )
|
|
{
|
|
if( szExt && *szExt )
|
|
szFile = hb_compIdentifierNew( HB_COMP_PARAM,
|
|
hb_xstrcpy( NULL, szFile, szExt, NULL ), HB_IDENT_FREE );
|
|
hb_compModuleAdd( HB_COMP_PARAM, szFile, HB_FALSE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void hb_compParserStop( HB_COMP_DECL )
|
|
{
|
|
HB_SYMBOL_UNUSED( HB_COMP_PARAM );
|
|
}
|