/*
 * The contents of this file are subject to the Netscape 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/NPL/

 * 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 Rhino code, released
 * May 6, 1999.

 * The Initial Developer of the Original Code is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
 * Rights Reserved.

 * Contributor(s): 

 * Alternatively, the contents of this file may be used under the
 * terms of the GNU Public License (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 NPL, 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 NPL or the GPL.
 */

#ifndef _JS_TOKEN_STREAM_H_
#define _JS_TOKEN_STREAM_H_

#include "js-zonenew.h"
#include "js-linebuffer.h"
#include "js-scriptable.h"

/* Classes */
class JSTokenStream: public JSZoneNew {
    friend class JSNativeGlobal;
    public:
        static  const int
                TSF_NEWLINES    = 0x0001,  // tokenize newlines
                TSF_FUNCTION    = 0x0002,  // scanning inside function body
                TSF_RETURN_EXPR = 0x0004,  // function has 'return expr;'
                TSF_RETURN_VOID = 0x0008,  // function has 'return;'
                TSF_REGEXP      = 0x0010;  // looking for a regular expression

        static const int
                // start enum
                _ERROR  = -1, // well-known as the only code < EOF
                _EOF    = 0,  // end of file token - (not EOF_CHAR)
                EOL             = 1,  // end of line
                // Beginning here are interpreter bytecodes.
                // Their values must not exceed 127.
                POPV            = 2,
                ENTERWITH       = 3,
                LEAVEWITH       = 4,
                RETURN          = 5,
                GOTO            = 6,
                IFEQ            = 7,
                IFNE            = 8,
                DUP             = 9,
                SETNAME         = 10,
                BITOR           = 11,
                BITXOR          = 12,
                BITAND          = 13,
                EQ              = 14,
                NE              = 15,
                LT              = 16,
                LE              = 17,
                GT              = 18,
                GE              = 19,
                LSH             = 20,
                RSH             = 21,
                URSH            = 22,
                ADD             = 23,
                SUB             = 24,
                MUL             = 25,
                DIV             = 26,
                MOD             = 27,
                BITNOT          = 28,
                NEG             = 29,
                NEW             = 30,
                DELPROP         = 31,
                TYPEOF          = 32,
                NAMEINC         = 33,
                PROPINC         = 34,
                ELEMINC         = 35,
                NAMEDEC         = 36,
                PROPDEC         = 37,
                ELEMDEC         = 38,
                GETPROP         = 39,
                SETPROP         = 40,
                GETELEM         = 41,
                SETELEM         = 42,
                CALL            = 43,
                NAME            = 44,
                NUMBER          = 45,
                STRING          = 46,
#ifdef VX
                _ZERO           = 47,
#else
                ZERO            = 47,
#endif
                ONE             = 48,
                _NULL   = 49,
                THIS            = 50,
                _FALSE          = 51,
                _TRUE           = 52,
                SHEQ            = 53,   // shallow equality (===)
                SHNE            = 54,   // shallow inequality (!==)
                CLOSURE         = 55,
                OBJECT          = 56,
                POP             = 57,
                POS             = 58,
                VARINC          = 59,
                VARDEC          = 60,
                BINDNAME        = 61,
                THROW           = 62,
                IN              = 63,
                INSTANCEOF      = 64,
                GOSUB           = 65,
                RETSUB          = 66,
                CALLSPECIAL     = 67,
                GETTHIS         = 68,
                NEWTEMP         = 69,
                USETEMP         = 70,
                GETBASE         = 71,
                GETVAR          = 72,
                SETVAR          = 73,
                UNDEFINED       = 74,
                TRY             = 75,
                ENDTRY          = 76,
                NEWSCOPE        = 77,
                TYPEOFNAME      = 78,
                ENUMINIT        = 79,
                ENUMNEXT        = 80,
                GETPROTO        = 81,
                GETPARENT       = 82,
                SETPROTO        = 83,
                SETPARENT       = 84,
                SCOPE           = 85,
                GETSCOPEPARENT = 86,
                JTHROW          = 87,
                // End of interpreter bytecodes
                SEMI            = 88,  // semicolon
                LB              = 89,  // left and right brackets
                RB              = 90,
                LC              = 91,  // left and right curlies (braces)
                RC              = 92,
                LP              = 93,  // left and right parentheses
                RP              = 94,
                COMMA           = 95,  // comma operator
                ASSIGN          = 96, // assignment ops (= += -= etc.)
                HOOK            = 97, // conditional (?:)
                COLON           = 98,
                OR              = 99, // logical or (||)
                AND             = 100, // logical and (&&)
                EQOP            = 101, // equality ops (== !=)
                RELOP           = 102, // relational ops (< <= > >=)
                SHOP            = 103, // shift ops (<< >> >>>)
                UNARYOP         = 104, // unary prefix operator
                INC             = 105, // increment/decrement (++ --)
                DEC             = 106,
                DOT             = 107, // member operator (.)
                PRIMARY         = 108, // true, false, null, this
                FUNCTION        = 109, // function keyword
                EXPORT          = 110, // export keyword
#ifdef VX
                _IMPORT         = 111, // import keyword
#else
                IMPORT          = 111, // import keyword
#endif
                IF              = 112, // if keyword
                ELSE            = 113, // else keyword
                SWITCH          = 114, // switch keyword
                CASE            = 115, // case keyword
                DEFAULT         = 116, // default keyword
                WHILE           = 117, // while keyword
                DO              = 118, // do keyword
                FOR             = 119, // for keyword
                BREAK           = 120, // break keyword
                CONTINUE        = 121, // continue keyword
                VAR             = 122, // var keyword
                WITH            = 123, // with keyword
                CATCH           = 124, // catch keyword
                FINALLY         = 125, // finally keyword
                RESERVED        = 126, // reserved keywords

                /** Added by Mike - these are JSOPs in the jsref, but I
                 * don't have them yet in the java implementation...
                 * so they go here.  Also whatever I needed.

                 * Most of these go in the 'op' field when returning
                 * more general token types, eg. 'DIV' as the op of
                 * 'ASSIGN'.
                 */
                NOP             = 127, // NOP
                NOT             = 128, // etc.
                PRE             = 129, // for INC, DEC nodes.
                POST            = 130,

                /**
                 * For JSOPs associated with keywords...
                 * eg. op = THIS; token = PRIMARY
                 */

#if defined(TARGET_OS_LINUX)
                VOIDX            = 131,
#else
                VOID             = 131,
#endif

                /* types used for the parse tree - these never get
                 * returned by the scanner.
                 */
                BLOCK           = 132, // statement block
                ARRAYLIT        = 133, // array literal
                OBJLIT          = 134, // object literal
                LABEL           = 135, // label
                TARGET          = 136,
                LOOP            = 137,
                ENUMDONE        = 138,
                EXPRSTMT        = 139,
                PARENT          = 140,
                CONVERT         = 141,
                JSR             = 142,
                NEWLOCAL        = 143,
                USELOCAL        = 144,
                SCRIPT          = 145,   // top-level node for entire script

                /**
                 * For the interpreted mode indicating a line number
                 * change in icodes.
                 */
                LINE            = 146,
#ifdef REUSE_LOCAL
                SOURCEFILE      = 147,
                DELTEMP         = 148;
#else
                SOURCEFILE      = 147;
#endif

                static const int        EOF_CHAR = -1;
    protected:
        static  jsString_t      *names;
        static  int             namesLength;

        JSLineBuffer    in;
        jsString_t      sourceName;
        jsString_t      line;
        JSScriptable    *scope;
        int             pushbackToken;
        int             tokenno;
        jsString_t      string;
        double          number;

        int             op;
#ifdef FASTER
        jsString_t      _string;
        jsString_t      regExp;
#endif

    public:
        int             flags;
        jsString_t      regExpFlags;

    protected:
        static  void    checkNames();
        static  jsBool_t
                        isAlpha(int c);
        static  jsBool_t
                        isDigit(int c);
        static  jsBool_t
                        isXDigit(int c);
        static  jsBool_t
                        isJSIdentifier(jsString_t s);
        static  int     digit(jsChar_t c, int radix);
        static  jsBool_t
                        isJavaIdentifierPart(int c);
        static  jsBool_t
                        isJavaIdentifierStart(int c);

        void    setString(JSContext *cx, jsString_t string);
        jsString_t
                tokenToString(JSContext *cx, int token);

    public:
        static  void    classInitialize();
        static  jsString_t
                        tokenToName(int type);
        static  jsBool_t
                        isJSSpace(int c);
        static  jsBool_t
                        isJSLineTerminator(int c);

        JSTokenStream(JSContext *cx, JSReader *in, JSScriptable *scope,
                jsString_t sourceName, int lineno);
        virtual ~JSTokenStream() {
        }

        int     stringToKeyword(jsString_t name);
        JSScriptable *
                getScope();
        jsBool_t
                matchToken(JSContext *cx, int toMatch);
        void    clearPushback();
        void    ungetToken(JSContext *cx, int tt);
        int     peekToken(JSContext *cx);
        int     peekTokenSameLine(JSContext *cx);
        int     getToken(JSContext *cx);
        void    reportSyntaxError(JSContext *cx, jsString_t messageProperty,
                        ...);
        jsString_t
                getSourceName();
        int     getLineno();
        int     getOp();
        jsString_t
                getString();
        double  getNumber();
        jsString_t
                getLine(JSContext *cx);
        int     getOffset();
        int     getTokenno();
        jsBool_t
                eof();
        void    destroy(JSContext *cx);
} ;

/* Inlines */
inline jsString_t
JSTokenStream::getSourceName()
{
    return sourceName;
}
inline int
JSTokenStream::getLineno()
{
    return in.getLineno();
}
inline int
JSTokenStream::getOp()
{
    return op;
}
inline jsString_t
JSTokenStream::getString()
{
    return string;
}
inline double
JSTokenStream::getNumber()
{
    return number;
}
inline jsString_t
JSTokenStream::getLine(JSContext *cx)
{
    return in.getLine(cx);
}
inline int
JSTokenStream::getOffset()
{
    return in.getOffset();
}
inline int
JSTokenStream::getTokenno()
{
    return tokenno;
}
inline jsBool_t
JSTokenStream::eof()
{
    return in.eof();
}

#endif /* _JS_TOKEN_STREAM_H_ */

