* *
% remove brandings and homepage from copyright header. Pass 2 - semi-auto.
* project homepage and name is described in README, amongst others
; this should make the diff between 3.4 and 3.2 easier to manage
2906 lines
114 KiB
Plaintext
2906 lines
114 KiB
Plaintext
%pure-parser
|
|
%parse-param { PHB_COMP pComp }
|
|
%lex-param { PHB_COMP pComp }
|
|
%name-prefix "hb_comp_yy"
|
|
%{
|
|
/*
|
|
* Compiler YACC rules and actions
|
|
*
|
|
* Copyright 1999 Antonio Linares <alinares@fivetech.com>
|
|
*
|
|
* 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.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
|
|
#include "hbcomp.h"
|
|
|
|
/* Compile using: bison -d -v harbour.y */
|
|
|
|
/* to pacify some meaningless warnings */
|
|
#if defined( __BORLANDC__ )
|
|
# if ! defined( __STDC__ )
|
|
# define __STDC__
|
|
# endif
|
|
# pragma warn -aus
|
|
# pragma warn -ccc
|
|
# pragma warn -rch
|
|
#elif defined( __WATCOMC__ )
|
|
# pragma warning 13 9
|
|
# pragma warning 368 9
|
|
#elif defined( _MSC_VER )
|
|
# pragma warning( disable : 4244 )
|
|
# pragma warning( disable : 4702 )
|
|
#endif
|
|
|
|
#undef alloca
|
|
#define alloca hb_xgrab
|
|
#undef malloc
|
|
#define malloc hb_xgrab
|
|
#undef realloc
|
|
#define realloc hb_xrealloc
|
|
#undef free
|
|
#define free hb_xfree
|
|
|
|
/* NOTE: these symbols are used internally in bison.simple
|
|
*/
|
|
#undef YYFREE
|
|
#define YYFREE hb_xfree
|
|
#undef YYMALLOC
|
|
#define YYMALLOC hb_xgrab
|
|
|
|
#define NO_YYERROR
|
|
|
|
/* NOTE: these symbols are defined explicitly to pacify warnings */
|
|
#define YYENABLE_NLS 0
|
|
#define YYLTYPE_IS_TRIVIAL 0
|
|
|
|
/* NOTE: increase the maximum size of bison stack size */
|
|
#define YYMAXDEPTH 100000
|
|
|
|
static void hb_compLoopStart( HB_COMP_DECL, HB_BOOL );
|
|
static void hb_compLoopEnd( HB_COMP_DECL );
|
|
static void hb_compLoopLoop( HB_COMP_DECL );
|
|
static void hb_compLoopExit( HB_COMP_DECL );
|
|
static void hb_compLoopHere( HB_COMP_DECL );
|
|
static long hb_compLoopCount( HB_COMP_DECL );
|
|
|
|
static void * hb_compElseIfGen( HB_COMP_DECL, void * pFirstElseIf, HB_SIZE nOffset ); /* generates a support structure for elseifs pcode fixups */
|
|
static void hb_compElseIfFix( HB_COMP_DECL, void * pIfElseIfs ); /* implements the ElseIfs pcode fixups */
|
|
|
|
static void hb_compRTVariableAdd( HB_COMP_DECL, PHB_EXPR, HB_BOOL );
|
|
static void hb_compRTVariableGen( HB_COMP_DECL, const char * );
|
|
|
|
static PHB_EXPR hb_compArrayDimPush( PHB_EXPR pInitValue, HB_COMP_DECL );
|
|
static void hb_compVariableDim( const char *, PHB_EXPR, HB_COMP_DECL );
|
|
|
|
static void hb_compForStart( HB_COMP_DECL, const char *szVarName, int iForEachDir );
|
|
static void hb_compForEnd( HB_COMP_DECL, const char *szVarName );
|
|
static void hb_compEnumStart( HB_COMP_DECL, PHB_EXPR pVars, PHB_EXPR pExprs, int descend );
|
|
static void hb_compEnumNext( HB_COMP_DECL, PHB_EXPR pExpr, int descend );
|
|
static void hb_compEnumEnd( HB_COMP_DECL, PHB_EXPR pExpr );
|
|
|
|
static void hb_compSwitchStart( HB_COMP_DECL, PHB_EXPR );
|
|
static void hb_compSwitchAdd( HB_COMP_DECL, PHB_EXPR );
|
|
static void hb_compSwitchEnd( HB_COMP_DECL );
|
|
|
|
static PHB_EXPR hb_compCheckMethod( HB_COMP_DECL, PHB_EXPR pExpr );
|
|
static PHB_EXPR hb_compCheckPassByRef( HB_COMP_DECL, PHB_EXPR pExpr );
|
|
|
|
#ifdef HB_YYDEBUG
|
|
#define YYDEBUG 1 /* Parser debug information support */
|
|
#endif
|
|
|
|
/* Controls if passing by reference '@' is allowed */
|
|
#define HB_PASSBYREF_OFF 0
|
|
#define HB_PASSBYREF_FUNCALL 1
|
|
#define HB_PASSBYREF_ARRAY 2
|
|
|
|
static void hb_compDebugStart( void ) { }
|
|
|
|
%}
|
|
|
|
%union /* special structure used by lex and yacc to share info */
|
|
{
|
|
const char * string; /* to hold a string returned by lex */
|
|
int iNumber; /* to hold a temporary integer number */
|
|
HB_SIZE sNumber; /* to hold a temporary HB_SIZE values */
|
|
HB_MAXINT lNumber; /* to hold a temporary long number */
|
|
HB_BOOL bTrue;
|
|
PHB_EXPR asExpr;
|
|
void * pVoid; /* to hold any memory structure we may need */
|
|
struct
|
|
{
|
|
HB_MAXINT lNumber; /* to hold a long number returned by lex */
|
|
HB_UCHAR bWidth; /* to hold the width of the value */
|
|
} valLong;
|
|
struct
|
|
{
|
|
double dNumber; /* to hold a double number returned by lex */
|
|
HB_UCHAR bWidth; /* to hold the width of the value */
|
|
HB_UCHAR bDec; /* to hold the number of decimal points in the value */
|
|
} valDouble;
|
|
struct
|
|
{
|
|
long date;
|
|
long time;
|
|
} valTimeStamp;
|
|
struct
|
|
{
|
|
char * string;
|
|
HB_SIZE length;
|
|
HB_BOOL dealloc;
|
|
} valChar;
|
|
struct
|
|
{
|
|
char * string;
|
|
HB_SIZE length;
|
|
int flags; /* Flag for early {|| ¯o} (1) or late {|| &(macro)} (2) binding */
|
|
} asCodeblock;
|
|
PHB_VARTYPE asVarType;
|
|
}
|
|
|
|
%{
|
|
/* This must be placed after the above union - the union is
|
|
* typedef-ined to YYSTYPE
|
|
*/
|
|
extern int yylex( YYSTYPE *, HB_COMP_DECL ); /* main lex token function, called by yyparse() */
|
|
extern void yyerror( HB_COMP_DECL, const char * ); /* parsing error management function */
|
|
%}
|
|
|
|
|
|
%token FUNCTION PROCEDURE IDENTIFIER RETURN NIL NUM_DOUBLE INASSIGN NUM_LONG
|
|
%token LOCAL STATIC IIF IF ELSE ELSEIF END ENDIF LITERAL TRUEVALUE FALSEVALUE
|
|
%token ANNOUNCE EXTERN DYNAMIC INIT EXIT AND OR NOT PUBLIC EQ NE1 NE2
|
|
%token INC DEC ALIASOP DOCASE CASE OTHERWISE ENDCASE ENDDO MEMVAR
|
|
%token WHILE LOOP FOR NEXT TO STEP LE GE FIELD IN PARAMETERS
|
|
%token PLUSEQ MINUSEQ MULTEQ DIVEQ POWER EXPEQ MODEQ
|
|
%token PRIVATE BEGINSEQ BREAK RECOVER RECOVERUSING ALWAYS ENDSEQ
|
|
%token 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
|
|
%token CBSTART DOIDENT
|
|
%token FOREACH DESCEND
|
|
%token DOSWITCH ENDSWITCH WITHOBJECT ENDWITH
|
|
%token NUM_DATE TIMESTAMP
|
|
%token EPSILON
|
|
%token HASHOP
|
|
%token THREAD
|
|
|
|
/*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
|
|
%right '<' '>' 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 <string> IdentName IDENTIFIER MACROVAR MACROTEXT CompTimeStr InAlias
|
|
%type <string> DOIDENT WHILE
|
|
%type <valChar> LITERAL
|
|
%type <valDouble> NUM_DOUBLE
|
|
%type <valLong> NUM_LONG
|
|
%type <valLong> NUM_DATE
|
|
%type <valTimeStamp> TIMESTAMP
|
|
%type <iNumber> FunScope
|
|
%type <iNumber> Descend
|
|
%type <iNumber> Params ParamList
|
|
%type <iNumber> VarList ExtVarList
|
|
%type <iNumber> FieldList
|
|
%type <sNumber> IfBegin
|
|
%type <sNumber> WhileBegin
|
|
%type <sNumber> BlockSeq AlwaysSeq Always RecoverSeq RecoverEmpty RecoverUsing
|
|
%type <pVoid> IfElseIf Cases
|
|
%type <asExpr> Argument ExtArgument RefArgument ArgList ElemList
|
|
%type <asExpr> BlockHead BlockExpList BlockVars BlockVarList
|
|
%type <asExpr> DoProc DoArgs DoArgument DoArgList
|
|
%type <asExpr> NumValue NumAlias
|
|
%type <asExpr> NilValue NilAlias
|
|
%type <asExpr> LiteralValue LiteralAlias
|
|
%type <asExpr> CodeBlock CodeBlockAlias
|
|
%type <asExpr> Logical LogicalAlias
|
|
%type <asExpr> DateValue TimeStampValue
|
|
%type <asExpr> SelfValue SelfAlias
|
|
%type <asExpr> Array ArrayAlias
|
|
%type <asExpr> ArrayAt ArrayAtAlias
|
|
%type <asExpr> Hash HashList HashAlias
|
|
%type <asExpr> Variable VarAlias
|
|
%type <asExpr> MacroVar MacroVarAlias
|
|
%type <asExpr> MacroExpr MacroExprAlias
|
|
%type <asExpr> MacroAny
|
|
%type <asExpr> AliasId AliasVar AliasExpr
|
|
%type <asExpr> VariableAt VariableAtAlias
|
|
%type <asExpr> FunIdentCall FunCall FunCallAlias FunRef
|
|
%type <asExpr> ObjectData ObjectDataAlias ObjectRef
|
|
%type <asExpr> ObjectMethod ObjectMethodAlias
|
|
%type <asExpr> IfInline IfInlineAlias
|
|
%type <asExpr> PareExpList PareExpListAlias ExpList
|
|
%type <asExpr> Expression ExtExpression SimpleExpression LValue LeftExpression
|
|
%type <asExpr> EmptyExpression
|
|
%type <asExpr> ExprAssign ExprOperEq ExprPreOp ExprPostOp
|
|
%type <asExpr> ExprEqual ExprMath ExprBool ExprRelation ExprUnary
|
|
%type <asExpr> ExprPlusEq ExprMinusEq ExprMultEq ExprDivEq ExprModEq ExprExpEq
|
|
%type <asExpr> ArrayIndex IndexList
|
|
%type <asExpr> DimIndex DimList
|
|
%type <asExpr> FieldAlias FieldVarAlias
|
|
%type <asExpr> PostOp
|
|
%type <asExpr> ForVar ForList ForExpr ForArgs
|
|
%type <asExpr> SwitchStart SwitchBegin
|
|
%type <asCodeblock> CBSTART
|
|
%type <asExpr> SendId
|
|
%type <asVarType> AsType StrongType AsArrayType AsArray
|
|
|
|
/*
|
|
We cannot use destructors for expressions. The internal bison logic cannot
|
|
detect properly if the expression was used or not in our grammar definition
|
|
so it's possible that destructors will never be executed or executed for
|
|
expressions which we freed ourself.
|
|
|
|
%destructor {
|
|
HB_COMP_EXPR_FREE( $$ );
|
|
}
|
|
Argument ExtArgument ArgList ...
|
|
*/
|
|
%destructor { if( $$.string ) hb_xfree( $$.string ); } CBSTART
|
|
%destructor { if( $$.dealloc ) hb_xfree( $$.string ); } LITERAL
|
|
|
|
%%
|
|
|
|
Main : Source
|
|
| /* empty file */
|
|
;
|
|
|
|
Source : Crlf
|
|
| Declaration
|
|
| Function
|
|
| Statement
|
|
| Line
|
|
| error Crlf { yyclearin; yyerrok; }
|
|
| Source Crlf
|
|
| Source Declaration
|
|
| Source Function
|
|
| Source Statement
|
|
| Source Line
|
|
| Source error Crlf { yyclearin; yyerrok; }
|
|
;
|
|
|
|
Line : LINE NUM_LONG Crlf
|
|
{ HB_COMP_PARAM->currLine = ( int ) $2.lNumber;
|
|
HB_COMP_PARAM->pLex->fEol = HB_FALSE; }
|
|
| LINE NUM_LONG LITERAL Crlf
|
|
{ HB_COMP_PARAM->currModule = hb_compIdentifierNew( HB_COMP_PARAM, $3.string, $3.dealloc ? HB_IDENT_FREE : HB_IDENT_STATIC );
|
|
HB_COMP_PARAM->currLine = ( int ) $2.lNumber;
|
|
HB_COMP_PARAM->pLex->fEol = HB_FALSE;
|
|
$3.dealloc = HB_FALSE; }
|
|
| LINE NUM_LONG LITERAL '@' LITERAL Crlf /* Xbase++ style */
|
|
{ HB_COMP_PARAM->currModule = hb_compIdentifierNew( HB_COMP_PARAM, $5.string, $5.dealloc ? HB_IDENT_FREE : HB_IDENT_STATIC );
|
|
HB_COMP_PARAM->currLine = ( int ) $2.lNumber;
|
|
HB_COMP_PARAM->pLex->fEol = HB_FALSE;
|
|
if( $3.dealloc ) { hb_xfree( $3.string ); $3.dealloc = HB_FALSE; }
|
|
$5.dealloc = HB_FALSE; }
|
|
;
|
|
|
|
Function : FunScope FUNCTION IdentName { hb_compFunctionAdd( HB_COMP_PARAM, $3, ( HB_SYMBOLSCOPE ) $1, 0 ); } Crlf
|
|
| FunScope PROCEDURE IdentName { hb_compFunctionAdd( HB_COMP_PARAM, $3, ( HB_SYMBOLSCOPE ) $1, HB_FUNF_PROCEDURE ); } Crlf
|
|
| FunScope FUNCTION IdentName { hb_compFunctionAdd( HB_COMP_PARAM, $3, ( HB_SYMBOLSCOPE ) $1, 0 ); HB_COMP_PARAM->iVarScope = HB_VSCOMP_PARAMETER; } '(' Params ')' Crlf
|
|
| FunScope PROCEDURE IdentName { hb_compFunctionAdd( HB_COMP_PARAM, $3, ( HB_SYMBOLSCOPE ) $1, HB_FUNF_PROCEDURE ); HB_COMP_PARAM->iVarScope = HB_VSCOMP_PARAMETER;} '(' Params ')' Crlf
|
|
;
|
|
|
|
FunScope : { $$ = HB_FS_PUBLIC; }
|
|
| STATIC { $$ = HB_FS_STATIC; }
|
|
| INIT { $$ = HB_FS_INIT; }
|
|
| EXIT { $$ = HB_FS_EXIT; }
|
|
;
|
|
|
|
Params : /*no parameters */ { $$ = 0; }
|
|
| EPSILON { HB_COMP_PARAM->functions.pLast->fVParams = HB_TRUE; $$ = 0; }
|
|
| ParamList
|
|
| ParamList ',' EPSILON { HB_COMP_PARAM->functions.pLast->fVParams = HB_TRUE; $$ = $1; }
|
|
;
|
|
|
|
AsType : /* not specified */ { $$ = hb_compVarTypeNew( HB_COMP_PARAM, ' ', NULL ); }
|
|
| StrongType
|
|
;
|
|
|
|
AsArrayType: /* not specified */ { $$ = hb_compVarTypeNew( HB_COMP_PARAM, ' ', NULL ); }
|
|
| AsArray
|
|
;
|
|
|
|
StrongType : AS_NUMERIC { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'N', NULL ); }
|
|
| AS_CHARACTER { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'C', NULL ); }
|
|
| AS_DATE { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'D', NULL ); }
|
|
| AS_LOGICAL { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'L', NULL ); }
|
|
| AS_BLOCK { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'B', NULL ); }
|
|
| AS_OBJECT { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'O', NULL ); }
|
|
| AS_CLASS IdentName { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'S', $2 ); }
|
|
| AS_VARIANT { $$ = hb_compVarTypeNew( HB_COMP_PARAM, ' ', NULL ); }
|
|
| AsArray
|
|
;
|
|
|
|
AsArray : AS_ARRAY { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'A', NULL ); }
|
|
| AS_NUMERIC_ARRAY { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'n', NULL ); }
|
|
| AS_CHARACTER_ARRAY { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'c', NULL ); }
|
|
| AS_DATE_ARRAY { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'd', NULL ); }
|
|
| AS_LOGICAL_ARRAY { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'l', NULL ); }
|
|
| AS_ARRAY_ARRAY { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'a', NULL ); }
|
|
| AS_BLOCK_ARRAY { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'b', NULL ); }
|
|
| AS_OBJECT_ARRAY { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 'o', NULL ); }
|
|
| AS_CLASS_ARRAY IdentName { $$ = hb_compVarTypeNew( HB_COMP_PARAM, 's', $2 ); }
|
|
;
|
|
|
|
ParamList : IdentName AsType { hb_compVariableAdd( HB_COMP_PARAM, $1, $2 ); $$ = 1; }
|
|
| ParamList ',' IdentName AsType { hb_compVariableAdd( HB_COMP_PARAM, $3, $4 ); $$++; }
|
|
;
|
|
|
|
/* NOTE: This allows 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_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN; }
|
|
| FunCall CrlfStmnt { HB_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN; }
|
|
| AliasExpr CrlfStmnt { HB_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN; }
|
|
| ObjectMethod CrlfStmnt { HB_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN; }
|
|
| MacroAny CrlfStmnt { if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_XBASE ) )
|
|
HB_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) );
|
|
else
|
|
HB_COMP_EXPR_FREE( HB_COMP_ERROR_SYNTAX( $1 ) );
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN;
|
|
}
|
|
| PareExpList CrlfStmnt { HB_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN; }
|
|
| ExprPreOp CrlfStmnt { HB_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN; }
|
|
| ExprPostOp CrlfStmnt { HB_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN; }
|
|
| ExprOperEq CrlfStmnt { HB_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN; }
|
|
| ExprEqual CrlfStmnt { HB_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN; }
|
|
| ExprAssign CrlfStmnt { HB_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN; }
|
|
| DoProc CrlfStmnt { HB_COMP_EXPR_FREE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN; }
|
|
| BREAK CrlfStmnt { hb_compGenBreak( HB_COMP_PARAM ); hb_compGenPCode2( HB_P_DOSHORT, 0, HB_COMP_PARAM );
|
|
HB_COMP_PARAM->functions.pLast->funFlags |= HB_FUNF_BREAK_CODE; }
|
|
| BREAK { hb_compLinePushIfInside( HB_COMP_PARAM ); } Expression Crlf
|
|
{
|
|
hb_compGenBreak( HB_COMP_PARAM ); HB_COMP_EXPR_FREE( hb_compExprGenPush( $3, HB_COMP_PARAM ) );
|
|
hb_compGenPCode2( HB_P_DOSHORT, 1, HB_COMP_PARAM );
|
|
HB_COMP_PARAM->functions.pLast->funFlags |= HB_FUNF_BREAK_CODE;
|
|
}
|
|
| EXIT CrlfStmnt { hb_compLoopExit( HB_COMP_PARAM ); HB_COMP_PARAM->functions.pLast->funFlags |= HB_FUNF_BREAK_CODE; }
|
|
| LOOP CrlfStmnt { hb_compLoopLoop( HB_COMP_PARAM ); HB_COMP_PARAM->functions.pLast->funFlags |= HB_FUNF_BREAK_CODE; }
|
|
| RETURN CrlfStmnt {
|
|
if( HB_COMP_PARAM->functions.pLast->wSeqCounter )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_EXIT_IN_SEQUENCE, "RETURN", NULL );
|
|
}
|
|
hb_compGenPCode1( HB_P_ENDPROC, HB_COMP_PARAM );
|
|
if( ( HB_COMP_PARAM->functions.pLast->funFlags & HB_FUNF_PROCEDURE ) == 0 )
|
|
{
|
|
/* return from a function without a return value */
|
|
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_NO_RETURN_VALUE, NULL, NULL );
|
|
}
|
|
HB_COMP_PARAM->functions.pLast->funFlags |= HB_FUNF_WITH_RETURN | HB_FUNF_BREAK_CODE;
|
|
}
|
|
| RETURN { hb_compLinePushIfInside( HB_COMP_PARAM ); }
|
|
Expression Crlf
|
|
{
|
|
if( HB_COMP_PARAM->functions.pLast->wSeqCounter )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_EXIT_IN_SEQUENCE, "RETURN", NULL );
|
|
}
|
|
/* TODO: check if return value agree with declared value */
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPush( $3, HB_COMP_PARAM ) );
|
|
if( HB_COMP_PARAM->functions.pLast->funFlags & HB_FUNF_EXTBLOCK )
|
|
/* extended clodeblock, use HB_P_ENDBLOCK to return value and stop execution */
|
|
hb_compGenPCode1( HB_P_ENDBLOCK, HB_COMP_PARAM );
|
|
else
|
|
hb_compGenPCode2( HB_P_RETVALUE, HB_P_ENDPROC, HB_COMP_PARAM );
|
|
if( HB_COMP_PARAM->functions.pLast->funFlags & HB_FUNF_PROCEDURE )
|
|
{
|
|
/* procedure returns a value */
|
|
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_PROC_RETURN_VALUE, NULL, NULL );
|
|
}
|
|
HB_COMP_PARAM->functions.pLast->funFlags |= HB_FUNF_WITH_RETURN | HB_FUNF_BREAK_CODE;
|
|
}
|
|
| PUBLIC { hb_compLinePushIfInside( HB_COMP_PARAM ); HB_COMP_PARAM->iVarScope = HB_VSCOMP_PUBLIC; }
|
|
ExtVarList
|
|
{ hb_compRTVariableGen( HB_COMP_PARAM, "__MVPUBLIC" );
|
|
HB_COMP_PARAM->iVarScope = HB_VSCOMP_NONE;
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN;
|
|
} Crlf
|
|
| PRIVATE { hb_compLinePushIfInside( HB_COMP_PARAM ); HB_COMP_PARAM->iVarScope = HB_VSCOMP_PRIVATE; }
|
|
ExtVarList
|
|
{ hb_compRTVariableGen( HB_COMP_PARAM, "__MVPRIVATE" );
|
|
HB_COMP_PARAM->iVarScope = HB_VSCOMP_NONE;
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN;
|
|
} Crlf
|
|
| VarDefs
|
|
| FieldsDef
|
|
| MemvarDef
|
|
| EXTERN ExtList Crlf
|
|
| DYNAMIC DynList Crlf
|
|
| ANNOUNCE IdentName {
|
|
if( HB_COMP_PARAM->szAnnounce == NULL )
|
|
HB_COMP_PARAM->szAnnounce = $2;
|
|
else
|
|
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_DUPL_ANNOUNCE, $2, NULL );
|
|
} Crlf
|
|
| PROCREQ CompTimeStr ')' Crlf
|
|
;
|
|
|
|
CompTimeStr : LITERAL {
|
|
if( $1.dealloc )
|
|
{
|
|
$1.string = ( char * ) hb_compIdentifierNew( HB_COMP_PARAM, $1.string, HB_IDENT_FREE );
|
|
$1.dealloc = HB_FALSE;
|
|
}
|
|
hb_compModuleAdd( HB_COMP_PARAM, $1.string, HB_FALSE );
|
|
}
|
|
| LITERAL '+' LITERAL {
|
|
{
|
|
char szFileName[ HB_PATH_MAX ];
|
|
hb_strncat( hb_strncpy( szFileName, $1.string, sizeof( szFileName ) - 1 ), $3.string, sizeof( szFileName ) - 1 );
|
|
hb_compModuleAdd( HB_COMP_PARAM, hb_compIdentifierNew( HB_COMP_PARAM, szFileName, HB_IDENT_COPY ), HB_FALSE );
|
|
if( $1.dealloc )
|
|
{
|
|
hb_xfree( $1.string );
|
|
$1.dealloc = HB_FALSE;
|
|
}
|
|
if( $3.dealloc )
|
|
{
|
|
hb_xfree( $3.string );
|
|
$3.dealloc = HB_FALSE;
|
|
}
|
|
}
|
|
}
|
|
;
|
|
|
|
CrlfStmnt : { hb_compLinePushIfInside( HB_COMP_PARAM ); } Crlf
|
|
;
|
|
|
|
LineStat : Crlf { $<lNumber>$ = 0; }
|
|
| Statement { $<lNumber>$ = 1; }
|
|
| Declaration { $<lNumber>$ = 1; }
|
|
| Line { $<lNumber>$ = 0; }
|
|
| ControlError { $<lNumber>$ = 0; hb_compCheckUnclosedStru( HB_COMP_PARAM, HB_COMP_PARAM->functions.pLast ); }
|
|
| error { if( HB_COMP_PARAM->ilastLineErr && HB_COMP_PARAM->ilastLineErr == HB_COMP_PARAM->currLine )
|
|
{
|
|
yyclearin;
|
|
}
|
|
else
|
|
{
|
|
yyerrok;
|
|
HB_COMP_PARAM->ilastLineErr = HB_COMP_PARAM->currLine;
|
|
}
|
|
$<lNumber>$ = 0;
|
|
}
|
|
;
|
|
|
|
ControlError : FunScopeId FUNCTION IdentName Crlf
|
|
| FunScopeId FUNCTION IdentName '(' Params ')' Crlf
|
|
| FunScopeId PROCEDURE IdentName Crlf
|
|
| FunScopeId PROCEDURE IdentName '(' Params ')' Crlf
|
|
;
|
|
|
|
FunScopeId :
|
|
| STATIC
|
|
| INIT
|
|
| EXIT
|
|
;
|
|
|
|
Statements : LineStat
|
|
| Statements LineStat { $<lNumber>$ += $<lNumber>2; }
|
|
;
|
|
|
|
EmptyStats : /* empty */ { $<lNumber>$ = 0; }
|
|
| Statements
|
|
;
|
|
|
|
ExtList : IdentName { hb_compExternAdd( HB_COMP_PARAM, $1, 0 ); }
|
|
| ExtList ',' IdentName { hb_compExternAdd( HB_COMP_PARAM, $3, 0 ); }
|
|
;
|
|
|
|
DynList : IdentName { hb_compExternAdd( HB_COMP_PARAM, $1, HB_FS_DEFERRED ); }
|
|
| DynList ',' IdentName { hb_compExternAdd( HB_COMP_PARAM, $3, HB_FS_DEFERRED ); }
|
|
;
|
|
|
|
IdentName : IDENTIFIER
|
|
| STEP { $$ = "STEP"; }
|
|
| TO { $$ = "TO"; }
|
|
| LOOP { $$ = "LOOP"; }
|
|
| EXIT { $$ = "EXIT"; }
|
|
| IN { $$ = "IN"; }
|
|
| OPTIONAL { $$ = $<string>1; }
|
|
| EXTERN { $$ = $<string>1; }
|
|
| DYNAMIC { $$ = $<string>1; }
|
|
| ANNOUNCE { $$ = $<string>1; }
|
|
| LOCAL { $$ = $<string>1; }
|
|
| MEMVAR { $$ = $<string>1; }
|
|
| STATIC { $$ = $<string>1; }
|
|
| PRIVATE { $$ = $<string>1; }
|
|
| PUBLIC { $$ = $<string>1; }
|
|
| PARAMETERS { $$ = $<string>1; }
|
|
| PROCREQ { $$ = $<string>1; }
|
|
| DESCEND { $$ = $<string>1; }
|
|
| THREAD { $$ = $<string>1; }
|
|
;
|
|
|
|
/* Numeric values
|
|
*/
|
|
NumValue : NUM_DOUBLE { $$ = hb_compExprNewDouble( $1.dNumber, $1.bWidth, $1.bDec, HB_COMP_PARAM ); }
|
|
| NUM_LONG { $$ = hb_compExprNewLong( $1.lNumber, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
DateValue : NUM_DATE { $$ = hb_compExprNewDate( ( long ) $1.lNumber, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
TimeStampValue : TIMESTAMP { $$ = hb_compExprNewTimeStamp( $1.date, $1.time, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
NumAlias : NUM_LONG ALIASOP { $$ = hb_compExprNewLong( $1.lNumber, HB_COMP_PARAM ); }
|
|
| NUM_DOUBLE ALIASOP { $$ = hb_compErrorAlias( HB_COMP_PARAM, hb_compExprNewDouble( $1.dNumber, $1.bWidth, $1.bDec, HB_COMP_PARAM ) ); }
|
|
;
|
|
|
|
/* NIL value
|
|
*/
|
|
NilValue : NIL { $$ = hb_compExprNewNil( HB_COMP_PARAM ); }
|
|
;
|
|
|
|
NilAlias : NilValue ALIASOP
|
|
;
|
|
|
|
/* Literal string value
|
|
*/
|
|
LiteralValue : LITERAL {
|
|
$$ = hb_compExprNewString( $1.string, $1.length, $1.dealloc, HB_COMP_PARAM );
|
|
$1.dealloc = HB_FALSE;
|
|
}
|
|
;
|
|
|
|
LiteralAlias : LiteralValue ALIASOP
|
|
;
|
|
|
|
/* Codeblock value
|
|
*/
|
|
CodeBlockAlias : CodeBlock ALIASOP
|
|
;
|
|
|
|
/* Logical value
|
|
*/
|
|
Logical : TRUEVALUE { $$ = hb_compExprNewLogical( HB_TRUE, HB_COMP_PARAM ); }
|
|
| FALSEVALUE { $$ = hb_compExprNewLogical( HB_FALSE, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
LogicalAlias : Logical ALIASOP
|
|
;
|
|
|
|
/* SELF value and expressions
|
|
*/
|
|
SelfValue : SELF { $$ = hb_compExprNewSelf( HB_COMP_PARAM ); }
|
|
;
|
|
|
|
SelfAlias : SelfValue ALIASOP
|
|
;
|
|
|
|
/* Literal array
|
|
*/
|
|
/*
|
|
Array : '{' { $<bTrue>$=HB_COMP_PARAM->iPassByRef; HB_COMP_PARAM->iPassByRef=HB_PASSBYREF_ARRAY; }
|
|
ElemList
|
|
'}' { $$ = hb_compExprNewArray( $3, HB_COMP_PARAM ); HB_COMP_PARAM->iPassByRef=$<bTrue>2; }
|
|
;
|
|
*/
|
|
Array : '{' ElemList '}' { $$ = hb_compExprNewArray( $2, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ArrayAlias : Array ALIASOP
|
|
;
|
|
|
|
/* Literal array access
|
|
*/
|
|
ArrayAt : Array ArrayIndex { $$ = $2; }
|
|
;
|
|
|
|
ArrayAtAlias : ArrayAt ALIASOP
|
|
;
|
|
|
|
Hash : '{' HASHOP '}' { $$ = hb_compExprNewHash( NULL, HB_COMP_PARAM ); }
|
|
| '{' HashList '}' { $$ = hb_compExprNewHash( $2, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
HashAlias: Hash ALIASOP
|
|
;
|
|
|
|
HashList : Expression HASHOP EmptyExpression { $$ = hb_compExprAddListExpr( hb_compExprNewList( $1, HB_COMP_PARAM ), $3 ); }
|
|
| HashList ',' Expression HASHOP EmptyExpression { $$ = hb_compExprAddListExpr( hb_compExprAddListExpr( $1, $3 ), $5 ); }
|
|
;
|
|
|
|
/* Variables
|
|
*/
|
|
Variable : IdentName { $$ = hb_compExprNewVar( $1, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
VarAlias : IdentName ALIASOP { $$ = hb_compExprNewAlias( $1, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
/* Macro variables
|
|
*/
|
|
MacroVar : MACROVAR { $$ = hb_compExprNewMacro( NULL, '&', $1, HB_COMP_PARAM ); }
|
|
| MACROTEXT { $$ = hb_compExprNewMacro( NULL, 0, $1, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
MacroVarAlias : MacroVar ALIASOP
|
|
;
|
|
|
|
/* Macro expressions
|
|
*/
|
|
MacroExpr : '&' PareExpList { $$ = hb_compExprNewMacro( $2, 0, NULL, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
MacroExprAlias : MacroExpr ALIASOP
|
|
;
|
|
|
|
MacroAny : MacroVar
|
|
| MacroExpr
|
|
;
|
|
|
|
/* Aliased variables
|
|
*/
|
|
/* special case: _FIELD-> and FIELD-> can be nested
|
|
*/
|
|
FieldAlias : FIELD ALIASOP { $$ = hb_compExprNewAlias( "FIELD", HB_COMP_PARAM ); }
|
|
| FIELD ALIASOP FieldAlias { $$ = $3; }
|
|
;
|
|
|
|
/* ignore _FIELD-> or FIELD-> if a real alias is specified
|
|
*/
|
|
FieldVarAlias : FieldAlias VarAlias { HB_COMP_EXPR_FREE( $1 ); $$ = $2; }
|
|
| FieldAlias NumAlias { HB_COMP_EXPR_FREE( $1 ); $$ = $2; }
|
|
| FieldAlias PareExpListAlias { HB_COMP_EXPR_FREE( $1 ); $$ = $2; }
|
|
| FieldAlias MacroVarAlias { HB_COMP_EXPR_FREE( $1 ); $$ = $2; }
|
|
| FieldAlias MacroExprAlias { HB_COMP_EXPR_FREE( $1 ); $$ = $2; }
|
|
| FieldAlias NilAlias { HB_COMP_EXPR_FREE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias LiteralAlias { HB_COMP_EXPR_FREE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias LogicalAlias { HB_COMP_EXPR_FREE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias CodeBlockAlias { HB_COMP_EXPR_FREE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias SelfAlias { HB_COMP_EXPR_FREE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias ArrayAlias { HB_COMP_EXPR_FREE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias ArrayAtAlias { HB_COMP_EXPR_FREE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias HashAlias { HB_COMP_EXPR_FREE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias IfInlineAlias { HB_COMP_EXPR_FREE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
;
|
|
|
|
AliasId : IdentName { $$ = hb_compExprNewVar( $1, HB_COMP_PARAM ); }
|
|
| MacroAny
|
|
;
|
|
|
|
AliasVar : NumAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2, HB_COMP_PARAM ); }
|
|
| MacroVarAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2, HB_COMP_PARAM ); }
|
|
| MacroExprAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2, HB_COMP_PARAM ); }
|
|
| PareExpListAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2, HB_COMP_PARAM ); }
|
|
| NilAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| LiteralAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| LogicalAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| CodeBlockAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| HashAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| SelfAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| ArrayAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| ArrayAtAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); } /* QUESTION: Clipper reports error here - we can handle this */
|
|
| VariableAtAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); } /* QUESTION: Clipper reports error here - we can handle this */
|
|
| IfInlineAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); } /* QUESTION: Clipper reports error here - we can handle this */
|
|
| FunCallAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); } /* QUESTION: Clipper reports error here - we can handle this */
|
|
| ObjectDataAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); } /* QUESTION: Clipper reports error here - we can handle this */
|
|
| ObjectMethodAlias AliasId { HB_COMP_EXPR_FREE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); } /* QUESTION: Clipper reports error here - we can handle this */
|
|
| VarAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2, HB_COMP_PARAM ); }
|
|
| FieldAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2, HB_COMP_PARAM ); }
|
|
| FieldVarAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
/* Aliased expressions
|
|
*/
|
|
/* NOTE: In the case:
|
|
* alias->( Expression )
|
|
* alias always selects a workarea at runtime
|
|
*/
|
|
AliasExpr : NumAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2, HB_COMP_PARAM ); }
|
|
| VarAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2, HB_COMP_PARAM ); }
|
|
| MacroVarAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2, HB_COMP_PARAM ); }
|
|
| MacroExprAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2, HB_COMP_PARAM ); }
|
|
| PareExpListAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2, HB_COMP_PARAM ); }
|
|
| FieldAlias PareExpList { HB_COMP_EXPR_FREE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); } /* QUESTION: Clipper reports error here - we can handle it */
|
|
;
|
|
|
|
/* Array expressions access
|
|
*/
|
|
VariableAt : NumValue ArrayIndex { $$ = $2; }
|
|
| NilValue ArrayIndex { $$ = $2; }
|
|
| DateValue ArrayIndex { $$ = $2; }
|
|
| TimeStampValue ArrayIndex { $$ = $2; }
|
|
| LiteralValue ArrayIndex { $$ = $2; }
|
|
| CodeBlock ArrayIndex { $$ = $2; }
|
|
| Logical ArrayIndex { $$ = $2; }
|
|
| Hash ArrayIndex { $$ = $2; }
|
|
| SelfValue ArrayIndex { $$ = $2; }
|
|
| Variable ArrayIndex { $$ = $2; }
|
|
| AliasVar ArrayIndex { $$ = $2; }
|
|
| AliasExpr ArrayIndex { $$ = $2; }
|
|
| MacroAny ArrayIndex { $$ = $2; }
|
|
| ObjectData ArrayIndex { $$ = $2; }
|
|
| ObjectMethod ArrayIndex { $$ = $2; }
|
|
| FunCall ArrayIndex { $$ = $2; }
|
|
| IfInline ArrayIndex { $$ = $2; }
|
|
| PareExpList ArrayIndex { $$ = $2; }
|
|
;
|
|
|
|
VariableAtAlias : VariableAt ALIASOP
|
|
;
|
|
/* function call
|
|
*/
|
|
FunIdentCall: IdentName '(' ArgList ')' { $$ = hb_compExprNewFunCall( hb_compExprNewFunName( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
FunCall : FunIdentCall
|
|
| MacroAny '(' ArgList ')' { $$ = hb_compExprNewFunCall( $1, $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
/* FunRef : '@' FunCall { $$ = hb_compCheckPassByRef( HB_COMP_PARAM, $2 ); } */
|
|
FunRef : '@' FunIdentCall { $$ = hb_compCheckPassByRef( HB_COMP_PARAM, $2 ); }
|
|
;
|
|
|
|
FunCallAlias : FunCall ALIASOP
|
|
;
|
|
|
|
ArgList : ExtArgument { $$ = hb_compExprNewArgList( $1, HB_COMP_PARAM ); }
|
|
| ArgList ',' ExtArgument { $$ = hb_compExprAddListExpr( $1, $3 ); }
|
|
;
|
|
|
|
Argument : EmptyExpression
|
|
| RefArgument
|
|
;
|
|
|
|
RefArgument : '@' IdentName { $$ = hb_compCheckPassByRef( HB_COMP_PARAM, hb_compExprNewVarRef( $2, HB_COMP_PARAM ) ); }
|
|
| '@' MacroVar { $$ = hb_compCheckPassByRef( HB_COMP_PARAM, hb_compExprNewRef( $2, HB_COMP_PARAM ) ); }
|
|
| '@' AliasVar { $$ = hb_compCheckPassByRef( HB_COMP_PARAM, hb_compExprNewRef( $2, HB_COMP_PARAM ) ); }
|
|
| '@' ObjectData { $$ = hb_compCheckPassByRef( HB_COMP_PARAM, hb_compExprNewRef( $2, HB_COMP_PARAM ) ); }
|
|
| '@' VariableAt { $$ = hb_compCheckPassByRef( HB_COMP_PARAM, $2 ); $$->value.asList.reference = HB_TRUE; }
|
|
;
|
|
|
|
ExtArgument : EPSILON { $$ = hb_compExprNewArgRef( HB_COMP_PARAM ); }
|
|
| Argument
|
|
;
|
|
|
|
/* Object's instance variable
|
|
*/
|
|
ObjectData : LeftExpression ':' SendId { $$ = hb_compCheckMethod( HB_COMP_PARAM, hb_compExprNewMethodObject( $3, $1 ) ); }
|
|
| ObjectRef ':' SendId { $$ = hb_compExprNewMethodObject( $3, $1 ); }
|
|
| ':' SendId { if( HB_COMP_PARAM->functions.pLast->wWithObjectCnt == 0 )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_WITHOBJECT, NULL, NULL );
|
|
$$ = $2;
|
|
}
|
|
;
|
|
|
|
SendId : IdentName { $$ = hb_compExprNewSend( $1, HB_COMP_PARAM ); }
|
|
| MacroAny { $$ = hb_compExprNewMacroSend( $1, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ObjectRef : '(' '@' IdentName ')' { $$ = hb_compExprNewVarRef( $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ObjectDataAlias : ObjectData ALIASOP
|
|
;
|
|
|
|
/* Object's method
|
|
*/
|
|
ObjectMethod : ObjectData '(' ArgList ')' { $$ = hb_compExprNewMethodCall( $1, $3 ); }
|
|
;
|
|
|
|
ObjectMethodAlias : ObjectMethod ALIASOP
|
|
;
|
|
|
|
|
|
/* NOTE: We have to distinguish IdentName here because it is repeated
|
|
* in DoArgument (a part of DO <proc> WITH .. statement)
|
|
* where it generates different action.
|
|
*/
|
|
SimpleExpression :
|
|
NumValue
|
|
| NilValue
|
|
| DateValue
|
|
| TimeStampValue
|
|
| LiteralValue
|
|
| CodeBlock
|
|
| Logical
|
|
| SelfValue
|
|
| SelfValue StrongType { $$ = $1; }
|
|
| Array
|
|
| ArrayAt
|
|
| Hash
|
|
| AliasVar
|
|
| AliasExpr
|
|
| MacroVar
|
|
| MacroExpr
|
|
| VariableAt
|
|
| FunCall
|
|
| FunCall StrongType { $$ = $1; }
|
|
| IfInline
|
|
| ObjectData
|
|
| ObjectData StrongType { $$ = $1; }
|
|
| ObjectMethod
|
|
| ObjectMethod StrongType { $$ = $1; }
|
|
| ExprAssign
|
|
| ExprOperEq
|
|
| ExprPostOp
|
|
| ExprPreOp
|
|
| ExprUnary
|
|
| ExprMath
|
|
| ExprBool
|
|
| ExprRelation
|
|
;
|
|
|
|
Expression : SimpleExpression
|
|
| Variable
|
|
| PareExpList
|
|
| Variable StrongType { $$ = $1; }
|
|
| PareExpList StrongType { $$ = $1; }
|
|
| FunRef
|
|
;
|
|
|
|
ExtExpression : EPSILON { $$ = hb_compExprNewArgRef( HB_COMP_PARAM ); }
|
|
| Expression
|
|
;
|
|
|
|
EmptyExpression : /* nothing => nil */ { $$ = hb_compExprNewEmpty( HB_COMP_PARAM ); }
|
|
| Expression
|
|
;
|
|
|
|
LValue : IdentName { $$ = hb_compExprNewVar( $1, HB_COMP_PARAM ); }
|
|
| AliasVar
|
|
| MacroVar
|
|
| MacroExpr
|
|
| ObjectData
|
|
| VariableAt
|
|
| PareExpList { $$ = hb_compExprListStrip( $1, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
/* 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
|
|
*/
|
|
LeftExpression : NumValue
|
|
| NilValue
|
|
| DateValue
|
|
| TimeStampValue
|
|
| LiteralValue
|
|
| CodeBlock
|
|
| Logical
|
|
| SelfValue
|
|
| Array
|
|
| ArrayAt
|
|
| Hash
|
|
| AliasVar
|
|
| AliasExpr
|
|
| MacroAny
|
|
| Variable
|
|
| VariableAt
|
|
| PareExpList
|
|
| FunCall
|
|
| IfInline
|
|
| ObjectData
|
|
| ObjectMethod
|
|
;
|
|
|
|
/* NOTE: PostOp can be used in one context only - it uses $0 rule
|
|
* (the rule that stands before PostOp)
|
|
*/
|
|
PostOp : INC { $$ = hb_compExprNewPostInc( $<asExpr>0, HB_COMP_PARAM ); }
|
|
| DEC { $$ = hb_compExprNewPostDec( $<asExpr>0, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprPostOp : LeftExpression PostOp %prec POST { $$ = $2; }
|
|
;
|
|
|
|
ExprPreOp : INC Expression %prec PRE { $$ = hb_compExprNewPreInc( $2, HB_COMP_PARAM ); }
|
|
| DEC Expression %prec PRE { $$ = hb_compExprNewPreDec( $2, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprUnary : NOT Expression { $$ = hb_compExprNewNot( $2, HB_COMP_PARAM ); }
|
|
| '-' Expression %prec UNARY { $$ = hb_compExprNewNegate( $2, HB_COMP_PARAM ); }
|
|
| '+' Expression %prec UNARY { $$ = $2; }
|
|
;
|
|
|
|
ExprEqual : LeftExpression '=' Expression %prec INASSIGN { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprAssign : LeftExpression INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprPlusEq : LeftExpression PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprMinusEq : LeftExpression MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprMultEq : LeftExpression MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprDivEq : LeftExpression DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprModEq : LeftExpression MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprExpEq : LeftExpression EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprOperEq : ExprPlusEq
|
|
| ExprMinusEq
|
|
| ExprMultEq
|
|
| ExprDivEq
|
|
| ExprModEq
|
|
| ExprExpEq
|
|
;
|
|
|
|
ExprMath : Expression '+' Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlus( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression '-' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinus( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression '*' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMult( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression '/' Expression { $$ = hb_compExprSetOperand( hb_compExprNewDiv( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression '%' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMod( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression POWER Expression { $$ = hb_compExprSetOperand( hb_compExprNewPower( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprBool : Expression AND Expression { $$ = hb_compExprSetOperand( hb_compExprNewAnd( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression OR Expression { $$ = hb_compExprSetOperand( hb_compExprNewOr( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprRelation: Expression EQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewEQ( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression '<' Expression { $$ = hb_compExprSetOperand( hb_compExprNewLT( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression '>' Expression { $$ = hb_compExprSetOperand( hb_compExprNewGT( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression LE Expression { $$ = hb_compExprSetOperand( hb_compExprNewLE( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression GE Expression { $$ = hb_compExprSetOperand( hb_compExprNewGE( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression NE1 Expression { $$ = hb_compExprSetOperand( hb_compExprNewNE( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression NE2 Expression { $$ = hb_compExprSetOperand( hb_compExprNewNE( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression '$' Expression { $$ = hb_compExprSetOperand( hb_compExprNewIN( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
| Expression '=' Expression { $$ = hb_compExprSetOperand( hb_compExprNewEqual( $1, HB_COMP_PARAM ), $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ArrayIndex : IndexList ']'
|
|
;
|
|
|
|
/* NOTE: $0 represents the expression before ArrayIndex
|
|
* Don't use ArrayIndex in other context than as an array index!
|
|
*/
|
|
IndexList : '[' ExtExpression { $$ = hb_compExprNewArrayAt( $<asExpr>0, $2, HB_COMP_PARAM ); }
|
|
| IndexList ',' ExtExpression { $$ = hb_compExprNewArrayAt( $1, $3, HB_COMP_PARAM ); }
|
|
| IndexList ']' '[' ExtExpression { $$ = hb_compExprNewArrayAt( $1, $4, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ElemList : ExtArgument { $$ = hb_compExprNewList( $1, HB_COMP_PARAM ); }
|
|
| ElemList ',' ExtArgument { $$ = hb_compExprAddListExpr( $1, $3 ); }
|
|
;
|
|
|
|
BlockHead : CBSTART { $<asExpr>$ = hb_compExprNewCodeBlock( $1.string, $1.length, $1.flags, HB_COMP_PARAM ); $1.string = NULL; }
|
|
BlockVars '|' { $$ = $<asExpr>2; }
|
|
;
|
|
|
|
/* NOTE: This uses $0 then don't use BlockVars, BlockVarList and BlockExpList in other context
|
|
*/
|
|
BlockVars : /* empty list */ { $$ = NULL; }
|
|
| EPSILON { $$ = NULL; $<asExpr>0->value.asCodeblock.flags |= HB_BLOCK_VPARAMS; }
|
|
| BlockVarList { $$ = $1; }
|
|
| BlockVarList ',' EPSILON { $$ = $1; $<asExpr>0->value.asCodeblock.flags |= HB_BLOCK_VPARAMS; }
|
|
;
|
|
|
|
BlockVarList : IdentName AsType { HB_COMP_PARAM->iVarScope = HB_VSCOMP_LOCAL; $$ = hb_compExprCBVarAdd( $<asExpr>0, $1, $2->cVarType, HB_COMP_PARAM ); }
|
|
| BlockVarList ',' IdentName AsType { HB_COMP_PARAM->iVarScope = HB_VSCOMP_LOCAL; $$ = hb_compExprCBVarAdd( $<asExpr>0, $3, $4->cVarType, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
BlockExpList : Expression { $$ = hb_compExprAddCodeblockExpr( $<asExpr>-1, $1 ); }
|
|
| BlockExpList ',' Expression { $$ = hb_compExprAddCodeblockExpr( $<asExpr>-1, $3 ); }
|
|
;
|
|
|
|
CodeBlock : BlockHead
|
|
{ $<bTrue>$ = HB_COMP_PARAM->functions.pLast->bBlock;
|
|
HB_COMP_PARAM->functions.pLast->bBlock = HB_TRUE; }
|
|
BlockExpList
|
|
{ HB_COMP_PARAM->functions.pLast->bBlock = $<bTrue>2; }
|
|
'}'
|
|
| BlockHead Crlf
|
|
{ /* 3 */
|
|
PHB_CBVAR pVar;
|
|
$<sNumber>$ = HB_COMP_PARAM->functions.pLast->nPCodePos;
|
|
$<sNumber>2 = HB_COMP_PARAM->lastLine;
|
|
hb_compCodeBlockStart( HB_COMP_PARAM, 0 );
|
|
HB_COMP_PARAM->functions.pLast->funFlags |= HB_FUNF_EXTBLOCK;
|
|
HB_COMP_PARAM->functions.pLast->fVParams =
|
|
( $1->value.asCodeblock.flags & HB_BLOCK_VPARAMS ) != 0;
|
|
|
|
$1->value.asCodeblock.flags |= HB_BLOCK_EXT;
|
|
if( $1->value.asCodeblock.string )
|
|
{
|
|
hb_xfree( $1->value.asCodeblock.string );
|
|
$1->value.asCodeblock.string = NULL;
|
|
$1->nLength = 0;
|
|
}
|
|
|
|
HB_COMP_PARAM->iVarScope = HB_VSCOMP_PARAMETER;
|
|
pVar = $1->value.asCodeblock.pLocals;
|
|
while( pVar )
|
|
{
|
|
hb_compVariableAdd( HB_COMP_PARAM, pVar->szName, hb_compVarTypeNew( HB_COMP_PARAM, pVar->bType, NULL ) );
|
|
pVar =pVar->pNext;
|
|
}
|
|
}
|
|
EmptyStats '}'
|
|
{ /* 6 */
|
|
hb_compCodeBlockEnd( HB_COMP_PARAM );
|
|
$$ = hb_compExprSetCodeblockBody( $1,
|
|
HB_COMP_PARAM->functions.pLast->pCode + $<sNumber>3,
|
|
HB_COMP_PARAM->functions.pLast->nPCodePos - $<sNumber>3 );
|
|
HB_COMP_PARAM->functions.pLast->nPCodePos = $<sNumber>3;
|
|
HB_COMP_PARAM->lastLine = $<sNumber>2;
|
|
}
|
|
;
|
|
|
|
ExpList : Expression { $$ = hb_compExprNewList( $1, HB_COMP_PARAM ); }
|
|
| ExpList ',' Expression { $$ = hb_compExprAddListExpr( $1, $3 ); }
|
|
|
|
PareExpList : '(' ExpList ')' { $$ = $2; }
|
|
;
|
|
|
|
PareExpListAlias : PareExpList ALIASOP
|
|
;
|
|
|
|
/* NOTE: Clipper allows to pass variable by reference only as
|
|
* function arguments, IIF() 2-nd and 3-rd arguments and as
|
|
* explicit array items {...@var...}
|
|
* AFAIK these are also the only one places where empty expressions in
|
|
* the parenthesis expressions list are accepted
|
|
*/
|
|
IfInline : IIF '(' Expression ',' Argument ',' Argument ')'
|
|
{ $$ = hb_compExprNewIIF( hb_compExprAddListExpr( hb_compExprAddListExpr( hb_compExprNewList( $3, HB_COMP_PARAM ), $5 ), $7 ) ); }
|
|
;
|
|
|
|
IfInlineAlias : IfInline ALIASOP
|
|
;
|
|
|
|
VarDefs : LOCAL { HB_COMP_PARAM->iVarScope = HB_VSCOMP_LOCAL; hb_compLinePush( HB_COMP_PARAM ); }
|
|
VarList Crlf
|
|
| STATIC { HB_COMP_PARAM->iVarScope = HB_VSCOMP_STATIC; hb_compLinePush( HB_COMP_PARAM ); }
|
|
VarList Crlf
|
|
| THREAD STATIC { HB_COMP_PARAM->iVarScope = HB_VSCOMP_TH_STATIC; hb_compLinePush( HB_COMP_PARAM ); }
|
|
VarList Crlf
|
|
| PARAMETERS { if( HB_COMP_PARAM->functions.pLast->funFlags & HB_FUNF_USES_LOCAL_PARAMS )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_PARAMETERS_NOT_ALLOWED, NULL, NULL );
|
|
else
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->wParamNum = 0;
|
|
HB_COMP_PARAM->iVarScope = ( HB_VSCOMP_PRIVATE | HB_VSCOMP_PARAMETER );
|
|
}
|
|
} MemvarList Crlf { HB_COMP_PARAM->iVarScope = HB_VSCOMP_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_COMP_PARAM, hb_compExprNewRTVar( NULL, $1, HB_COMP_PARAM ), HB_FALSE ); }
|
|
| MacroVar AsType INASSIGN Expression
|
|
{ HB_COMP_EXPR_FREE( hb_compExprGenPush( $4, HB_COMP_PARAM ) );
|
|
hb_compRTVariableAdd( HB_COMP_PARAM, hb_compExprNewRTVar( NULL, $1, HB_COMP_PARAM ), HB_TRUE );
|
|
}
|
|
| MacroVar DimList AsArrayType
|
|
{
|
|
HB_COMP_EXPR_FREE( hb_compArrayDimPush( $2, HB_COMP_PARAM ) );
|
|
hb_compRTVariableAdd( HB_COMP_PARAM, hb_compExprNewRTVar( NULL, $1, HB_COMP_PARAM ), HB_TRUE );
|
|
}
|
|
;
|
|
|
|
VarDef : IdentName AsType
|
|
{
|
|
hb_compVariableAdd( HB_COMP_PARAM, $1, $2 );
|
|
if( HB_COMP_PARAM->iVarScope & HB_VSCOMP_STATIC )
|
|
{
|
|
hb_compStaticDefStart( HB_COMP_PARAM ); /* switch to statics pcode buffer */
|
|
hb_compStaticDefEnd( HB_COMP_PARAM, $1 );
|
|
}
|
|
else if( HB_COMP_PARAM->iVarScope == HB_VSCOMP_PUBLIC || HB_COMP_PARAM->iVarScope == HB_VSCOMP_PRIVATE )
|
|
{
|
|
hb_compRTVariableAdd( HB_COMP_PARAM, hb_compExprNewRTVar( $1, NULL, HB_COMP_PARAM ), HB_FALSE );
|
|
}
|
|
else if( HB_COMP_PARAM->iVarScope == HB_VSCOMP_LOCAL &&
|
|
( HB_COMP_PARAM->functions.pLast->funFlags & HB_FUNF_EXTBLOCK ) )
|
|
{
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPush( hb_compExprNewNil( HB_COMP_PARAM ), HB_COMP_PARAM ) );
|
|
}
|
|
}
|
|
| IdentName AsType { $<iNumber>$ = HB_COMP_PARAM->iVarScope;
|
|
hb_compVariableAdd( HB_COMP_PARAM, $1, $2 );
|
|
}
|
|
INASSIGN Expression
|
|
{
|
|
HB_COMP_PARAM->iVarScope = $<iNumber>3;
|
|
if( HB_COMP_PARAM->iVarScope & HB_VSCOMP_STATIC )
|
|
{
|
|
hb_compStaticDefStart( HB_COMP_PARAM ); /* switch to statics pcode buffer */
|
|
HB_COMP_EXPR_FREE( hb_compExprGenStatement( hb_compExprAssignStatic( hb_compExprNewVar( $1, HB_COMP_PARAM ), $5, HB_COMP_PARAM ), HB_COMP_PARAM ) );
|
|
hb_compStaticDefEnd( HB_COMP_PARAM, $1 );
|
|
}
|
|
else if( HB_COMP_PARAM->iVarScope == HB_VSCOMP_PUBLIC || HB_COMP_PARAM->iVarScope == HB_VSCOMP_PRIVATE )
|
|
{
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPush( $5, HB_COMP_PARAM ) );
|
|
hb_compRTVariableAdd( HB_COMP_PARAM, hb_compExprNewRTVar( $1, NULL, HB_COMP_PARAM ), HB_TRUE );
|
|
}
|
|
else if( HB_COMP_PARAM->iVarScope == HB_VSCOMP_LOCAL &&
|
|
( HB_COMP_PARAM->functions.pLast->funFlags & HB_FUNF_EXTBLOCK ) )
|
|
{
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPush( $5, HB_COMP_PARAM ) );
|
|
}
|
|
else
|
|
{
|
|
HB_COMP_EXPR_FREE( hb_compExprGenStatement( hb_compExprAssign( hb_compExprNewVar( $1, HB_COMP_PARAM ), $5, HB_COMP_PARAM ), HB_COMP_PARAM ) );
|
|
}
|
|
HB_COMP_PARAM->iVarScope = $<iNumber>3;
|
|
}
|
|
|
|
| IdentName DimList AsArrayType { hb_compVariableDim( $1, $2, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
/* NOTE: DimList and DimIndex is the same as ArrayIndex and IndexList
|
|
* however we are using quite different actions here
|
|
*/
|
|
DimList : DimIndex ']'
|
|
;
|
|
|
|
DimIndex : '[' Expression { $$ = hb_compExprNewArgList( $2, HB_COMP_PARAM ); }
|
|
| DimIndex ',' Expression { $$ = hb_compExprAddListExpr( $1, $3 ); }
|
|
| DimIndex ']' '[' Expression { $$ = hb_compExprAddListExpr( $1, $4 ); }
|
|
;
|
|
|
|
FieldsDef : FIELD { HB_COMP_PARAM->iVarScope = HB_VSCOMP_FIELD; }
|
|
FieldList InAlias Crlf
|
|
{
|
|
if( $4 ) hb_compFieldSetAlias( HB_COMP_PARAM, $4, $3 );
|
|
}
|
|
;
|
|
|
|
FieldList : IdentName AsType { $$ = hb_compFieldsCount( HB_COMP_PARAM ); hb_compVariableAdd( HB_COMP_PARAM, $1, $2 ); }
|
|
| FieldList ',' IdentName AsType { hb_compVariableAdd( HB_COMP_PARAM, $3, $4 ); }
|
|
;
|
|
|
|
InAlias : /* no alias */ { $$ = NULL; }
|
|
| IN IdentName { $$ = $2; }
|
|
;
|
|
|
|
MemvarDef : MEMVAR { HB_COMP_PARAM->iVarScope = HB_VSCOMP_MEMVAR; } MemvarList Crlf
|
|
;
|
|
|
|
MemvarList : IdentName AsType { hb_compVariableAdd( HB_COMP_PARAM, $1, $2 ); }
|
|
| MemvarList ',' IdentName AsType { hb_compVariableAdd( HB_COMP_PARAM, $3, $4 ); }
|
|
;
|
|
|
|
Declaration: DECLARE IdentName '(' { hb_compDeclaredAdd( HB_COMP_PARAM, $2 ); HB_COMP_PARAM->szDeclaredFun = $2; } DecList ')' AsType Crlf
|
|
{
|
|
if( HB_COMP_PARAM->pLastDeclared )
|
|
{
|
|
HB_COMP_PARAM->pLastDeclared->cType = $7->cVarType;
|
|
|
|
if( HB_TOUPPER( $7->cVarType ) == 'S' )
|
|
{
|
|
HB_COMP_PARAM->pLastDeclared->pClass = hb_compClassFind( HB_COMP_PARAM, $7->szFromClass );
|
|
if( ! HB_COMP_PARAM->pLastDeclared->pClass )
|
|
{
|
|
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_CLASS_NOT_FOUND, $7->szFromClass, HB_COMP_PARAM->pLastDeclared->szName );
|
|
HB_COMP_PARAM->pLastDeclared->cType = ( HB_ISUPPER( ( HB_UCHAR ) $7->cVarType ) ? 'O' : 'o' );
|
|
}
|
|
}
|
|
}
|
|
HB_COMP_PARAM->szDeclaredFun = NULL;
|
|
HB_COMP_PARAM->iVarScope = HB_VSCOMP_NONE;
|
|
}
|
|
| DECLARE IdentName { HB_COMP_PARAM->pLastClass = hb_compClassAdd( HB_COMP_PARAM, $2, NULL ); } ClassInfo Crlf { HB_COMP_PARAM->iVarScope = HB_VSCOMP_NONE; }
|
|
| DECLARE_CLASS IdentName Crlf { HB_COMP_PARAM->pLastClass = hb_compClassAdd( HB_COMP_PARAM, $2, NULL ); HB_COMP_PARAM->iVarScope = HB_VSCOMP_NONE; }
|
|
| DECLARE_CLASS IdentName IdentName Crlf { HB_COMP_PARAM->pLastClass = hb_compClassAdd( HB_COMP_PARAM, $2, $3 ); HB_COMP_PARAM->iVarScope = HB_VSCOMP_NONE; }
|
|
| DECLARE_MEMBER DecMethod Crlf { HB_COMP_PARAM->iVarScope = HB_VSCOMP_NONE; }
|
|
| DECLARE_MEMBER '{' AsType { HB_COMP_PARAM->cDataListType = $3->cVarType; } DecDataList '}' Crlf { HB_COMP_PARAM->cDataListType = 0; HB_COMP_PARAM->iVarScope = HB_VSCOMP_NONE; }
|
|
;
|
|
|
|
DecDataList: DecData
|
|
| DecDataList ',' DecData
|
|
;
|
|
|
|
ClassInfo : DecMethod
|
|
| ClassInfo DecMethod
|
|
| DecData
|
|
| ClassInfo DecData
|
|
;
|
|
|
|
DecMethod : IdentName '(' { HB_COMP_PARAM->pLastMethod = hb_compMethodAdd( HB_COMP_PARAM, HB_COMP_PARAM->pLastClass, $1 ); } DecListExt ')' AsType
|
|
{
|
|
if( HB_COMP_PARAM->pLastMethod )
|
|
{
|
|
HB_COMP_PARAM->pLastMethod->cType = $6->cVarType;
|
|
if( HB_TOUPPER( $6->cVarType ) == 'S' )
|
|
{
|
|
HB_COMP_PARAM->pLastMethod->pClass = hb_compClassFind( HB_COMP_PARAM, $6->szFromClass );
|
|
if( ! HB_COMP_PARAM->pLastMethod->pClass )
|
|
{
|
|
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_CLASS_NOT_FOUND, $6->szFromClass, HB_COMP_PARAM->pLastMethod->szName );
|
|
HB_COMP_PARAM->pLastMethod->cType = ( HB_ISUPPER( ( HB_UCHAR ) $6->cVarType ) ? 'O' : 'o' );
|
|
}
|
|
}
|
|
}
|
|
HB_COMP_PARAM->pLastMethod = NULL;
|
|
}
|
|
;
|
|
|
|
DecData : IdentName { HB_COMP_PARAM->pLastMethod = hb_compMethodAdd( HB_COMP_PARAM, HB_COMP_PARAM->pLastClass, $1 ); } AsType
|
|
{
|
|
if( HB_COMP_PARAM->pLastMethod )
|
|
{
|
|
PHB_HCLASS pClass;
|
|
char szSetData[ HB_SYMBOL_NAME_LEN + 1 ];
|
|
int iLen;
|
|
HB_BYTE cVarType = $3->cVarType;
|
|
|
|
/* List Type overrides if exists. */
|
|
if( HB_COMP_PARAM->cDataListType )
|
|
cVarType = HB_COMP_PARAM->cDataListType;
|
|
|
|
HB_COMP_PARAM->pLastMethod->cType = cVarType;
|
|
if( HB_TOUPPER( cVarType ) == 'S' )
|
|
{
|
|
pClass = hb_compClassFind( HB_COMP_PARAM, $3->szFromClass );
|
|
HB_COMP_PARAM->pLastMethod->pClass = pClass;
|
|
if( ! HB_COMP_PARAM->pLastMethod->pClass )
|
|
{
|
|
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_CLASS_NOT_FOUND, $3->szFromClass, HB_COMP_PARAM->pLastMethod->szName );
|
|
HB_COMP_PARAM->pLastMethod->cType = ( HB_ISUPPER( ( HB_UCHAR ) cVarType ) ? 'O' :'o' );
|
|
}
|
|
}
|
|
else
|
|
pClass = NULL;
|
|
|
|
iLen = ( int ) strlen( $1 );
|
|
if( iLen >= HB_SYMBOL_NAME_LEN )
|
|
iLen = HB_SYMBOL_NAME_LEN - 1;
|
|
szSetData[ 0 ] = '_';
|
|
memcpy( szSetData + 1, $1, iLen );
|
|
szSetData[ iLen + 1 ] = '\0';
|
|
|
|
HB_COMP_PARAM->pLastMethod = hb_compMethodAdd( HB_COMP_PARAM, HB_COMP_PARAM->pLastClass,
|
|
hb_compIdentifierNew( HB_COMP_PARAM, szSetData, HB_IDENT_COPY ) );
|
|
HB_COMP_PARAM->pLastMethod->cType = cVarType;
|
|
HB_COMP_PARAM->pLastMethod->iParamCount = 1;
|
|
|
|
HB_COMP_PARAM->pLastMethod->cParamTypes = ( HB_BYTE * ) hb_xgrab( 1 );
|
|
HB_COMP_PARAM->pLastMethod->pParamClasses = ( PHB_HCLASS * ) hb_xgrab( sizeof( HB_HCLASS ) );
|
|
|
|
HB_COMP_PARAM->pLastMethod->cParamTypes[ 0 ] = cVarType;
|
|
HB_COMP_PARAM->pLastMethod->pParamClasses[ 0 ] = pClass;
|
|
|
|
if( HB_TOUPPER( cVarType ) == 'S' )
|
|
{
|
|
HB_COMP_PARAM->pLastMethod->pClass = pClass;
|
|
}
|
|
}
|
|
|
|
HB_COMP_PARAM->pLastMethod = NULL;
|
|
}
|
|
;
|
|
|
|
DecList : /* Nothing */
|
|
| FormalList
|
|
| OptList
|
|
| FormalList ',' OptList
|
|
;
|
|
|
|
DecListExt : /* Nothing */
|
|
| FormalList
|
|
| OptList
|
|
| EPSILON
|
|
| FormalList ',' EPSILON
|
|
| FormalList ',' OptList
|
|
| FormalList ',' OptList ',' EPSILON
|
|
;
|
|
|
|
DummyArgList : DummyArgument
|
|
| DummyArgList ',' DummyArgument
|
|
;
|
|
|
|
DummyArgument : EmptyExpression { HB_COMP_EXPR_FREE( $1 ); }
|
|
;
|
|
|
|
FormalList : IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $1, $2 ); }
|
|
| '@' IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $2, hb_compVarTypeNew( HB_COMP_PARAM, $3->cVarType + HB_VT_OFFSET_BYREF, NULL ) ); }
|
|
| '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $2, hb_compVarTypeNew( HB_COMP_PARAM, 'F', NULL ) ); }
|
|
| FormalList ',' IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $3, $4 ); }
|
|
| FormalList ',' '@' IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $4, hb_compVarTypeNew( HB_COMP_PARAM, $5->cVarType + HB_VT_OFFSET_BYREF, NULL ) ); }
|
|
| FormalList ',' '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $4, hb_compVarTypeNew( HB_COMP_PARAM, 'F', NULL ) ); }
|
|
;
|
|
|
|
OptList : OPTIONAL IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $2, hb_compVarTypeNew( HB_COMP_PARAM, $3->cVarType + HB_VT_OFFSET_OPTIONAL, NULL ) ); }
|
|
| OPTIONAL '@' IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $3, hb_compVarTypeNew( HB_COMP_PARAM, $4->cVarType + HB_VT_OFFSET_OPTIONAL + HB_VT_OFFSET_BYREF, NULL ) ); }
|
|
| OPTIONAL '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $3, hb_compVarTypeNew( HB_COMP_PARAM, 'F' + HB_VT_OFFSET_OPTIONAL + HB_VT_OFFSET_BYREF, NULL ) ); }
|
|
| OptList ',' OPTIONAL IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $4, hb_compVarTypeNew( HB_COMP_PARAM, $5->cVarType + HB_VT_OFFSET_OPTIONAL, NULL ) ); }
|
|
| OptList ',' OPTIONAL '@' IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $5, hb_compVarTypeNew( HB_COMP_PARAM, $6->cVarType + HB_VT_OFFSET_OPTIONAL + HB_VT_OFFSET_BYREF, NULL ) ); }
|
|
| OptList ',' OPTIONAL '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $5, hb_compVarTypeNew( HB_COMP_PARAM, 'F' + HB_VT_OFFSET_OPTIONAL + HB_VT_OFFSET_BYREF, NULL ) ); }
|
|
;
|
|
|
|
ExecFlow : IfEndif
|
|
| DoCase
|
|
| DoWhile
|
|
| ForNext
|
|
| BeginSeq
|
|
| ForEach
|
|
| DoSwitch
|
|
| WithObject
|
|
;
|
|
|
|
IfEndif : IfBegin EndIf { hb_compGenJumpHere( $1, HB_COMP_PARAM ); }
|
|
| IfBegin IfElse EndIf { hb_compGenJumpHere( $1, HB_COMP_PARAM ); }
|
|
| IfBegin IfElseIf EndIf { hb_compGenJumpHere( $1, HB_COMP_PARAM ); hb_compElseIfFix( HB_COMP_PARAM, $2 ); }
|
|
| IfBegin IfElseIf IfElse EndIf { hb_compGenJumpHere( $1, HB_COMP_PARAM ); hb_compElseIfFix( HB_COMP_PARAM, $2 ); }
|
|
;
|
|
|
|
IfBegin : IF ExpList
|
|
{ ++HB_COMP_PARAM->functions.pLast->wIfCounter; hb_compLinePushIfInside( HB_COMP_PARAM ); }
|
|
Crlf
|
|
{ HB_COMP_EXPR_FREE( hb_compExprGenPush( $2, HB_COMP_PARAM ) ); $<sNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM ); }
|
|
EmptyStats
|
|
{ $$ = hb_compGenJump( 0, HB_COMP_PARAM ); hb_compGenJumpHere( $<sNumber>5, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
IfElse : ELSE Crlf { HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_BREAK_CODE; }
|
|
EmptyStats
|
|
;
|
|
|
|
IfElseIf : ELSEIF { HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_BREAK_CODE; hb_compLinePush( HB_COMP_PARAM ); }
|
|
ExpList Crlf
|
|
{ HB_COMP_EXPR_FREE( hb_compExprGenPush( $3, HB_COMP_PARAM ) );
|
|
$<sNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
EmptyStats
|
|
{ $$ = hb_compElseIfGen( HB_COMP_PARAM, NULL, hb_compGenJump( 0, HB_COMP_PARAM ) );
|
|
hb_compGenJumpHere( $<sNumber>5, HB_COMP_PARAM );
|
|
}
|
|
|
|
| IfElseIf ELSEIF { HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_BREAK_CODE; hb_compLinePush( HB_COMP_PARAM ); }
|
|
ExpList Crlf
|
|
{ HB_COMP_EXPR_FREE( hb_compExprGenPush( $4, HB_COMP_PARAM ) );
|
|
$<sNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
EmptyStats
|
|
{ $$ = hb_compElseIfGen( HB_COMP_PARAM, $1, hb_compGenJump( 0, HB_COMP_PARAM ) );
|
|
hb_compGenJumpHere( $<sNumber>6, HB_COMP_PARAM );
|
|
}
|
|
;
|
|
|
|
EndIf : EndIfID
|
|
{
|
|
if( HB_COMP_PARAM->functions.pLast->wIfCounter )
|
|
--HB_COMP_PARAM->functions.pLast->wIfCounter;
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ ( HB_FUNF_WITH_RETURN | HB_FUNF_BREAK_CODE );
|
|
}
|
|
;
|
|
|
|
EndIfID : ENDIF
|
|
| END
|
|
;
|
|
|
|
DoCase : DoCaseBegin
|
|
Cases
|
|
EndCase { hb_compElseIfFix( HB_COMP_PARAM, $2 ); }
|
|
|
|
| DoCaseBegin
|
|
Otherwise
|
|
EndCase
|
|
|
|
| DoCaseBegin
|
|
EndCase
|
|
|
|
| DoCaseBegin
|
|
Cases
|
|
Otherwise
|
|
EndCase { hb_compElseIfFix( HB_COMP_PARAM, $2 ); }
|
|
;
|
|
|
|
EndCase : EndCaseID
|
|
{ if( HB_COMP_PARAM->functions.pLast->wCaseCounter )
|
|
--HB_COMP_PARAM->functions.pLast->wCaseCounter;
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ ( HB_FUNF_WITH_RETURN | HB_FUNF_BREAK_CODE );
|
|
}
|
|
;
|
|
|
|
EndCaseID : ENDCASE
|
|
| END
|
|
;
|
|
|
|
DoCaseStart : DOCASE { ++HB_COMP_PARAM->functions.pLast->wCaseCounter; hb_compLinePushIfDebugger( HB_COMP_PARAM );} Crlf
|
|
;
|
|
|
|
DoCaseBegin : DoCaseStart
|
|
| DoCaseStart Statements {
|
|
if( $<lNumber>2 > 0 )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_MAYHEM_IN_CASE, NULL, NULL );
|
|
}
|
|
}
|
|
;
|
|
|
|
Cases : CASE { hb_compLinePushIfInside( HB_COMP_PARAM ); } ExpList Crlf
|
|
{
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPush( $3, HB_COMP_PARAM ) );
|
|
$<sNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
EmptyStats
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_BREAK_CODE;
|
|
$$ = hb_compElseIfGen( HB_COMP_PARAM, NULL, hb_compGenJump( 0, HB_COMP_PARAM ) );
|
|
hb_compGenJumpHere( $<sNumber>5, HB_COMP_PARAM );
|
|
}
|
|
|
|
| Cases CASE { hb_compLinePushIfInside( HB_COMP_PARAM ); } ExpList Crlf
|
|
{
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPush( $4, HB_COMP_PARAM ) );
|
|
$<sNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
EmptyStats
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_BREAK_CODE;
|
|
$$ = hb_compElseIfGen( HB_COMP_PARAM, $1, hb_compGenJump( 0, HB_COMP_PARAM ) );
|
|
hb_compGenJumpHere( $<sNumber>6, HB_COMP_PARAM );
|
|
}
|
|
;
|
|
|
|
Otherwise : OTHERWISE {hb_compLinePushIfDebugger( HB_COMP_PARAM ); } Crlf { HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_BREAK_CODE; }
|
|
EmptyStats
|
|
| Otherwise OTHERWISE { hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_MAYHEM_IN_CASE, NULL, NULL ); } Crlf
|
|
EmptyStats
|
|
;
|
|
|
|
DoWhile : WhileBegin ExpList Crlf
|
|
{
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPush( $2, HB_COMP_PARAM ) );
|
|
$<sNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
EmptyStats
|
|
{
|
|
hb_compLoopHere( HB_COMP_PARAM );
|
|
hb_compGenJump( $1 - HB_COMP_PARAM->functions.pLast->nPCodePos, HB_COMP_PARAM );
|
|
}
|
|
EndWhile
|
|
{
|
|
hb_compGenJumpHere( $<sNumber>4, HB_COMP_PARAM );
|
|
if( HB_COMP_PARAM->functions.pLast->wWhileCounter )
|
|
--HB_COMP_PARAM->functions.pLast->wWhileCounter;
|
|
hb_compLoopEnd( HB_COMP_PARAM );
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_WITH_RETURN;
|
|
}
|
|
;
|
|
|
|
WhileBegin : WHILE
|
|
{
|
|
$$ = HB_COMP_PARAM->functions.pLast->nPCodePos;
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
++HB_COMP_PARAM->functions.pLast->wWhileCounter;
|
|
hb_compLoopStart( HB_COMP_PARAM, HB_TRUE );
|
|
}
|
|
;
|
|
|
|
EndWhile : EndWhileID
|
|
{ HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_BREAK_CODE; }
|
|
;
|
|
|
|
EndWhileID : ENDDO
|
|
| END
|
|
;
|
|
|
|
ForNext : FOR LValue ForAssign Expression /* 1 2 3 4 */
|
|
{ /* 5 */
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
$<iNumber>1 = HB_COMP_PARAM->currLine;
|
|
hb_compDebugStart();
|
|
++HB_COMP_PARAM->functions.pLast->wForCounter;
|
|
$2 = hb_compExprReduce( $2, HB_COMP_PARAM );
|
|
$<asExpr>$ = hb_compExprGenPush( hb_compExprAssign( $2, $4, HB_COMP_PARAM ), HB_COMP_PARAM );
|
|
if( hb_compExprAsSymbol( $2 ) )
|
|
{
|
|
hb_compForStart( HB_COMP_PARAM, hb_compExprAsSymbol( $2 ), 0 );
|
|
}
|
|
}
|
|
TO ExpList StepExpr /* 6 7 8 */
|
|
{ /* 9 */
|
|
hb_compLoopStart( HB_COMP_PARAM, HB_TRUE );
|
|
$<sNumber>$ = hb_compGenJump( 0, HB_COMP_PARAM );
|
|
}
|
|
Crlf /* 10 */
|
|
{ /* 11 */
|
|
$<sNumber>$ = HB_COMP_PARAM->functions.pLast->nPCodePos;
|
|
}
|
|
ForStatements /* 12 */
|
|
{
|
|
int iSign, iLine;
|
|
|
|
hb_compLoopHere( HB_COMP_PARAM );
|
|
|
|
iLine = HB_COMP_PARAM->currLine;
|
|
HB_COMP_PARAM->currLine = $<iNumber>1;
|
|
hb_compLinePush( HB_COMP_PARAM );
|
|
HB_COMP_PARAM->currLine = iLine;
|
|
|
|
if( $<asExpr>8 )
|
|
{
|
|
$<asExpr>8 = hb_compExprReduce( $<asExpr>8, HB_COMP_PARAM );
|
|
iSign = hb_compExprAsNumSign( $<asExpr>8 );
|
|
HB_COMP_EXPR_CLEAR( hb_compExprGenPush( hb_compExprSetOperand( hb_compExprNewPlusEq( $2, HB_COMP_PARAM ), $<asExpr>8, HB_COMP_PARAM ), HB_COMP_PARAM ) );
|
|
}
|
|
else
|
|
{
|
|
iSign = 1;
|
|
HB_COMP_EXPR_CLEAR( hb_compExprGenPush( hb_compExprNewPreInc( $2, HB_COMP_PARAM ), HB_COMP_PARAM ) );
|
|
}
|
|
hb_compGenJumpHere( $<sNumber>9, HB_COMP_PARAM );
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPush( $7, HB_COMP_PARAM ) ); /* end */
|
|
if( iSign )
|
|
{
|
|
hb_compGenPCode1( ( HB_BYTE ) ( iSign > 0 ? HB_P_GREATER : HB_P_LESS ), HB_COMP_PARAM );
|
|
if( $<asExpr>8 )
|
|
HB_COMP_EXPR_FREE( $<asExpr>8 );
|
|
}
|
|
else
|
|
{
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPush( $<asExpr>8, HB_COMP_PARAM ) ); /* step */
|
|
hb_compGenPCode1( HB_P_FORTEST, HB_COMP_PARAM );
|
|
}
|
|
|
|
hb_compGenJumpFalse( $<sNumber>11 - HB_COMP_PARAM->functions.pLast->nPCodePos, HB_COMP_PARAM );
|
|
hb_compLoopEnd( HB_COMP_PARAM );
|
|
if( hb_compExprAsSymbol( $<asExpr>2 ) )
|
|
hb_compForEnd( HB_COMP_PARAM, hb_compExprAsSymbol( $<asExpr>2 ) );
|
|
HB_COMP_EXPR_FREE( $<asExpr>5 ); /* deletes $5, $2, $4 */
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ ( HB_FUNF_WITH_RETURN | HB_FUNF_BREAK_CODE );
|
|
}
|
|
;
|
|
|
|
ForAssign : '='
|
|
| INASSIGN
|
|
;
|
|
|
|
StepExpr : /* default step expression */ { $<asExpr>$ = NULL; }
|
|
| STEP ExpList { $<asExpr>$ = hb_compExprReduce( $2, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ForStatements : EmptyStats EndForID
|
|
{
|
|
hb_compLinePush( HB_COMP_PARAM );
|
|
if( HB_COMP_PARAM->functions.pLast->wForCounter )
|
|
--HB_COMP_PARAM->functions.pLast->wForCounter;
|
|
}
|
|
;
|
|
|
|
EndForID : NEXT
|
|
| NEXT IdentName
|
|
| END
|
|
| END IdentName
|
|
;
|
|
|
|
ForVar : IdentName { $$ = hb_compExprNewVarRef( $1, HB_COMP_PARAM ); }
|
|
| AliasVar { $$ = hb_compExprNewRef( $1, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ForList : ForVar { $$ = hb_compExprNewArgList( $1, HB_COMP_PARAM ); }
|
|
| ForList ',' ForVar { $$ = hb_compExprAddListExpr( $1, $3 ); }
|
|
;
|
|
|
|
ForExpr : '@' IdentName { $$ = hb_compExprNewVarRef( $2, HB_COMP_PARAM ); }
|
|
| Expression
|
|
;
|
|
|
|
ForArgs : ForExpr { $$ = hb_compExprNewArgList( $1, HB_COMP_PARAM ); }
|
|
| ForArgs ',' ForExpr { $$ = hb_compExprAddListExpr( $1, $3 ); }
|
|
;
|
|
|
|
|
|
ForEach : FOREACH ForList IN ForArgs /* 1 2 3 4 */
|
|
{
|
|
++HB_COMP_PARAM->functions.pLast->wForCounter; /* 5 */
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
hb_compDebugStart();
|
|
}
|
|
Descend /* 6 */
|
|
{
|
|
/* 7 */
|
|
$2 = hb_compExprReduce( $2, HB_COMP_PARAM );
|
|
$4 = hb_compExprReduce( $4, HB_COMP_PARAM );
|
|
hb_compEnumStart( HB_COMP_PARAM, $2, $4, $6 );
|
|
|
|
hb_compLoopStart( HB_COMP_PARAM, HB_TRUE );
|
|
$<sNumber>$ = HB_COMP_PARAM->functions.pLast->nPCodePos;
|
|
}
|
|
Crlf /* 8 */
|
|
{
|
|
/* 9 */
|
|
$<sNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
ForStatements /* 10 */
|
|
{
|
|
hb_compLoopHere( HB_COMP_PARAM );
|
|
hb_compEnumNext( HB_COMP_PARAM, $2, $6 );
|
|
hb_compGenJump( $<sNumber>7 - HB_COMP_PARAM->functions.pLast->nPCodePos, HB_COMP_PARAM );
|
|
|
|
hb_compGenJumpHere( $<sNumber>9, HB_COMP_PARAM );
|
|
hb_compLoopEnd( HB_COMP_PARAM );
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ ( HB_FUNF_WITH_RETURN | HB_FUNF_BREAK_CODE );
|
|
hb_compEnumEnd( HB_COMP_PARAM, $2 );
|
|
HB_COMP_EXPR_FREE( $2 );
|
|
HB_COMP_EXPR_FREE( $4 );
|
|
}
|
|
;
|
|
|
|
Descend : /* default up */ { $$ = 1; }
|
|
| DESCEND { $$ = -1; }
|
|
;
|
|
|
|
DoSwitch : SwitchBegin
|
|
{
|
|
hb_compLoopStart( HB_COMP_PARAM, HB_FALSE );
|
|
hb_compSwitchStart( HB_COMP_PARAM, $1 );
|
|
hb_compGenJump( 0, HB_COMP_PARAM );
|
|
}
|
|
SwitchCases
|
|
EndSwitch
|
|
{
|
|
hb_compSwitchEnd( HB_COMP_PARAM );
|
|
hb_compLoopEnd( HB_COMP_PARAM );
|
|
}
|
|
|
|
| SwitchBegin
|
|
EndSwitch
|
|
{
|
|
HB_COMP_EXPR_FREE( $1 );
|
|
}
|
|
;
|
|
|
|
EndSwitch : EndSwitchID
|
|
{
|
|
if( HB_COMP_PARAM->functions.pLast->wSwitchCounter )
|
|
--HB_COMP_PARAM->functions.pLast->wSwitchCounter;
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ ( HB_FUNF_WITH_RETURN | HB_FUNF_BREAK_CODE );
|
|
}
|
|
;
|
|
|
|
EndSwitchID : ENDSWITCH
|
|
| END
|
|
;
|
|
|
|
SwitchStart : DOSWITCH
|
|
{
|
|
++HB_COMP_PARAM->functions.pLast->wSwitchCounter;
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
}
|
|
Expression Crlf
|
|
{
|
|
$$ = hb_compExprReduce( $3, HB_COMP_PARAM );
|
|
}
|
|
;
|
|
|
|
SwitchBegin : SwitchStart
|
|
| SwitchStart Statements
|
|
{
|
|
if( $<lNumber>2 > 0 )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_MAYHEM_IN_CASE, NULL, NULL );
|
|
}
|
|
}
|
|
;
|
|
|
|
SwitchCases : CASE Expression { hb_compSwitchAdd( HB_COMP_PARAM, $2 ); hb_compLinePush( HB_COMP_PARAM ); } Crlf
|
|
EmptyStats
|
|
|
|
| SwitchCases CASE Expression { hb_compSwitchAdd( HB_COMP_PARAM, $3 ); hb_compLinePush( HB_COMP_PARAM ); } Crlf
|
|
EmptyStats
|
|
|
|
| SwitchDefault
|
|
|
|
| SwitchCases SwitchDefault
|
|
;
|
|
|
|
SwitchDefault : OTHERWISE { hb_compSwitchAdd( HB_COMP_PARAM, NULL ); hb_compLinePush( HB_COMP_PARAM ); } Crlf { HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_BREAK_CODE; }
|
|
EmptyStats
|
|
;
|
|
|
|
BeginSeq : BEGINSEQ /* 1 */
|
|
{ /* 2 */
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
++HB_COMP_PARAM->functions.pLast->wSeqCounter;
|
|
$<sNumber>$ = hb_compSequenceBegin( HB_COMP_PARAM );
|
|
}
|
|
BlockSeq /* 3 */
|
|
Crlf /* 4 */
|
|
EmptyStats /* 5 */
|
|
{ /* 6 */
|
|
/* Set jump address for HB_P_SEQBEGIN opcode - this address
|
|
* will be used in BREAK code if there is no RECOVER clause
|
|
*/
|
|
if( $3 )
|
|
hb_compGenPCode1( HB_P_POP, HB_COMP_PARAM );
|
|
hb_compGenJumpHere( $<sNumber>2, HB_COMP_PARAM );
|
|
$<sNumber>$ = hb_compSequenceEnd( HB_COMP_PARAM );
|
|
$<lNumber>4 = hb_compLoopCount( HB_COMP_PARAM );
|
|
}
|
|
RecoverSeq /* 7 */
|
|
{ /* 8 */
|
|
/* Replace END address with RECOVER address in
|
|
* HB_P_SEQBEGIN opcode if there is RECOVER clause
|
|
*/
|
|
if( $7 )
|
|
hb_compGenJumpThere( $<sNumber>2, $7, HB_COMP_PARAM );
|
|
else if( HB_COMP_PARAM->functions.pLast->wSeqCounter )
|
|
--HB_COMP_PARAM->functions.pLast->wSeqCounter;
|
|
}
|
|
AlwaysSeq /* 9 */
|
|
{ /* 10 */
|
|
long lLoopCount = hb_compLoopCount( HB_COMP_PARAM );
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ ( HB_FUNF_WITH_RETURN | HB_FUNF_BREAK_CODE );
|
|
if( $9 )
|
|
{
|
|
if( $<lNumber>4 != lLoopCount )
|
|
{
|
|
/* ALWAYS statement after RECOVER with EXIT/LOOP statments */
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_ALWAYS_AFTER_EXIT, "EXIT/LOOP", NULL );
|
|
}
|
|
--HB_COMP_PARAM->functions.pLast->wAlwaysCounter;
|
|
/* replace END address with ALWAYS address in
|
|
HB_P_SEQEND opcode */
|
|
hb_compGenJumpThere( $<sNumber>6, $9, HB_COMP_PARAM );
|
|
/* Fix ALWAYS address in HB_P_SEQALWAYS opcode */
|
|
hb_compGenJumpThere( $<sNumber>2 - 4, $9, HB_COMP_PARAM );
|
|
/* Fix ALWAYSEND address in HB_P_ALWAYSBEGIN opcode */
|
|
hb_compGenJumpHere( $9 + 1, HB_COMP_PARAM );
|
|
hb_compGenPCode1( HB_P_ALWAYSEND, HB_COMP_PARAM );
|
|
}
|
|
else
|
|
{
|
|
/* Fix END address in HB_P_SEQEND opcode */
|
|
hb_compGenJumpHere( $<sNumber>6, HB_COMP_PARAM );
|
|
}
|
|
hb_compSequenceFinish( HB_COMP_PARAM, $<sNumber>2, $<sNumber>6, $9,
|
|
$<lNumber>5 != 0, $7 != 0, $<lNumber>4 == lLoopCount );
|
|
}
|
|
EndSeqID /* 10 */
|
|
;
|
|
|
|
EndSeqID : ENDSEQ
|
|
| END
|
|
;
|
|
|
|
BlockSeq : /* no always */ { $$ = 0; }
|
|
| WITH Expression
|
|
{
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPush( $2, HB_COMP_PARAM ) );
|
|
hb_compGenPCode1( HB_P_SEQBLOCK, HB_COMP_PARAM );
|
|
$$ = HB_COMP_PARAM->functions.pLast->nPCodePos;
|
|
}
|
|
;
|
|
|
|
AlwaysSeq : /* no always */ { $$ = 0; }
|
|
| Always Crlf EmptyStats
|
|
;
|
|
|
|
Always : ALWAYS
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ ( HB_FUNF_WITH_RETURN | HB_FUNF_BREAK_CODE );
|
|
$$ = HB_COMP_PARAM->functions.pLast->nPCodePos;
|
|
++HB_COMP_PARAM->functions.pLast->wAlwaysCounter;
|
|
hb_compSequenceAlways( HB_COMP_PARAM );
|
|
}
|
|
;
|
|
|
|
RecoverSeq : /* no recover */ { $$ = 0; HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_BREAK_CODE; }
|
|
| RecoverEmpty Crlf EmptyStats
|
|
| RecoverUsing Crlf EmptyStats
|
|
;
|
|
|
|
RecoverEmpty : RECOVER
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_BREAK_CODE;
|
|
$$ = HB_COMP_PARAM->functions.pLast->nPCodePos;
|
|
if( HB_COMP_PARAM->functions.pLast->wSeqCounter )
|
|
--HB_COMP_PARAM->functions.pLast->wSeqCounter;
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
hb_compGenPCode2( HB_P_SEQRECOVER, HB_P_POP, HB_COMP_PARAM );
|
|
}
|
|
;
|
|
|
|
RecoverUsing : RECOVERUSING IdentName
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->funFlags &= ~ HB_FUNF_BREAK_CODE;
|
|
$$ = HB_COMP_PARAM->functions.pLast->nPCodePos;
|
|
if( HB_COMP_PARAM->functions.pLast->wSeqCounter )
|
|
--HB_COMP_PARAM->functions.pLast->wSeqCounter;
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
hb_compGenPCode1( HB_P_SEQRECOVER, HB_COMP_PARAM );
|
|
hb_compGenPopVar( $2, HB_COMP_PARAM );
|
|
}
|
|
;
|
|
|
|
/* 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
|
|
*/
|
|
DoProc : DO MacroAny DoArgs
|
|
{
|
|
$$ = hb_compExprNewFunCall( $2, $3, HB_COMP_PARAM );
|
|
}
|
|
| DOIDENT DoArgs
|
|
{
|
|
hb_compModuleAdd( HB_COMP_PARAM, $1, HB_FALSE );
|
|
/* DOIDENT is the only one identifier which can be returned in lower letters */
|
|
$$ = hb_compExprNewFunCall( hb_compExprNewFunName( hb_compIdentifierNew( HB_COMP_PARAM, hb_strupr( hb_strdup( $1 ) ), HB_IDENT_FREE ), HB_COMP_PARAM ), $2, HB_COMP_PARAM );
|
|
}
|
|
;
|
|
|
|
DoArgs : /* empty */ { $$ = NULL; }
|
|
| WITH DoArgList { $$ = $2; }
|
|
;
|
|
|
|
DoArgList : ',' { $$ = hb_compExprAddListExpr( hb_compExprNewArgList( hb_compExprNewNil( HB_COMP_PARAM ), HB_COMP_PARAM ), hb_compExprNewNil( HB_COMP_PARAM ) ); }
|
|
| ',' DoArgument { $$ = hb_compExprAddListExpr( hb_compExprNewArgList( hb_compExprNewNil( HB_COMP_PARAM ), HB_COMP_PARAM ), $2 ); }
|
|
| DoArgument { $$ = hb_compExprNewArgList( $1, HB_COMP_PARAM ); }
|
|
| DoArgList ',' { $$ = hb_compExprAddListExpr( $1, hb_compExprNewNil( HB_COMP_PARAM ) ); }
|
|
| DoArgList ',' DoArgument { $$ = hb_compExprAddListExpr( $1, $3 ); }
|
|
;
|
|
|
|
DoArgument : IdentName { $$ = hb_compExprNewVarRef( $1, HB_COMP_PARAM ); }
|
|
| RefArgument
|
|
| FunRef
|
|
| SimpleExpression
|
|
| PareExpList
|
|
;
|
|
|
|
WithObject : WITHOBJECT Expression Crlf
|
|
{
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPush( $2, HB_COMP_PARAM ) );
|
|
$<sNumber>$ = HB_COMP_PARAM->functions.pLast->nPCodePos;
|
|
hb_compGenPCode1( HB_P_WITHOBJECTSTART, HB_COMP_PARAM );
|
|
HB_COMP_PARAM->functions.pLast->wWithObjectCnt++;
|
|
}
|
|
EmptyStats
|
|
EndWithID
|
|
{ if( HB_COMP_PARAM->functions.pLast->wWithObjectCnt )
|
|
--HB_COMP_PARAM->functions.pLast->wWithObjectCnt;
|
|
if( $<lNumber>5 )
|
|
hb_compGenPCode1( HB_P_WITHOBJECTEND, HB_COMP_PARAM );
|
|
else
|
|
{
|
|
hb_compNOOPfill( HB_COMP_PARAM->functions.pLast,
|
|
$<sNumber>4, 1, HB_FALSE, HB_TRUE );
|
|
hb_compGenPCode1( HB_P_POP, HB_COMP_PARAM );
|
|
}
|
|
}
|
|
;
|
|
|
|
EndWithID : ENDWITH
|
|
| END
|
|
;
|
|
|
|
Crlf : '\n' { HB_COMP_PARAM->fError = HB_FALSE; }
|
|
| ';'
|
|
;
|
|
|
|
%%
|
|
|
|
/*
|
|
** ------------------------------------------------------------------------ **
|
|
*/
|
|
|
|
/*
|
|
* Avoid tracing in preprocessor/compiler.
|
|
*/
|
|
#if ! defined( HB_TRACE_UTILS )
|
|
#if defined( HB_TRACE_LEVEL )
|
|
#undef HB_TRACE_LEVEL
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/* ************************************************************************* */
|
|
|
|
/*
|
|
* 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( HB_COMP_DECL, HB_BOOL fCanLoop )
|
|
{
|
|
PHB_LOOPEXIT pLoop = ( PHB_LOOPEXIT ) hb_xgrab( sizeof( HB_LOOPEXIT ) );
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
if( pFunc->pLoops )
|
|
{
|
|
PHB_LOOPEXIT pLast = pFunc->pLoops;
|
|
|
|
while( pLast->pNext )
|
|
pLast = pLast->pNext;
|
|
pLast->pNext = pLoop;
|
|
}
|
|
else
|
|
pFunc->pLoops = pLoop;
|
|
|
|
pLoop->nOffset = pFunc->nPCodePos; /* store the start position */
|
|
pLoop->fCanLoop = fCanLoop; /* can we use LOOP inside */
|
|
pLoop->wSeqCounter = pFunc->wSeqCounter; /* store current SEQUENCE counter */
|
|
pLoop->wWithObjectCnt = pFunc->wWithObjectCnt; /* store current WITH OBJECT counter */
|
|
pLoop->wAlwaysCounter = pFunc->wAlwaysCounter; /* store current ALWAYS counter */
|
|
pLoop->pExitList = NULL;
|
|
pLoop->pLoopList = NULL;
|
|
pLoop->pNext = NULL;
|
|
}
|
|
|
|
/*
|
|
* return number of LOOP of EXIT statement in the top most structure
|
|
*/
|
|
static long hb_compLoopCount( HB_COMP_DECL )
|
|
{
|
|
PHB_LOOPEXIT pLastLoop, pLastExit, pLoop;
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
long lCount = 0;
|
|
|
|
pLastLoop = pLastExit = NULL;
|
|
pLoop = pFunc->pLoops;
|
|
while( pLoop )
|
|
{
|
|
if( pLoop->fCanLoop )
|
|
pLastLoop = pLoop;
|
|
pLastExit = pLoop;
|
|
pLoop = pLoop->pNext;
|
|
}
|
|
|
|
if( pLastLoop )
|
|
{
|
|
while( pLastLoop->pLoopList )
|
|
{
|
|
++lCount;
|
|
pLastLoop = pLastLoop->pLoopList;
|
|
}
|
|
}
|
|
if( pLastExit )
|
|
{
|
|
while( pLastExit->pExitList )
|
|
{
|
|
++lCount;
|
|
pLastExit = pLastExit->pExitList;
|
|
}
|
|
}
|
|
|
|
return lCount;
|
|
}
|
|
|
|
/*
|
|
* Stores the position of LOOP statement to fix it later at the end of loop
|
|
*/
|
|
static void hb_compLoopLoop( HB_COMP_DECL )
|
|
{
|
|
PHB_LOOPEXIT pLast = NULL, pLoop;
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
pLoop = pFunc->pLoops;
|
|
while( pLoop )
|
|
{
|
|
if( pLoop->fCanLoop )
|
|
pLast = pLoop;
|
|
pLoop = pLoop->pNext;
|
|
}
|
|
|
|
if( ! pLast )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_UNMATCHED_EXIT, "LOOP", NULL );
|
|
}
|
|
else
|
|
{
|
|
if( pLast->wSeqCounter != pFunc->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 when there is no
|
|
* ALWAYS block
|
|
*/
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_EXIT_IN_SEQUENCE, "LOOP", NULL );
|
|
}
|
|
else if( pLast->wAlwaysCounter != pFunc->wAlwaysCounter )
|
|
{
|
|
/* Attempt to LOOP from ALWAYS block of BEGIN/END sequence
|
|
*/
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_EXIT_IN_SEQUENCE, "LOOP", NULL );
|
|
}
|
|
else
|
|
{
|
|
HB_USHORT wWithObjectCnt = pLast->wWithObjectCnt;
|
|
|
|
pLoop = ( PHB_LOOPEXIT ) hb_xgrab( sizeof( HB_LOOPEXIT ) );
|
|
pLoop->pLoopList = NULL;
|
|
while( pLast->pLoopList )
|
|
pLast = pLast->pLoopList;
|
|
pLast->pLoopList = pLoop;
|
|
|
|
while( wWithObjectCnt < pFunc->wWithObjectCnt )
|
|
{
|
|
hb_compGenPCode1( HB_P_WITHOBJECTEND, HB_COMP_PARAM );
|
|
wWithObjectCnt++;
|
|
}
|
|
/* store the position to fix */
|
|
pLoop->nOffset = pFunc->nPCodePos;
|
|
hb_compGenJump( 0, HB_COMP_PARAM );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Stores the position of EXIT statement to fix it later at the end of loop
|
|
*/
|
|
static void hb_compLoopExit( HB_COMP_DECL )
|
|
{
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
if( ! pFunc->pLoops )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_UNMATCHED_EXIT, "EXIT", NULL );
|
|
}
|
|
else
|
|
{
|
|
PHB_LOOPEXIT pLast, pLoop;
|
|
|
|
pLast = pFunc->pLoops;
|
|
while( pLast->pNext )
|
|
pLast = pLast->pNext;
|
|
|
|
if( pLast->wSeqCounter != pFunc->wSeqCounter )
|
|
{
|
|
/* Attempt to EXIT from BEGIN/END sequence
|
|
* Current SEQUENCE counter is different then at the beginning of loop
|
|
* Notice that EXIT is allowed in RECOVER code when there is no
|
|
* ALWAYS block
|
|
*/
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_EXIT_IN_SEQUENCE, "EXIT", NULL );
|
|
}
|
|
else if( pLast->wAlwaysCounter != pFunc->wAlwaysCounter )
|
|
{
|
|
/* Attempt to EXIT from ALWAYS block of BEGIN/END sequence
|
|
*/
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_EXIT_IN_SEQUENCE, "EXIT", NULL );
|
|
}
|
|
else
|
|
{
|
|
HB_USHORT wWithObjectCnt = pLast->wWithObjectCnt;
|
|
|
|
pLoop = ( PHB_LOOPEXIT ) hb_xgrab( sizeof( HB_LOOPEXIT ) );
|
|
pLoop->pExitList = NULL;
|
|
while( pLast->pExitList )
|
|
pLast = pLast->pExitList;
|
|
pLast->pExitList = pLoop;
|
|
|
|
while( wWithObjectCnt < pFunc->wWithObjectCnt )
|
|
{
|
|
hb_compGenPCode1( HB_P_WITHOBJECTEND, HB_COMP_PARAM );
|
|
wWithObjectCnt++;
|
|
}
|
|
/* store the position to fix */
|
|
pLoop->nOffset = pFunc->nPCodePos;
|
|
hb_compGenJump( 0, HB_COMP_PARAM );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fixes the LOOP statement
|
|
*/
|
|
static void hb_compLoopHere( HB_COMP_DECL )
|
|
{
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
PHB_LOOPEXIT pLoop = pFunc->pLoops, pFree, pLast;
|
|
|
|
if( pLoop )
|
|
{
|
|
while( pLoop->pNext )
|
|
pLoop = pLoop->pNext;
|
|
|
|
pLast = pLoop;
|
|
pLoop = pLoop->pLoopList;
|
|
while( pLoop )
|
|
{
|
|
hb_compGenJumpHere( pLoop->nOffset + 1, HB_COMP_PARAM );
|
|
pFree = pLoop;
|
|
pLoop = pLoop->pLoopList;
|
|
hb_xfree( pFree );
|
|
}
|
|
pLast->pLoopList = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fixes the EXIT statements and releases memory allocated for current loop
|
|
*/
|
|
static void hb_compLoopEnd( HB_COMP_DECL )
|
|
{
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
PHB_LOOPEXIT pLoop = pFunc->pLoops, pLast = pFunc->pLoops, pExit, pFree;
|
|
|
|
if( pLoop )
|
|
{
|
|
while( pLoop->pNext )
|
|
{
|
|
pLast = pLoop;
|
|
pLoop = pLoop->pNext;
|
|
}
|
|
|
|
pExit = pLoop->pExitList;
|
|
while( pExit )
|
|
{
|
|
hb_compGenJumpHere( pExit->nOffset + 1, HB_COMP_PARAM );
|
|
pFree = pExit;
|
|
pExit = pExit->pExitList;
|
|
hb_xfree( pFree );
|
|
}
|
|
|
|
pLast->pNext = NULL;
|
|
if( pLoop == pFunc->pLoops )
|
|
pFunc->pLoops = NULL;
|
|
hb_xfree( pLoop );
|
|
}
|
|
}
|
|
|
|
void hb_compLoopKill( PHB_HFUNC pFunc )
|
|
{
|
|
PHB_LOOPEXIT pLoop, pFree;
|
|
|
|
while( pFunc->pLoops )
|
|
{
|
|
pLoop = pFunc->pLoops;
|
|
while( pLoop->pExitList )
|
|
{
|
|
pFree = pLoop->pExitList;
|
|
pLoop->pExitList = pFree->pExitList;
|
|
hb_xfree( pFree );
|
|
}
|
|
while( pLoop->pLoopList )
|
|
{
|
|
pFree = pLoop->pLoopList;
|
|
pLoop->pLoopList = pFree->pLoopList;
|
|
hb_xfree( pFree );
|
|
}
|
|
pFunc->pLoops = pLoop->pNext;
|
|
hb_xfree( pLoop );
|
|
}
|
|
}
|
|
|
|
static void * hb_compElseIfGen( HB_COMP_DECL, void * pFirst, HB_SIZE nOffset )
|
|
{
|
|
PHB_ELSEIF pElseIf = ( PHB_ELSEIF ) hb_xgrab( sizeof( HB_ELSEIF ) ), pLast;
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
pElseIf->nOffset = nOffset;
|
|
pElseIf->pPrev = NULL;
|
|
pElseIf->pElseif = NULL;
|
|
|
|
if( pFirst )
|
|
{
|
|
pLast = ( PHB_ELSEIF ) pFirst;
|
|
while( pLast->pElseif )
|
|
pLast = pLast->pElseif;
|
|
pLast->pElseif = pElseIf;
|
|
}
|
|
else
|
|
{
|
|
if( pFunc->elseif )
|
|
{
|
|
pElseIf->pPrev = pFunc->elseif;
|
|
}
|
|
pFirst = pElseIf;
|
|
pFunc->elseif = pElseIf;
|
|
}
|
|
return pFirst;
|
|
}
|
|
|
|
|
|
static void hb_compElseIfFix( HB_COMP_DECL, void * pFixElseIfs )
|
|
{
|
|
PHB_ELSEIF pFix = ( PHB_ELSEIF ) pFixElseIfs;
|
|
PHB_ELSEIF pDel;
|
|
|
|
HB_COMP_PARAM->functions.pLast->elseif = pFix->pPrev;
|
|
while( pFix )
|
|
{
|
|
hb_compGenJumpHere( pFix->nOffset, HB_COMP_PARAM );
|
|
pDel = pFix;
|
|
pFix = pFix->pElseif;
|
|
hb_xfree( pDel );
|
|
}
|
|
}
|
|
|
|
void hb_compElseIfKill( PHB_HFUNC pFunc )
|
|
{
|
|
PHB_ELSEIF pFix;
|
|
PHB_ELSEIF pDel;
|
|
|
|
while( pFunc->elseif )
|
|
{
|
|
pFix = pFunc->elseif;
|
|
pFunc->elseif = pFix->pPrev;
|
|
while( pFix )
|
|
{
|
|
pDel = pFix;
|
|
pFix = pFix->pElseif;
|
|
hb_xfree( pDel );
|
|
}
|
|
}
|
|
}
|
|
|
|
static void hb_compRTVariableAdd( HB_COMP_DECL, PHB_EXPR pVar, HB_BOOL bPopInitValue )
|
|
{
|
|
PHB_RTVAR pRTvar = ( PHB_RTVAR ) hb_xgrab( sizeof( HB_RTVAR ) );
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
pRTvar->pVar = pVar;
|
|
pRTvar->bPopValue = bPopInitValue;
|
|
pRTvar->pNext = NULL;
|
|
pRTvar->pPrev = NULL;
|
|
|
|
if( pFunc->rtvars )
|
|
{
|
|
PHB_RTVAR pLast = pFunc->rtvars;
|
|
while( pLast->pNext )
|
|
pLast = pLast->pNext;
|
|
pLast->pNext = pRTvar;
|
|
pRTvar->pPrev = pLast;
|
|
}
|
|
else
|
|
pFunc->rtvars = pRTvar;
|
|
}
|
|
|
|
static void hb_compRTVariableGen( HB_COMP_DECL, const char * szCreateFun )
|
|
{
|
|
HB_USHORT usCount = 0;
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
PHB_RTVAR pVar = pFunc->rtvars;
|
|
PHB_RTVAR pDel;
|
|
|
|
/* generate the function call frame */
|
|
hb_compGenPushFunCall( szCreateFun, HB_FN_UDF, HB_COMP_PARAM );
|
|
|
|
/* push variable names to create */
|
|
while( pVar->pNext )
|
|
{
|
|
pVar->pVar = hb_compExprGenPush( pVar->pVar, HB_COMP_PARAM );
|
|
pVar = pVar->pNext;
|
|
++usCount;
|
|
}
|
|
pVar->pVar = hb_compExprGenPush( pVar->pVar, HB_COMP_PARAM );
|
|
++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 ), HB_COMP_PARAM );
|
|
else
|
|
hb_compGenPCode2( HB_P_DOSHORT, ( HB_BYTE ) usCount, HB_COMP_PARAM );
|
|
|
|
/* pop initial values */
|
|
while( pVar )
|
|
{
|
|
if( pVar->bPopValue )
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPop( pVar->pVar, HB_COMP_PARAM ) );
|
|
else
|
|
HB_COMP_EXPR_FREE( pVar->pVar );
|
|
pDel = pVar;
|
|
pVar = pVar->pPrev;
|
|
hb_xfree( pDel );
|
|
}
|
|
pFunc->rtvars = NULL;
|
|
}
|
|
|
|
void hb_compRTVariableKill( HB_COMP_DECL, PHB_HFUNC pFunc )
|
|
{
|
|
PHB_RTVAR pVar;
|
|
|
|
while( pFunc->rtvars )
|
|
{
|
|
pVar = pFunc->rtvars;
|
|
|
|
HB_COMP_EXPR_FREE( pVar->pVar );
|
|
pFunc->rtvars = pVar->pPrev;
|
|
hb_xfree( pVar );
|
|
}
|
|
pFunc->rtvars = NULL;
|
|
}
|
|
|
|
static PHB_EXPR hb_compArrayDimPush( PHB_EXPR pInitValue, HB_COMP_DECL )
|
|
{
|
|
HB_USHORT uCount = ( HB_USHORT ) hb_compExprListLen( pInitValue );
|
|
|
|
if( uCount == 1 && hb_compExprIsInteger( pInitValue->value.asList.pExprList ) &&
|
|
hb_compExprAsInteger( pInitValue->value.asList.pExprList ) == 0 )
|
|
{
|
|
hb_compGenPCode3( HB_P_ARRAYGEN, 0, 0, HB_COMP_PARAM );
|
|
}
|
|
else
|
|
{
|
|
pInitValue = hb_compExprGenPush( pInitValue, HB_COMP_PARAM );
|
|
hb_compGenPCode3( HB_P_ARRAYDIM, HB_LOBYTE( uCount ), HB_HIBYTE( uCount ), HB_COMP_PARAM );
|
|
}
|
|
return pInitValue;
|
|
}
|
|
|
|
static void hb_compVariableDim( const char * szName, PHB_EXPR pInitValue, HB_COMP_DECL )
|
|
{
|
|
if( HB_COMP_PARAM->iVarScope == HB_VSCOMP_PUBLIC || HB_COMP_PARAM->iVarScope == HB_VSCOMP_PRIVATE )
|
|
{
|
|
hb_compVariableAdd( HB_COMP_PARAM, szName, hb_compVarTypeNew( HB_COMP_PARAM, 'A', NULL ) );
|
|
HB_COMP_EXPR_FREE( hb_compArrayDimPush( pInitValue, HB_COMP_PARAM ) );
|
|
hb_compRTVariableAdd( HB_COMP_PARAM, hb_compExprNewRTVar( szName, NULL, HB_COMP_PARAM ), HB_TRUE );
|
|
}
|
|
else if( HB_COMP_PARAM->iVarScope & HB_VSCOMP_STATIC )
|
|
{
|
|
PHB_EXPR pVar = hb_compExprNewVar( szName, HB_COMP_PARAM );
|
|
PHB_EXPR pAssign;
|
|
|
|
/* create a static variable */
|
|
hb_compVariableAdd( HB_COMP_PARAM, szName, hb_compVarTypeNew( HB_COMP_PARAM, 'A', NULL ) );
|
|
|
|
hb_compStaticDefStart( HB_COMP_PARAM ); /* switch to statics pcode buffer */
|
|
/* create an array */
|
|
pInitValue = hb_compArrayDimPush( pInitValue, HB_COMP_PARAM );
|
|
/* now pop an array */
|
|
pVar = hb_compExprGenPop( pVar, HB_COMP_PARAM );
|
|
/* check if valid initializers were used but don't generate any code */
|
|
pAssign = hb_compExprAssignStatic( pVar, pInitValue, HB_COMP_PARAM );
|
|
/* delete all used expressions */
|
|
HB_COMP_EXPR_FREE( pAssign );
|
|
hb_compStaticDefEnd( HB_COMP_PARAM, szName );
|
|
}
|
|
else
|
|
{
|
|
hb_compVariableAdd( HB_COMP_PARAM, szName, hb_compVarTypeNew( HB_COMP_PARAM, 'A', NULL ) );
|
|
HB_COMP_EXPR_FREE( hb_compArrayDimPush( pInitValue, HB_COMP_PARAM ) );
|
|
if( HB_COMP_PARAM->iVarScope != HB_VSCOMP_LOCAL ||
|
|
!( HB_COMP_PARAM->functions.pLast->funFlags & HB_FUNF_EXTBLOCK ) )
|
|
{
|
|
HB_COMP_EXPR_FREE( hb_compExprGenPop( hb_compExprNewVar( szName, HB_COMP_PARAM ), HB_COMP_PARAM ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
static void hb_compForStart( HB_COMP_DECL, const char *szVarName, int iForEachDir )
|
|
{
|
|
PHB_ENUMERATOR pEnumVar;
|
|
|
|
pEnumVar = HB_COMP_PARAM->functions.pLast->pEnum;
|
|
if( pEnumVar == NULL )
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->pEnum = ( PHB_ENUMERATOR ) hb_xgrab( sizeof( HB_ENUMERATOR ) );
|
|
pEnumVar = HB_COMP_PARAM->functions.pLast->pEnum;
|
|
}
|
|
else
|
|
{
|
|
HB_BOOL bWarn = HB_TRUE;
|
|
PHB_ENUMERATOR pLast = pEnumVar;
|
|
|
|
while( pEnumVar )
|
|
{
|
|
if( strcmp( pEnumVar->szName, szVarName ) == 0 )
|
|
{
|
|
/* Enumerator variable exists already - throw warning */
|
|
if( bWarn )
|
|
{
|
|
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_FORVAR_DUPL, szVarName, NULL );
|
|
bWarn = HB_FALSE;
|
|
}
|
|
}
|
|
pLast = pEnumVar;
|
|
pEnumVar = pEnumVar->pNext;
|
|
}
|
|
pLast->pNext = ( PHB_ENUMERATOR ) hb_xgrab( sizeof( HB_ENUMERATOR ) );
|
|
pEnumVar = pLast->pNext;
|
|
}
|
|
pEnumVar->szName = szVarName;
|
|
pEnumVar->iForEachDir = iForEachDir;
|
|
pEnumVar->pNext = NULL;
|
|
}
|
|
|
|
static HB_BOOL hb_compForEachVarError( HB_COMP_DECL, const char *szVarName, int * piDir )
|
|
{
|
|
PHB_ENUMERATOR pEnumVar;
|
|
|
|
pEnumVar = HB_COMP_PARAM->functions.pLast->pEnum;
|
|
if( pEnumVar && ! HB_COMP_PARAM->functions.pLast->bBlock )
|
|
{
|
|
while( pEnumVar )
|
|
{
|
|
if( strcmp( pEnumVar->szName, szVarName ) == 0 )
|
|
{
|
|
* piDir = pEnumVar->iForEachDir;
|
|
if( * piDir != 0 )
|
|
{
|
|
/* only if it is FOR EACH enumerator
|
|
* generate warning if it is FOR/NEXT loop
|
|
*/
|
|
return HB_FALSE;
|
|
}
|
|
}
|
|
pEnumVar = pEnumVar->pNext;
|
|
}
|
|
}
|
|
|
|
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_ENUM_INVALID, szVarName, NULL );
|
|
return HB_TRUE;
|
|
}
|
|
|
|
static void hb_compForEnd( HB_COMP_DECL, const char *szVar )
|
|
{
|
|
PHB_ENUMERATOR * pEnumVar;
|
|
|
|
HB_SYMBOL_UNUSED( szVar );
|
|
|
|
pEnumVar = &HB_COMP_PARAM->functions.pLast->pEnum;
|
|
if( *pEnumVar )
|
|
{
|
|
while( ( *pEnumVar )->pNext )
|
|
pEnumVar = &( *pEnumVar )->pNext;
|
|
|
|
hb_xfree( *pEnumVar );
|
|
*pEnumVar = NULL;
|
|
}
|
|
}
|
|
|
|
static HB_COMP_CARGO2_FUNC( hb_compEnumEvalStart )
|
|
{
|
|
const char * szName = hb_compExprAsSymbol( ( PHB_EXPR ) cargo );
|
|
|
|
if( szName )
|
|
hb_compForStart( HB_COMP_PARAM, szName, HB_COMP_PARAM->fDescend ? -1 : 1 );
|
|
|
|
hb_compExprGenPush( ( PHB_EXPR ) dummy, HB_COMP_PARAM ); /* expression */
|
|
hb_compExprGenPush( ( PHB_EXPR ) cargo, HB_COMP_PARAM ); /* variable */
|
|
}
|
|
|
|
static void hb_compEnumStart( HB_COMP_DECL, PHB_EXPR pVars, PHB_EXPR pExprs, int descend )
|
|
{
|
|
HB_SIZE ulLen;
|
|
|
|
if( hb_compExprListLen( pVars ) != hb_compExprListLen( pExprs ) )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_FORVAR_DIFF, NULL, NULL );
|
|
}
|
|
|
|
HB_COMP_PARAM->fDescend = descend < 0;
|
|
ulLen = hb_compExprListEval2( HB_COMP_PARAM, pVars, pExprs, hb_compEnumEvalStart );
|
|
|
|
if( ulLen > 255 )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_FORVAR_TOOMANY, NULL, NULL );
|
|
}
|
|
else
|
|
{
|
|
hb_compGenPCode3( HB_P_ENUMSTART, ( HB_BYTE ) ( ulLen & 0xFF ), ( HB_BYTE ) ( descend > 0 ? 1 : 0 ), HB_COMP_PARAM );
|
|
}
|
|
}
|
|
|
|
static void hb_compEnumNext( HB_COMP_DECL, PHB_EXPR pExpr, int descend )
|
|
{
|
|
HB_SYMBOL_UNUSED( pExpr );
|
|
if( descend > 0 )
|
|
{
|
|
hb_compGenPCode1( HB_P_ENUMNEXT, HB_COMP_PARAM );
|
|
}
|
|
else
|
|
{
|
|
hb_compGenPCode1( HB_P_ENUMPREV, HB_COMP_PARAM );
|
|
}
|
|
}
|
|
|
|
static HB_COMP_CARGO_FUNC( hb_compEnumEvalEnd )
|
|
{
|
|
const char * szName = hb_compExprAsSymbol( ( PHB_EXPR ) cargo );
|
|
|
|
if( szName )
|
|
hb_compForEnd( HB_COMP_PARAM, szName );
|
|
}
|
|
|
|
static void hb_compEnumEnd( HB_COMP_DECL, PHB_EXPR pExpr )
|
|
{
|
|
hb_compExprListEval( HB_COMP_PARAM, pExpr, hb_compEnumEvalEnd );
|
|
hb_compGenPCode1( HB_P_ENUMEND, HB_COMP_PARAM );
|
|
}
|
|
|
|
static void hb_compSwitchStart( HB_COMP_DECL, PHB_EXPR pExpr )
|
|
{
|
|
PHB_SWITCHCMD pSwitch = ( PHB_SWITCHCMD ) hb_xgrab( sizeof( HB_SWITCHCMD ) );
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
pSwitch->pCases = NULL;
|
|
pSwitch->pLast = NULL;
|
|
pSwitch->nDefault = 0;
|
|
pSwitch->nOffset = pFunc->nPCodePos;
|
|
pSwitch->pExpr = pExpr;
|
|
pSwitch->pPrev = pFunc->pSwitch;
|
|
pFunc->pSwitch = pSwitch;
|
|
}
|
|
|
|
static void hb_compSwitchAdd( HB_COMP_DECL, PHB_EXPR pExpr )
|
|
{
|
|
PHB_SWITCHCASE pCase;
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
pFunc->funFlags &= ~HB_FUNF_BREAK_CODE;
|
|
|
|
if( pExpr )
|
|
{
|
|
/* normal CASE */
|
|
pCase = ( PHB_SWITCHCASE ) hb_xgrab( sizeof( HB_SWITCHCASE ) );
|
|
pCase->nOffset = pFunc->nPCodePos;
|
|
pCase->pNext = NULL;
|
|
pCase->pExpr = pExpr = hb_compExprReduce( pExpr, HB_COMP_PARAM );
|
|
if( !( hb_compExprIsLong( pExpr ) || hb_compExprIsString( pExpr ) ) )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_NOT_LITERAL_CASE, NULL, NULL );
|
|
else if( pFunc->pSwitch->pCases )
|
|
{
|
|
PHB_SWITCHCASE pCases = pFunc->pSwitch->pCases;
|
|
while( pCases )
|
|
{
|
|
HB_BOOL fEqual = HB_FALSE;
|
|
|
|
if( hb_compExprIsLong( pExpr ) )
|
|
{
|
|
if( hb_compExprIsLong( pCases->pExpr ) )
|
|
fEqual = hb_compExprAsLongNum( pExpr ) == hb_compExprAsLongNum( pCases->pExpr );
|
|
}
|
|
else
|
|
{
|
|
if( hb_compExprIsString( pCases->pExpr ) )
|
|
fEqual = hb_compExprAsStringLen( pExpr ) == hb_compExprAsStringLen( pCases->pExpr ) &&
|
|
memcmp( hb_compExprAsString( pExpr ),
|
|
hb_compExprAsString( pCases->pExpr ),
|
|
hb_compExprAsStringLen( pExpr ) ) == 0;
|
|
}
|
|
if( fEqual )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_DUPL_CASE, NULL, NULL );
|
|
pCases = pCases->pNext;
|
|
}
|
|
}
|
|
|
|
if( pFunc->pSwitch->pLast )
|
|
{
|
|
pFunc->pSwitch->pLast->pNext = pCase;
|
|
pFunc->pSwitch->pLast = pCase;
|
|
}
|
|
else
|
|
{
|
|
pFunc->pSwitch->pCases = pFunc->pSwitch->pLast = pCase;
|
|
}
|
|
if( hb_compExprIsString( pExpr ) && hb_compExprAsStringLen( pExpr ) > 255 )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_INVALID_STR, NULL, NULL );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* DEFAULT */
|
|
if( pFunc->pSwitch->nDefault )
|
|
{
|
|
/* more than one default clause */
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_MAYHEM_IN_CASE, NULL, NULL );
|
|
}
|
|
else
|
|
{
|
|
pFunc->pSwitch->nDefault = pFunc->nPCodePos;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void hb_compSwitchEnd( HB_COMP_DECL )
|
|
{
|
|
PHB_HFUNC pFunc = HB_COMP_PARAM->functions.pLast;
|
|
PHB_SWITCHCMD pSwitch = pFunc->pSwitch;
|
|
PHB_EXPR pExpr = pSwitch->pExpr;
|
|
PHB_SWITCHCASE pCase, pTmp;
|
|
HB_SIZE ulExitPos, ulCountPos;
|
|
int iCount = 0;
|
|
|
|
/* skip switch pcode if there was no EXIT in the last CASE
|
|
* or in the DEFAULT case
|
|
*/
|
|
ulExitPos = hb_compGenJump( 0, HB_COMP_PARAM );
|
|
hb_compGenJumpHere( pSwitch->nOffset + 1, HB_COMP_PARAM );
|
|
|
|
pCase = pSwitch->pCases;
|
|
if( hb_compExprIsLong( pExpr ) || hb_compExprIsString( pExpr ) )
|
|
{
|
|
HB_BOOL fGen = HB_FALSE;
|
|
while( pCase )
|
|
{
|
|
if( hb_compExprIsLong( pCase->pExpr ) )
|
|
{
|
|
fGen = hb_compExprIsLong( pExpr ) &&
|
|
hb_compExprAsLongNum( pExpr ) ==
|
|
hb_compExprAsLongNum( pCase->pExpr );
|
|
}
|
|
else if( hb_compExprIsString( pCase->pExpr ) )
|
|
{
|
|
fGen = hb_compExprIsString( pExpr ) &&
|
|
hb_compExprAsStringLen( pExpr ) ==
|
|
hb_compExprAsStringLen( pCase->pExpr ) &&
|
|
memcmp( hb_compExprAsString( pExpr ),
|
|
hb_compExprAsString( pCase->pExpr ),
|
|
hb_compExprAsStringLen( pExpr ) ) == 0;
|
|
}
|
|
if( fGen )
|
|
{
|
|
hb_compGenJumpThere( hb_compGenJump( 0, HB_COMP_PARAM ),
|
|
pCase->nOffset, HB_COMP_PARAM );
|
|
break;
|
|
}
|
|
pCase = pCase->pNext;
|
|
}
|
|
if( pSwitch->nDefault && ! fGen )
|
|
{
|
|
hb_compGenJumpThere( hb_compGenJump( 0, HB_COMP_PARAM ),
|
|
pSwitch->nDefault, HB_COMP_PARAM );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HB_BOOL fSwitchCase = HB_COMP_PARAM->fSwitchCase;
|
|
HB_BOOL fMacroText = ( HB_COMP_PARAM->supported & HB_COMPFLAG_MACROTEXT ) != 0;
|
|
|
|
pExpr = hb_compExprGenPush( pExpr, HB_COMP_PARAM );
|
|
ulCountPos = pFunc->nPCodePos + 1;
|
|
hb_compGenPCode3( HB_P_SWITCH, 0, 0, HB_COMP_PARAM );
|
|
HB_COMP_PARAM->fSwitchCase = HB_TRUE;
|
|
HB_COMP_PARAM->supported &= ~HB_COMPFLAG_MACROTEXT;
|
|
while( pCase )
|
|
{
|
|
if( hb_compExprIsLong( pCase->pExpr ) || hb_compExprIsString( pCase->pExpr ) )
|
|
{
|
|
iCount++;
|
|
pCase->pExpr = hb_compExprGenPush( pCase->pExpr, HB_COMP_PARAM );
|
|
hb_compGenJumpThere( hb_compGenJump( 0, HB_COMP_PARAM ),
|
|
pCase->nOffset, HB_COMP_PARAM );
|
|
}
|
|
pCase = pCase->pNext;
|
|
}
|
|
if( pSwitch->nDefault )
|
|
{
|
|
iCount++;
|
|
hb_compGenPCode1( HB_P_PUSHNIL, HB_COMP_PARAM );
|
|
hb_compGenJumpThere( hb_compGenJump( 0, HB_COMP_PARAM ),
|
|
pSwitch->nDefault, HB_COMP_PARAM );
|
|
}
|
|
HB_PUT_LE_UINT16( pFunc->pCode + ulCountPos, iCount );
|
|
|
|
HB_COMP_PARAM->fSwitchCase = fSwitchCase;
|
|
if( fMacroText )
|
|
HB_COMP_PARAM->supported |= HB_COMPFLAG_MACROTEXT;
|
|
}
|
|
|
|
hb_compGenJumpHere( ulExitPos, HB_COMP_PARAM );
|
|
|
|
if( pExpr )
|
|
HB_COMP_EXPR_FREE( pExpr );
|
|
|
|
pCase = pSwitch->pCases;
|
|
while( pCase )
|
|
{
|
|
HB_COMP_EXPR_FREE( pCase->pExpr );
|
|
pTmp = pCase->pNext;
|
|
hb_xfree( pCase );
|
|
pCase = pTmp;
|
|
}
|
|
pFunc->pSwitch = pSwitch->pPrev;
|
|
hb_xfree( pSwitch );
|
|
}
|
|
|
|
/* Release all switch statements
|
|
*/
|
|
void hb_compSwitchKill( HB_COMP_DECL, PHB_HFUNC pFunc )
|
|
{
|
|
PHB_SWITCHCASE pCase;
|
|
PHB_SWITCHCMD pSwitch;
|
|
|
|
while( pFunc->pSwitch )
|
|
{
|
|
while( pFunc->pSwitch->pCases )
|
|
{
|
|
pCase = pFunc->pSwitch->pCases;
|
|
HB_COMP_EXPR_FREE( pCase->pExpr );
|
|
pFunc->pSwitch->pCases = pCase->pNext;
|
|
hb_xfree( pCase );
|
|
}
|
|
pSwitch = pFunc->pSwitch;
|
|
pFunc->pSwitch = pSwitch->pPrev;
|
|
if( pSwitch->pExpr )
|
|
HB_COMP_EXPR_FREE( pSwitch->pExpr );
|
|
hb_xfree( pSwitch );
|
|
}
|
|
}
|
|
|
|
static PHB_EXPR hb_compCheckPassByRef( HB_COMP_DECL, PHB_EXPR pExpr )
|
|
{
|
|
if( pExpr->ExprType == HB_ET_FUNCALL )
|
|
{
|
|
if( hb_compExprParamListLen( pExpr->value.asFunCall.pParms ) == 0 )
|
|
{
|
|
PHB_EXPR pDelExpr = pExpr;
|
|
if( pExpr->value.asFunCall.pFunName->ExprType == HB_ET_MACRO )
|
|
{
|
|
pExpr = pExpr->value.asFunCall.pFunName;
|
|
HB_COMP_EXPR_CLEAR( pDelExpr );
|
|
}
|
|
else
|
|
{
|
|
pExpr = hb_compExprNewFunRef( hb_compExprAsSymbol( pExpr ), HB_COMP_PARAM );
|
|
HB_COMP_EXPR_FREE( pDelExpr );
|
|
}
|
|
return pExpr;
|
|
}
|
|
else
|
|
{
|
|
const char * szDesc;
|
|
|
|
szDesc = hb_compExprAsSymbol( pExpr );
|
|
if( ! szDesc )
|
|
szDesc = hb_compExprDescription( pExpr );
|
|
|
|
return hb_compErrorRefer( HB_COMP_PARAM, pExpr, szDesc );
|
|
}
|
|
}
|
|
|
|
return pExpr;
|
|
}
|
|
|
|
static PHB_EXPR hb_compCheckMethod( HB_COMP_DECL, PHB_EXPR pExpr )
|
|
{
|
|
if( pExpr->value.asMessage.szMessage &&
|
|
pExpr->value.asMessage.pObject &&
|
|
pExpr->value.asMessage.pObject->ExprType == HB_ET_VARIABLE &&
|
|
pExpr->value.asMessage.szMessage[ 0 ] == '_' &&
|
|
strncmp( "__ENUM", pExpr->value.asMessage.szMessage, 6 ) == 0 )
|
|
{
|
|
const char * szMessage = pExpr->value.asMessage.szMessage + 6;
|
|
|
|
if( strcmp( "INDEX", szMessage ) == 0 ||
|
|
strcmp( "KEY", szMessage ) == 0 ||
|
|
strcmp( "BASE", szMessage ) == 0 ||
|
|
strcmp( "VALUE", szMessage ) == 0 ||
|
|
strcmp( "ISFIRST", szMessage ) == 0 ||
|
|
strcmp( "ISLAST", szMessage ) == 0 )
|
|
{
|
|
int iDir = 0;
|
|
if( ! hb_compForEachVarError( HB_COMP_PARAM, pExpr->value.asMessage.pObject->value.asSymbol.name, &iDir ) )
|
|
{
|
|
pExpr->value.asMessage.pObject->ExprType = HB_ET_VARREF;
|
|
#if 0
|
|
if( iDir < 0 )
|
|
{
|
|
if( strcmp( "ISFIRST", szMessage ) == 0 )
|
|
pExpr->value.asMessage.szMessage = "__ENUMISLAST";
|
|
else if( strcmp( "ISLAST", szMessage ) == 0 )
|
|
pExpr->value.asMessage.szMessage = "__ENUMISFIRST";
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
return pExpr;
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
|
|
HB_BOOL hb_compCheckUnclosedStru( HB_COMP_DECL, PHB_HFUNC pFunc )
|
|
{
|
|
HB_BOOL fUnclosed = HB_TRUE;
|
|
|
|
if( pFunc->wIfCounter )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_UNCLOSED_STRU, "IF", NULL );
|
|
pFunc->wIfCounter = 0;
|
|
}
|
|
else if( pFunc->wForCounter )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_UNCLOSED_STRU, "FOR", NULL );
|
|
pFunc->wForCounter = 0;
|
|
}
|
|
else if( pFunc->wWhileCounter )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_UNCLOSED_STRU, "WHILE", NULL );
|
|
pFunc->wWhileCounter = 0;
|
|
}
|
|
else if( pFunc->wCaseCounter )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_UNCLOSED_STRU, "CASE", NULL );
|
|
pFunc->wCaseCounter = 0;
|
|
}
|
|
else if( pFunc->wSwitchCounter )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_UNCLOSED_STRU, "SWITCH", NULL );
|
|
pFunc->wSwitchCounter = 0;
|
|
}
|
|
else if( pFunc->wWithObjectCnt )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_UNCLOSED_STRU, "WITH OBJECT", NULL );
|
|
pFunc->wWithObjectCnt = 0;
|
|
}
|
|
else if( pFunc->wSeqCounter )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_UNCLOSED_STRU, "BEGIN SEQUENCE", NULL );
|
|
pFunc->wSeqCounter = 0;
|
|
}
|
|
else if( pFunc->funFlags & HB_FUNF_EXTBLOCK )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_UNCLOSED_STRU, "{||...}", NULL );
|
|
pFunc->funFlags &= ~HB_FUNF_EXTBLOCK;
|
|
}
|
|
else
|
|
fUnclosed = HB_FALSE;
|
|
|
|
return fUnclosed;
|
|
}
|
|
|
|
void yyerror( HB_COMP_DECL, const char * s )
|
|
{
|
|
if( ! HB_COMP_PARAM->pLex->lasttok || HB_COMP_PARAM->pLex->lasttok[ 0 ] == '\n' )
|
|
{
|
|
if( HB_COMP_PARAM->iErrorCount == 0 || ! hb_pp_eof( HB_COMP_PARAM->pLex->pPP ) )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_INCOMPLETE_STMT, NULL, NULL );
|
|
}
|
|
else
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_YACC, s, HB_COMP_PARAM->pLex->lasttok );
|
|
}
|