/* ------------------------------------------------------------ */ protected void seekTo(char seek, Source source) { while (source.hasNext()) { char c = source.peek(); if (c == seek) return; if (!Character.isWhitespace(c)) throw new IllegalStateException("Unexpected '" + c + " while seeking '" + seek + "'"); source.next(); } throw new IllegalStateException("Expected '" + seek + "'"); }
/* ------------------------------------------------------------ */ protected Object parseArray(Source source) { if (source.next() != '[') throw new IllegalStateException(); int size = 0; ArrayList list = null; Object item = null; boolean coma = true; while (source.hasNext()) { char c = source.peek(); switch (c) { case ']': source.next(); switch (size) { case 0: return newArray(0); case 1: Object array = newArray(1); Array.set(array, 0, item); return array; default: return list.toArray(newArray(list.size())); } case ',': if (coma) throw new IllegalStateException(); coma = true; source.next(); break; default: if (Character.isWhitespace(c)) source.next(); else { coma = false; if (size++ == 0) item = contextForArray().parse(source); else if (list == null) { list = new ArrayList(); list.add(item); item = contextForArray().parse(source); list.add(item); item = null; } else { item = contextForArray().parse(source); list.add(item); item = null; } } } } throw new IllegalStateException("unexpected end of array"); }
/* ------------------------------------------------------------ */ protected char seekTo(String seek, Source source) { while (source.hasNext()) { char c = source.peek(); if (seek.indexOf(c) >= 0) { return c; } if (!Character.isWhitespace(c)) throw new IllegalStateException( "Unexpected '" + c + "' while seeking one of '" + seek + "'"); source.next(); } throw new IllegalStateException("Expected one of '" + seek + "'"); }
/* ------------------------------------------------------------ */ public Number parseNumber(Source source) { boolean minus = false; long number = 0; StringBuilder buffer = null; longLoop: while (source.hasNext()) { char c = source.peek(); switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': number = number * 10 + (c - '0'); source.next(); break; case '-': case '+': if (number != 0) throw new IllegalStateException("bad number"); minus = true; source.next(); break; case '.': case 'e': case 'E': buffer = new StringBuilder(16); if (minus) buffer.append('-'); buffer.append(number); buffer.append(c); source.next(); break longLoop; default: break longLoop; } } if (buffer == null) return minus ? -1 * number : number; doubleLoop: while (source.hasNext()) { char c = source.peek(); switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': case '.': case '+': case 'e': case 'E': buffer.append(c); source.next(); break; default: break doubleLoop; } } return new Double(buffer.toString()); }
/* ------------------------------------------------------------ */ public Object parse(Source source) { int comment_state = 0; // 0=no comment, 1="/", 2="/*", 3="/* *" -1="//" while (source.hasNext()) { char c = source.peek(); // handle // or /* comment if (comment_state == 1) { switch (c) { case '/': comment_state = -1; break; case '*': comment_state = 2; } } // handle /* */ comment else if (comment_state > 1) { switch (c) { case '*': comment_state = 3; break; case '/': if (comment_state == 3) comment_state = 0; else comment_state = 2; break; default: comment_state = 2; } } // handle // comment else if (comment_state < 0) { switch (c) { case '\r': case '\n': comment_state = 0; break; default: break; } } // handle unknown else { switch (c) { case '{': return parseObject(source); case '[': return parseArray(source); case '"': return parseString(source); case '-': return parseNumber(source); case 'n': complete("null", source); return null; case 't': complete("true", source); return Boolean.TRUE; case 'f': complete("false", source); return Boolean.FALSE; case 'u': complete("undefined", source); return null; case 'N': complete("NaN", source); return null; case '/': comment_state = 1; break; default: if (Character.isDigit(c)) return parseNumber(source); else if (Character.isWhitespace(c)) break; return handleUnknown(source, c); } } source.next(); } return null; }
/* ------------------------------------------------------------ */ public Object parse(Source source, boolean stripOuterComment) { int comment_state = 0; // 0=no comment, 1="/", 2="/*", 3="/* *" -1="//" if (!stripOuterComment) return parse(source); int strip_state = 1; // 0=no strip, 1=wait for /*, 2= wait for */ Object o = null; while (source.hasNext()) { char c = source.peek(); // handle // or /* comment if (comment_state == 1) { switch (c) { case '/': comment_state = -1; break; case '*': comment_state = 2; if (strip_state == 1) { comment_state = 0; strip_state = 2; } } } // handle /* */ comment else if (comment_state > 1) { switch (c) { case '*': comment_state = 3; break; case '/': if (comment_state == 3) { comment_state = 0; if (strip_state == 2) return o; } else comment_state = 2; break; default: comment_state = 2; } } // handle // comment else if (comment_state < 0) { switch (c) { case '\r': case '\n': comment_state = 0; default: break; } } // handle unknown else { if (!Character.isWhitespace(c)) { if (c == '/') comment_state = 1; else if (c == '*') comment_state = 3; else if (o == null) { o = parse(source); continue; } } } source.next(); } return o; }