+ /** append the largest expression beginning with prefix containing no operators of precedence below <tt>minPrecedence</tt> */
+ public ByteCodeBlock startExpr() throws IOException { return startExpr(-1); }
+ public void startExpr(ByteCodeBlock block) throws IOException { startExpr(-1, block); }
+ public ByteCodeBlock startExpr(int minPrecedence) throws IOException {
+ ByteCodeBlock ret = new ByteCodeBlock(line, sourceName);
+ startExpr(minPrecedence, ret);
+ return ret.size() == 0 ? null : ret;
+ }
+
+ public void startExpr(int minPrecedence, ByteCodeBlock appendTo) throws IOException {
+ int tok = getToken();
+ int curLine = line;
+ if (tok == -1) return;
+ if (minPrecedence > 0 && precedence[tok] != 0)
+ if (precedence[tok] < minPrecedence || (precedence[tok] == minPrecedence && !isRightAssociative[tok]))
+ { pushBackToken(); return; }
+
+ ByteCodeBlock b = appendTo;
+
+ switch (tok) {
+ case NUMBER: continueExpr(b.add(ByteCodeBlock.LITERAL, number), minPrecedence); return;
+ case STRING: continueExpr(b.add(ByteCodeBlock.LITERAL, string), minPrecedence); return;
+ case THIS: continueExpr(b.add(TOPSCOPE, null), minPrecedence); return;
+ case NULL: continueExpr(b.add(ByteCodeBlock.LITERAL, null), minPrecedence); return;
+ case TRUE: case FALSE: continueExpr(b.add(ByteCodeBlock.LITERAL, new Boolean(tok == TRUE)), minPrecedence); return;
+ case LB: {
+ b.add(ARRAY, new Integer(0));
+ int i = 0;
+ while(true) {
+ int size = b.size();
+ startExpr(b);
+ if (size == b.size())
+ if (peekToken() == RB) { consume(RB); continueExpr(b, minPrecedence); return; }
+ b.add(LITERAL, new Integer(i++));
+ if (size == b.size()) b.add(LITERAL, null);
+ b.add(PUT);
+ b.add(POP);
+ if (peekToken() == RB) { consume(RB); continueExpr(b, minPrecedence); return; }
+ consume(COMMA);
+ }
+ }
+ case SUB: {
+ consume(NUMBER);
+ continueExpr(b.add(ByteCodeBlock.LITERAL, new Double(number.doubleValue() * -1)), minPrecedence);
+ return;
+ }
+ case LP: {
+ startExpr(b);
+ consume(RP);
+ continueExpr(b, minPrecedence);
+ return;
+ }
+ case INC: case DEC: {
+ // prefix
+ startExpr(precedence[tok], b);
+ b.set(b.size() - 1, tok, new Boolean(true));
+ continueExpr(b, minPrecedence);
+ return;
+ }
+ case BANG: case BITNOT: case TYPEOF: {
+ startExpr(precedence[tok], b);
+ b.add(tok);
+ continueExpr(b, minPrecedence);
+ return;
+ }
+ case LC: {
+ b.add(OBJECT, null);
+ if (peekToken() == RC) { consume(RC); continueExpr(b, minPrecedence); return; }
+ while(true) {
+ if (peekToken() != NAME && peekToken() != STRING) throw new Error("expected NAME or STRING");