* harbour/include/hbcomp.h
* harbour/include/hbcompdf.h
* harbour/source/compiler/hbmain.c
* harbour/source/compiler/complex.c
* harbour/source/compiler/harbour.y
* harbour/source/compiler/harbour.yyc
! moved function related variables and structures from HB_COMP to
PFUNCTION - it fixes many different problems which can appear in
some code, also the recent Mindaugas' example
! initialize statement value in error action to avoid valgrind/CodeGuard
warning reports when syntax error appear in some complex statements
* harbour/source/rtl/scrollbr.prg
* repalced TAB with SPACEs
2831 lines
113 KiB
Plaintext
2831 lines
113 KiB
Plaintext
%pure-parser
|
|
%parse-param { HB_COMP_PTR pComp }
|
|
%lex-param { HB_COMP_PTR pComp }
|
|
%name-prefix = "hb_comp"
|
|
%{
|
|
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* Harbour Project source code:
|
|
* Compiler YACC rules and actions
|
|
*
|
|
* Copyright 1999 Antonio Linares <alinares@fivetech.com>
|
|
* www - http://www.harbour-project.org
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 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 warnings in BCC */
|
|
#if defined( __BORLANDC__ ) && !defined( __STDC__ )
|
|
# define __STDC__
|
|
#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
|
|
|
|
static void hb_compLoopStart( HB_COMP_DECL, 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, ULONG ulOffset ); /* 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, HB_EXPR_PTR, BOOL );
|
|
static void hb_compRTVariableGen( HB_COMP_DECL, char * );
|
|
|
|
static HB_EXPR_PTR hb_compArrayDimPush( HB_EXPR_PTR pInitValue, HB_COMP_DECL );
|
|
static void hb_compVariableDim( char *, HB_EXPR_PTR, HB_COMP_DECL );
|
|
|
|
static void hb_compForStart( HB_COMP_DECL, char *szVarName, BOOL bForEach );
|
|
static void hb_compForEnd( HB_COMP_DECL, char *szVarName );
|
|
static void hb_compEnumStart( HB_COMP_DECL, HB_EXPR_PTR pVars, HB_EXPR_PTR pExprs, int descend );
|
|
static void hb_compEnumNext( HB_COMP_DECL, HB_EXPR_PTR pExpr, int descend );
|
|
static void hb_compEnumEnd( HB_COMP_DECL, HB_EXPR_PTR pExpr );
|
|
|
|
static void hb_compSwitchStart( HB_COMP_DECL );
|
|
static void hb_compSwitchAdd( HB_COMP_DECL, HB_EXPR_PTR );
|
|
static void hb_compSwitchEnd( HB_COMP_DECL );
|
|
|
|
static HB_EXPR_PTR hb_compCheckPassByRef( HB_COMP_DECL, HB_EXPR_PTR pExpr );
|
|
|
|
#ifdef HARBOUR_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 */
|
|
{
|
|
char * string; /* to hold a string returned by lex */
|
|
int iNumber; /* to hold a temporary integer number */
|
|
HB_LONG lNumber; /* to hold a temporary long number */
|
|
BOOL bTrue;
|
|
HB_EXPR_PTR asExpr;
|
|
void * pVoid; /* to hold any memory structure we may need */
|
|
struct
|
|
{
|
|
HB_LONG lNumber; /* to hold a long number returned by lex */
|
|
UCHAR bWidth; /* to hold the width of the value */
|
|
} valLong;
|
|
struct
|
|
{
|
|
double dNumber; /* to hold a double number returned by lex */
|
|
/* NOTE: Intentionally using "unsigned char" instead of "BYTE" */
|
|
UCHAR bWidth; /* to hold the width of the value */
|
|
UCHAR bDec; /* to hold the number of decimal points in the value */
|
|
} valDouble;
|
|
struct
|
|
{
|
|
char * string;
|
|
int length;
|
|
BOOL dealloc;
|
|
} valChar;
|
|
struct
|
|
{
|
|
char * string;
|
|
int length;
|
|
int flags; /* Flag for early {|| ¯o} (1) or late {|| &(macro)} (2) binding */
|
|
} asCodeblock;
|
|
struct
|
|
{
|
|
BOOL bMacro;
|
|
union
|
|
{
|
|
char * string;
|
|
HB_EXPR_PTR macro;
|
|
} value;
|
|
} asMessage;
|
|
};
|
|
|
|
%{
|
|
/* 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, 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
|
|
%token EPSILON
|
|
%token HASHOP
|
|
|
|
/*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 <iNumber> FunScope
|
|
%type <iNumber> Params ParamList
|
|
%type <iNumber> IfBegin VarList ExtVarList
|
|
%type <iNumber> FieldList
|
|
%type <iNumber> Descend
|
|
%type <lNumber> WhileBegin
|
|
%type <pVoid> IfElseIf Cases
|
|
%type <asExpr> Argument ExtArgument RefArgument ArgList ElemList
|
|
%type <asExpr> BlockHead BlockExpList BlockVars BlockVarList
|
|
%type <asExpr> DoName 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
|
|
%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> 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 <asCodeblock> CBSTART
|
|
%type <asMessage> SendId
|
|
|
|
/*
|
|
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_DELETE( $$ );
|
|
}
|
|
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 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 = FALSE;
|
|
if( $3.dealloc ) { hb_xfree( $3.string ); $3.dealloc = 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 = FALSE;
|
|
if( $3.dealloc ) { hb_xfree( $3.string ); $3.dealloc = FALSE; }
|
|
if( $5.dealloc ) { hb_xfree( $5.string ); $5.dealloc = FALSE; } }
|
|
;
|
|
|
|
Function : FunScope FUNCTION IdentName { HB_COMP_PARAM->cVarType = ' '; hb_compFunctionAdd( HB_COMP_PARAM, $3, ( HB_SYMBOLSCOPE ) $1, 0 ); } Crlf
|
|
| FunScope PROCEDURE IdentName { HB_COMP_PARAM->cVarType = ' '; hb_compFunctionAdd( HB_COMP_PARAM, $3, ( HB_SYMBOLSCOPE ) $1, FUN_PROCEDURE ); } Crlf
|
|
| FunScope FUNCTION IdentName { HB_COMP_PARAM->cVarType = ' '; hb_compFunctionAdd( HB_COMP_PARAM, $3, ( HB_SYMBOLSCOPE ) $1, 0 ); HB_COMP_PARAM->iVarScope = VS_PARAMETER; } '(' Params ')' Crlf
|
|
| FunScope PROCEDURE IdentName { HB_COMP_PARAM->cVarType = ' '; hb_compFunctionAdd( HB_COMP_PARAM, $3, ( HB_SYMBOLSCOPE ) $1, FUN_PROCEDURE ); HB_COMP_PARAM->iVarScope = VS_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 = TRUE; $$ = 0; }
|
|
| ParamList
|
|
| ParamList ',' EPSILON { HB_COMP_PARAM->functions.pLast->fVParams = TRUE; $$ = $1; }
|
|
;
|
|
|
|
AsType : /* not specified */ { HB_COMP_PARAM->cVarType = ' '; }
|
|
| StrongType
|
|
;
|
|
|
|
AsArrayType: /* not specified */ { HB_COMP_PARAM->cVarType = ' '; }
|
|
| AsArray
|
|
;
|
|
|
|
StrongType : AS_NUMERIC { HB_COMP_PARAM->cVarType = 'N'; }
|
|
| AS_CHARACTER { HB_COMP_PARAM->cVarType = 'C'; }
|
|
| AS_DATE { HB_COMP_PARAM->cVarType = 'D'; }
|
|
| AS_LOGICAL { HB_COMP_PARAM->cVarType = 'L'; }
|
|
| AS_BLOCK { HB_COMP_PARAM->cVarType = 'B'; }
|
|
| AS_OBJECT { HB_COMP_PARAM->cVarType = 'O'; }
|
|
| AS_CLASS IdentName { HB_COMP_PARAM->cVarType = 'S'; HB_COMP_PARAM->szFromClass = $2; }
|
|
| AS_VARIANT { HB_COMP_PARAM->cVarType = ' '; }
|
|
| AsArray
|
|
;
|
|
|
|
AsArray : AS_ARRAY { HB_COMP_PARAM->cVarType = 'A'; }
|
|
| AS_NUMERIC_ARRAY { HB_COMP_PARAM->cVarType = 'n'; }
|
|
| AS_CHARACTER_ARRAY { HB_COMP_PARAM->cVarType = 'c'; }
|
|
| AS_DATE_ARRAY { HB_COMP_PARAM->cVarType = 'd'; }
|
|
| AS_LOGICAL_ARRAY { HB_COMP_PARAM->cVarType = 'l'; }
|
|
| AS_ARRAY_ARRAY { HB_COMP_PARAM->cVarType = 'a'; }
|
|
| AS_BLOCK_ARRAY { HB_COMP_PARAM->cVarType = 'b'; }
|
|
| AS_OBJECT_ARRAY { HB_COMP_PARAM->cVarType = 'o'; }
|
|
| AS_CLASS_ARRAY IdentName { HB_COMP_PARAM->cVarType = 's'; HB_COMP_PARAM->szFromClass = $2; }
|
|
;
|
|
|
|
ParamList : IdentName AsType { hb_compVariableAdd( HB_COMP_PARAM, $1, HB_COMP_PARAM->cVarType ); $$ = 1; }
|
|
| ParamList ',' IdentName AsType { hb_compVariableAdd( HB_COMP_PARAM, $3, HB_COMP_PARAM->cVarType ); $$++; }
|
|
;
|
|
|
|
/* 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_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
| FunCall CrlfStmnt { HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
| AliasExpr CrlfStmnt { HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
| ObjectMethod CrlfStmnt { HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
| MacroVar CrlfStmnt { if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_XBASE ) )
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) );
|
|
else
|
|
HB_COMP_EXPR_DELETE( HB_COMP_ERROR_SYNTAX( $1 ) );
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN;
|
|
}
|
|
| MacroExpr CrlfStmnt { if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_XBASE ) )
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) );
|
|
else
|
|
HB_COMP_EXPR_DELETE( HB_COMP_ERROR_SYNTAX( $1 ) );
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN;
|
|
}
|
|
| PareExpList CrlfStmnt { HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
| ExprPreOp CrlfStmnt { HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
| ExprPostOp CrlfStmnt { HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
| ExprOperEq CrlfStmnt { HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
| ExprEqual CrlfStmnt { HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
| ExprAssign CrlfStmnt { HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
| DoProc CrlfStmnt { HB_COMP_EXPR_DELETE( hb_compExprGenStatement( $1, HB_COMP_PARAM ) ); HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
| BREAK CrlfStmnt { hb_compGenBreak( HB_COMP_PARAM ); hb_compGenPCode2( HB_P_DOSHORT, 0, HB_COMP_PARAM );
|
|
HB_COMP_PARAM->functions.pLast->bFlags |= FUN_BREAK_CODE; }
|
|
| BREAK { hb_compLinePushIfInside( HB_COMP_PARAM ); } Expression Crlf
|
|
{
|
|
hb_compGenBreak( HB_COMP_PARAM ); HB_COMP_EXPR_DELETE( hb_compExprGenPush( $3, HB_COMP_PARAM ) );
|
|
hb_compGenPCode2( HB_P_DOSHORT, 1, HB_COMP_PARAM );
|
|
HB_COMP_PARAM->functions.pLast->bFlags |= FUN_BREAK_CODE;
|
|
}
|
|
| EXIT CrlfStmnt { hb_compLoopExit( HB_COMP_PARAM ); HB_COMP_PARAM->functions.pLast->bFlags |= FUN_BREAK_CODE; }
|
|
| LOOP CrlfStmnt { hb_compLoopLoop( HB_COMP_PARAM ); HB_COMP_PARAM->functions.pLast->bFlags |= FUN_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->bFlags & FUN_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->bFlags |= FUN_WITH_RETURN | FUN_BREAK_CODE;
|
|
}
|
|
| RETURN { hb_compLinePushIfInside( HB_COMP_PARAM ); HB_COMP_PARAM->cVarType = ' '; }
|
|
Expression Crlf
|
|
{
|
|
HB_COMP_PARAM->cVarType = ' ';
|
|
|
|
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_DELETE( hb_compExprGenPush( $3, HB_COMP_PARAM ) );
|
|
if( HB_COMP_PARAM->functions.pLast->bFlags & FUN_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->bFlags & FUN_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->bFlags |= FUN_WITH_RETURN | FUN_BREAK_CODE;
|
|
}
|
|
| PUBLIC { hb_compLinePushIfInside( HB_COMP_PARAM ); HB_COMP_PARAM->iVarScope = VS_PUBLIC; }
|
|
ExtVarList
|
|
{ hb_compRTVariableGen( HB_COMP_PARAM, "__MVPUBLIC" );
|
|
HB_COMP_PARAM->cVarType = ' '; HB_COMP_PARAM->iVarScope = VS_NONE;
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN;
|
|
} Crlf
|
|
| PRIVATE { hb_compLinePushIfInside( HB_COMP_PARAM ); HB_COMP_PARAM->iVarScope = VS_PRIVATE; }
|
|
ExtVarList
|
|
{ hb_compRTVariableGen( HB_COMP_PARAM, "__MVPRIVATE" );
|
|
HB_COMP_PARAM->cVarType = ' '; HB_COMP_PARAM->iVarScope = VS_NONE;
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN;
|
|
} Crlf
|
|
| VarDefs
|
|
| FieldsDef
|
|
| MemvarDef
|
|
| EXTERN ExtList Crlf
|
|
| DYNAMIC DynList Crlf
|
|
| ANNOUNCE IdentName {
|
|
if( HB_COMP_PARAM->szAnnounce == NULL )
|
|
{
|
|
/* check for reserved name
|
|
* NOTE: Clipper doesn't check for it
|
|
*/
|
|
char * szFunction = hb_compReservedName( $2 );
|
|
if( szFunction )
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_FUNC_RESERVED, szFunction, $2 );
|
|
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 { HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_WITH_RETURN; }
|
|
;
|
|
|
|
CompTimeStr : LITERAL {
|
|
if( $1.dealloc )
|
|
{
|
|
$1.string = hb_compIdentifierNew( HB_COMP_PARAM, $1.string, HB_IDENT_FREE );
|
|
$1.dealloc = FALSE;
|
|
}
|
|
hb_compAutoOpenAdd( HB_COMP_PARAM, $1.string );
|
|
}
|
|
| LITERAL '+' LITERAL {
|
|
{
|
|
char szFileName[ _POSIX_PATH_MAX + 1 ];
|
|
hb_strncat( hb_strncpy( szFileName, $1.string, _POSIX_PATH_MAX ), $3.string, _POSIX_PATH_MAX );
|
|
hb_compAutoOpenAdd( HB_COMP_PARAM, hb_compIdentifierNew( HB_COMP_PARAM, szFileName, HB_IDENT_COPY ) );
|
|
if( $1.dealloc )
|
|
{
|
|
hb_xfree( $1.string );
|
|
$1.dealloc = FALSE;
|
|
}
|
|
if( $3.dealloc )
|
|
{
|
|
hb_xfree( $3.string );
|
|
$3.dealloc = 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; }
|
|
;
|
|
|
|
/* 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( $1.lNumber, 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 = FALSE;
|
|
}
|
|
;
|
|
|
|
LiteralAlias : LiteralValue ALIASOP
|
|
;
|
|
|
|
/* Codeblock value
|
|
*/
|
|
CodeBlockAlias : CodeBlock ALIASOP
|
|
;
|
|
|
|
/* Logical value
|
|
*/
|
|
Logical : TRUEVALUE { $$ = hb_compExprNewLogical( TRUE, HB_COMP_PARAM ); }
|
|
| FALSEVALUE { $$ = hb_compExprNewLogical( 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
|
|
;
|
|
|
|
/* 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_DELETE( $1 ); $$ = $2; }
|
|
| FieldAlias NumAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = $2; }
|
|
| FieldAlias PareExpListAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = $2; }
|
|
| FieldAlias MacroVarAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = $2; }
|
|
| FieldAlias MacroExprAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = $2; }
|
|
| FieldAlias NilAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias LiteralAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias LogicalAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias CodeBlockAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias SelfAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias ArrayAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias ArrayAtAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias HashAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
| FieldAlias IfInlineAlias { HB_COMP_EXPR_DELETE( $1 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $2 ); }
|
|
;
|
|
|
|
AliasId : IdentName { $$ = hb_compExprNewVar( $1, HB_COMP_PARAM ); }
|
|
| MacroVar
|
|
| MacroExpr
|
|
;
|
|
|
|
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_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| LiteralAlias AliasId { HB_COMP_EXPR_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| LogicalAlias AliasId { HB_COMP_EXPR_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| CodeBlockAlias AliasId { HB_COMP_EXPR_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| HashAlias AliasId { HB_COMP_EXPR_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| SelfAlias AliasId { HB_COMP_EXPR_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| ArrayAlias AliasId { HB_COMP_EXPR_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); }
|
|
| ArrayAtAlias AliasId { HB_COMP_EXPR_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); } /* QUESTION: Clipper reports error here - we can handle this */
|
|
| VariableAtAlias AliasId { HB_COMP_EXPR_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); } /* QUESTION: Clipper reports error here - we can handle this */
|
|
| IfInlineAlias AliasId { HB_COMP_EXPR_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); } /* QUESTION: Clipper reports error here - we can handle this */
|
|
| FunCallAlias AliasId { HB_COMP_EXPR_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); } /* QUESTION: Clipper reports error here - we can handle this */
|
|
| ObjectDataAlias AliasId { HB_COMP_EXPR_DELETE( $2 ); $$ = hb_compErrorAlias( HB_COMP_PARAM, $1 ); } /* QUESTION: Clipper reports error here - we can handle this */
|
|
| ObjectMethodAlias AliasId { HB_COMP_EXPR_DELETE( $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_DELETE( $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; }
|
|
| LiteralValue ArrayIndex { $$ = $2; }
|
|
| CodeBlock ArrayIndex { $$ = $2; }
|
|
| Logical ArrayIndex { $$ = $2; }
|
|
| Hash ArrayIndex { $$ = $2; }
|
|
| SelfValue ArrayIndex { $$ = $2; }
|
|
| Variable ArrayIndex { $$ = $2; }
|
|
| AliasVar ArrayIndex { $$ = $2; }
|
|
| AliasExpr ArrayIndex { $$ = $2; }
|
|
| MacroVar ArrayIndex { $$ = $2; }
|
|
| MacroExpr ArrayIndex { $$ = $2; }
|
|
| ObjectData ArrayIndex { $$ = $2; }
|
|
| ObjectMethod ArrayIndex { $$ = $2; }
|
|
| FunCall ArrayIndex { $$ = $2; }
|
|
| IfInline ArrayIndex { $$ = $2; }
|
|
| PareExpList ArrayIndex { $$ = $2; }
|
|
;
|
|
|
|
VariableAtAlias : VariableAt ALIASOP
|
|
;
|
|
|
|
FunIdentCall: IdentName '(' { $<bTrue>$ = HB_COMP_PARAM->iPassByRef;HB_COMP_PARAM->iPassByRef=HB_PASSBYREF_FUNCALL;} ArgList ')' { $$ = hb_compExprNewFunCall( hb_compExprNewFunName( $1, HB_COMP_PARAM ), $4, HB_COMP_PARAM ); HB_COMP_PARAM->iPassByRef = $<bTrue>3; }
|
|
/* function call
|
|
*/
|
|
FunCall : FunIdentCall
|
|
| MacroVar '(' { $<bTrue>$ = HB_COMP_PARAM->iPassByRef;HB_COMP_PARAM->iPassByRef=HB_PASSBYREF_FUNCALL;} ArgList ')' { $$ = hb_compExprNewFunCall( $1, $4, HB_COMP_PARAM ); HB_COMP_PARAM->iPassByRef = $<bTrue>3; }
|
|
| MacroExpr '(' { $<bTrue>$ = HB_COMP_PARAM->iPassByRef;HB_COMP_PARAM->iPassByRef=HB_PASSBYREF_FUNCALL;} ArgList ')' { $$ = hb_compExprNewFunCall( $1, $4, HB_COMP_PARAM ); HB_COMP_PARAM->iPassByRef = $<bTrue>3; }
|
|
;
|
|
|
|
/* 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 = TRUE; }
|
|
;
|
|
|
|
ExtArgument : EPSILON { $$ = hb_compExprNewArgRef( HB_COMP_PARAM ); }
|
|
| Argument
|
|
;
|
|
|
|
/* Object's instance variable
|
|
*/
|
|
ObjectData : LeftExpression ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro, HB_COMP_PARAM ) : hb_compExprNewSend( $1, $3.value.string, NULL, HB_COMP_PARAM )); }
|
|
| ObjectRef ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro, HB_COMP_PARAM ) : hb_compExprNewSend( $1, $3.value.string, NULL, HB_COMP_PARAM )); }
|
|
| ':' 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.bMacro ? hb_compExprNewSend( NULL, NULL, $2.value.macro, HB_COMP_PARAM ) : hb_compExprNewSend( NULL, $2.value.string, NULL, HB_COMP_PARAM ));
|
|
}
|
|
;
|
|
|
|
SendId : IdentName { $$.value.string = $1; $$.bMacro=FALSE; }
|
|
| MacroVar { $$.value.macro = $1; $$.bMacro=TRUE; }
|
|
| MacroExpr { $$.value.macro = $1; $$.bMacro=TRUE; }
|
|
;
|
|
|
|
ObjectRef : '(' '@' IdentName ')' { $$ = hb_compExprNewVarRef( $3, HB_COMP_PARAM ); }
|
|
|
|
|
|
ObjectDataAlias : ObjectData ALIASOP
|
|
;
|
|
|
|
/* Object's method
|
|
*/
|
|
ObjectMethod : ObjectData '(' {$<bTrue>$=HB_COMP_PARAM->iPassByRef;HB_COMP_PARAM->iPassByRef=HB_PASSBYREF_FUNCALL;} ArgList ')' { $$ = hb_compExprNewMethodCall( $1, $4 ); HB_COMP_PARAM->iPassByRef=$<bTrue>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
|
|
| LiteralValue
|
|
| CodeBlock
|
|
| Logical
|
|
| SelfValue
|
|
| SelfValue {HB_COMP_PARAM->cVarType = ' ';} StrongType { $$ = $1; }
|
|
| Array
|
|
| ArrayAt
|
|
| Hash
|
|
| AliasVar
|
|
| AliasExpr
|
|
| MacroVar
|
|
| MacroExpr
|
|
| VariableAt
|
|
| FunCall
|
|
| FunCall {HB_COMP_PARAM->cVarType = ' ';} StrongType { $$ = $1; }
|
|
| IfInline
|
|
| ObjectData
|
|
| ObjectData {HB_COMP_PARAM->cVarType = ' ';} StrongType { $$ = $1; }
|
|
| ObjectMethod
|
|
| ObjectMethod {HB_COMP_PARAM->cVarType = ' ';} StrongType { $$ = $1; }
|
|
| ExprAssign
|
|
| ExprOperEq
|
|
| ExprPostOp
|
|
| ExprPreOp
|
|
| ExprUnary
|
|
| ExprMath
|
|
| ExprBool
|
|
| ExprRelation
|
|
;
|
|
|
|
Expression : SimpleExpression
|
|
| Variable
|
|
| PareExpList
|
|
| Variable { HB_COMP_PARAM->cVarType = ' ';} StrongType { $$ = $1; }
|
|
| PareExpList { HB_COMP_PARAM->cVarType = ' ';} 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, NULL ); }
|
|
;
|
|
|
|
/* 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
|
|
| LiteralValue
|
|
| CodeBlock
|
|
| Logical
|
|
| SelfValue
|
|
| Array
|
|
| ArrayAt
|
|
| Hash
|
|
| AliasVar
|
|
| AliasExpr
|
|
| MacroVar
|
|
| MacroExpr
|
|
| 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; }
|
|
;
|
|
|
|
ExprAssign : NumValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| NilValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| DateValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| LiteralValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| CodeBlock INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| Logical INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| SelfValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| Array INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| ArrayAt INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| Hash INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| AliasVar INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| AliasExpr INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| MacroVar INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| MacroExpr INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| Variable INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); HB_COMP_PARAM->cVarType = ' ';}
|
|
| VariableAt INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); HB_COMP_PARAM->cVarType = ' ';}
|
|
| PareExpList INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| IfInline INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| FunCall INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
| ObjectData INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); HB_COMP_PARAM->cVarType = ' ';}
|
|
| ObjectMethod INASSIGN Expression { $$ = hb_compExprAssign( $1, $3, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
ExprEqual : LeftExpression '=' Expression %prec INASSIGN { $$ = 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 { $$ = 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 = VS_LOCAL; $$ = hb_compExprCBVarAdd( $<asExpr>0, $1, HB_COMP_PARAM->cVarType, HB_COMP_PARAM ); HB_COMP_PARAM->cVarType = ' '; }
|
|
| BlockVarList ',' IdentName AsType { HB_COMP_PARAM->iVarScope = VS_LOCAL; $$ = hb_compExprCBVarAdd( $<asExpr>0, $3, HB_COMP_PARAM->cVarType, HB_COMP_PARAM ); HB_COMP_PARAM->cVarType = ' '; }
|
|
;
|
|
|
|
BlockExpList : Expression { $$ = hb_compExprAddCodeblockExpr( $<asExpr>0, $1 ); }
|
|
| BlockExpList ',' Expression { $$ = hb_compExprAddCodeblockExpr( $<asExpr>0, $3 ); }
|
|
;
|
|
|
|
CodeBlock : BlockHead BlockExpList '}'
|
|
| BlockHead Crlf
|
|
{ /* 3 */
|
|
HB_CBVAR_PTR pVar;
|
|
$<lNumber>$ = HB_COMP_PARAM->functions.pLast->lPCodePos;
|
|
hb_compCodeBlockStart( HB_COMP_PARAM, TRUE );
|
|
HB_COMP_PARAM->functions.pLast->bFlags |= FUN_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->ulLength = 0;
|
|
}
|
|
|
|
HB_COMP_PARAM->iVarScope = VS_PARAMETER;
|
|
pVar = $1->value.asCodeblock.pLocals;
|
|
while( pVar )
|
|
{
|
|
hb_compVariableAdd( HB_COMP_PARAM, pVar->szName, pVar->bType );
|
|
pVar =pVar->pNext;
|
|
}
|
|
}
|
|
EmptyStats '}'
|
|
{ /* 6 */
|
|
hb_compCodeBlockEnd( HB_COMP_PARAM );
|
|
$$ = hb_compExprSetCodeblockBody( $1,
|
|
HB_COMP_PARAM->functions.pLast->pCode + ( ULONG ) $<lNumber>3,
|
|
HB_COMP_PARAM->functions.pLast->lPCodePos - ( ULONG ) $<lNumber>3 );
|
|
HB_COMP_PARAM->functions.pLast->lPCodePos = ( ULONG ) $<lNumber>3;
|
|
HB_COMP_PARAM->lastLinePos = 0;
|
|
}
|
|
;
|
|
|
|
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 = VS_LOCAL; hb_compLinePush( HB_COMP_PARAM ); }
|
|
VarList Crlf { HB_COMP_PARAM->cVarType = ' '; }
|
|
| STATIC { HB_COMP_PARAM->iVarScope = VS_STATIC; hb_compLinePush( HB_COMP_PARAM ); }
|
|
VarList Crlf { HB_COMP_PARAM->cVarType = ' '; }
|
|
| PARAMETERS { if( HB_COMP_PARAM->functions.pLast->bFlags & FUN_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 = ( VS_PRIVATE | VS_PARAMETER );
|
|
}
|
|
} MemvarList Crlf { HB_COMP_PARAM->iVarScope = VS_NONE; }
|
|
;
|
|
|
|
VarList : VarDef { $$ = 1; }
|
|
| VarList ',' VarDef { $$++; }
|
|
;
|
|
|
|
ExtVarList : ExtVarDef { $$ = 1; }
|
|
| ExtVarList ',' ExtVarDef { $$++; }
|
|
;
|
|
|
|
/* NOTE: if STATIC or LOCAL variables are declared and initialized then we can
|
|
* assign a value immediately - however for PRIVATE and PUBLIC variables
|
|
* initialization have to be delayed because we have to create these variables
|
|
* first.
|
|
*/
|
|
ExtVarDef : VarDef
|
|
| MacroVar AsType
|
|
{ hb_compRTVariableAdd( HB_COMP_PARAM, hb_compExprNewRTVar( NULL, $1, HB_COMP_PARAM ), FALSE ); }
|
|
| MacroVar AsType INASSIGN Expression
|
|
{ HB_COMP_EXPR_DELETE( hb_compExprGenPush( $4, HB_COMP_PARAM ) );
|
|
hb_compRTVariableAdd( HB_COMP_PARAM, hb_compExprNewRTVar( NULL, $1, HB_COMP_PARAM ), TRUE );
|
|
}
|
|
| MacroVar DimList AsArrayType
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compArrayDimPush( $2, HB_COMP_PARAM ) );
|
|
hb_compRTVariableAdd( HB_COMP_PARAM, hb_compExprNewRTVar( NULL, $1, HB_COMP_PARAM ), TRUE );
|
|
}
|
|
;
|
|
|
|
VarDef : IdentName AsType { hb_compVariableAdd( HB_COMP_PARAM, $1, HB_COMP_PARAM->cVarType ); }
|
|
{
|
|
if( HB_COMP_PARAM->iVarScope == VS_STATIC )
|
|
{
|
|
hb_compStaticDefStart( HB_COMP_PARAM ); /* switch to statics pcode buffer */
|
|
hb_compStaticDefEnd( HB_COMP_PARAM, $1 );
|
|
}
|
|
else if( HB_COMP_PARAM->iVarScope == VS_PUBLIC || HB_COMP_PARAM->iVarScope == VS_PRIVATE )
|
|
{
|
|
hb_compRTVariableAdd( HB_COMP_PARAM, hb_compExprNewRTVar( $1, NULL, HB_COMP_PARAM ), FALSE );
|
|
}
|
|
else if( HB_COMP_PARAM->iVarScope == VS_LOCAL &&
|
|
( HB_COMP_PARAM->functions.pLast->bFlags & FUN_EXTBLOCK ) )
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenPush( hb_compExprNewNil( HB_COMP_PARAM ), HB_COMP_PARAM ) );
|
|
}
|
|
}
|
|
| IdentName AsType { $<iNumber>$ = HB_COMP_PARAM->iVarScope;
|
|
hb_compVariableAdd( HB_COMP_PARAM, $1, HB_COMP_PARAM->cVarType );
|
|
}
|
|
INASSIGN {HB_COMP_PARAM->cVarType = ' ';} Expression
|
|
{
|
|
HB_COMP_PARAM->cVarType = ' ';
|
|
|
|
HB_COMP_PARAM->iVarScope = $<iNumber>3;
|
|
if( HB_COMP_PARAM->iVarScope == VS_STATIC )
|
|
{
|
|
hb_compStaticDefStart( HB_COMP_PARAM ); /* switch to statics pcode buffer */
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenStatement( hb_compExprAssignStatic( hb_compExprNewVar( $1, HB_COMP_PARAM ), $6, HB_COMP_PARAM ), HB_COMP_PARAM ) );
|
|
hb_compStaticDefEnd( HB_COMP_PARAM, $1 );
|
|
}
|
|
else if( HB_COMP_PARAM->iVarScope == VS_PUBLIC || HB_COMP_PARAM->iVarScope == VS_PRIVATE )
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenPush( $6, HB_COMP_PARAM ) );
|
|
hb_compRTVariableAdd( HB_COMP_PARAM, hb_compExprNewRTVar( $1, NULL, HB_COMP_PARAM ), TRUE );
|
|
}
|
|
else if( HB_COMP_PARAM->iVarScope == VS_LOCAL &&
|
|
( HB_COMP_PARAM->functions.pLast->bFlags & FUN_EXTBLOCK ) )
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenPush( $6, HB_COMP_PARAM ) );
|
|
}
|
|
else
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenStatement( hb_compExprAssign( hb_compExprNewVar( $1, HB_COMP_PARAM ), $6, 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 = VS_FIELD; }
|
|
FieldList InAlias Crlf
|
|
{
|
|
if( $4 ) hb_compFieldSetAlias( HB_COMP_PARAM, $4, $3 );
|
|
HB_COMP_PARAM->cVarType = ' ';
|
|
}
|
|
;
|
|
|
|
FieldList : IdentName AsType { $$=hb_compFieldsCount( HB_COMP_PARAM ); hb_compVariableAdd( HB_COMP_PARAM, $1, HB_COMP_PARAM->cVarType ); }
|
|
| FieldList ',' IdentName AsType { hb_compVariableAdd( HB_COMP_PARAM, $3, HB_COMP_PARAM->cVarType ); }
|
|
;
|
|
|
|
InAlias : /* no alias */ { $$ = NULL; }
|
|
| IN IdentName { $$ = $2; }
|
|
;
|
|
|
|
MemvarDef : MEMVAR { HB_COMP_PARAM->iVarScope = VS_MEMVAR; } MemvarList Crlf { HB_COMP_PARAM->cVarType = ' '; }
|
|
;
|
|
|
|
MemvarList : IdentName AsType { hb_compVariableAdd( HB_COMP_PARAM, $1, HB_COMP_PARAM->cVarType ); }
|
|
| MemvarList ',' IdentName AsType { hb_compVariableAdd( HB_COMP_PARAM, $3, HB_COMP_PARAM->cVarType ); }
|
|
;
|
|
|
|
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 = HB_COMP_PARAM->cVarType;
|
|
|
|
if ( toupper( HB_COMP_PARAM->cVarType ) == 'S' )
|
|
{
|
|
HB_COMP_PARAM->pLastDeclared->pClass = hb_compClassFind( HB_COMP_PARAM, HB_COMP_PARAM->szFromClass );
|
|
if( ! HB_COMP_PARAM->pLastDeclared->pClass )
|
|
{
|
|
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_CLASS_NOT_FOUND, HB_COMP_PARAM->szFromClass, HB_COMP_PARAM->pLastDeclared->szName );
|
|
HB_COMP_PARAM->pLastDeclared->cType = ( isupper( ( int ) HB_COMP_PARAM->cVarType ) ? 'O' : 'o' );
|
|
}
|
|
|
|
/* Resetting */
|
|
HB_COMP_PARAM->szFromClass = NULL;
|
|
}
|
|
}
|
|
HB_COMP_PARAM->szDeclaredFun = NULL;
|
|
HB_COMP_PARAM->cVarType = ' ';
|
|
HB_COMP_PARAM->iVarScope = VS_NONE;
|
|
}
|
|
| DECLARE IdentName { HB_COMP_PARAM->pLastClass = hb_compClassAdd( HB_COMP_PARAM, $2, NULL ); } ClassInfo Crlf { HB_COMP_PARAM->iVarScope = VS_NONE; }
|
|
| DECLARE_CLASS IdentName Crlf { HB_COMP_PARAM->pLastClass = hb_compClassAdd( HB_COMP_PARAM, $2, NULL ); HB_COMP_PARAM->iVarScope = VS_NONE; }
|
|
| DECLARE_CLASS IdentName IdentName Crlf { HB_COMP_PARAM->pLastClass = hb_compClassAdd( HB_COMP_PARAM, $2, $3 ); HB_COMP_PARAM->iVarScope = VS_NONE; }
|
|
| DECLARE_MEMBER DecMethod Crlf { HB_COMP_PARAM->iVarScope = VS_NONE; }
|
|
| DECLARE_MEMBER '{' AsType { HB_COMP_PARAM->cDataListType = HB_COMP_PARAM->cVarType; } DecDataList '}' Crlf { HB_COMP_PARAM->cDataListType = 0; HB_COMP_PARAM->iVarScope = VS_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 ); } DecList ')' AsType
|
|
{
|
|
if( HB_COMP_PARAM->pLastMethod )
|
|
{
|
|
HB_COMP_PARAM->pLastMethod->cType = HB_COMP_PARAM->cVarType;
|
|
if ( toupper( HB_COMP_PARAM->cVarType ) == 'S' )
|
|
{
|
|
HB_COMP_PARAM->pLastMethod->pClass = hb_compClassFind( HB_COMP_PARAM, HB_COMP_PARAM->szFromClass );
|
|
if( ! HB_COMP_PARAM->pLastMethod->pClass )
|
|
{
|
|
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_CLASS_NOT_FOUND, HB_COMP_PARAM->szFromClass, HB_COMP_PARAM->pLastMethod->szName );
|
|
HB_COMP_PARAM->pLastMethod->cType = ( isupper( ( int ) HB_COMP_PARAM->cVarType ) ? 'O' : 'o' );
|
|
}
|
|
|
|
HB_COMP_PARAM->szFromClass = NULL;
|
|
}
|
|
}
|
|
HB_COMP_PARAM->pLastMethod = NULL;
|
|
HB_COMP_PARAM->cVarType = ' ';
|
|
}
|
|
;
|
|
|
|
DecData : IdentName { HB_COMP_PARAM->pLastMethod = hb_compMethodAdd( HB_COMP_PARAM, HB_COMP_PARAM->pLastClass, $1 ); } AsType
|
|
{
|
|
if( HB_COMP_PARAM->pLastMethod )
|
|
{
|
|
PCOMCLASS pClass;
|
|
char szSetData[ HB_SYMBOL_NAME_LEN + 1 ];
|
|
int iLen;
|
|
|
|
/* List Type overrides if exists. */
|
|
if( HB_COMP_PARAM->cDataListType ) HB_COMP_PARAM->cVarType = HB_COMP_PARAM->cDataListType;
|
|
|
|
HB_COMP_PARAM->pLastMethod->cType = HB_COMP_PARAM->cVarType;
|
|
if ( toupper( HB_COMP_PARAM->cVarType ) == 'S' )
|
|
{
|
|
pClass = hb_compClassFind( HB_COMP_PARAM, HB_COMP_PARAM->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, HB_COMP_PARAM->szFromClass, HB_COMP_PARAM->pLastMethod->szName );
|
|
HB_COMP_PARAM->pLastMethod->cType = ( isupper( ( int ) HB_COMP_PARAM->cVarType ) ? 'O' :'o' );
|
|
}
|
|
}
|
|
else
|
|
pClass = NULL;
|
|
|
|
iLen = 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 = HB_COMP_PARAM->cVarType;
|
|
HB_COMP_PARAM->pLastMethod->iParamCount = 1;
|
|
|
|
/* TOFIX: these allocations causes memory leaks */
|
|
HB_COMP_PARAM->pLastMethod->cParamTypes = ( BYTE * ) hb_xgrab( 1 );
|
|
HB_COMP_PARAM->pLastMethod->pParamClasses = ( PCOMCLASS * ) hb_xgrab( sizeof( COMCLASS ) );
|
|
|
|
HB_COMP_PARAM->pLastMethod->cParamTypes[0] = HB_COMP_PARAM->cVarType;
|
|
HB_COMP_PARAM->pLastMethod->pParamClasses[0] = pClass;
|
|
|
|
if ( toupper( HB_COMP_PARAM->cVarType ) == 'S' )
|
|
{
|
|
HB_COMP_PARAM->pLastMethod->pClass = pClass;
|
|
HB_COMP_PARAM->szFromClass = NULL;
|
|
}
|
|
}
|
|
|
|
HB_COMP_PARAM->pLastMethod = NULL;
|
|
HB_COMP_PARAM->cVarType = ' ';
|
|
}
|
|
;
|
|
|
|
DecList : /* Nothing */
|
|
| FormalList
|
|
| OptList
|
|
| FormalList ',' OptList
|
|
;
|
|
|
|
DummyArgList : DummyArgument
|
|
| DummyArgList ',' DummyArgument
|
|
;
|
|
|
|
DummyArgument : EmptyExpression { HB_COMP_EXPR_DELETE( $1 ); }
|
|
;
|
|
|
|
FormalList : IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $1, HB_COMP_PARAM->cVarType ); }
|
|
| '@' IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $2, HB_COMP_PARAM->cVarType + VT_OFFSET_BYREF ); }
|
|
| '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $2, 'F' ); }
|
|
| FormalList ',' IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $3, HB_COMP_PARAM->cVarType ); }
|
|
| FormalList ',' '@' IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $4, HB_COMP_PARAM->cVarType + VT_OFFSET_BYREF ); }
|
|
| FormalList ',' '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $4, 'F' ); }
|
|
;
|
|
|
|
OptList : OPTIONAL IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $2, HB_COMP_PARAM->cVarType + VT_OFFSET_OPTIONAL ); }
|
|
| OPTIONAL '@' IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $3, HB_COMP_PARAM->cVarType + VT_OFFSET_OPTIONAL + VT_OFFSET_BYREF ); }
|
|
| OPTIONAL '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $3, HB_COMP_PARAM->cVarType + VT_OFFSET_OPTIONAL + VT_OFFSET_BYREF ); }
|
|
| OptList ',' OPTIONAL IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $4, HB_COMP_PARAM->cVarType + VT_OFFSET_OPTIONAL ); }
|
|
| OptList ',' OPTIONAL '@' IdentName AsType { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $5, HB_COMP_PARAM->cVarType + VT_OFFSET_OPTIONAL + VT_OFFSET_BYREF ); }
|
|
| OptList ',' OPTIONAL '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( HB_COMP_PARAM, $5, HB_COMP_PARAM->cVarType + VT_OFFSET_OPTIONAL + VT_OFFSET_BYREF ); }
|
|
;
|
|
|
|
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 Expression
|
|
{ ++HB_COMP_PARAM->functions.pLast->wIfCounter; hb_compLinePushIfInside( HB_COMP_PARAM ); }
|
|
Crlf
|
|
{ HB_COMP_EXPR_DELETE( hb_compExprGenPush( $2, HB_COMP_PARAM ) ); $$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM ); }
|
|
EmptyStats
|
|
{ $$ = hb_compGenJump( 0, HB_COMP_PARAM ); hb_compGenJumpHere( $<iNumber>5, HB_COMP_PARAM ); }
|
|
;
|
|
|
|
IfElse : ELSE Crlf { HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_BREAK_CODE; }
|
|
EmptyStats
|
|
;
|
|
|
|
IfElseIf : ELSEIF { HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_BREAK_CODE; hb_compLinePush( HB_COMP_PARAM ); }
|
|
Expression Crlf
|
|
{ HB_COMP_EXPR_DELETE( hb_compExprGenPush( $3, HB_COMP_PARAM ) );
|
|
$<iNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
EmptyStats
|
|
{ $$ = hb_compElseIfGen( HB_COMP_PARAM, NULL, hb_compGenJump( 0, HB_COMP_PARAM ) );
|
|
hb_compGenJumpHere( $<iNumber>5, HB_COMP_PARAM );
|
|
}
|
|
|
|
| IfElseIf ELSEIF { HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_BREAK_CODE; hb_compLinePush( HB_COMP_PARAM ); }
|
|
Expression Crlf
|
|
{ HB_COMP_EXPR_DELETE( hb_compExprGenPush( $4, HB_COMP_PARAM ) );
|
|
$<iNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
EmptyStats
|
|
{ $$ = hb_compElseIfGen( HB_COMP_PARAM, $1, hb_compGenJump( 0, HB_COMP_PARAM ) );
|
|
hb_compGenJumpHere( $<iNumber>6, HB_COMP_PARAM );
|
|
}
|
|
;
|
|
|
|
EndIf : EndIfID
|
|
{
|
|
if( HB_COMP_PARAM->functions.pLast->wIfCounter )
|
|
--HB_COMP_PARAM->functions.pLast->wIfCounter;
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ ( FUN_WITH_RETURN | FUN_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->bFlags &= ~ ( FUN_WITH_RETURN | FUN_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 ); } Expression Crlf
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenPush( $3, HB_COMP_PARAM ) );
|
|
$<iNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
EmptyStats
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_BREAK_CODE;
|
|
$$ = hb_compElseIfGen( HB_COMP_PARAM, NULL, hb_compGenJump( 0, HB_COMP_PARAM ) );
|
|
hb_compGenJumpHere( $<iNumber>5, HB_COMP_PARAM );
|
|
}
|
|
|
|
| Cases CASE { hb_compLinePushIfInside( HB_COMP_PARAM ); } Expression Crlf
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenPush( $4, HB_COMP_PARAM ) );
|
|
$<iNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
EmptyStats
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_BREAK_CODE;
|
|
$$ = hb_compElseIfGen( HB_COMP_PARAM, $1, hb_compGenJump( 0, HB_COMP_PARAM ) );
|
|
hb_compGenJumpHere( $<iNumber>6, HB_COMP_PARAM );
|
|
}
|
|
;
|
|
|
|
Otherwise : OTHERWISE {hb_compLinePushIfDebugger( HB_COMP_PARAM ); } Crlf { HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_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 Expression Crlf
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenPush( $2, HB_COMP_PARAM ) );
|
|
$<lNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
EmptyStats
|
|
{
|
|
hb_compLoopHere( HB_COMP_PARAM );
|
|
hb_compGenJump( ( ULONG ) $1 - HB_COMP_PARAM->functions.pLast->lPCodePos, HB_COMP_PARAM );
|
|
}
|
|
EndWhile
|
|
{
|
|
hb_compGenJumpHere( ( ULONG ) $<lNumber>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->bFlags &= ~ FUN_WITH_RETURN;
|
|
}
|
|
;
|
|
|
|
WhileBegin : WHILE
|
|
{
|
|
$$ = HB_COMP_PARAM->functions.pLast->lPCodePos;
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
++HB_COMP_PARAM->functions.pLast->wWhileCounter;
|
|
hb_compLoopStart( HB_COMP_PARAM, TRUE );
|
|
}
|
|
;
|
|
|
|
EndWhile : EndWhileID
|
|
{ HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_BREAK_CODE; }
|
|
;
|
|
|
|
EndWhileID : ENDDO
|
|
| END
|
|
;
|
|
|
|
ForNext : FOR LValue ForAssign Expression /* 1 2 3 4 */
|
|
{ /* 5 */
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
$<lNumber>1 = HB_COMP_PARAM->currLine;
|
|
hb_compDebugStart();
|
|
++HB_COMP_PARAM->functions.pLast->wForCounter;
|
|
$<asExpr>$ = hb_compExprGenPush( hb_compExprAssign( $2, $4, HB_COMP_PARAM ), HB_COMP_PARAM );
|
|
if( hb_compExprAsSymbol( $<asExpr>2 ) )
|
|
{
|
|
hb_compForStart( HB_COMP_PARAM, hb_compExprAsSymbol( $<asExpr>2 ), FALSE );
|
|
}
|
|
}
|
|
TO Expression StepExpr /* 6 7 8 */
|
|
{ /* 9 */
|
|
hb_compLoopStart( HB_COMP_PARAM, TRUE );
|
|
$<lNumber>$ = hb_compGenJump( 0, HB_COMP_PARAM );
|
|
}
|
|
Crlf /* 10 */
|
|
{ /* 11 */
|
|
$<lNumber>$ = HB_COMP_PARAM->functions.pLast->lPCodePos;
|
|
}
|
|
ForStatements /* 12 */
|
|
{
|
|
int iSign, iLine;
|
|
|
|
hb_compLoopHere( HB_COMP_PARAM );
|
|
|
|
iLine = HB_COMP_PARAM->currLine;
|
|
HB_COMP_PARAM->currLine = ( int ) $<lNumber>1;
|
|
hb_compLinePush( HB_COMP_PARAM );
|
|
HB_COMP_PARAM->currLine = iLine;
|
|
|
|
iSign = $<asExpr>8 ? hb_compExprAsNumSign( $<asExpr>8 ) : 1;
|
|
if( $<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
|
|
HB_COMP_EXPR_CLEAR( hb_compExprGenPush( hb_compExprNewPreInc( $2, HB_COMP_PARAM ), HB_COMP_PARAM ) );
|
|
hb_compGenJumpHere( ( ULONG ) $<lNumber>9, HB_COMP_PARAM );
|
|
hb_compExprGenPush( $7, HB_COMP_PARAM ); /* end */
|
|
if( iSign )
|
|
hb_compGenPCode1( iSign > 0 ? HB_P_GREATER : HB_P_LESS, HB_COMP_PARAM );
|
|
else
|
|
{
|
|
hb_compExprGenPush( $<asExpr>8, HB_COMP_PARAM ); /* step */
|
|
hb_compGenPCode1( HB_P_FORTEST, HB_COMP_PARAM );
|
|
}
|
|
|
|
hb_compGenJumpFalse( ( ULONG ) $<lNumber>11 - HB_COMP_PARAM->functions.pLast->lPCodePos, 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_DELETE( $7 );
|
|
HB_COMP_EXPR_DELETE( $<asExpr>5 ); /* deletes $5, $2, $4 */
|
|
if( $<asExpr>8 )
|
|
HB_COMP_EXPR_DELETE( $<asExpr>8 );
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ ( FUN_WITH_RETURN | FUN_BREAK_CODE );
|
|
}
|
|
;
|
|
|
|
ForAssign : '='
|
|
| INASSIGN
|
|
;
|
|
|
|
StepExpr : /* default step expression */ { $<asExpr>$ = NULL; }
|
|
| STEP Expression { $<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
|
|
*/
|
|
hb_compEnumStart( HB_COMP_PARAM, $2, $4, $6 );
|
|
|
|
hb_compLoopStart( HB_COMP_PARAM, TRUE );
|
|
$<lNumber>$ = HB_COMP_PARAM->functions.pLast->lPCodePos;
|
|
}
|
|
Crlf /* 8 */
|
|
{
|
|
/* 9
|
|
*/
|
|
$<lNumber>$ = hb_compGenJumpFalse( 0, HB_COMP_PARAM );
|
|
}
|
|
ForStatements /* 10 */
|
|
{
|
|
hb_compLoopHere( HB_COMP_PARAM );
|
|
hb_compEnumNext( HB_COMP_PARAM, $2, $6 );
|
|
hb_compGenJump( ( ULONG ) $<lNumber>7 - HB_COMP_PARAM->functions.pLast->lPCodePos, HB_COMP_PARAM );
|
|
|
|
hb_compGenJumpHere( ( ULONG ) $<lNumber>9, HB_COMP_PARAM );
|
|
hb_compLoopEnd( HB_COMP_PARAM );
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ ( FUN_WITH_RETURN | FUN_BREAK_CODE );
|
|
hb_compEnumEnd( HB_COMP_PARAM, $2 );
|
|
HB_COMP_EXPR_DELETE( $2 );
|
|
HB_COMP_EXPR_DELETE( $4 );
|
|
}
|
|
;
|
|
|
|
Descend : /* default up */ { $$ = 1; }
|
|
| DESCEND { $$ = -1; }
|
|
;
|
|
|
|
DoSwitch : SwitchBegin
|
|
{
|
|
hb_compLoopStart( HB_COMP_PARAM, FALSE );
|
|
hb_compSwitchStart( HB_COMP_PARAM );
|
|
hb_compGenJump( 0, HB_COMP_PARAM );
|
|
}
|
|
SwitchCases
|
|
EndSwitch
|
|
{
|
|
hb_compSwitchEnd( HB_COMP_PARAM );
|
|
hb_compLoopEnd( HB_COMP_PARAM );
|
|
}
|
|
|
|
| SwitchBegin
|
|
EndSwitch
|
|
{
|
|
hb_compGenPCode1( HB_P_POP, HB_COMP_PARAM );
|
|
}
|
|
;
|
|
|
|
EndSwitch : EndSwitchID
|
|
{
|
|
if( HB_COMP_PARAM->functions.pLast->wSwitchCounter )
|
|
--HB_COMP_PARAM->functions.pLast->wSwitchCounter;
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ ( FUN_WITH_RETURN | FUN_BREAK_CODE );
|
|
}
|
|
;
|
|
|
|
EndSwitchID : ENDSWITCH
|
|
| END
|
|
;
|
|
|
|
SwitchStart : DOSWITCH
|
|
{ ++HB_COMP_PARAM->functions.pLast->wSwitchCounter;
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
}
|
|
Expression Crlf
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenPush( $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->bFlags &= ~ FUN_BREAK_CODE; }
|
|
EmptyStats
|
|
;
|
|
|
|
BeginSeq : BEGINSEQ /* 1 */
|
|
{ /* 2 */
|
|
hb_compLinePushIfInside( HB_COMP_PARAM );
|
|
++HB_COMP_PARAM->functions.pLast->wSeqCounter;
|
|
$<lNumber>$ = 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( $<lNumber>3 )
|
|
hb_compGenPCode1( HB_P_POP, HB_COMP_PARAM );
|
|
hb_compGenJumpHere( ( ULONG ) $<lNumber>2, HB_COMP_PARAM );
|
|
$<lNumber>$ = 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( $<lNumber>7 )
|
|
hb_compGenJumpThere( ( ULONG ) $<lNumber>2, ( ULONG ) $<lNumber>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->bFlags &= ~ ( FUN_WITH_RETURN | FUN_BREAK_CODE );
|
|
if( $<lNumber>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( ( ULONG ) $<lNumber>6, ( ULONG ) $<lNumber>9, HB_COMP_PARAM );
|
|
/* Fix ALWAYS address in HB_P_SEQALWAYS opcode */
|
|
hb_compGenJumpThere( ( ULONG ) $<lNumber>2 - 4, ( ULONG ) $<lNumber>9, HB_COMP_PARAM );
|
|
/* Fix ALWAYSEND address in HB_P_ALWAYSBEGIN opcode */
|
|
hb_compGenJumpHere( ( ULONG ) $<lNumber>9 + 1, HB_COMP_PARAM );
|
|
hb_compGenPCode1( HB_P_ALWAYSEND, HB_COMP_PARAM );
|
|
}
|
|
else
|
|
{
|
|
/* Fix END address in HB_P_SEQEND opcode */
|
|
hb_compGenJumpHere( ( ULONG ) $<lNumber>6, HB_COMP_PARAM );
|
|
}
|
|
hb_compSequenceFinish( HB_COMP_PARAM, ( ULONG ) $<lNumber>2, ( ULONG ) $<lNumber>6, ( ULONG ) $<lNumber>9,
|
|
$<lNumber>5 != 0, $<lNumber>7 != 0, $<lNumber>4 == lLoopCount );
|
|
}
|
|
EndSeqID /* 10 */
|
|
;
|
|
|
|
EndSeqID : ENDSEQ
|
|
| END
|
|
;
|
|
|
|
BlockSeq : /* no always */ { $<lNumber>$ = 0; }
|
|
| WITH Expression
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenPush( $2, HB_COMP_PARAM ) );
|
|
hb_compGenPCode1( HB_P_SEQBLOCK, HB_COMP_PARAM );
|
|
$<lNumber>$ = HB_COMP_PARAM->functions.pLast->lPCodePos;
|
|
}
|
|
;
|
|
|
|
AlwaysSeq : /* no always */ { $<lNumber>$ = 0; }
|
|
| Always Crlf EmptyStats
|
|
;
|
|
|
|
Always : ALWAYS
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ ( FUN_WITH_RETURN | FUN_BREAK_CODE );
|
|
$<lNumber>$ = HB_COMP_PARAM->functions.pLast->lPCodePos;
|
|
++HB_COMP_PARAM->functions.pLast->wAlwaysCounter;
|
|
hb_compSequenceAlways( HB_COMP_PARAM );
|
|
}
|
|
;
|
|
|
|
RecoverSeq : /* no recover */ { $<lNumber>$ = 0; HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_BREAK_CODE; }
|
|
| RecoverEmpty Crlf EmptyStats
|
|
| RecoverUsing Crlf EmptyStats
|
|
;
|
|
|
|
RecoverEmpty : RECOVER
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->bFlags &= ~ FUN_BREAK_CODE;
|
|
$<lNumber>$ = HB_COMP_PARAM->functions.pLast->lPCodePos;
|
|
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->bFlags &= ~ FUN_BREAK_CODE;
|
|
$<lNumber>$ = HB_COMP_PARAM->functions.pLast->lPCodePos;
|
|
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
|
|
*/
|
|
DoName : MacroVar
|
|
| MacroExpr
|
|
;
|
|
|
|
DoProc : DO DoName
|
|
{ $<bTrue>$ = HB_COMP_PARAM->iPassByRef;HB_COMP_PARAM->iPassByRef=HB_PASSBYREF_FUNCALL; }
|
|
DoArgs
|
|
{
|
|
$$ = hb_compExprNewFunCall( $2, $4, HB_COMP_PARAM );
|
|
HB_COMP_PARAM->iPassByRef = $<bTrue>3;
|
|
}
|
|
| DOIDENT
|
|
{ $<bTrue>$ = HB_COMP_PARAM->iPassByRef;HB_COMP_PARAM->iPassByRef=HB_PASSBYREF_FUNCALL; }
|
|
DoArgs
|
|
{
|
|
hb_compAutoOpenAdd( HB_COMP_PARAM, $1 );
|
|
/* 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 ), $3, HB_COMP_PARAM );
|
|
HB_COMP_PARAM->iPassByRef = $<bTrue>2;
|
|
}
|
|
;
|
|
|
|
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_DELETE( hb_compExprGenPush( $2, HB_COMP_PARAM ) );
|
|
$<lNumber>$ = HB_COMP_PARAM->functions.pLast->lPCodePos;
|
|
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,
|
|
( ULONG ) $<lNumber>4, 1, FALSE, TRUE );
|
|
hb_compGenPCode1( HB_P_POP, HB_COMP_PARAM );
|
|
}
|
|
}
|
|
;
|
|
|
|
EndWithID : ENDWITH
|
|
| END
|
|
;
|
|
|
|
Crlf : '\n' { HB_COMP_PARAM->fError = 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, BOOL fCanLoop )
|
|
{
|
|
HB_LOOPEXIT_PTR pLoop = ( HB_LOOPEXIT_PTR ) hb_xgrab( sizeof( HB_LOOPEXIT ) );
|
|
PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
if( pFunc->pLoops )
|
|
{
|
|
HB_LOOPEXIT_PTR pLast = pFunc->pLoops;
|
|
|
|
while( pLast->pNext )
|
|
pLast = pLast->pNext;
|
|
pLast->pNext = pLoop;
|
|
}
|
|
else
|
|
pFunc->pLoops = pLoop;
|
|
|
|
pLoop->ulOffset = pFunc->lPCodePos; /* 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 )
|
|
{
|
|
HB_LOOPEXIT_PTR pLastLoop, pLastExit, pLoop;
|
|
PFUNCTION 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 )
|
|
{
|
|
HB_LOOPEXIT_PTR pLast = NULL, pLoop;
|
|
PFUNCTION 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
|
|
{
|
|
USHORT wWithObjectCnt = pLast->wWithObjectCnt;
|
|
|
|
pLoop = ( HB_LOOPEXIT_PTR ) 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->ulOffset = pFunc->lPCodePos;
|
|
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 )
|
|
{
|
|
PFUNCTION 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
|
|
{
|
|
HB_LOOPEXIT_PTR 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
|
|
{
|
|
USHORT wWithObjectCnt = pLast->wWithObjectCnt;
|
|
|
|
pLoop = ( HB_LOOPEXIT_PTR ) 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->ulOffset = pFunc->lPCodePos;
|
|
hb_compGenJump( 0, HB_COMP_PARAM );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fixes the LOOP statement
|
|
*/
|
|
static void hb_compLoopHere( HB_COMP_DECL )
|
|
{
|
|
PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;
|
|
HB_LOOPEXIT_PTR pLoop = pFunc->pLoops, pFree, pLast;
|
|
|
|
if( pLoop )
|
|
{
|
|
while( pLoop->pNext )
|
|
pLoop = pLoop->pNext;
|
|
|
|
pLast = pLoop;
|
|
pLoop = pLoop->pLoopList;
|
|
while( pLoop )
|
|
{
|
|
hb_compGenJumpHere( pLoop->ulOffset + 1, HB_COMP_PARAM );
|
|
pFree = pLoop;
|
|
pLoop = pLoop->pLoopList;
|
|
hb_xfree( ( void * ) pFree );
|
|
}
|
|
pLast->pLoopList = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fixes the EXIT statements and releases memory allocated for current loop
|
|
*/
|
|
static void hb_compLoopEnd( HB_COMP_DECL )
|
|
{
|
|
PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;
|
|
HB_LOOPEXIT_PTR 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->ulOffset + 1, HB_COMP_PARAM );
|
|
pFree = pExit;
|
|
pExit = pExit->pExitList;
|
|
hb_xfree( ( void * ) pFree );
|
|
}
|
|
|
|
pLast->pNext = NULL;
|
|
if( pLoop == pFunc->pLoops )
|
|
pFunc->pLoops = NULL;
|
|
hb_xfree( ( void * ) pLoop );
|
|
}
|
|
}
|
|
|
|
void hb_compLoopKill( PFUNCTION pFunc )
|
|
{
|
|
HB_LOOPEXIT_PTR pLoop, pFree;
|
|
|
|
while( pFunc->pLoops )
|
|
{
|
|
pLoop = pFunc->pLoops;
|
|
while( pLoop->pExitList )
|
|
{
|
|
pFree = pLoop->pExitList;
|
|
pLoop->pExitList = pFree->pExitList;
|
|
hb_xfree( ( void * ) pFree );
|
|
}
|
|
while( pLoop->pLoopList )
|
|
{
|
|
pFree = pLoop->pLoopList;
|
|
pLoop->pLoopList = pFree->pLoopList;
|
|
hb_xfree( ( void * ) pFree );
|
|
}
|
|
pFunc->pLoops = pLoop->pNext;
|
|
hb_xfree( ( void * ) pLoop );
|
|
}
|
|
}
|
|
|
|
static void * hb_compElseIfGen( HB_COMP_DECL, void * pFirst, ULONG ulOffset )
|
|
{
|
|
HB_ELSEIF_PTR pElseIf = ( HB_ELSEIF_PTR ) hb_xgrab( sizeof( HB_ELSEIF ) ), pLast;
|
|
PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
pElseIf->ulOffset = ulOffset;
|
|
pElseIf->pPrev = NULL;
|
|
pElseIf->pElseif = NULL;
|
|
|
|
if( pFirst )
|
|
{
|
|
pLast = ( HB_ELSEIF_PTR ) 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 )
|
|
{
|
|
HB_ELSEIF_PTR pFix = ( HB_ELSEIF_PTR ) pFixElseIfs;
|
|
HB_ELSEIF_PTR pDel;
|
|
|
|
HB_COMP_PARAM->functions.pLast->elseif = pFix->pPrev;
|
|
while( pFix )
|
|
{
|
|
hb_compGenJumpHere( pFix->ulOffset, HB_COMP_PARAM );
|
|
pDel = pFix;
|
|
pFix = pFix->pElseif;
|
|
hb_xfree( pDel );
|
|
}
|
|
}
|
|
|
|
void hb_compElseIfKill( PFUNCTION pFunc )
|
|
{
|
|
HB_ELSEIF_PTR pFix;
|
|
HB_ELSEIF_PTR 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, HB_EXPR_PTR pVar, BOOL bPopInitValue )
|
|
{
|
|
HB_RTVAR_PTR pRTvar = ( HB_RTVAR_PTR ) hb_xgrab( sizeof( HB_RTVAR ) );
|
|
PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
pRTvar->pVar = pVar;
|
|
pRTvar->bPopValue = bPopInitValue;
|
|
pRTvar->pNext = NULL;
|
|
pRTvar->pPrev = NULL;
|
|
|
|
if( pFunc->rtvars )
|
|
{
|
|
HB_RTVAR_PTR 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, char * szCreateFun )
|
|
{
|
|
USHORT usCount = 0;
|
|
PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;
|
|
HB_RTVAR_PTR pVar = pFunc->rtvars;
|
|
HB_RTVAR_PTR pDel;
|
|
|
|
/* generate the function call frame */
|
|
hb_compGenPushFunCall( szCreateFun, HB_COMP_PARAM );
|
|
|
|
/* push variable names to create */
|
|
while( pVar->pNext )
|
|
{
|
|
hb_compExprGenPush( pVar->pVar, HB_COMP_PARAM );
|
|
pVar = pVar->pNext;
|
|
++usCount;
|
|
}
|
|
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, ( BYTE ) usCount, HB_COMP_PARAM );
|
|
|
|
/* pop initial values */
|
|
while( pVar )
|
|
{
|
|
if( pVar->bPopValue )
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenPop( pVar->pVar, HB_COMP_PARAM ) );
|
|
else
|
|
HB_COMP_EXPR_DELETE( pVar->pVar );
|
|
pDel = pVar;
|
|
pVar = pVar->pPrev;
|
|
hb_xfree( pDel );
|
|
}
|
|
pFunc->rtvars = NULL;
|
|
}
|
|
|
|
void hb_compRTVariableKill( HB_COMP_DECL, PFUNCTION pFunc )
|
|
{
|
|
HB_RTVAR_PTR pVar;
|
|
|
|
while( pFunc->rtvars )
|
|
{
|
|
pVar = pFunc->rtvars;
|
|
|
|
HB_COMP_EXPR_DELETE( pVar->pVar );
|
|
pFunc->rtvars = pVar->pPrev;
|
|
hb_xfree( pVar );
|
|
}
|
|
pFunc->rtvars = NULL;
|
|
}
|
|
|
|
static HB_EXPR_PTR hb_compArrayDimPush( HB_EXPR_PTR pInitValue, HB_COMP_DECL )
|
|
{
|
|
USHORT uCount = (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( char * szName, HB_EXPR_PTR pInitValue, HB_COMP_DECL )
|
|
{
|
|
if( HB_COMP_PARAM->iVarScope == VS_PUBLIC || HB_COMP_PARAM->iVarScope == VS_PRIVATE )
|
|
{
|
|
hb_compVariableAdd( HB_COMP_PARAM, szName, 'A' );
|
|
HB_COMP_EXPR_DELETE( hb_compArrayDimPush( pInitValue, HB_COMP_PARAM ) );
|
|
hb_compRTVariableAdd( HB_COMP_PARAM, hb_compExprNewRTVar( szName, NULL, HB_COMP_PARAM ), TRUE );
|
|
}
|
|
else if( HB_COMP_PARAM->iVarScope == VS_STATIC )
|
|
{
|
|
HB_EXPR_PTR pVar = hb_compExprNewVar( szName, HB_COMP_PARAM );
|
|
HB_EXPR_PTR pAssign;
|
|
|
|
/* create a static variable */
|
|
hb_compVariableAdd( HB_COMP_PARAM, szName, 'A' );
|
|
hb_compStaticDefStart( HB_COMP_PARAM ); /* switch to statics pcode buffer */
|
|
/* create an array */
|
|
pInitValue = hb_compArrayDimPush( pInitValue, HB_COMP_PARAM );
|
|
/* check if valid initializers were used but don't generate any code */
|
|
pAssign = hb_compExprAssignStatic( pVar, pInitValue, HB_COMP_PARAM );
|
|
/* now pop an array */
|
|
hb_compExprGenPop( pVar, HB_COMP_PARAM );
|
|
/* delete all used expressions */
|
|
HB_COMP_EXPR_DELETE( pAssign );
|
|
hb_compStaticDefEnd( HB_COMP_PARAM, szName );
|
|
}
|
|
else
|
|
{
|
|
hb_compVariableAdd( HB_COMP_PARAM, szName, 'A' );
|
|
HB_COMP_EXPR_DELETE( hb_compArrayDimPush( pInitValue, HB_COMP_PARAM ) );
|
|
if( HB_COMP_PARAM->iVarScope != VS_LOCAL ||
|
|
!( HB_COMP_PARAM->functions.pLast->bFlags & FUN_EXTBLOCK ) )
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenPop( hb_compExprNewVar( szName, HB_COMP_PARAM ), HB_COMP_PARAM ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
static void hb_compForStart( HB_COMP_DECL, char *szVarName, BOOL bForEach )
|
|
{
|
|
HB_ENUMERATOR_PTR pEnumVar;
|
|
|
|
pEnumVar = HB_COMP_PARAM->functions.pLast->pEnum;
|
|
if( pEnumVar == NULL )
|
|
{
|
|
HB_COMP_PARAM->functions.pLast->pEnum = (HB_ENUMERATOR_PTR) hb_xgrab( sizeof(HB_ENUMERATOR) );
|
|
pEnumVar = HB_COMP_PARAM->functions.pLast->pEnum;
|
|
}
|
|
else
|
|
{
|
|
BOOL bWarn = TRUE;
|
|
HB_ENUMERATOR_PTR 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 = FALSE;
|
|
}
|
|
}
|
|
pLast = pEnumVar;
|
|
pEnumVar = pEnumVar->pNext;
|
|
}
|
|
pLast->pNext = (HB_ENUMERATOR_PTR) hb_xgrab( sizeof( HB_ENUMERATOR ) );
|
|
pEnumVar = pLast->pNext;
|
|
}
|
|
pEnumVar->szName = szVarName;
|
|
pEnumVar->bForEach = bForEach;
|
|
pEnumVar->pNext = NULL;
|
|
}
|
|
|
|
BOOL hb_compForEachVarError( HB_COMP_DECL, char *szVarName )
|
|
{
|
|
HB_ENUMERATOR_PTR pEnumVar;
|
|
|
|
pEnumVar = HB_COMP_PARAM->functions.pLast->pEnum;
|
|
if( pEnumVar )
|
|
{
|
|
while( pEnumVar )
|
|
{
|
|
if( strcmp( pEnumVar->szName, szVarName ) == 0 )
|
|
{
|
|
if( pEnumVar->bForEach )
|
|
{
|
|
/* only if it is FOR EACH enumerator
|
|
* generate warning if it is FOR/NEXT loop
|
|
*/
|
|
return FALSE;
|
|
}
|
|
}
|
|
pEnumVar = pEnumVar->pNext;
|
|
}
|
|
}
|
|
|
|
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_ENUM_INVALID, szVarName, NULL );
|
|
return TRUE;
|
|
}
|
|
|
|
static void hb_compForEnd( HB_COMP_DECL, char *szVar )
|
|
{
|
|
HB_ENUMERATOR_PTR pEnumVar;
|
|
|
|
HB_SYMBOL_UNUSED( szVar );
|
|
|
|
pEnumVar = HB_COMP_PARAM->functions.pLast->pEnum;
|
|
if( pEnumVar->pNext )
|
|
{
|
|
HB_ENUMERATOR_PTR pLast = pEnumVar;
|
|
|
|
while( pEnumVar->pNext )
|
|
{
|
|
pLast = pEnumVar;
|
|
pEnumVar = pEnumVar->pNext;
|
|
}
|
|
hb_xfree( pEnumVar );
|
|
pLast->pNext = NULL;
|
|
}
|
|
else
|
|
{
|
|
hb_xfree( pEnumVar );
|
|
HB_COMP_PARAM->functions.pLast->pEnum = NULL;
|
|
}
|
|
}
|
|
|
|
static HB_CARGO2_FUNC( hb_compEnumEvalStart )
|
|
{
|
|
char * szName = hb_compExprAsSymbol( (HB_EXPR_PTR)cargo );
|
|
if( szName )
|
|
hb_compForStart( HB_COMP_PARAM, szName, TRUE );
|
|
|
|
hb_compExprGenPush( (HB_EXPR_PTR)dummy, HB_COMP_PARAM ); /* expression */
|
|
hb_compExprGenPush( (HB_EXPR_PTR)cargo, HB_COMP_PARAM ); /* variable */
|
|
}
|
|
|
|
static void hb_compEnumStart( HB_COMP_DECL, HB_EXPR_PTR pVars, HB_EXPR_PTR pExprs, int descend )
|
|
{
|
|
ULONG ulLen;
|
|
|
|
if( hb_compExprListLen(pVars) != hb_compExprListLen(pExprs) )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_FORVAR_DIFF, NULL, NULL );
|
|
}
|
|
|
|
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
|
|
{
|
|
BYTE Len;
|
|
Len = (BYTE) (ulLen & 0xFF);
|
|
hb_compGenPCode3( HB_P_ENUMSTART, Len, descend > 0 ? 1 : 0, HB_COMP_PARAM );
|
|
}
|
|
}
|
|
|
|
static void hb_compEnumNext( HB_COMP_DECL, HB_EXPR_PTR 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_CARGO_FUNC( hb_compEnumEvalEnd )
|
|
{
|
|
char * szName = hb_compExprAsSymbol( (HB_EXPR_PTR)cargo );
|
|
|
|
if( szName )
|
|
hb_compForEnd( HB_COMP_PARAM, szName );
|
|
}
|
|
|
|
static void hb_compEnumEnd( HB_COMP_DECL, HB_EXPR_PTR pExpr )
|
|
{
|
|
hb_compExprListEval( HB_COMP_PARAM, pExpr, hb_compEnumEvalEnd );
|
|
hb_compGenPCode1( HB_P_ENUMEND, HB_COMP_PARAM );
|
|
}
|
|
|
|
static void hb_compSwitchStart( HB_COMP_DECL )
|
|
{
|
|
HB_SWITCHCMD_PTR pSwitch = (HB_SWITCHCMD_PTR) hb_xgrab( sizeof( HB_SWITCHCMD ) );
|
|
PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
pSwitch->pCases = NULL;
|
|
pSwitch->pLast = NULL;
|
|
pSwitch->ulDefault = 0;
|
|
pSwitch->ulOffset = pFunc->lPCodePos;
|
|
pSwitch->iCount = 0;
|
|
pSwitch->pPrev = pFunc->pSwitch;
|
|
pFunc->pSwitch = pSwitch;
|
|
}
|
|
|
|
static void hb_compSwitchAdd( HB_COMP_DECL, HB_EXPR_PTR pExpr )
|
|
{
|
|
HB_SWITCHCASE_PTR pCase;
|
|
PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;
|
|
|
|
pFunc->bFlags &= ~FUN_BREAK_CODE;
|
|
|
|
if( pExpr )
|
|
{
|
|
/* normal CASE */
|
|
pCase = (HB_SWITCHCASE_PTR) hb_xgrab( sizeof( HB_SWITCHCASE ) );
|
|
pCase->ulOffset = pFunc->lPCodePos;
|
|
pCase->pNext = NULL;
|
|
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 );
|
|
}
|
|
pCase->pExpr = pExpr;
|
|
|
|
if( pFunc->pSwitch->pLast )
|
|
{
|
|
pFunc->pSwitch->pLast->pNext = pCase;
|
|
pFunc->pSwitch->pLast = pCase;
|
|
}
|
|
else
|
|
{
|
|
pFunc->pSwitch->pCases = pFunc->pSwitch->pLast = pCase;
|
|
}
|
|
pFunc->pSwitch->iCount++;
|
|
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->ulDefault )
|
|
{
|
|
/* 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->ulDefault = pFunc->lPCodePos;
|
|
pFunc->pSwitch->iCount++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static void hb_compSwitchEnd( HB_COMP_DECL )
|
|
{
|
|
BOOL fLongOptimize = HB_COMP_PARAM->fLongOptimize;
|
|
BOOL fTextSubst = HB_COMP_PARAM->fTextSubst;
|
|
PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;
|
|
HB_SWITCHCASE_PTR pCase = pFunc->pSwitch->pCases;
|
|
HB_SWITCHCASE_PTR pTmp;
|
|
HB_SWITCHCMD_PTR pTmpSw;
|
|
ULONG ulExitPos;
|
|
|
|
/* 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( pFunc->pSwitch->ulOffset + 1, HB_COMP_PARAM );
|
|
hb_compGenPCode3( HB_P_SWITCH, HB_LOBYTE( pFunc->pSwitch->iCount ), HB_HIBYTE( pFunc->pSwitch->iCount ), HB_COMP_PARAM );
|
|
HB_COMP_PARAM->fLongOptimize = FALSE;
|
|
HB_COMP_PARAM->fTextSubst = FALSE;
|
|
while( pCase )
|
|
{
|
|
if( pCase->pExpr )
|
|
{
|
|
if( hb_compExprIsLong( pCase->pExpr ) || hb_compExprIsString( pCase->pExpr ) )
|
|
{
|
|
HB_COMP_EXPR_DELETE( hb_compExprGenPush( pCase->pExpr, HB_COMP_PARAM ) );
|
|
hb_compGenJumpThere( hb_compGenJump( 0, HB_COMP_PARAM ), pCase->ulOffset, HB_COMP_PARAM );
|
|
}
|
|
else
|
|
{
|
|
HB_COMP_EXPR_DELETE( pCase->pExpr );
|
|
}
|
|
}
|
|
pCase = pCase->pNext;
|
|
}
|
|
|
|
if( pFunc->pSwitch->ulDefault )
|
|
{
|
|
hb_compGenPCode1( HB_P_PUSHNIL, HB_COMP_PARAM );
|
|
hb_compGenJumpThere( hb_compGenJump( 0, HB_COMP_PARAM ),
|
|
pFunc->pSwitch->ulDefault, HB_COMP_PARAM );
|
|
}
|
|
|
|
HB_COMP_PARAM->fLongOptimize = fLongOptimize;
|
|
HB_COMP_PARAM->fTextSubst = fTextSubst;
|
|
|
|
hb_compGenJumpHere( ulExitPos, HB_COMP_PARAM );
|
|
|
|
pCase = pFunc->pSwitch->pCases;
|
|
while( pCase )
|
|
{
|
|
pTmp = pCase->pNext;
|
|
hb_xfree( (void *)pCase );
|
|
pCase = pTmp;
|
|
}
|
|
pTmpSw = pFunc->pSwitch;
|
|
pFunc->pSwitch = pFunc->pSwitch->pPrev;
|
|
hb_xfree( pTmpSw );
|
|
}
|
|
|
|
/* Release all switch statements
|
|
*/
|
|
void hb_compSwitchKill( HB_COMP_DECL, PFUNCTION pFunc )
|
|
{
|
|
HB_SWITCHCASE_PTR pCase;
|
|
HB_SWITCHCMD_PTR pSwitch;
|
|
|
|
while( pFunc->pSwitch )
|
|
{
|
|
while( pFunc->pSwitch->pCases )
|
|
{
|
|
pCase = pFunc->pSwitch->pCases;
|
|
HB_COMP_EXPR_DELETE( pCase->pExpr );
|
|
pFunc->pSwitch->pCases = pCase->pNext;
|
|
hb_xfree( (void *) pCase );
|
|
}
|
|
pSwitch = pFunc->pSwitch;
|
|
pFunc->pSwitch = pSwitch->pPrev;
|
|
hb_xfree( (void *) pSwitch );
|
|
}
|
|
}
|
|
|
|
static HB_EXPR_PTR hb_compCheckPassByRef( HB_COMP_DECL, HB_EXPR_PTR pExpr )
|
|
{
|
|
if( pExpr->ExprType == HB_ET_FUNCALL )
|
|
{
|
|
if( hb_compExprParamListLen( pExpr->value.asFunCall.pParms ) == 0 )
|
|
{
|
|
HB_EXPR_PTR 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_DELETE( 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 );
|
|
}
|
|
}
|
|
#if 0
|
|
else if( !( HB_COMP_PARAM->iPassByRef & ( HB_PASSBYREF_FUNCALL | HB_PASSBYREF_ARRAY ) ) )
|
|
{
|
|
const char * szDesc;
|
|
if( pExpr->ExprType == HB_ET_REFERENCE )
|
|
{
|
|
HB_EXPR_PTR pDelExpr = pExpr;
|
|
pExpr = pExpr->value.asReference;
|
|
HB_COMP_EXPR_CLEAR( pDelExpr );
|
|
}
|
|
|
|
szDesc = hb_compExprAsSymbol( pExpr );
|
|
if( ! szDesc )
|
|
szDesc = hb_compExprDescription( pExpr );
|
|
|
|
return hb_compErrorRefer( HB_COMP_PARAM, pExpr, szDesc );
|
|
}
|
|
#endif
|
|
return pExpr;
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
|
|
BOOL hb_compCheckUnclosedStru( HB_COMP_DECL, PFUNCTION pFunc )
|
|
{
|
|
BOOL fUnclosed = 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->bFlags & FUN_EXTBLOCK )
|
|
{
|
|
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_UNCLOSED_STRU, "{||...}", NULL );
|
|
pFunc->bFlags &= ~FUN_EXTBLOCK;
|
|
}
|
|
else
|
|
fUnclosed = FALSE;
|
|
|
|
return fUnclosed;
|
|
}
|
|
|
|
void yyerror( HB_COMP_DECL, char * s )
|
|
{
|
|
if( !HB_COMP_PARAM->pLex->lasttok || HB_COMP_PARAM->pLex->lasttok[ 0 ] == '\n' )
|
|
{
|
|
if( ! 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 );
|
|
}
|