+
+ /**
+ * Assuming that a complete assignable (lvalue) has just been
+ * parsed and the object and key are on the stack,
+ * <tt>continueExprAfterAssignable</tt> will attempt to parse an
+ * expression that modifies the assignable. This method always
+ * decreases the stack depth by exactly one element.
+ */
+ private void continueExprAfterAssignable(JSFunction b,int minPrecedence) throws IOException {
+ int saveParserLine = parserLine;
+ _continueExprAfterAssignable(b,minPrecedence);
+ parserLine = saveParserLine;
+ }
+ private void _continueExprAfterAssignable(JSFunction b,int minPrecedence) throws IOException {
+ if (b == null) throw new Error("got null b; this should never happen");
+ int tok = getToken();
+ if (minPrecedence != -1 && (precedence[tok] < minPrecedence || (precedence[tok] == minPrecedence && !isRightAssociative[tok])))
+ // force the default case
+ tok = -1;
+ switch(tok) {
+ case ASSIGN_BITOR: case ASSIGN_BITXOR: case ASSIGN_BITAND: case ASSIGN_LSH: case ASSIGN_RSH: case ASSIGN_URSH:
+ case ASSIGN_MUL: case ASSIGN_DIV: case ASSIGN_MOD: case ASSIGN_ADD: case ASSIGN_SUB: {
+ b.add(parserLine, GET_PRESERVE);
+ startExpr(b, precedence[tok]);
+ int size = b.size;
+ if (tok == ASSIGN_ADD || tok == ASSIGN_SUB) {
+ b.add(parserLine, tok);
+ }
+ // tok-1 is always s/^ASSIGN_// (0 is BITOR, 1 is ASSIGN_BITOR, etc)
+ b.add(parserLine, tok - 1, tok-1==ADD ? new Integer(2) : null);
+ b.add(parserLine, PUT);
+ b.add(parserLine, SWAP);
+ b.add(parserLine, POP);
+ if (tok == ASSIGN_ADD || tok == ASSIGN_SUB) b.set(size, tok, new Integer(b.size - size));
+ break;
+ }
+ case INC: case DEC: { // postfix
+ b.add(parserLine, GET_PRESERVE, Boolean.TRUE);
+ b.add(parserLine, LITERAL, new Integer(1));
+ b.add(parserLine, tok == INC ? ADD : SUB, null);
+ b.add(parserLine, PUT, null);
+ b.add(parserLine, SWAP, null);
+ b.add(parserLine, POP, null);
+ b.add(parserLine, LITERAL, new Integer(1));
+ b.add(parserLine, tok == INC ? SUB : ADD, null); // undo what we just did, since this is postfix
+ break;
+ }
+ case ASSIGN: {
+ startExpr(b, precedence[tok]);
+ b.add(parserLine, PUT);
+ b.add(parserLine, SWAP);
+ b.add(parserLine, POP);
+ break;
+ }
+ case LP: {
+ int n = parseArgs(b, false);
+
+ // if the object supports GETCALL, we use this, and jump over the following two instructions
+ b.add(parserLine,CALLMETHOD,new Integer(n));
+ b.add(parserLine,GET);
+ b.add(parserLine,CALL,new Integer(n));
+ break;
+ }
+ default: {
+ pushBackToken();
+ if(b.get(b.size-1) == LITERAL && b.getArg(b.size-1) != null)
+ b.set(b.size-1,GET,b.getArg(b.size-1));
+ else
+ b.add(parserLine, GET);
+ return;
+ }
+ }
+ }
+
+