Exemple #1
0
        /// <summary>
        /// Support for non-ecma "get"/"set" spidermonkey extension.
        /// </summary>
        /// <example>
        ///		NAME getter: FUNCTION () SCOPE
        ///		NAME setter: FUNCTION () SCOPE
        /// </example>
        bool CheckForGetterOrSetter (ObjArray elems)
        {
            int tt;

            string name = ts.String;
            consumeToken ();

            tt = peekToken ();
            if (tt != Token.NAME)
                return false;
            string type = ts.String;
            if (type != "getter" && type != "setter") {
                return false;
            }
            consumeToken ();

            matchToken (Token.COLON);
            matchToken (Token.FUNCTION);

            Node func = function (FunctionNode.FUNCTION_EXPRESSION);
            object property = ScriptRuntime.getIndexObject (name);

            elems.add ((type [0] == 'g') ? (object)new Node.GetterPropertyLiteral (property)
                : (object)new Node.SetterPropertyLiteral (property));
            elems.add (func);

            return true;
        }
Exemple #2
0
        Node primaryExpr ()
        {
            try {
                if (currentStackIndex++ > ScriptRuntime.MAXSTACKSIZE) {
                    currentStackIndex = 0;
                    throw Context.ReportRuntimeError (
                        ScriptRuntime.GetMessage ("mag.too.deep.parser.recursion"), sourceURI, ts.Lineno, null, 0);
                }

                Node pn;

                int ttFlagged = nextFlaggedToken ();
                int tt = ttFlagged & CLEAR_TI_MASK;

                switch (tt) {


                    case Token.FUNCTION:
                        return function (FunctionNode.FUNCTION_EXPRESSION);


                    case Token.LB: {
                            ObjArray elems = new ObjArray ();
                            int skipCount = 0;
                            decompiler.AddToken (Token.LB);
                            bool after_lb_or_comma = true;
                            for (; ; ) {
                                tt = peekToken ();

                                if (tt == Token.COMMA) {
                                    consumeToken ();
                                    decompiler.AddToken (Token.COMMA);
                                    if (!after_lb_or_comma) {
                                        after_lb_or_comma = true;
                                    }
                                    else {
                                        elems.add ((object)null);
                                        ++skipCount;
                                    }
                                }
                                else if (tt == Token.RB) {
                                    consumeToken ();
                                    decompiler.AddToken (Token.RB);
                                    break;
                                }
                                else {
                                    if (!after_lb_or_comma) {
                                        ReportError ("msg.no.bracket.arg");
                                    }
                                    elems.add (assignExpr (false));
                                    after_lb_or_comma = false;
                                }
                            }
                            return nf.CreateArrayLiteral (elems, skipCount);
                        }


                    case Token.LC: {
                            ObjArray elems = new ObjArray ();
                            decompiler.AddToken (Token.LC);
                            if (!matchToken (Token.RC)) {

                                bool first = true;
                                do {
                                    object property;

                                    if (!first)
                                        decompiler.AddToken (Token.COMMA);
                                    else
                                        first = false;

                                    tt = peekToken ();
                                    switch (tt) {

                                        case Token.NAME:
                                        case Token.STRING:
                                            consumeToken ();
                                            if (compilerEnv.getterAndSetterSupport) {
                                                if (tt == Token.NAME)
                                                    if (CheckForGetOrSet (elems) || CheckForGetterOrSetter (elems))
                                                        goto next_prop;
                                            }


                                            // map NAMEs to STRINGs in object literal context
                                            // but tell the decompiler the proper type
                                            string s = ts.String;
                                            if (tt == Token.NAME) {
                                                decompiler.AddName (s);
                                            }
                                            else {
                                                decompiler.AddString (s);
                                            }
                                            property = ScriptRuntime.getIndexObject (s);

                                            break;


                                        case Token.NUMBER:
                                            consumeToken ();
                                            double n = ts.Number;
                                            decompiler.AddNumber (n);
                                            property = ScriptRuntime.getIndexObject (n);
                                            break;


                                        case Token.RC:
                                            // trailing comma is OK.

                                            goto commaloop_brk;

                                        default:
                                            ReportError ("msg.bad.prop");

                                            goto commaloop_brk;

                                    }
                                    mustMatchToken (Token.COLON, "msg.no.colon.prop");

                                    // OBJLIT is used as ':' in object literal for
                                    // decompilation to solve spacing ambiguity.
                                    decompiler.AddToken (Token.OBJECTLIT);
                                    elems.add (property);
                                    elems.add (assignExpr (false));

                                next_prop:
                                    ;
                                }
                                while (matchToken (Token.COMMA));

                            commaloop_brk:
                                ;


                                mustMatchToken (Token.RC, "msg.no.brace.prop");
                            }
                            decompiler.AddToken (Token.RC);
                            return nf.CreateObjectLiteral (elems);
                        }


                    case Token.LP:

                        /* Brendan's IR-jsparse.c makes a new node tagged with
                        * TOK_LP here... I'm not sure I understand why.  Isn't
                        * the grouping already implicit in the structure of the
                        * parse tree?  also TOK_LP is already overloaded (I
                        * think) in the C IR as 'function call.'  */
                        decompiler.AddToken (Token.LP);
                        pn = expr (false);
                        decompiler.AddToken (Token.RP);
                        mustMatchToken (Token.RP, "msg.no.paren");
                        return pn;


                    case Token.XMLATTR:
                        mustHaveXML ();
                        decompiler.AddToken (Token.XMLATTR);
                        pn = attributeAccess (null, 0);
                        return pn;


                    case Token.NAME: {
                            string name = ts.String;
                            if ((ttFlagged & TI_CHECK_LABEL) != 0) {
                                if (peekToken () == Token.COLON) {
                                    // Do not consume colon, it is used as unwind indicator
                                    // to return to statementHelper.
                                    // TODO: Better way?
                                    return nf.CreateLabel (ts.Lineno);
                                }
                            }

                            decompiler.AddName (name);
                            if (compilerEnv.isXmlAvailable ()) {
                                pn = propertyName (null, name, 0);
                            }
                            else {
                                pn = nf.CreateName (name);
                            }
                            return pn;
                        }


                    case Token.NUMBER: {
                            double n = ts.Number;
                            decompiler.AddNumber (n);
                            return nf.CreateNumber (n);
                        }


                    case Token.STRING: {
                            string s = ts.String;
                            decompiler.AddString (s);
                            return nf.CreateString (s);
                        }


                    case Token.DIV:
                    case Token.ASSIGN_DIV: {
                            // Got / or /= which should be treated as regexp in fact
                            ts.readRegExp (tt);
                            string flags = ts.regExpFlags;
                            ts.regExpFlags = null;
                            string re = ts.String;
                            decompiler.AddRegexp (re, flags);
                            int index = currentScriptOrFn.addRegexp (re, flags);
                            return nf.CreateRegExp (index);
                        }


                    case Token.NULL:
                    case Token.THIS:
                    case Token.FALSE:
                    case Token.TRUE:
                        decompiler.AddToken (tt);
                        return nf.CreateLeaf (tt);


                    case Token.RESERVED:
                        ReportError ("msg.reserved.id");
                        break;


                    case Token.ERROR:
                        /* the scanner or one of its subroutines reported the error. */
                        break;


                    case Token.EOF:
                        ReportError ("msg.unexpected.eof");
                        break;


                    default:
                        ReportError ("msg.syntax");
                        break;

                }
                return null; // should never reach here
            }
            finally {
                currentStackIndex--;
            }
        }