// xpath.h

#ifndef XPATH_H
#define XPATH_H

#ifndef FARBOOK_H
#include "atom.h"
#include "fsslang.h"

// XPath class declaration

// XPathItem type declarations
const ushort XP_NOTYPE   =    0;
const ushort XP_BOOLEAN  =    1;
const ushort XP_NUMBER   =    2;
const ushort XP_STRING   =    3;
const ushort XP_NODESET  =    4;

const ulong XPE_OK       =    0;

const ushort iXPathStack = 1002;

// Parser operator ids

#ifndef _SLANGER
#endif // _SLANGER

// The CXPathItem object acts a carrier for the data types that XPath
// must deal with. These are
//  * Boolean
//  * Number (doubles)
//  * String
//  * NodeSet
// Always use the CXPathItem::Type() method to determine the type of
// data that a CXPathItem object is carrying. Then use the appropriate
// Get-method (Boolean, Number, String, or NodeSet). Using a Get-method
// inconsistent with the Type() will obtain a nul value.
class CXPathItem: public CItem {
   friend class CXPath;
   friend class CXPathStack;

      FB_USE CXPathItem(void);
      FB_USE CXPathItem(bool         _value);
      FB_USE CXPathItem(double       _value);
      FB_USE CXPathItem(Pchar        _value);
      FB_USE CXPathItem(RPCNodeList  _value);
      FB_USE CXPathItem(RPCNode      _value);
      FB_USE CXPathItem(RPCXPathItem _value);

      virtual FB_USE ~CXPathItem();

      virtual FB_USE_(short) Ima(void);
      virtual FB_USE_(Pchar) IAm(void);
      virtual FB_USE_(bool)  Isa(const short _type);

      FB_USE_(void) Set(bool        _value);
      FB_USE_(void) Set(double      _value);
      FB_USE_(void) Set(Pchar       _value);
      FB_USE_(void) Set(RPCNodeList _value);

      FB_USE_(ushort)     Type   (void);
      FB_USE_(bool)       Boolean(void);
      FB_USE_(Pdouble)    Number (void);
      FB_USE_(Pchar)      String (void);
      FB_USE_(PCNodeList) NodeSet(void);

      void       clear  (void);

      PCNode     node;
      direction  order;
      ulong      position;
      ulong      size;
      ushort     type;
      bool       bValue;
      double     dValue;
      Pchar      sValue;
      PCNodeList nValue;
   }; // CXPathItem

// The CXPathStack object supports the XPath module for the evaluator
// and context stacks.

#ifndef _SLANGER

class CXPathStack: public CList {
      FB_USE CXPathStack(void);
      virtual FB_USE ~CXPathStack();

      virtual FB_USE_(short) Ima(void);
      virtual FB_USE_(Pchar) IAm(void);
      virtual FB_USE_(bool)  Isa(const short _type);

      FB_USE_(void)        Init      (void);
      FB_USE_(void)        Dup       (void);

      FB_USE_(ushort)      TypeAtTOS (void);
      FB_USE_(bool)        BoolAtTOS (void);
      FB_USE_(double)      DblAtTOS  (void);
      FB_USE_(Pchar)       StrAtTOS  (void);
      FB_USE_(PCNodeList)  NodesAtTOS(void);
      FB_USE_(PCXPathItem) ItemAtTOS (void);

      FB_USE_(PCXPathItem) PushV     (void);
      FB_USE_(PCXPathItem) PushL     (void);
      FB_USE_(PCXPathItem) PushX     (RPCXPathItem _value);
      FB_USE_(PCXPathItem) PushB     (bool         _value);
      FB_USE_(PCXPathItem) PushD     (double       _value);
      FB_USE_(PCXPathItem) PushS     (Pchar        _value);
      FB_USE_(PCXPathItem) PushNL    (RPCNodeList  _value);
      FB_USE_(PCXPathItem) PushN     (RPCNode      _value);

      FB_USE_(void)        SetTOS    (bool         _value);
      FB_USE_(void)        SetTOS    (double       _value);
      FB_USE_(void)        SetTOS    (Pchar        _value);
      FB_USE_(void)        SetTOS    (RPCNodeList  _value);

      FB_USE_(PCXPathItem) Pop       (void);
   }; // CXPathStack

#endif // _SLANGER

// The CXPath object parses and evaluates an XPath expression against
// a CNode object in a CDocument object
class FBC_USE CXPath: public CAtom {
      FB_USE CXPath(void);
      virtual FB_USE ~CXPath();

      virtual FB_USE_(short) Ima(void);
      virtual FB_USE_(Pchar) IAm(void);
      virtual FB_USE_(bool)  Isa(const short _type);

      FB_USE_(PCNode)      SelectSingleNode(RPCNode _node,
                                            Pchar   _path,
                                            bool    _extend = false);
      FB_USE_(PCNodeList)  SelectNodes     (RPCNode _node,
                                            Pchar   _path);
      FB_USE_(PCXPathItem) Evaluate        (RPCNode _node,
                                            Pchar   _path);

      FB_USE_(ulong)       Error           (void) { return err; }

      // for debugging
      FB_USE_(Pchar)       Parse           (Pchar _path);

      void error              (ErrorMsg _err);

      // Evaluator
      void eval               (Pchar _postFixExp);
      void evalAnd            (void);
      void evalDiv            (void);
      void evalEQ             (void);
      void evalFunction       (void);
      void evalGTE            (void);
      void evalGT             (void);
      void evalLBox           (void);
      void evalLTE            (void);
      void evalLT             (void);
      void evalMinus          (void);
      void evalMod            (void);
      void evalMul            (void);
      void evalNegate         (void);
      void evalNE             (void);
      void evalNmbr           (void);
      void evalOr             (void);
      void evalPath           (void);
      void evalPlus           (void);
      void evalQuotedString   (void);
      void evalRoot           (void);
      void evalStep           (void);
      void evalUnaryMinus     (void);
      void evalUnion          (void);
      void evalUnwind         (void);
      void evalVariable       (void);

           evalPredicate      (RPCNodeList _nodes,
                               Pchar       _exp,
                               direction   _order);

      // Equality evaluators
      void evalEQ_NDS_NDS   (RPCXPathItem _a, RPCXPathItem _b);
      void evalEQ_NDS_STR   (RPCXPathItem _a, RPCXPathItem _b);
      void evalEQ_NDS_DBL   (RPCXPathItem _a, RPCXPathItem _b);
      void evalEQ_NDS_BOL   (RPCXPathItem _a, RPCXPathItem _b);
      void evalEQ_STR_STR   (RPCXPathItem _a, RPCXPathItem _b);
      void evalEQ_STR_DBL   (RPCXPathItem _a, RPCXPathItem _b);
      void evalEQ_STR_BOL   (RPCXPathItem _a, RPCXPathItem _b);
      void evalEQ_DBL_DBL   (RPCXPathItem _a, RPCXPathItem _b);
      void evalEQ_DBL_BOL   (RPCXPathItem _a, RPCXPathItem _b);
      void evalEQ_BOL_BOL   (RPCXPathItem _a, RPCXPathItem _b);

      void evalNE_NDS_NDS   (RPCXPathItem _a, RPCXPathItem _b);
      void evalNE_NDS_STR   (RPCXPathItem _a, RPCXPathItem _b);
      void evalNE_NDS_DBL   (RPCXPathItem _a, RPCXPathItem _b);
      void evalNE_NDS_BOL   (RPCXPathItem _a, RPCXPathItem _b);

      // Relational evaluators
      void evalGTE_NDS_NDS  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_NDS_STR  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_NDS_DBL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_NDS_BOL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_STR_NDS  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_STR_STR  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_STR_DBL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_STR_BOL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_DBL_NDS  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_DBL_STR  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_DBL_DBL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_DBL_BOL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_BOL_NDS  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_BOL_STR  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_BOL_DBL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalGTE_BOL_BOL  (RPCXPathItem _a, RPCXPathItem _b);

      void evalLTE_NDS_NDS  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_NDS_STR  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_NDS_DBL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_NDS_BOL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_STR_NDS  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_STR_STR  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_STR_DBL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_STR_BOL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_DBL_NDS  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_DBL_STR  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_DBL_DBL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_DBL_BOL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_BOL_NDS  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_BOL_STR  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_BOL_DBL  (RPCXPathItem _a, RPCXPathItem _b);
      void evalLTE_BOL_BOL  (RPCXPathItem _a, RPCXPathItem _b);

      // Boolean functions
      void evalBoolean         (void);
      void evalNot             (void);
      void evalTrue            (void);
      void evalFalse           (void);

      // Number functions
      void evalNumber          (void);
      void evalSum             (void);
      void evalFloor           (void);
      void evalCeiling         (void);
      void evalRound           (void);

      // String functions
      void evalString          (void);
      void evalConcat          (void);
      void evalStarts_with     (void);
      void evalContains        (void);
      void evalSubstring_before(void);
      void evalSubstring_after (void);
      void evalSubstring       (void);
      void evalString_length   (void);
      void evalNormalize_space (void);
      void evalTranslate       (void);
      void evalMatch           (void);

      // Nodeset functions
      void evalLast            (void);
      void evalPosition        (void);
      void evalCount           (void);
      void evalId              (void);
      void evalLocal_Name      (void);
      void evalName            (void);
      void evalNamespace_uri   (void);

      // Type conversions
      Pchar       stringValue      (RPCNode      _node);
      double      numberValue      (RPCNode      _node);
      PCXPathItem convertToBoolean (RPCXPathItem _item);
      PCXPathItem convertToNumber  (RPCXPathItem _item);
      PCXPathItem convertToString  (RPCXPathItem _item);

      // DOM traversal methods by axis
      PCNodeList travelOnAxis      (PCNode _contextNode,
                                    Pchar  _axisName,
                                    Pchar  _name);

      PCNodeList ancestor          (PCNode _contextNode, Pchar _name);
      PCNodeList ancestorOrSelf    (PCNode _contextNode, Pchar _name);
      PCNodeList attribute         (PCNode _contextNode, Pchar _name);
      PCNodeList child             (PCNode _contextNode, Pchar _name);
      PCNodeList descendant        (PCNode _contextNode, Pchar _name);
      PCNodeList descendantOrSelf  (PCNode _contextNode, Pchar _name);
      PCNodeList following         (PCNode _contextNode, Pchar _name);
      PCNodeList followingSibling  (PCNode _contextNode, Pchar _name);
      PCNodeList nameSpace         (PCNode _contextNode, Pchar _name);
      PCNodeList parent            (PCNode _contextNode, Pchar _name);
      PCNodeList preceding         (PCNode _contextNode, Pchar _name);
      PCNodeList precedingSibling  (PCNode _contextNode, Pchar _name);
      PCNodeList self              (PCNode _contextNode, Pchar _name);

      void downInDocOrder          (PCNodeList _list,
                                    PCNode     _node,
                                    Pchar      _name);
      void downInBackOrder         (PCNodeList _list,
                                    PCNode     _node,
                                    Pchar      _name);

      // Evaluator Tokenizer
      void initEvalTokenizer       (Pchar _postFixExp);
      bool getEvalToken            (void);

      // Parser
      bool parse                   (Pchar  _inFixExp,
                                    Pchar  _postFixExp,
                                    ushort _size);
      void expr                    (void);
      void orExpr                  (void);
      void andExpr                 (void);
      void equalityExpr            (void);
      void relationalExpr          (void);
      void additiveExpr            (void);
      void multiplicativeExpr      (void);
      void unaryExpr               (void);
      void unionExpr               (void);
      void pathExpr                (void);
      bool filterExpr              (void);
      bool primaryExpr             (void);
      void functionCall            (void);
      void locationPath            (void);
      void relativeLocationPath    (ushort _steps);
      void step                    (void);
      bool abbreviatedStep         (void);
      void axisName                (void);
      bool abbreviatedAxisSpecifier(void);
      void nodeTest                (void);
      bool nameTest                (void);
      bool nodeType                (void);
      void predicateExpr           (void);

      // Parser symbol outputter
      void outputPostfix           (Pchar _symbol);
      void outputPostfix           (char  _op);

      // Parser Tokenizer
      void initParseTokenizer      (Pchar _inFixExp);
      void getParseToken           (void);
      void getSymbol               (void);
      void getVariable             (void);
      void getNumber               (void);
      void getQuotedString         (void);
      void getOp                   (void);
      bool getCh                   (void);
      char chkCh                   (void);
      void skipSpaces              (void);
      char getEntity               (RPchar _p);

      // Shared variables
      Pchar        stoken;
      ushort       op;
      char         ch;

      // Evaluator variables
      PCNode       node;
      PCXPathStack ctxtStack;
      PCXPathStack evalStack;
      int          iExp;
      PCRecord     exp;
      bool         extend;

      // Parser variables
      bool         atEnd;
      bool         isOp;
      bool         wasOp;
      ushort       lop;
      Pchar        inFixExp;
      Pchar        pInFixExp;
      Pchar        postFixExp;
   }; // CXPath

#endif // XPATH_H