📄 exp.cpp
字号:
/*************************************************************************** exp.cpp - description ------------------- begin : Thu Jan 17 2002 copyright : (C) 2002 by email : ***************************************************************************//*************************************************************************** * * * 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. * * * ***************************************************************************//* $Id: exp.cpp,v 1.9 2000/11/10 19:04:17 dbryson Exp $ Xbase project source code This file contains logic for handling Xbase expressions. Copyright (C) 1997 Startech, Gary A. Kunkel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Mail: Technology Associates, Inc. XBase Project 1455 Deming Way #11 Sparks, NV 89434 USA Email: xbase@techass.com See our website at: xdb.sourceforge.net V 1.0 10/10/97 - Initial release of software V 1.5 1/2/97 - Added memo field support V 1.6a 4/1/98 - Added expression support V 1.6b 4/8/98 - Numeric index keys V 1.7.1 5/25/98 - Enhanced expression support V 1.8.0a 1/27/99 - Release v1.8 upgrade*/#ifdef __GNUG__ #pragma implementation "exp.h"#endif#ifdef __WIN32__#include "xbconfigw32.h"#else#include "xbconfig.h"#endif#include "xbase.h"#ifdef XB_EXPRESSIONS#include <ctype.h>#include <string>using namespace std;#include "xbexcept.h"/*! \file exp.cpp*/// set the default date formatxbString xbExpn::DefaultDateFormat = "MM/DD/YY";/************************************************************************//* putting this part in EXP did not work */static xbFuncDtl FuncList[] ={ /* Func # of Return Name parms Type */ { "ABS", 1, 'N' }, { "ASC", 1, 'N' }, { "AT", 2, 'N' }, { "CDOW", 1, 'C' }, { "CHR", 1, 'C' }, { "CMONTH", 1, 'C' }, { "DATE", 0, 'C' }, { "DAY", 1, 'N' }, { "DESCEND", 1, 'C' }, { "DOW", 1, 'N' }, { "DTOC", 1, 'C' }, { "DTOS", 1, 'C' }, { "EXP", 1, 'N' }, { "IIF", 3, 'C' }, { "INT", 1, 'N' }, { "ISALPHA", 1, 'L' }, { "ISLOWER", 1, 'L' }, { "ISUPPER", 1, 'L' }, { "LEFT", 2, 'C' }, { "LEN", 1, 'N' }, { "LOG", 1, 'N' }, { "LOWER", 1, 'C' }, { "LTRIM", 1, 'C' }, { "MAX", 2, 'N' }, { "MIN", 2, 'N' }, { "MONTH", 1, 'N' }, { "RECNO", 0, 'N' }, { "REPLICATE", 2, 'C' }, { "RIGHT", 2, 'C' }, { "RTRIM", 1, 'C' }, { "SPACE", 1, 'C' }, { "SQRT", 1, 'N' }, { "STR", 1, 'C' }, { "STRZERO", 1, 'C' }, { "SUBSTR", 3, 'C' }, { "TRIM", 1, 'C' }, { "UPPER", 1, 'C' }, { "VAL", 1, 'N' }, { "YEAR", 1, 'N' }, { 0, 0, 0 },};/*************************************************************************///! Constructor/*!*/xbExpn::xbExpn( void ){ TokenType = 0x00; Tree = NULL; TokenLen = 0; OpLen1 = 0; OpLen2 = 0; OpDataLen1 = 0; OpDataLen2 = 0; Op1 = NULL; Op2 = NULL; XbaseFuncList = FuncList; memset( WorkBuf, 0x00, WorkBufMaxLen+1 );}/*************************************************************************///! Get information on a function./*! Returns the information specifed (Option) for the specified function. \param Function name of function to get information about \param Option One of the following: \htmlonly <p> <table border=2><tr><th>Option</th><th>Description</th></tr> <tr><td>1</td><td>Return minimum number of parms</td></tr> <tr><td>2</td><td>Return function result type</td></tr> <tr><td>?</td><td>Return 0 if valid function</td></tr> </table> \endhtmlonly \latexonly \\ \\ \begin{tabular}{|l|l|} \hline \textbf{Option} & \textbf{Description} \\ \hline \hline 1 & Return minimum number of parms \\ \hline 2 & Return function result type \\ \hline ? & Return 0 if valid function \\ \hline \end{tabular} \endlatexonly \returns requested information or -1 on failure.*/xbShort xbExpn::GetFuncInfo( const char * Function, xbShort Option ){/* Option = 1 - return minimum number of needed parms 2 - return function result type ? - return 0 if valid function*/ xbFuncDtl * f; xbShort i, len; const char *s; if(( Option<1 )||( Option>2 )) xb_error( XB_INVALID_OPTION ); s = Function; len = 0; while( *s && *s != '(' ) { s++; len++; } f = XbaseFuncList; i = 0; while( f[i].FuncName ){ if( strncmp( f[i].FuncName, Function, len ) == 0 ) return( (Option==1) ? f[i].ParmCnt : f[i].ReturnType ); i++; } return -1;}/*************************************************************************///! IsWhiteSpace/*!*/xbShort xbExpn::IsWhiteSpace( char c ){ return(( c == 0x20 )? 1 : 0 ); }/*************************************************************************///! GetNextToken/*!*/xbShort xbExpn::GetNextToken( const char * s, xbShort MaxLen ){ /* TreeResultType Settings Token Action/ Was Type Result Unv N N Unv C C Unv Function Table Lookup Unv Field Field Type Not L Any Logical L */ xbShort Wctr, Wtype, Wsw, EmptyCtr, MaxCtr, MaxCtrSave; const char *sp, *np, *pp; /* save, next and previous pointer */ LogicalType = 0; TokenType = 0; TokenLen = 0; EmptyCtr = 0; MaxCtr = 0; if( !s || ! *s ) xb_error(XB_NO_DATA); /* go past any initial white space */ while( s && *s && IsWhiteSpace( *s )){ s++; MaxCtr++; if (MaxCtr >= MaxLen) return XB_NO_ERROR; }/* 1 check for parens *//* '(', if found go to corresponding ')', if no ')', return -1 */ if( *s == '(' || *s == '{' ) { if( *s == '{' ) Wtype = 0; else Wtype = 1; Wctr = 1; s++; MaxCtr++; if( MaxCtr >= MaxLen ) xb_error(XB_PARSE_ERROR); while( s && *s ) { if(( *s == ')' && Wtype == 1 ) || (*s == '}' && Wtype == 0 )) { Wctr--; if( Wctr == 0 ) { if( EmptyCtr != 0 ) { TokenType = 'E'; PreviousType = 'E'; } else xb_error(XB_PARSE_ERROR); TokenLen += 2; return XB_NO_ERROR; } } else if(( *s == '(' && Wtype == 1 ) || (*s == '{' && Wtype == 0 )){ Wctr++; EmptyCtr++; } else if( *s != ' ' ) EmptyCtr++; s++; TokenLen++; MaxCtr++; if( MaxCtr >= MaxLen ) xb_error(XB_PARSE_ERROR); } xb_error(XB_PARSE_ERROR); }/* 2 - Check for Constants *//* check for "'" or """, if no corresponding quote return -1 */ if( *s == '"' || *s == '\'' ){ if( *s == '"' ) Wtype = 0; else Wtype = 1; TokenType = 'C'; /* set to constant */ PreviousType = 'C'; s++; MaxCtr++; if (MaxCtr >= MaxLen) return XB_NO_ERROR; while( s && *s ){ if(( *s == '"' && Wtype == 0 ) || (*s == '\'' && Wtype == 1 )) return XB_NO_ERROR; s++; TokenLen++; MaxCtr++; if (MaxCtr >= MaxLen) return XB_NO_ERROR; } xb_error(XB_PARSE_ERROR); }/* check for .T. .F. .TRUE. or .FALSE. */ if( s && *s && *s == '.' ){ if(( strncmp( s, ".T.", 3 ) == 0 ) || ( strncmp( s, ".F.", 3 ) == 0 )){ TokenLen = 3; TokenType = 'C'; /* constant */ PreviousType = 'C'; LogicalType = 1; return XB_NO_ERROR; } else if( strncmp( s, ".TRUE.", 6 ) == 0 ){ TokenLen = 6; TokenType = 'C'; /* constant */ PreviousType = 'C'; LogicalType = 1; return XB_NO_ERROR; } else if( strncmp( s, ".FALSE.", 7 ) == 0 ){ TokenLen = 7; TokenType = 'C'; /* constant */ PreviousType = 'C'; LogicalType = 1; return XB_NO_ERROR; } }/* check for positive, negative or decimal number constants */ if(( *s == '-' && ( PreviousType == 'O' || PreviousType == 0 )) || ( *s == '+' && ( PreviousType == 'O' || PreviousType == 0 )) || *s == '.' || isdigit( *s )){ sp = s; MaxCtrSave = MaxCtr; Wsw = Wctr = 0; if( *s == '.' ){ Wctr++; s++; MaxCtr++; if (MaxCtr >= MaxLen) xb_error(XB_PARSE_ERROR); if( s && *s && isdigit( *s )) TokenLen++; else Wsw++; } else if( *s == '-' ){ s++; TokenLen++; MaxCtr++; if( MaxCtr >= MaxLen ) xb_error(XB_PARSE_ERROR); /* go past any white space between sign and number */ while( s && *s && IsWhiteSpace( *s )){ s++; TokenLen++; MaxCtr++; if( MaxCtr >= MaxLen ) xb_error(XB_PARSE_ERROR); } } if( isdigit( *s ) || (*s == '.' && !Wsw )){ while(s && *s && ((*s == '.' && Wctr < 2 ) || isdigit(*s)) && !Wsw ){ if( *s == '.' ) { Wctr++; if( Wctr > 1 ) break; s++; MaxCtr++; if( MaxCtr >= MaxLen ){ TokenType = 'N'; PreviousType = 'N'; return XB_NO_ERROR; } if( s && *s && isdigit( *s )) TokenLen++; else Wsw++; } else{ s++; TokenLen++; MaxCtr++; if( MaxCtr >= MaxLen ) { TokenType = 'N'; PreviousType = 'N'; return XB_NO_ERROR; } } } TokenType = 'N'; /* constant */ PreviousType = 'N'; return XB_NO_ERROR; } else { s = sp; MaxCtr = MaxCtrSave; } }/* 2) Check for operators */#if 0 if( *s == '+' || *s == '-' || *s == '/' || *s == '=' || *s == '$' || *s == '^' || *s == '#' ) { TokenLen = 1; TokenType = 'O'; PreviousType = 'O'; return XB_NO_ERROR; }#else // changed 3/25/00 dtb if( *s == '+' || *s == '-' || *s == '/' || *s == '^') { TokenLen = 1; TokenType = 'O'; PreviousType = 'O'; return XB_NO_ERROR; } if(*s == '=' || *s == '$' || *s == '#' ) { LogicalType = 1; TokenLen = 1; TokenType = 'O'; PreviousType = 'O'; return XB_NO_ERROR; }#endif if( *s == '*' ) { s++; MaxCtr++; if( MaxCtr >= MaxLen ) xb_error(XB_PARSE_ERROR); TokenType = 'O'; PreviousType = 'O'; if( *s == '*' ){ TokenLen = 2; return XB_NO_ERROR; } else{ TokenLen = 1; return XB_NO_ERROR; } } if( *s == '<' || *s == '>' ) { s++; MaxCtr++; if( MaxCtr >= MaxLen ) xb_error(XB_PARSE_ERROR); LogicalType = 1; // added 3/25/00 dtb TokenType = 'O'; PreviousType = 'O'; if( *s == '<' || *s == '>' || *s == '=' ){ TokenLen = 2; return XB_NO_ERROR; } else { TokenLen = 1; return XB_NO_ERROR; } } /* check for .NOT. .OR. .AND. */ if( s && *s && *s == '.' ){ if( strncmp( s, ".NOT.", 5 ) == 0 ){ TokenLen = 5; TokenType = 'O'; /* constant */ PreviousType = 'O'; LogicalType = 1; return XB_NO_ERROR; } else if( strncmp( s, ".AND.", 5 ) == 0 ){ TokenLen = 5; TokenType = 'O'; /* constant */ PreviousType = 'O'; LogicalType = 1; return XB_NO_ERROR; } else if( strncmp( s, ".OR.", 4 ) == 0 ){ TokenLen = 4; TokenType = 'O'; /* constant */ PreviousType = 'O'; LogicalType = 1; return XB_NO_ERROR; } } /* If get this far, must be function or database field */ while( s && *s ){ s++; TokenLen++; MaxCtr++; if( MaxCtr >= MaxLen ) { TokenType = 'D'; PreviousType = 'D'; return XB_NO_ERROR; } if( s && *s && *s == '(' ) { /* look for corresponding ) */ Wctr = 1; s++; TokenLen++; MaxCtr++; if( MaxCtr >= MaxLen )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -