Updated Grammar for matching JsonArray to be left-associative rather than right-associative. Gson can now parse arrays of size over 11MB instead of 80KB which was the prior limit. Thanks for the tip, kenotron.

This commit is contained in:
Inderjeet Singh 2009-08-22 01:03:27 +00:00
parent c13fc568c7
commit cbcf7defa3
12 changed files with 1037 additions and 905 deletions

View File

@ -19,9 +19,9 @@ package com.google.gson;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
/** /**
@ -39,7 +39,7 @@ public final class JsonArray extends JsonElement implements Iterable<JsonElement
* Creates an empty JsonArray. * Creates an empty JsonArray.
*/ */
public JsonArray() { public JsonArray() {
elements = new LinkedList<JsonElement>(); elements = new ArrayList<JsonElement>();
} }
/** /**

View File

@ -138,6 +138,10 @@ final class JsonParserJavacc implements JsonParserJavaccConstants {
JsonArray array = new JsonArray(); JsonArray array = new JsonArray();
jj_consume_token(31); jj_consume_token(31);
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 32:
array = JsonArrayEmpty(array);
{if (true) return array;}
break;
case DIGITS: case DIGITS:
case NULL: case NULL:
case NAN: case NAN:
@ -148,31 +152,51 @@ final class JsonParserJavacc implements JsonParserJavaccConstants {
case 27: case 27:
case 31: case 31:
case 33: case 33:
Elements(array); JsonArrayElement(array);
label_1:
while (true) {
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 29:
;
break; break;
default: default:
jj_la1[6] = jj_gen; jj_la1[6] = jj_gen;
; break label_1;
}
JsonArrayNextElement(array);
} }
jj_consume_token(32); jj_consume_token(32);
array.reverse(); {if (true) return array;}
break;
default:
jj_la1[7] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
throw new Error("Missing return statement in function");
}
final private JsonArray JsonArrayEmpty(JsonArray array) throws ParseException {
jj_consume_token(32);
{if (true) return array;} {if (true) return array;}
throw new Error("Missing return statement in function"); throw new Error("Missing return statement in function");
} }
final private void Elements(JsonArray array) throws ParseException { final private JsonArray JsonArrayElement(JsonArray array) throws ParseException {
JsonElement element; JsonElement element = null;
element = JsonValue(); element = JsonValue();
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 29:
jj_consume_token(29);
Elements(array);
break;
default:
jj_la1[7] = jj_gen;
;
}
array.add(element); array.add(element);
{if (true) return array;}
throw new Error("Missing return statement in function");
}
final private JsonArray JsonArrayNextElement(JsonArray array) throws ParseException {
JsonElement element = null;
jj_consume_token(29);
element = JsonValue();
array.add(element);
{if (true) return array;}
throw new Error("Missing return statement in function");
} }
final private JsonElement JsonValue() throws ParseException { final private JsonElement JsonValue() throws ParseException {
@ -406,36 +430,36 @@ final class JsonParserJavacc implements JsonParserJavaccConstants {
finally { jj_save(0, xla); } finally { jj_save(0, xla); }
} }
private boolean jj_3R_4() { private boolean jj_3R_3() {
if (jj_scan_token(NAN)) return true;
return false;
}
private boolean jj_3R_2() {
Token xsp;
xsp = jj_scanpos;
if (jj_3R_3()) {
jj_scanpos = xsp;
if (jj_3R_4()) return true;
}
return false;
}
private boolean jj_3R_5() {
if (jj_scan_token(33)) return true; if (jj_scan_token(33)) return true;
return false; return false;
} }
private boolean jj_3R_3() { private boolean jj_3R_4() {
Token xsp; Token xsp;
xsp = jj_scanpos; xsp = jj_scanpos;
if (jj_3R_4()) jj_scanpos = xsp; if (jj_3R_5()) jj_scanpos = xsp;
if (jj_scan_token(INFINITY)) return true; if (jj_scan_token(INFINITY)) return true;
return false; return false;
} }
private boolean jj_3_1() { private boolean jj_3_1() {
if (jj_3R_1()) return true; if (jj_3R_2()) return true;
return false;
}
private boolean jj_3R_2() {
if (jj_scan_token(NAN)) return true;
return false;
}
private boolean jj_3R_1() {
Token xsp;
xsp = jj_scanpos;
if (jj_3R_2()) {
jj_scanpos = xsp;
if (jj_3R_3()) return true;
}
return false; return false;
} }
@ -458,10 +482,10 @@ final class JsonParserJavacc implements JsonParserJavaccConstants {
jj_la1_init_1(); jj_la1_init_1();
} }
private static void jj_la1_init_0() { private static void jj_la1_init_0() {
jj_la1_0 = new int[] {0x4000000,0x880307c0,0x8c0307c1,0x31800,0x20000000,0x31800,0x880307c0,0x20000000,0x880307c0,0x30740,0x0,0x20,0x40,0x0,0x300,0x0,0x1800,0x30000,}; jj_la1_0 = new int[] {0x4000000,0x880307c0,0x8c0307c1,0x31800,0x20000000,0x31800,0x20000000,0x880307c0,0x880307c0,0x30740,0x0,0x20,0x40,0x0,0x300,0x0,0x1800,0x30000,};
} }
private static void jj_la1_init_1() { private static void jj_la1_init_1() {
jj_la1_1 = new int[] {0x0,0x2,0x2,0x0,0x0,0x0,0x2,0x0,0x2,0x2,0x4,0x0,0x2,0x2,0x2,0x2,0x0,0x0,}; jj_la1_1 = new int[] {0x0,0x2,0x2,0x0,0x0,0x0,0x0,0x3,0x2,0x2,0x4,0x0,0x2,0x2,0x2,0x2,0x0,0x0,};
} }
final private JJCalls[] jj_2_rtns = new JJCalls[1]; final private JJCalls[] jj_2_rtns = new JJCalls[1];
private boolean jj_rescan = false; private boolean jj_rescan = false;

View File

@ -6,7 +6,6 @@ package com.google.gson;
* Token literal values and constants. * Token literal values and constants.
* Generated by org.javacc.parser.OtherFilesGen#start() * Generated by org.javacc.parser.OtherFilesGen#start()
*/ */
@SuppressWarnings("all")
interface JsonParserJavaccConstants { interface JsonParserJavaccConstants {
/** End of File. */ /** End of File. */

View File

@ -1077,9 +1077,7 @@ protected Token jjFillToken()
beginColumn = input_stream.getBeginColumn(); beginColumn = input_stream.getBeginColumn();
endLine = input_stream.getEndLine(); endLine = input_stream.getEndLine();
endColumn = input_stream.getEndColumn(); endColumn = input_stream.getEndColumn();
t = Token.newToken(jjmatchedKind); t = Token.newToken(jjmatchedKind, curTokenImage);
t.kind = jjmatchedKind;
t.image = curTokenImage;
t.beginLine = beginLine; t.beginLine = beginLine;
t.endLine = endLine; t.endLine = endLine;

View File

@ -1,4 +1,5 @@
/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */ /* Generated By:JavaCC: Do not edit this line. ParseException.java Version 4.1 */
/* JavaCCOptions:KEEP_LINE_COL=null */
package com.google.gson; package com.google.gson;
/** /**
@ -13,25 +14,25 @@ package com.google.gson;
@SuppressWarnings("all") @SuppressWarnings("all")
final class ParseException extends Exception { final class ParseException extends Exception {
/**
* The version identifier for this Serializable class.
* Increment only if the <i>serialized</i> form of the
* class changes.
*/
private static final long serialVersionUID = 1L;
/** /**
* This constructor is used by the method "generateParseException" * This constructor is used by the method "generateParseException"
* in the generated parser. Calling this constructor generates * in the generated parser. Calling this constructor generates
* a new object of this type with the fields "currentToken", * a new object of this type with the fields "currentToken",
* "expectedTokenSequences", and "tokenImage" set. The boolean * "expectedTokenSequences", and "tokenImage" set.
* flag "specialConstructor" is also set to true to indicate that
* this constructor was used to create this object.
* This constructor calls its super class with the empty string
* to force the "toString" method of parent class "Throwable" to
* print the error message in the form:
* ParseException: <result of getMessage>
*/ */
public ParseException(Token currentTokenVal, public ParseException(Token currentTokenVal,
int[][] expectedTokenSequencesVal, int[][] expectedTokenSequencesVal,
String[] tokenImageVal String[] tokenImageVal
) )
{ {
super(""); super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
specialConstructor = true;
currentToken = currentTokenVal; currentToken = currentTokenVal;
expectedTokenSequences = expectedTokenSequencesVal; expectedTokenSequences = expectedTokenSequencesVal;
tokenImage = tokenImageVal; tokenImage = tokenImageVal;
@ -49,20 +50,13 @@ final class ParseException extends Exception {
public ParseException() { public ParseException() {
super(); super();
specialConstructor = false;
} }
/** Constructor with message. */
public ParseException(String message) { public ParseException(String message) {
super(message); super(message);
specialConstructor = false;
} }
/**
* This variable determines which constructor was used to create
* this object and thereby affects the semantics of the
* "getMessage" method (see below).
*/
protected boolean specialConstructor;
/** /**
* This is the last token that has been consumed successfully. If * This is the last token that has been consumed successfully. If
@ -86,19 +80,16 @@ final class ParseException extends Exception {
public String[] tokenImage; public String[] tokenImage;
/** /**
* This method has the standard behavior when this object has been * It uses "currentToken" and "expectedTokenSequences" to generate a parse
* created using the standard constructors. Otherwise, it uses
* "currentToken" and "expectedTokenSequences" to generate a parse
* error message and returns it. If this object has been created * error message and returns it. If this object has been created
* due to a parse error, and you do not catch it (it gets thrown * due to a parse error, and you do not catch it (it gets thrown
* from the parser), then this method is called during the printing * from the parser) the correct error message
* of the final stack trace, and hence the correct error message
* gets displayed. * gets displayed.
*/ */
public String getMessage() { private static String initialise(Token currentToken,
if (!specialConstructor) { int[][] expectedTokenSequences,
return super.getMessage(); String[] tokenImage) {
} String eol = System.getProperty("line.separator", "\n");
StringBuffer expected = new StringBuffer(); StringBuffer expected = new StringBuffer();
int maxSize = 0; int maxSize = 0;
for (int i = 0; i < expectedTokenSequences.length; i++) { for (int i = 0; i < expectedTokenSequences.length; i++) {
@ -106,7 +97,7 @@ final class ParseException extends Exception {
maxSize = expectedTokenSequences[i].length; maxSize = expectedTokenSequences[i].length;
} }
for (int j = 0; j < expectedTokenSequences[i].length; j++) { for (int j = 0; j < expectedTokenSequences[i].length; j++) {
expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" "); expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
} }
if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
expected.append("..."); expected.append("...");
@ -121,7 +112,10 @@ final class ParseException extends Exception {
retval += tokenImage[0]; retval += tokenImage[0];
break; break;
} }
retval += " " + tokenImage[tok.kind];
retval += " \"";
retval += add_escapes(tok.image); retval += add_escapes(tok.image);
retval += " \"";
tok = tok.next; tok = tok.next;
} }
retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
@ -145,7 +139,7 @@ final class ParseException extends Exception {
* when these raw version cannot be used as part of an ASCII * when these raw version cannot be used as part of an ASCII
* string literal. * string literal.
*/ */
protected String add_escapes(String str) { static String add_escapes(String str) {
StringBuffer retval = new StringBuffer(); StringBuffer retval = new StringBuffer();
char ch; char ch;
for (int i = 0; i < str.length(); i++) { for (int i = 0; i < str.length(); i++) {
@ -191,3 +185,4 @@ final class ParseException extends Exception {
} }
} }
/* JavaCC - OriginalChecksum=bf6325585417e7bd5d488795e151433b (do not edit this line) */

View File

@ -1,18 +1,20 @@
/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */ /* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.1 */
/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package com.google.gson; package com.google.gson;
/** /**
* An implementation of interface CharStream, where the stream is assumed to * An implementation of interface CharStream, where the stream is assumed to
* contain only ASCII characters (without unicode processing). * contain only ASCII characters (without unicode processing).
*/ */
@SuppressWarnings("all") @SuppressWarnings("all")
final class SimpleCharStream final class SimpleCharStream
{ {
/** Whether parser is static. */
public static final boolean staticFlag = false; public static final boolean staticFlag = false;
int bufsize; int bufsize;
int available; int available;
int tokenBegin; int tokenBegin;
/** Position in buffer. */
public int bufpos = -1; public int bufpos = -1;
protected int bufline[]; protected int bufline[];
protected int bufcolumn[]; protected int bufcolumn[];
@ -45,8 +47,7 @@ final class SimpleCharStream
if (wrapAround) if (wrapAround)
{ {
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
System.arraycopy(buffer, 0, newbuffer, System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
bufsize - tokenBegin, bufpos);
buffer = newbuffer; buffer = newbuffer;
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
@ -110,8 +111,7 @@ final class SimpleCharStream
int i; int i;
try { try {
if ((i = inputStream.read(buffer, maxNextCharInd, if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
available - maxNextCharInd)) == -1)
{ {
inputStream.close(); inputStream.close();
throw new java.io.IOException(); throw new java.io.IOException();
@ -129,6 +129,7 @@ final class SimpleCharStream
} }
} }
/** Start. */
public char BeginToken() throws java.io.IOException public char BeginToken() throws java.io.IOException
{ {
tokenBegin = -1; tokenBegin = -1;
@ -178,6 +179,7 @@ final class SimpleCharStream
bufcolumn[bufpos] = column; bufcolumn[bufpos] = column;
} }
/** Read a character. */
public char readChar() throws java.io.IOException public char readChar() throws java.io.IOException
{ {
if (inBuf > 0) if (inBuf > 0)
@ -196,7 +198,7 @@ final class SimpleCharStream
char c = buffer[bufpos]; char c = buffer[bufpos];
UpdateLineColumn(c); UpdateLineColumn(c);
return (c); return c;
} }
/** /**
@ -217,22 +219,27 @@ final class SimpleCharStream
return bufline[bufpos]; return bufline[bufpos];
} }
/** Get token end column number. */
public int getEndColumn() { public int getEndColumn() {
return bufcolumn[bufpos]; return bufcolumn[bufpos];
} }
/** Get token end line number. */
public int getEndLine() { public int getEndLine() {
return bufline[bufpos]; return bufline[bufpos];
} }
/** Get token beginning column number. */
public int getBeginColumn() { public int getBeginColumn() {
return bufcolumn[tokenBegin]; return bufcolumn[tokenBegin];
} }
/** Get token beginning line number. */
public int getBeginLine() { public int getBeginLine() {
return bufline[tokenBegin]; return bufline[tokenBegin];
} }
/** Backup a number of characters. */
public void backup(int amount) { public void backup(int amount) {
inBuf += amount; inBuf += amount;
@ -240,6 +247,7 @@ final class SimpleCharStream
bufpos += bufsize; bufpos += bufsize;
} }
/** Constructor. */
public SimpleCharStream(java.io.Reader dstream, int startline, public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn, int buffersize) int startcolumn, int buffersize)
{ {
@ -253,16 +261,20 @@ final class SimpleCharStream
bufcolumn = new int[buffersize]; bufcolumn = new int[buffersize];
} }
/** Constructor. */
public SimpleCharStream(java.io.Reader dstream, int startline, public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn) int startcolumn)
{ {
this(dstream, startline, startcolumn, 4096); this(dstream, startline, startcolumn, 4096);
} }
/** Constructor. */
public SimpleCharStream(java.io.Reader dstream) public SimpleCharStream(java.io.Reader dstream)
{ {
this(dstream, 1, 1, 4096); this(dstream, 1, 1, 4096);
} }
/** Reinitialise. */
public void ReInit(java.io.Reader dstream, int startline, public void ReInit(java.io.Reader dstream, int startline,
int startcolumn, int buffersize) int startcolumn, int buffersize)
{ {
@ -282,81 +294,96 @@ final class SimpleCharStream
bufpos = -1; bufpos = -1;
} }
/** Reinitialise. */
public void ReInit(java.io.Reader dstream, int startline, public void ReInit(java.io.Reader dstream, int startline,
int startcolumn) int startcolumn)
{ {
ReInit(dstream, startline, startcolumn, 4096); ReInit(dstream, startline, startcolumn, 4096);
} }
/** Reinitialise. */
public void ReInit(java.io.Reader dstream) public void ReInit(java.io.Reader dstream)
{ {
ReInit(dstream, 1, 1, 4096); ReInit(dstream, 1, 1, 4096);
} }
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
{ {
this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
} }
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, int startline, public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn, int buffersize) int startcolumn, int buffersize)
{ {
this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
} }
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
int startcolumn) throws java.io.UnsupportedEncodingException int startcolumn) throws java.io.UnsupportedEncodingException
{ {
this(dstream, encoding, startline, startcolumn, 4096); this(dstream, encoding, startline, startcolumn, 4096);
} }
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, int startline, public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn) int startcolumn)
{ {
this(dstream, startline, startcolumn, 4096); this(dstream, startline, startcolumn, 4096);
} }
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
{ {
this(dstream, encoding, 1, 1, 4096); this(dstream, encoding, 1, 1, 4096);
} }
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream) public SimpleCharStream(java.io.InputStream dstream)
{ {
this(dstream, 1, 1, 4096); this(dstream, 1, 1, 4096);
} }
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, String encoding, int startline, public void ReInit(java.io.InputStream dstream, String encoding, int startline,
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
{ {
ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
} }
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, int startline, public void ReInit(java.io.InputStream dstream, int startline,
int startcolumn, int buffersize) int startcolumn, int buffersize)
{ {
ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
} }
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
{ {
ReInit(dstream, encoding, 1, 1, 4096); ReInit(dstream, encoding, 1, 1, 4096);
} }
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream) public void ReInit(java.io.InputStream dstream)
{ {
ReInit(dstream, 1, 1, 4096); ReInit(dstream, 1, 1, 4096);
} }
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, String encoding, int startline, public void ReInit(java.io.InputStream dstream, String encoding, int startline,
int startcolumn) throws java.io.UnsupportedEncodingException int startcolumn) throws java.io.UnsupportedEncodingException
{ {
ReInit(dstream, encoding, startline, startcolumn, 4096); ReInit(dstream, encoding, startline, startcolumn, 4096);
} }
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, int startline, public void ReInit(java.io.InputStream dstream, int startline,
int startcolumn) int startcolumn)
{ {
ReInit(dstream, startline, startcolumn, 4096); ReInit(dstream, startline, startcolumn, 4096);
} }
/** Get token literal value. */
public String GetImage() public String GetImage()
{ {
if (bufpos >= tokenBegin) if (bufpos >= tokenBegin)
@ -366,6 +393,7 @@ final class SimpleCharStream
new String(buffer, 0, bufpos + 1); new String(buffer, 0, bufpos + 1);
} }
/** Get the suffix. */
public char[] GetSuffix(int len) public char[] GetSuffix(int len)
{ {
char[] ret = new char[len]; char[] ret = new char[len];
@ -382,6 +410,7 @@ final class SimpleCharStream
return ret; return ret;
} }
/** Reset buffer when finished. */
public void Done() public void Done()
{ {
buffer = null; buffer = null;
@ -409,8 +438,7 @@ final class SimpleCharStream
int i = 0, j = 0, k = 0; int i = 0, j = 0, k = 0;
int nextColDiff = 0, columnDiff = 0; int nextColDiff = 0, columnDiff = 0;
while (i < len && while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
{ {
bufline[j] = newLine; bufline[j] = newLine;
nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
@ -438,3 +466,4 @@ final class SimpleCharStream
} }
} }
/* JavaCC - OriginalChecksum=351e3d8e62614bff24f1b9ba2fd77764 (do not edit this line) */

View File

@ -1,12 +1,19 @@
/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ /* Generated By:JavaCC: Do not edit this line. Token.java Version 4.1 */
/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package com.google.gson; package com.google.gson;
/** /**
* Describes the input token stream. * Describes the input token stream.
*/ */
@SuppressWarnings("all") @SuppressWarnings("all")
final class Token { final class Token implements java.io.Serializable {
/**
* The version identifier for this Serializable class.
* Increment only if the <i>serialized</i> form of the
* class changes.
*/
private static final long serialVersionUID = 1L;
/** /**
* An integer that describes the kind of this token. This numbering * An integer that describes the kind of this token. This numbering
@ -15,12 +22,14 @@ final class Token {
*/ */
public int kind; public int kind;
/** /** The line number of the first character of this Token. */
* beginLine and beginColumn describe the position of the first character public int beginLine;
* of this token; endLine and endColumn describe the position of the /** The column number of the first character of this Token. */
* last character of this token. public int beginColumn;
*/ /** The line number of the last character of this Token. */
public int beginLine, beginColumn, endLine, endColumn; public int endLine;
/** The column number of the last character of this Token. */
public int endColumn;
/** /**
* The string image of the token. * The string image of the token.
@ -51,6 +60,40 @@ final class Token {
*/ */
public Token specialToken; public Token specialToken;
/**
* An optional attribute value of the Token.
* Tokens which are not used as syntactic sugar will often contain
* meaningful values that will be used later on by the compiler or
* interpreter. This attribute value is often different from the image.
* Any subclass of Token that actually wants to return a non-null value can
* override this method as appropriate.
*/
public Object getValue() {
return null;
}
/**
* No-argument constructor
*/
public Token() {}
/**
* Constructs a new token for the specified Image.
*/
public Token(int kind)
{
this(kind, null);
}
/**
* Constructs a new token for the specified Image and Kind.
*/
public Token(int kind, String image)
{
this.kind = kind;
this.image = image;
}
/** /**
* Returns the image. * Returns the image.
*/ */
@ -64,19 +107,25 @@ final class Token {
* can create and return subclass objects based on the value of ofKind. * can create and return subclass objects based on the value of ofKind.
* Simply add the cases to the switch for all those special cases. * Simply add the cases to the switch for all those special cases.
* For example, if you have a subclass of Token called IDToken that * For example, if you have a subclass of Token called IDToken that
* you want to create if ofKind is ID, simlpy add something like : * you want to create if ofKind is ID, simply add something like :
* *
* case MyParserConstants.ID : return new IDToken(); * case MyParserConstants.ID : return new IDToken(ofKind, image);
* *
* to the following switch statement. Then you can cast matchedToken * to the following switch statement. Then you can cast matchedToken
* variable to the appropriate type and use it in your lexical actions. * variable to the appropriate type and use sit in your lexical actions.
*/ */
public static final Token newToken(int ofKind) public static Token newToken(int ofKind, String image)
{ {
switch(ofKind) switch(ofKind)
{ {
default : return new Token(); default : return new Token(ofKind, image);
} }
} }
public static Token newToken(int ofKind)
{
return newToken(ofKind, null);
}
} }
/* JavaCC - OriginalChecksum=f683548fa415467062989dfb10c566e6 (do not edit this line) */

View File

@ -1,20 +1,30 @@
/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ /* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 4.1 */
/* JavaCCOptions: */
package com.google.gson; package com.google.gson;
/** Token Manager Error. */
@SuppressWarnings("all") @SuppressWarnings("all")
final class TokenMgrError extends Error final class TokenMgrError extends Error
{ {
/**
* The version identifier for this Serializable class.
* Increment only if the <i>serialized</i> form of the
* class changes.
*/
private static final long serialVersionUID = 1L;
/* /*
* Ordinals for various reasons why an Error of this type can be thrown. * Ordinals for various reasons why an Error of this type can be thrown.
*/ */
/** /**
* Lexical error occured. * Lexical error occurred.
*/ */
static final int LEXICAL_ERROR = 0; static final int LEXICAL_ERROR = 0;
/** /**
* An attempt wass made to create a second instance of a static token manager. * An attempt was made to create a second instance of a static token manager.
*/ */
static final int STATIC_LEXER_ERROR = 1; static final int STATIC_LEXER_ERROR = 1;
@ -35,7 +45,7 @@ final class TokenMgrError extends Error
int errorCode; int errorCode;
/** /**
* Replaces unprintable characters by their espaced (or unicode escaped) * Replaces unprintable characters by their escaped (or unicode escaped)
* equivalents in the given string * equivalents in the given string
*/ */
protected static final String addEscapes(String str) { protected static final String addEscapes(String str) {
@ -87,11 +97,11 @@ final class TokenMgrError extends Error
* Returns a detailed message for the Error when it is thrown by the * Returns a detailed message for the Error when it is thrown by the
* token manager to indicate a lexical error. * token manager to indicate a lexical error.
* Parameters : * Parameters :
* EOFSeen : indicates if EOF caused the lexicl error * EOFSeen : indicates if EOF caused the lexical error
* curLexState : lexical state in which this error occured * curLexState : lexical state in which this error occurred
* errorLine : line number when the error occured * errorLine : line number when the error occurred
* errorColumn : column number when the error occured * errorColumn : column number when the error occurred
* errorAfter : prefix that was seen before this error occured * errorAfter : prefix that was seen before this error occurred
* curchar : the offending character * curchar : the offending character
* Note: You can customize the lexical error message by modifying this method. * Note: You can customize the lexical error message by modifying this method.
*/ */
@ -120,15 +130,19 @@ final class TokenMgrError extends Error
* Constructors of various flavors follow. * Constructors of various flavors follow.
*/ */
/** No arg constructor. */
public TokenMgrError() { public TokenMgrError() {
} }
/** Constructor with message and reason. */
public TokenMgrError(String message, int reason) { public TokenMgrError(String message, int reason) {
super(message); super(message);
errorCode = reason; errorCode = reason;
} }
/** Full Constructor. */
public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
} }
} }
/* JavaCC - OriginalChecksum=f9c23e3fca926dbaf51c810110262be0 (do not edit this line) */

View File

@ -116,20 +116,29 @@ private JsonPrimitive JsonMemberName() :
private JsonArray JsonArray() : private JsonArray JsonArray() :
{ JsonArray array = new JsonArray(); } { JsonArray array = new JsonArray(); }
{ {
"[" [ Elements(array) ] "]" "[" (
{ array=JsonArrayEmpty(array) {return array;} |
array.reverse(); JsonArrayElement(array) (JsonArrayNextElement(array))* "]" {return array; } )
return array;
}
} }
private void Elements(JsonArray array) : private JsonArray JsonArrayEmpty(JsonArray array) :
{ }
{ {
JsonElement element; "]" { return array; }
} }
private JsonArray JsonArrayElement(JsonArray array) :
{ JsonElement element = null; }
{ {
element=JsonValue() [ "," Elements(array) ] element=JsonValue() {array.add(element);}
{ array.add(element); } { return array; }
}
private JsonArray JsonArrayNextElement(JsonArray array) :
{ JsonElement element = null; }
{
"," element=JsonValue() {array.add(element);}
{ return array; }
} }
private JsonElement JsonValue() : private JsonElement JsonValue() :

View File

@ -18,6 +18,7 @@ package com.google.gson.functional;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;
import com.google.gson.common.MoreAsserts; import com.google.gson.common.MoreAsserts;
import com.google.gson.common.TestTypes.BagOfPrimitives; import com.google.gson.common.TestTypes.BagOfPrimitives;
import com.google.gson.common.TestTypes.CrazyLongTypeAdapter; import com.google.gson.common.TestTypes.CrazyLongTypeAdapter;
@ -55,6 +56,15 @@ public class ArrayTest extends TestCase {
MoreAsserts.assertEquals(expected, actual); MoreAsserts.assertEquals(expected, actual);
} }
public void testInvalidArrayDeserialization() {
String json = "[1, 2 3, 4, 5]";
try {
gson.fromJson(json, int[].class);
fail("Gson should not deserialize array elements with missing ,");
} catch (JsonParseException expected) {
}
}
public void testEmptyArraySerialization() { public void testEmptyArraySerialization() {
int[] target = {}; int[] target = {};
assertEquals("[]", gson.toJson(target)); assertEquals("[]", gson.toJson(target));
@ -66,7 +76,10 @@ public class ArrayTest extends TestCase {
Integer[] actualObject2 = gson.fromJson("[]", Integer[].class); Integer[] actualObject2 = gson.fromJson("[]", Integer[].class);
assertTrue(actualObject2.length == 0); assertTrue(actualObject2.length == 0);
}
actualObject = gson.fromJson("[ ]", int[].class);
assertTrue(actualObject.length == 0);
}
public void testNullsInArraySerialization() { public void testNullsInArraySerialization() {
String[] array = {"foo", null, "bar"}; String[] array = {"foo", null, "bar"};

View File

@ -117,16 +117,18 @@ public class ObjectTest extends TestCase {
} }
public void testClassWithTransientFieldsSerialization() throws Exception { public void testClassWithTransientFieldsSerialization() throws Exception {
ClassWithTransientFields target = new ClassWithTransientFields(1L); ClassWithTransientFields<Long> target = new ClassWithTransientFields<Long>(1L);
assertEquals(target.getExpectedJson(), gson.toJson(target)); assertEquals(target.getExpectedJson(), gson.toJson(target));
} }
@SuppressWarnings("unchecked")
public void testClassWithTransientFieldsDeserialization() throws Exception { public void testClassWithTransientFieldsDeserialization() throws Exception {
String json = "{\"longValue\":[1]}"; String json = "{\"longValue\":[1]}";
ClassWithTransientFields target = gson.fromJson(json, ClassWithTransientFields.class); ClassWithTransientFields target = gson.fromJson(json, ClassWithTransientFields.class);
assertEquals(json, target.getExpectedJson()); assertEquals(json, target.getExpectedJson());
} }
@SuppressWarnings("unchecked")
public void testClassWithTransientFieldsDeserializationTransientFieldsPassedInJsonAreIgnored() public void testClassWithTransientFieldsDeserializationTransientFieldsPassedInJsonAreIgnored()
throws Exception { throws Exception {
String json = "{\"transientLongValue\":1,\"longValue\":[1]}"; String json = "{\"transientLongValue\":1,\"longValue\":[1]}";

View File

@ -148,9 +148,9 @@ public class PerformanceTest extends TestCase {
/** /**
* Created in response to http://code.google.com/p/google-gson/issues/detail?id=96 * Created in response to http://code.google.com/p/google-gson/issues/detail?id=96
*/ */
// Last I tested, Gson was able to deserialize a byte array of 80KB // Last I tested, Gson was able to deserialize a byte array of 11MB
public void disable_testByteArrayDeserialization() { public void disable_testByteArrayDeserialization() {
for (int numElements = 32768; true; numElements += 4096) { for (int numElements = 10639296; true; numElements += 16384) {
StringBuilder sb = new StringBuilder(numElements*2); StringBuilder sb = new StringBuilder(numElements*2);
sb.append("["); sb.append("[");
boolean first = true; boolean first = true;