/* 
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 * 
 * The Original Code is the Sablotron XSLT Processor.
 * 
 * The Initial Developer of the Original Code is Ginger Alliance Ltd.
 * Portions created by Ginger Alliance are Copyright (C) 2000 Ginger
 * Alliance Ltd. All Rights Reserved.
 * 
 * Contributor(s):
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL"), in which case the provisions of the GPL are applicable 
 * instead of those above.  If you wish to allow use of your 
 * version of this file only under the terms of the GPL and not to
 * allow others to use your version of this file under the MPL,
 * indicate your decision by deleting the provisions above and
 * replace them with the notice and other provisions required by
 * the GPL.  If you do not delete the provisions above, a recipient
 * may use your version of this file under either the MPL or the
 * GPL.
 */

// EXPR.H

#ifndef ExprHIncl
#define ExprHIncl

#include "base.h"
#include "datastr.h"
#include "proc.h"

class Vertex;

/**********************************************************
token types
**********************************************************/

enum ExToken
{
    //end of parsed string
    TOK_END,
        
        //names
        TOK_NAME,       // name test, incl. '*' and 'prefix:*'
        TOK_AXISNAME,   // name followed by ::
        TOK_NTNAME,     // node(), text() etc.
        TOK_FNAME,      // other names followed by (
        
        //symbols
        TOK_LPAREN,     TOK_RPAREN,
        TOK_LBRACKET,   TOK_RBRACKET,
        TOK_PERIOD,     TOK_DPERIOD,
        TOK_ATSIGN,     TOK_COMMA,
        TOK_DCOLON,     TOK_DSLASH,
        TOK_SLASH,
        
        //variable reference ($...)
        TOK_VAR,
        //string in quotes
        TOK_LITERAL,
        //real number
        TOK_NUMBER,
        
        //operators
        TOKGROUP_OPERATORS,
        TOK_OR = TOKGROUP_OPERATORS,
        TOK_AND,
        TOK_EQ,
        TOK_NEQ,
        TOK_LT,
        TOK_GT,
        TOK_LE,
        TOK_GE,
        TOK_PLUS,
        TOK_MINUS2,
        TOK_MINUS = TOK_MINUS2,
        TOK_MULT,
        TOK_MOD,
        TOK_DIV,
        TOK_MINUS1,
        TOK_VERT,

        TOK_STAR,        // as wildcard in names
        TOK_NONE
}; 

class TokenItem /* : public SabObj */
{
public:
    ExToken tok;
    char* firstc;
    int len;
    void speak(DStr &, SpeakMode mode);
};

//ExNodeType is defined in base.h
//array exNodeTypeNames in base.cpp

class Tokenizer /* : public SabObj */
{
public:
	int findTop(ExToken token, int from);
    Tokenizer();
    ~Tokenizer();
    eFlag tokenize(const Str &astring);
    eFlag getToken(char *&, TokenItem&, ExToken);
    void speak(DStr &s, SpeakMode mode);
    eFlag getDelim(int &, Bool = FALSE);
    void stripParens(int &, int &);
    DStr string;
    PList<TokenItem*> items;
private:
    ExToken tryShort(char *&, ExToken);
    eFlag lookToken(ExToken &, char*, ExToken);
    eFlag getToken_(ExToken &, char*&, ExToken);
    eFlag getNumber(char *&);
    eFlag getName(ExToken&, char *&, ExToken);
};

/*
XPath expression types. Correspondence to Sablotron classes:
NUMBER          class Number
STRING          class Str
BOOLEAN         Bool
NODESET         class Context
*/

enum ExType
{
    EX_NUMBER,
        EX_STRING,
        EX_BOOLEAN,
        EX_NODESET,
        EX_NODESET_PATTERN,
        EX_NONE,
        EX_FRAGMENT,
        EX_UNKNOWN
        
};

/*
The following enum comprises four categories of "functors": 
(1) basic (atom, variable reference etc.) 
(2) operators (EXFO_...)
(3) functions in the XPath core library (EXFF_XPATH_...)
(4) functions in the XSLT core library (EXFF_XSLT_...)

Groups (2) through (4) should be listed in the given order (that is, operators -
XPath functions - XSLT functions) and should end with an item ..._Z 
(e.g. EXFO_Z).
*/

enum ExFunctor 
{
    EXF_ATOM,
        EXF_VAR,
        EXF_LOCPATH,
        EXF_LOCSTEP,
        EXF_OTHER_FUNC,
        EXF_FILTER,
        EXF_STRINGSEQ,
        EXF_FRAGMENT,
        EXF_NONE,
        
        // EXFO_... (operators)
        EXFO_OR,
        EXFO_AND,
        EXFO_EQ,
        EXFO_NEQ,
        EXFO_LT,
        EXFO_LE,
        EXFO_GT,
        EXFO_GE,
        EXFO_PLUS,
        EXFO_MINUS2,
        EXFO_MINUS = EXFO_MINUS2,
        EXFO_MULT,
        EXFO_DIV,
        EXFO_MOD,
        EXFO_MINUS1,
        EXFO_UNION,
        EXFO_Z,             //last in group
        
        //functions (fall into 2 groups: core XPath and core XSLT)
        EXF_FUNCTION,

        // XPath, NODESET
        EXFF_LAST,
        EXFF_POSITION,
        EXFF_COUNT,
        EXFF_ID,
        EXFF_LOCAL_NAME,
        EXFF_NAMESPACE_URI,
        EXFF_NAME,

        // XPath, STRING
        EXFF_STRING,
        EXFF_CONCAT,
        EXFF_STARTS_WITH,
        EXFF_CONTAINS,
        EXFF_SUBSTRING_BEFORE,
        EXFF_SUBSTRING_AFTER,
        EXFF_SUBSTRING,
        EXFF_STRING_LENGTH,
        EXFF_NORMALIZE_SPACE,
        EXFF_TRANSLATE,

		// Upfront, STRING
		EXFF_URL_ENCODE,
		EXFF_HTML_ENCODE,
		EXFF_JAVASCRIPT_ENCODE,

        // XPath, BOOLEAN
        EXFF_BOOLEAN,
        EXFF_NOT,
        EXFF_TRUE,
        EXFF_FALSE,
        EXFF_LANG,

        // XPath, NUMBER
        EXFF_NUMBER,
        EXFF_SUM,
        EXFF_FLOOR,
        EXFF_CEILING,
        EXFF_ROUND,

        // XSLT core
        EXFF_DOCUMENT,
        EXFF_KEY,
        EXFF_FORMAT_NUMBER,
        EXFF_CURRENT,
        EXFF_UNPARSED_ENTITY_URI,
        EXFF_GENERATE_ID,
        EXFF_SYSTEM_PROPERTY,
        EXFF_NONE
};

class Expression;

typedef PList<Expression *> ExprList;

/**********************************************************
N u m b e r
**********************************************************/

class Number /* : public SabObj */
{
public:
    Number();
    Number(double);
    Number& operator= (double);
    Number& operator= (const Str &);
    operator double ();
    Bool operator== (double);
    Bool operator< (double);
    Bool operator> (double);
    Bool operator== (Number&);
    Bool operator< (Number&);
    Bool operator> (Number&);
    Bool isNaN();
    Bool isInf();
    void setNaN();
private:
    double x;
    Bool _NaN;
};

/**********************************************************
L o c S t e p
**********************************************************/

class Element;

class LocStep /* : public SabObj */
{
public:
    LocStep(ExAxis = AXIS_NONE, ExNodeType = EXNODE_NONE);
    ~LocStep();
    void set(ExAxis, ExNodeType);
    eFlag parse(Tokenizer&, int&, Element *ownerV);
    ExAxis ax;
    ExNodeType ntype;
    QName ntest;
    ExprList preds;
    void speak(DStr &s, SpeakMode mode);
    Bool matches(Vertex *);
    eFlag createContextNoPreds(Context *&, int);
};


/**********************************************************
E x p r e s s i o n
**********************************************************/

class Element;

class Expression /* : public SabObj */
{
public:
    Expression(Element *, ExFunctor = EXF_NONE);
    ~Expression();
    void clearContent();
    void
        setLS(ExAxis, ExNodeType);
    void speak(DStr &,SpeakMode);
    eFlag 
        parse(const DStr &, Bool = FALSE);
    eFlag 
        parse(Tokenizer&, int, int);
    eFlag eval(Expression &, Context *);
    Number tonumber();
    Str tostring();
    char *tostringCharPtr();
    const Str& tostringRef() const;
    Bool tobool();
    Context& tonodeset();
    const Context& tonodesetRef();
    Bool matches(Context *);
    eFlag trueFor(Context *, Bool&);
    //
    ExType type;
    ExFunctor functor;
    ExprList args;
    eFlag createLPContext(Context *&, int);
    eFlag createLPContextSum(int, Context *&);
    eFlag createContext(Context *&, int = -1);
    LocStep *step;
    int hasPath;
    void setAtom(Context*);
    void setAtom(const Number&);
    void setAtom(const DStr&);
    void setAtom(Bool);
    Tree *setFragment();
    Tree *pTree;
    Element *ownerV;
private:
    union
    {
        QName *pName;    //of function or variable
        Str *patomstring;
        Bool atombool;
        Number *patomnumber;
        Context *patomnodeset;
    };
    Bool compareCC(ExFunctor, const Context &, const Context &);
    Bool compareCS(ExFunctor, const Context &, const DStr &);
    Bool compareCN(ExFunctor, const Context &, const Number &);
    eFlag compare(Bool &, Expression &, ExFunctor);
    Bool isOp(ExToken, int &);
    eFlag callOp(Expression&, ExprList&);
    eFlag callFunc(Expression&, ExprList&, Context *);
    eFlag parseBasic(Tokenizer &, int, int);
    eFlag parseLP(Tokenizer&, int &, Bool = FALSE);
    Bool matchesLP(Vertex *v, int lastIndex);
    Bool 
        isPattern;
    Bool patternOK();
    void setAtomNoCopy(Context &);
};

#endif //ifndef ExprHIncl
