/* xbexp.h XBase64 Software Library Copyright (c) 1997,2003,2014,2022 Gary A Kunkel The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. Email Contact: XDB-devel@lists.sourceforge.net XDB-users@lists.sourceforge.net */ #ifndef __XB_EXP_H__ #define __XB_EXP_H__ // #ifdef CMAKE_COMPILER_IS_GNUCC // #pragma interface // #endif #define XB_NULL_DATE 21474835648 #ifdef XB_FUNCTION_SUPPORT #define XB_EXP_CHAR 'C' #define XB_EXP_DATE 'D' #define XB_EXP_LOGICAL 'L' #define XB_EXP_NUMERIC 'N' #define XB_EXP_UNKNOWN 'U' #endif #ifdef XB_EXPRESSION_SUPPORT #define XB_EXP_CONSTANT 'C' #define XB_EXP_FUNCTION 'F' #define XB_EXP_FIELD 'D' #define XB_EXP_OPERATOR 'O' #define XB_EXP_NOTROOT 'N' // not root node, needs further parsing #define XB_EXP_PRE_OPERATOR 'B' // (B)efore) pre increment, pre decrement #define XB_EXP_POST_OPERATOR 'A' // (A)fter) post increment, pre decrement #define XB_END_OF_EXPRESSION -100 // #define XB_UNBALANCED_PARENS -101 // #define XB_UNBALANCED_QUOTES -102 namespace xb{ ///@cond DOXYOFF struct XBDLLEXPORT xbExpToken { xbString sExpression; // in - expression to pull next token from // out - remainder of the expression after token removed xbString sToken; // next token pulled from the expression char cNodeType; // one of XB_EXP_CONSTANT, XB_EXP_FUNCTION, XB_EXP_FIELD, XB_EXP_OPERATOR, XB_EXP_NOTROOT char cReturnType; // one of XB_EXP_CHAR, XB_EXP_DATE, XB_EXP_LOGICAL, XB_EXP_NUMERIC, XB_EXP_UNKNOWN xbInt16 iSts; // return status after retrieving or attempting next token from expression // 0 = no error // XB_END_OF_EXPRESSION // XB_UNBALANCED_PARENS // XB_UNBALANCED_QUOTES char cPrevNodeType; // previous node type char cPrevReturnType; // previous return type // constructor xbExpToken() { cNodeType = 0; cReturnType = 0; iSts = 0; cPrevNodeType = 0; cPrevReturnType = 0; } }; ///@endcond DOXYOFF /************************************************************************/ //! @brief Class for handling expressions. /*! The xbExp class is used for parsing and evaluating expression. The Xbase64 library includes an expression parsing module which assists application programmers by providing a high level data manipulation tool and also allows for building complex index keys. The functions included were derived from dBASE III Plus, Dbase IV and Clipper.

Internal fuctioning

The expression module works in two phases. Firstly, method ParseExpression is called and builds an expression tree from all the components of the expression. The tree is made up of individual nodes. The expression is checked for valid field names, literals, operands and functions. Any field references are resolved. If fields are used in an expression and the database name for the field is not included in the name with the -> operand, the routines assume the associated database has been successfully opened.
Secondly, method ProcessExpression is called to process the expression tree created by ParseExpression(). The routine parses each node in the expression tree, executing functions, processing operands and manipulating data to produce the desired result.
If an expression will be processed repeatedly, it is best to pre-parse the tree using ParseExpression, then for each new call to the expression, execute method ProcessExpression which processes the tree.

Expression Return Types

Expressions will return a type of CHAR, NUMERIC, DATE or LOGICAL.
An expression return type can be determined with method GetExpressionResultType after parsing it.
Expressions returning a return type of CHAR are limited to a 200 byte internal buffer. There is also a 100 byte limit for NDX index key support. If the 200 byte limit is not large enough for your application, adjust field enum { WorkBufMaxLen = 200 }; in file exp.h.

Expression Functions

Each expression function also has a corresponding C++ function. It is slightly more efficient to call the C++ functions directly, rather than execute the expression parsing routines.

Expression Components

Expressions are made up of one or more tokens. A token is one of literal, database field, operand or function. Literals are either numeric or character. Character literals are enclosed in 'single' or "double" quotes. numeric literals are a series of one or more contiguous numerals, ".", "+" or "-'".

A field is simply a field name in the default database, or is in the form of database->fieldname. */ class XBDLLEXPORT xbExp{ public: xbExp( xbXBase * ); xbExp( xbXBase *, xbDbf * ); virtual ~xbExp(); void ClearTreeHandle(); #ifdef XB_DEBUG_SUPPORT void DumpTree( xbInt16 iOption ); void DumpToken( xbExpToken &t, xbInt16 iOption = 0 ); #endif xbInt16 GetResultLen() const; char GetReturnType() const; xbInt16 GetBoolResult( xbBool &bResult ); xbInt16 GetDateResult( xbDate &dtResult ); xbInt16 GetNumericResult( xbDouble &dResult ); xbInt16 GetStringResult( xbString &sResult ); xbInt16 GetStringResult( char * vpResult, xbUInt32 ulLen ); xbExpNode *GetTreeHandle(); xbInt16 ParseExpression( const xbString &sExpression ); xbInt16 ParseExpression( xbDbf *dbf, const xbString &sExpression ); xbInt16 ProcessExpression(); xbInt16 ProcessExpression( xbInt16 iRecBufSw ); protected: xbInt16 GetNextToken( xbExpToken &t ); xbInt16 OperatorWeight( const xbString &sOperator ); xbExpNode *GetNextNode( xbExpNode * n ) const; // traverses the tree from bottom left node, right, then up private: // methods // xbInt16 CalcExpressionResultLen(); xbInt16 CalcFunctionResultLen( xbExpNode *n ) const; xbInt16 CalcCharNodeLen( xbExpNode *n ); xbInt16 CheckParensAndQuotes( const xbString &sExpression ); xbInt16 GetExpressionResultLen() const; xbInt16 GetTokenCharConstant ( xbExpToken &t ); xbInt16 GetTokenDatabaseField ( xbExpToken &t ); xbInt16 GetTokenDateConstant ( xbExpToken &t ); xbInt16 GetTokenFunction ( xbExpToken &t ); xbInt16 GetTokenLogicalConstant( xbExpToken &t ); xbInt16 GetTokenNumericConstant( xbExpToken &t ); xbInt16 GetTokenOperator ( xbExpToken &t ); xbInt16 GetTokenParen ( xbExpToken &t ); xbBool IsFunction ( const xbString &sExp, char &cReturnType ); xbBool IsLogicalConstant ( const xbString &sExp ); xbBool IsNumericConstant ( const xbString &sExp, char cPrevNodeType ); xbBool IsOperator ( const xbString &sExp ); char IsTokenSeparator ( char c ); xbBool IsWhiteSpace ( char c ); xbInt16 ParseExpression ( const xbString &sExpression, xbInt16 iWeight ); xbInt16 ParseExpressionConstant( xbExpToken &t, xbExpNode *n ); xbInt16 ParseExpressionFunction( xbExpToken &t, xbExpNode *n, xbInt16 iWeight ); xbInt16 ParseExpressionFunctionParms( const xbString &sParms, xbLinkList &llParms ); xbInt16 ParseExpressionField ( xbExpToken &t, xbExpNode *n ); xbInt16 ParseExpressionOperator( xbExpToken &t, xbExpNode *n, xbInt16 iWeight ); xbInt16 ProcessExpressionFunction( xbExpNode *n, xbInt16 iRecBufSw = 0 ); xbInt16 ProcessExpressionOperator( xbExpNode *n ); private: // fields xbXBase *xbase; xbDbf *dbf; xbExpNode *nTree; // pointer to tree of expNodes // xbInt16 iExpLen; // size of expression result }; /* Expression handler */ }; #endif // XB_EXPRESSION_SUPPORT #endif // __XB_EXP_H__