From bdb2b910a5ebd92471de13d7e90d54408f6b093e Mon Sep 17 00:00:00 2001 From: Florian Frank Date: Wed, 27 Jul 2011 02:14:54 +0200 Subject: started quirks mode for generator --- java/src/json/ext/Generator.java | 6 +-- java/src/json/ext/GeneratorMethods.java | 4 +- java/src/json/ext/GeneratorService.java | 2 +- java/src/json/ext/GeneratorState.java | 46 +++++++++++++++----- java/src/json/ext/OptionsReader.java | 2 +- java/src/json/ext/Parser.java | 74 ++++++++++++++++----------------- java/src/json/ext/Parser.rl | 30 ++++++------- java/src/json/ext/ParserService.java | 2 +- java/src/json/ext/Utils.java | 2 +- 9 files changed, 96 insertions(+), 72 deletions(-) (limited to 'java/src') diff --git a/java/src/json/ext/Generator.java b/java/src/json/ext/Generator.java index fbc394f..78dc078 100644 --- a/java/src/json/ext/Generator.java +++ b/java/src/json/ext/Generator.java @@ -1,6 +1,6 @@ /* * This code is copyrighted work by Daniel Luz . - * + * * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files * for details. */ @@ -85,11 +85,11 @@ public final class Generator { /** * A class that concentrates all the information that is shared by * generators working on a single session. - * + * *

A session is defined as the process of serializing a single root * object; any handler directly called by container handlers (arrays and * hashes/objects) shares this object with its caller. - * + * *

Note that anything called indirectly (via {@link GENERIC_HANDLER}) * won't be part of the session. */ diff --git a/java/src/json/ext/GeneratorMethods.java b/java/src/json/ext/GeneratorMethods.java index 356f2d0..637b579 100644 --- a/java/src/json/ext/GeneratorMethods.java +++ b/java/src/json/ext/GeneratorMethods.java @@ -1,6 +1,6 @@ /* * This code is copyrighted work by Daniel Luz . - * + * * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files * for details. */ @@ -25,7 +25,7 @@ import org.jruby.util.ByteList; /** * A class that populates the * Json::Ext::Generator::GeneratorMethods module. - * + * * @author mernen */ class GeneratorMethods { diff --git a/java/src/json/ext/GeneratorService.java b/java/src/json/ext/GeneratorService.java index 2f3b07e..ed33639 100644 --- a/java/src/json/ext/GeneratorService.java +++ b/java/src/json/ext/GeneratorService.java @@ -1,6 +1,6 @@ /* * This code is copyrighted work by Daniel Luz . - * + * * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files * for details. */ diff --git a/java/src/json/ext/GeneratorState.java b/java/src/json/ext/GeneratorState.java index f04eda2..a53ff12 100644 --- a/java/src/json/ext/GeneratorState.java +++ b/java/src/json/ext/GeneratorState.java @@ -1,6 +1,6 @@ /* * This code is copyrighted work by Daniel Luz . - * + * * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files * for details. */ @@ -24,10 +24,10 @@ import org.jruby.util.ByteList; /** * The JSON::Ext::Generator::State class. - * + * *

This class is used to create State instances, that are use to hold data * while generating a JSON text from a a Ruby data structure. - * + * * @author mernen */ public class GeneratorState extends RubyObject { @@ -76,6 +76,11 @@ public class GeneratorState extends RubyObject { */ private boolean asciiOnly = DEFAULT_ASCII_ONLY; static final boolean DEFAULT_ASCII_ONLY = false; + /** + * XXX + */ + private boolean quirksMode = DEFAULT_QUIRKS_MODE; + static final boolean DEFAULT_QUIRKS_MODE = false; /** * The current depth (inside a #to_json call) @@ -94,7 +99,7 @@ public class GeneratorState extends RubyObject { /** * State.from_state(opts) - * + * *

Creates a State object from opts, which ought to be * {@link RubyHash Hash} to create a new State instance * configured by opts, something else to create an @@ -136,11 +141,11 @@ public class GeneratorState extends RubyObject { /** * State#initialize(opts = {}) - * + * * Instantiates a new State object, configured by opts. - * + * * opts can have the following keys: - * + * *

*
:indent *
a {@link RubyString String} used to indent levels (default: "") @@ -151,7 +156,7 @@ public class GeneratorState extends RubyObject { *
a String that is put before a ":" pair delimiter * (default: "") *
:object_nl - *
a String that is put at the end of a JSON object (default: "") + *
a String that is put at the end of a JSON object (default: "") *
:array_nl *
a String that is put at the end of a JSON array (default: "") *
:allow_nan @@ -181,6 +186,7 @@ public class GeneratorState extends RubyObject { this.maxNesting = orig.maxNesting; this.allowNaN = orig.allowNaN; this.asciiOnly = orig.asciiOnly; + this.quirksMode = orig.quirksMode; this.depth = orig.depth; return this; } @@ -191,7 +197,7 @@ public class GeneratorState extends RubyObject { @JRubyMethod public IRubyObject generate(ThreadContext context, IRubyObject obj) { RubyString result = Generator.generateJson(context, obj, this); - if (!objectOrArrayLiteral(result)) { + if (!quirksMode && !objectOrArrayLiteral(result)) { throw Utils.newException(context, Utils.M_GENERATOR_ERROR, "only generation of JSON objects or arrays allowed"); } @@ -364,6 +370,22 @@ public class GeneratorState extends RubyObject { return context.getRuntime().newBoolean(asciiOnly); } + @JRubyMethod(name="quirks_mode") + public RubyBoolean quirks_mode_get(ThreadContext context) { + return context.getRuntime().newBoolean(quirksMode); + } + + @JRubyMethod(name="quirks_mode=") + public IRubyObject quirks_mode_set(IRubyObject quirks_mode) { + quirksMode = quirks_mode.isTrue(); + return quirks_mode.getRuntime().newBoolean(quirksMode); + } + + @JRubyMethod(name="quirks_mode?") + public RubyBoolean quirks_mode_p(ThreadContext context) { + return context.getRuntime().newBoolean(quirksMode); + } + public int getDepth() { return depth; } @@ -390,7 +412,7 @@ public class GeneratorState extends RubyObject { /** * State#configure(opts) - * + * *

Configures this State instance with the {@link RubyHash Hash} * opts, and returns itself. * @param vOpts The options hash @@ -418,6 +440,7 @@ public class GeneratorState extends RubyObject { maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING); allowNaN = opts.getBool("allow_nan", DEFAULT_ALLOW_NAN); asciiOnly = opts.getBool("ascii_only", DEFAULT_ASCII_ONLY); + quirksMode = opts.getBool("quirks_mode", DEFAULT_QUIRKS_MODE); depth = opts.getInt("depth", 0); @@ -426,7 +449,7 @@ public class GeneratorState extends RubyObject { /** * State#to_h() - * + * *

Returns the configuration instance variables as a hash, that can be * passed to the configure method. * @return @@ -443,6 +466,7 @@ public class GeneratorState extends RubyObject { result.op_aset(context, runtime.newSymbol("array_nl"), array_nl_get(context)); result.op_aset(context, runtime.newSymbol("allow_nan"), allow_nan_p(context)); result.op_aset(context, runtime.newSymbol("ascii_only"), ascii_only_p(context)); + result.op_aset(context, runtime.newSymbol("quirks_mode"), quirks_mode_p(context)); result.op_aset(context, runtime.newSymbol("max_nesting"), max_nesting_get(context)); result.op_aset(context, runtime.newSymbol("depth"), depth_get(context)); return result; diff --git a/java/src/json/ext/OptionsReader.java b/java/src/json/ext/OptionsReader.java index c9c9c94..a0b76b1 100644 --- a/java/src/json/ext/OptionsReader.java +++ b/java/src/json/ext/OptionsReader.java @@ -1,6 +1,6 @@ /* * This code is copyrighted work by Daniel Luz . - * + * * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files * for details. */ diff --git a/java/src/json/ext/Parser.java b/java/src/json/ext/Parser.java index cea42d4..6f9b30a 100644 --- a/java/src/json/ext/Parser.java +++ b/java/src/json/ext/Parser.java @@ -2,7 +2,7 @@ // line 1 "Parser.rl" /* * This code is copyrighted work by Daniel Luz . - * + * * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files * for details. */ @@ -31,16 +31,16 @@ import org.jruby.util.ByteList; /** * The JSON::Ext::Parser class. - * + * *

This is the JSON parser implemented as a Java class. To use it as the * standard parser, set *

JSON.parser = JSON::Ext::Parser
* This is performed for you when you include "json/ext". - * + * *

This class does not perform the actual parsing, just acts as an interface * to Ruby code. When the {@link #parse()} method is invoked, a * Parser.ParserSession object is instantiated, which handles the process. - * + * * @author mernen */ public class Parser extends RubyObject { @@ -71,7 +71,7 @@ public class Parser extends RubyObject { /** * Multiple-value return for internal parser methods. - * + * *

All the parseStuff methods return instances of * ParserResult when successful, or null when * there's a problem with the input data. @@ -100,18 +100,18 @@ public class Parser extends RubyObject { /** * Parser.new(source, opts = {}) - * + * *

Creates a new JSON::Ext::Parser instance for the string * source. * It will be configured by the opts Hash. * opts can have the following keys: - * + * *

*
:max_nesting *
The maximum depth of nesting allowed in the parsed data * structures. Disable depth checking with :max_nesting => false|nil|0, * it defaults to 19. - * + * *
:allow_nan *
If set to true, allow NaN, * Infinity and -Infinity in defiance of RFC 4627 @@ -120,15 +120,15 @@ public class Parser extends RubyObject { *
:symbolize_names *
If set to true, returns symbols for the names (keys) in * a JSON object. Otherwise strings are returned, which is also the default. - * + * *
:create_additions *
If set to false, the Parser doesn't create additions * even if a matchin class and create_id was found. This option * defaults to true. - * + * *
:object_class *
Defaults to Hash. - * + * *
:array_class *
Defaults to Array. *
@@ -229,7 +229,7 @@ public class Parser extends RubyObject { /** * Parser#parse() - * + * *

Parses the current JSON text source and returns the * complete data structure as a result. */ @@ -240,7 +240,7 @@ public class Parser extends RubyObject { /** * Parser#source() - * + * *

Returns a copy of the current source string, that was * used to construct this Parser. */ @@ -268,7 +268,7 @@ public class Parser extends RubyObject { /** * A string parsing session. - * + * *

Once a ParserSession is instantiated, the source string should not * change until the parsing is complete. The ParserSession object assumes * the source {@link RubyString} is still associated to its original @@ -308,11 +308,11 @@ public class Parser extends RubyObject { return context.getRuntime(); } - + // line 335 "Parser.rl" - + // line 317 "Parser.java" private static byte[] init__JSON_value_actions_0() { @@ -434,14 +434,14 @@ static final int JSON_value_en_main = 1; int cs = EVIL; IRubyObject result = null; - + // line 439 "Parser.java" { cs = JSON_value_start; } // line 448 "Parser.rl" - + // line 446 "Parser.java" { int _klen; @@ -675,7 +675,7 @@ case 5: } } - + // line 680 "Parser.java" private static byte[] init__JSON_integer_actions_0() { @@ -781,7 +781,7 @@ static final int JSON_integer_en_main = 1; ParserResult parseInteger(int p, int pe) { int cs = EVIL; - + // line 786 "Parser.java" { cs = JSON_integer_start; @@ -789,7 +789,7 @@ static final int JSON_integer_en_main = 1; // line 474 "Parser.rl" int memo = p; - + // line 794 "Parser.java" { int _klen; @@ -911,7 +911,7 @@ case 5: return new ParserResult(number, p + 1); } - + // line 916 "Parser.java" private static byte[] init__JSON_float_actions_0() { @@ -1020,7 +1020,7 @@ static final int JSON_float_en_main = 1; ParserResult parseFloat(int p, int pe) { int cs = EVIL; - + // line 1025 "Parser.java" { cs = JSON_float_start; @@ -1028,7 +1028,7 @@ static final int JSON_float_en_main = 1; // line 510 "Parser.rl" int memo = p; - + // line 1033 "Parser.java" { int _klen; @@ -1150,7 +1150,7 @@ case 5: return new ParserResult(number, p + 1); } - + // line 1155 "Parser.java" private static byte[] init__JSON_string_actions_0() { @@ -1260,7 +1260,7 @@ static final int JSON_string_en_main = 1; int cs = EVIL; IRubyObject result = null; - + // line 1265 "Parser.java" { cs = JSON_string_start; @@ -1268,7 +1268,7 @@ static final int JSON_string_en_main = 1; // line 563 "Parser.rl" int memo = p; - + // line 1273 "Parser.java" { int _klen; @@ -1408,7 +1408,7 @@ case 5: } }); } catch (JumpException e) { } - if (memoArray[1] != null) { + if (memoArray[1] != null) { RubyClass klass = (RubyClass) memoArray[1]; if (klass.respondsTo("json_creatable?") && klass.callMethod(context, "json_creatable?").isTrue()) { @@ -1425,7 +1425,7 @@ case 5: } } - + // line 1430 "Parser.java" private static byte[] init__JSON_array_actions_0() { @@ -1556,14 +1556,14 @@ static final int JSON_array_en_main = 1; (RubyArray)parser.arrayClass.newInstance(context, IRubyObject.NULL_ARRAY, Block.NULL_BLOCK); - + // line 1561 "Parser.java" { cs = JSON_array_start; } // line 652 "Parser.rl" - + // line 1568 "Parser.java" { int _klen; @@ -1697,7 +1697,7 @@ case 5: } } - + // line 1702 "Parser.java" private static byte[] init__JSON_object_actions_0() { @@ -1839,14 +1839,14 @@ static final int JSON_object_en_main = 1; (RubyHash)parser.objectClass.newInstance(context, IRubyObject.NULL_ARRAY, Block.NULL_BLOCK); - + // line 1844 "Parser.java" { cs = JSON_object_start; } // line 731 "Parser.rl" - + // line 1851 "Parser.java" { int _klen; @@ -2016,7 +2016,7 @@ case 5: return new ParserResult(returnedResult, p + 1); } - + // line 2021 "Parser.java" private static byte[] init__JSON_actions_0() { @@ -2129,7 +2129,7 @@ static final int JSON_en_main = 1; int p, pe; IRubyObject result = null; - + // line 2134 "Parser.java" { cs = JSON_start; @@ -2138,7 +2138,7 @@ static final int JSON_en_main = 1; // line 798 "Parser.rl" p = byteList.begin(); pe = p + byteList.length(); - + // line 2143 "Parser.java" { int _klen; diff --git a/java/src/json/ext/Parser.rl b/java/src/json/ext/Parser.rl index 779d3f3..6b99574 100644 --- a/java/src/json/ext/Parser.rl +++ b/java/src/json/ext/Parser.rl @@ -1,6 +1,6 @@ /* * This code is copyrighted work by Daniel Luz . - * + * * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files * for details. */ @@ -29,16 +29,16 @@ import org.jruby.util.ByteList; /** * The JSON::Ext::Parser class. - * + * *

This is the JSON parser implemented as a Java class. To use it as the * standard parser, set *

JSON.parser = JSON::Ext::Parser
* This is performed for you when you include "json/ext". - * + * *

This class does not perform the actual parsing, just acts as an interface * to Ruby code. When the {@link #parse()} method is invoked, a * Parser.ParserSession object is instantiated, which handles the process. - * + * * @author mernen */ public class Parser extends RubyObject { @@ -69,7 +69,7 @@ public class Parser extends RubyObject { /** * Multiple-value return for internal parser methods. - * + * *

All the parseStuff methods return instances of * ParserResult when successful, or null when * there's a problem with the input data. @@ -98,18 +98,18 @@ public class Parser extends RubyObject { /** * Parser.new(source, opts = {}) - * + * *

Creates a new JSON::Ext::Parser instance for the string * source. * It will be configured by the opts Hash. * opts can have the following keys: - * + * *

*
:max_nesting *
The maximum depth of nesting allowed in the parsed data * structures. Disable depth checking with :max_nesting => false|nil|0, * it defaults to 19. - * + * *
:allow_nan *
If set to true, allow NaN, * Infinity and -Infinity in defiance of RFC 4627 @@ -118,15 +118,15 @@ public class Parser extends RubyObject { *
:symbolize_names *
If set to true, returns symbols for the names (keys) in * a JSON object. Otherwise strings are returned, which is also the default. - * + * *
:create_additions *
If set to false, the Parser doesn't create additions * even if a matchin class and create_id was found. This option * defaults to true. - * + * *
:object_class *
Defaults to Hash. - * + * *
:array_class *
Defaults to Array. *
@@ -227,7 +227,7 @@ public class Parser extends RubyObject { /** * Parser#parse() - * + * *

Parses the current JSON text source and returns the * complete data structure as a result. */ @@ -238,7 +238,7 @@ public class Parser extends RubyObject { /** * Parser#source() - * + * *

Returns a copy of the current source string, that was * used to construct this Parser. */ @@ -266,7 +266,7 @@ public class Parser extends RubyObject { /** * A string parsing session. - * + * *

Once a ParserSession is instantiated, the source string should not * change until the parsing is complete. The ParserSession object assumes * the source {@link RubyString} is still associated to its original @@ -578,7 +578,7 @@ public class Parser extends RubyObject { } }); } catch (JumpException e) { } - if (memoArray[1] != null) { + if (memoArray[1] != null) { RubyClass klass = (RubyClass) memoArray[1]; if (klass.respondsTo("json_creatable?") && klass.callMethod(context, "json_creatable?").isTrue()) { diff --git a/java/src/json/ext/ParserService.java b/java/src/json/ext/ParserService.java index f2ecae1..dde8834 100644 --- a/java/src/json/ext/ParserService.java +++ b/java/src/json/ext/ParserService.java @@ -1,6 +1,6 @@ /* * This code is copyrighted work by Daniel Luz . - * + * * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files * for details. */ diff --git a/java/src/json/ext/Utils.java b/java/src/json/ext/Utils.java index f52ac8d..44d6a55 100644 --- a/java/src/json/ext/Utils.java +++ b/java/src/json/ext/Utils.java @@ -1,6 +1,6 @@ /* * This code is copyrighted work by Daniel Luz . - * + * * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files * for details. */ -- cgit v1.2.1 From 9d0b1ca629f6f5bc558a4b3f887f0f8cf154fe78 Mon Sep 17 00:00:00 2001 From: Florian Frank Date: Wed, 27 Jul 2011 02:46:10 +0200 Subject: Implement quirks_mode This allows parsing of primitive values --- java/src/json/ext/GeneratorState.java | 7 +- java/src/json/ext/Parser.java | 457 +++++++++++++++++++++++++++------- java/src/json/ext/Parser.rl | 93 +++++-- 3 files changed, 448 insertions(+), 109 deletions(-) (limited to 'java/src') diff --git a/java/src/json/ext/GeneratorState.java b/java/src/json/ext/GeneratorState.java index f04eda2..6ea269a 100644 --- a/java/src/json/ext/GeneratorState.java +++ b/java/src/json/ext/GeneratorState.java @@ -72,7 +72,8 @@ public class GeneratorState extends RubyObject { private boolean allowNaN = DEFAULT_ALLOW_NAN; static final boolean DEFAULT_ALLOW_NAN = false; /** - * XXX + * If set to true all JSON documents generated do not contain + * any other characters than ASCII characters. */ private boolean asciiOnly = DEFAULT_ASCII_ONLY; static final boolean DEFAULT_ASCII_ONLY = false; @@ -186,7 +187,9 @@ public class GeneratorState extends RubyObject { } /** - * XXX + * Generates a valid JSON document from object obj and returns + * the result. If no valid JSON document can be created this method raises + * a GeneratorError exception. */ @JRubyMethod public IRubyObject generate(ThreadContext context, IRubyObject obj) { diff --git a/java/src/json/ext/Parser.java b/java/src/json/ext/Parser.java index cea42d4..84a36ac 100644 --- a/java/src/json/ext/Parser.java +++ b/java/src/json/ext/Parser.java @@ -51,6 +51,7 @@ public class Parser extends RubyObject { private int maxNesting; private boolean allowNaN; private boolean symbolizeNames; + private boolean quirksMode; private RubyClass objectClass; private RubyClass arrayClass; private RubyHash match_string; @@ -120,6 +121,10 @@ public class Parser extends RubyObject { *

:symbolize_names *
If set to true, returns symbols for the names (keys) in * a JSON object. Otherwise strings are returned, which is also the default. + * + *
:quirks_mode? + *
If set to true, if the parse is in quirks_mode, false + * otherwise. * *
:create_additions *
If set to false, the Parser doesn't create additions @@ -148,19 +153,21 @@ public class Parser extends RubyObject { if (this.vSource != null) { throw runtime.newTypeError("already initialized instance"); } - RubyString source = convertEncoding(context, args[0].convertToString()); OptionsReader opts = new OptionsReader(context, args.length > 1 ? args[1] : null); this.maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING); this.allowNaN = opts.getBool("allow_nan", false); this.symbolizeNames = opts.getBool("symbolize_names", false); + this.quirksMode = opts.getBool("quirks_mode", false); this.createId = opts.getString("create_id", getCreateId(context)); this.createAdditions = opts.getBool("create_additions", true); this.objectClass = opts.getClass("object_class", runtime.getHash()); this.arrayClass = opts.getClass("array_class", runtime.getArray()); this.match_string = opts.getHash("match_string"); - this.vSource = source; + this.vSource = args[0].convertToString(); + if (!quirksMode) this.vSource = convertEncoding(context, vSource); + return this; } @@ -249,6 +256,17 @@ public class Parser extends RubyObject { return checkAndGetSource().dup(); } + /** + * Parser#quirks_mode?() + * + *

If set to true, if the parse is in quirks_mode, false + * otherwise. + */ + @JRubyMethod(name = "quirks_mode?") + public IRubyObject quirks_mode_p(ThreadContext context) { + return context.getRuntime().newBoolean(quirksMode); + } + public RubyString checkAndGetSource() { if (vSource != null) { return vSource; @@ -309,11 +327,11 @@ public class Parser extends RubyObject { } -// line 335 "Parser.rl" +// line 353 "Parser.rl" -// line 317 "Parser.java" +// line 335 "Parser.java" private static byte[] init__JSON_value_actions_0() { return new byte [] { @@ -427,7 +445,7 @@ static final int JSON_value_error = 0; static final int JSON_value_en_main = 1; -// line 441 "Parser.rl" +// line 459 "Parser.rl" ParserResult parseValue(int p, int pe) { @@ -435,14 +453,14 @@ static final int JSON_value_en_main = 1; IRubyObject result = null; -// line 439 "Parser.java" +// line 457 "Parser.java" { cs = JSON_value_start; } -// line 448 "Parser.rl" +// line 466 "Parser.rl" -// line 446 "Parser.java" +// line 464 "Parser.java" { int _klen; int _trans = 0; @@ -468,13 +486,13 @@ case 1: while ( _nacts-- > 0 ) { switch ( _JSON_value_actions[_acts++] ) { case 9: -// line 426 "Parser.rl" +// line 444 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 478 "Parser.java" +// line 496 "Parser.java" } } @@ -537,25 +555,25 @@ case 1: switch ( _JSON_value_actions[_acts++] ) { case 0: -// line 343 "Parser.rl" +// line 361 "Parser.rl" { result = getRuntime().getNil(); } break; case 1: -// line 346 "Parser.rl" +// line 364 "Parser.rl" { result = getRuntime().getFalse(); } break; case 2: -// line 349 "Parser.rl" +// line 367 "Parser.rl" { result = getRuntime().getTrue(); } break; case 3: -// line 352 "Parser.rl" +// line 370 "Parser.rl" { if (parser.allowNaN) { result = getConstant(CONST_NAN); @@ -565,7 +583,7 @@ case 1: } break; case 4: -// line 359 "Parser.rl" +// line 377 "Parser.rl" { if (parser.allowNaN) { result = getConstant(CONST_INFINITY); @@ -575,9 +593,9 @@ case 1: } break; case 5: -// line 366 "Parser.rl" +// line 384 "Parser.rl" { - if (pe > p + 9 && + if (pe > p + 9 - (parser.quirksMode ? 1 : 0) && absSubSequence(p, p + 9).toString().equals(JSON_MINUS_INFINITY)) { if (parser.allowNaN) { @@ -604,7 +622,7 @@ case 1: } break; case 6: -// line 392 "Parser.rl" +// line 410 "Parser.rl" { ParserResult res = parseString(p, pe); if (res == null) { @@ -617,7 +635,7 @@ case 1: } break; case 7: -// line 402 "Parser.rl" +// line 420 "Parser.rl" { currentNesting++; ParserResult res = parseArray(p, pe); @@ -632,7 +650,7 @@ case 1: } break; case 8: -// line 414 "Parser.rl" +// line 432 "Parser.rl" { currentNesting++; ParserResult res = parseObject(p, pe); @@ -646,7 +664,7 @@ case 1: } } break; -// line 650 "Parser.java" +// line 668 "Parser.java" } } } @@ -666,7 +684,7 @@ case 5: break; } } -// line 449 "Parser.rl" +// line 467 "Parser.rl" if (cs >= JSON_value_first_final && result != null) { return new ParserResult(result, p); @@ -676,7 +694,7 @@ case 5: } -// line 680 "Parser.java" +// line 698 "Parser.java" private static byte[] init__JSON_integer_actions_0() { return new byte [] { @@ -690,7 +708,7 @@ private static final byte _JSON_integer_actions[] = init__JSON_integer_actions_0 private static byte[] init__JSON_integer_key_offsets_0() { return new byte [] { - 0, 0, 4, 7, 9, 11 + 0, 0, 4, 7, 9, 9 }; } @@ -720,7 +738,7 @@ private static final byte _JSON_integer_single_lengths[] = init__JSON_integer_si private static byte[] init__JSON_integer_range_lengths_0() { return new byte [] { - 0, 1, 1, 1, 1, 0 + 0, 1, 1, 1, 0, 1 }; } @@ -730,7 +748,7 @@ private static final byte _JSON_integer_range_lengths[] = init__JSON_integer_ran private static byte[] init__JSON_integer_index_offsets_0() { return new byte [] { - 0, 0, 4, 7, 9, 11 + 0, 0, 4, 7, 9, 10 }; } @@ -740,7 +758,7 @@ private static final byte _JSON_integer_index_offsets[] = init__JSON_integer_ind private static byte[] init__JSON_integer_indicies_0() { return new byte [] { - 0, 2, 3, 1, 2, 3, 1, 1, 4, 3, 4, 1, + 0, 2, 3, 1, 2, 3, 1, 1, 4, 1, 3, 4, 0 }; } @@ -751,7 +769,7 @@ private static final byte _JSON_integer_indicies[] = init__JSON_integer_indicies private static byte[] init__JSON_integer_trans_targs_0() { return new byte [] { - 2, 0, 3, 4, 5 + 2, 0, 3, 5, 4 }; } @@ -769,28 +787,28 @@ private static final byte _JSON_integer_trans_actions[] = init__JSON_integer_tra static final int JSON_integer_start = 1; -static final int JSON_integer_first_final = 5; +static final int JSON_integer_first_final = 3; static final int JSON_integer_error = 0; static final int JSON_integer_en_main = 1; -// line 468 "Parser.rl" +// line 486 "Parser.rl" ParserResult parseInteger(int p, int pe) { int cs = EVIL; -// line 786 "Parser.java" +// line 804 "Parser.java" { cs = JSON_integer_start; } -// line 474 "Parser.rl" +// line 492 "Parser.rl" int memo = p; -// line 794 "Parser.java" +// line 812 "Parser.java" { int _klen; int _trans = 0; @@ -871,13 +889,13 @@ case 1: switch ( _JSON_integer_actions[_acts++] ) { case 0: -// line 462 "Parser.rl" +// line 480 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 881 "Parser.java" +// line 899 "Parser.java" } } } @@ -897,7 +915,7 @@ case 5: break; } } -// line 476 "Parser.rl" +// line 494 "Parser.rl" if (cs < JSON_integer_first_final) { return null; @@ -912,7 +930,7 @@ case 5: } -// line 916 "Parser.java" +// line 934 "Parser.java" private static byte[] init__JSON_float_actions_0() { return new byte [] { @@ -926,7 +944,7 @@ private static final byte _JSON_float_actions[] = init__JSON_float_actions_0(); private static byte[] init__JSON_float_key_offsets_0() { return new byte [] { - 0, 0, 4, 7, 10, 12, 18, 22, 24, 30, 35 + 0, 0, 4, 7, 10, 12, 16, 18, 23, 29, 29 }; } @@ -937,8 +955,8 @@ private static char[] init__JSON_float_trans_keys_0() { return new char [] { 45, 48, 49, 57, 48, 49, 57, 46, 69, 101, 48, 57, - 69, 101, 45, 46, 48, 57, 43, 45, 48, 57, 48, 57, - 69, 101, 45, 46, 48, 57, 46, 69, 101, 48, 57, 0 + 43, 45, 48, 57, 48, 57, 46, 69, 101, 48, 57, 69, + 101, 45, 46, 48, 57, 69, 101, 45, 46, 48, 57, 0 }; } @@ -948,7 +966,7 @@ private static final char _JSON_float_trans_keys[] = init__JSON_float_trans_keys private static byte[] init__JSON_float_single_lengths_0() { return new byte [] { - 0, 2, 1, 3, 0, 2, 2, 0, 2, 3, 0 + 0, 2, 1, 3, 0, 2, 0, 3, 2, 0, 2 }; } @@ -958,7 +976,7 @@ private static final byte _JSON_float_single_lengths[] = init__JSON_float_single private static byte[] init__JSON_float_range_lengths_0() { return new byte [] { - 0, 1, 1, 0, 1, 2, 1, 1, 2, 1, 0 + 0, 1, 1, 0, 1, 1, 1, 1, 2, 0, 2 }; } @@ -968,7 +986,7 @@ private static final byte _JSON_float_range_lengths[] = init__JSON_float_range_l private static byte[] init__JSON_float_index_offsets_0() { return new byte [] { - 0, 0, 4, 7, 11, 13, 18, 22, 24, 29, 34 + 0, 0, 4, 7, 11, 13, 17, 19, 24, 29, 30 }; } @@ -979,8 +997,8 @@ private static byte[] init__JSON_float_indicies_0() { return new byte [] { 0, 2, 3, 1, 2, 3, 1, 4, 5, 5, 1, 6, - 1, 5, 5, 1, 6, 7, 8, 8, 9, 1, 9, 1, - 1, 1, 1, 9, 7, 4, 5, 5, 3, 1, 1, 0 + 1, 7, 7, 8, 1, 8, 1, 4, 5, 5, 3, 1, + 5, 5, 1, 6, 9, 1, 1, 1, 1, 8, 9, 0 }; } @@ -990,7 +1008,7 @@ private static final byte _JSON_float_indicies[] = init__JSON_float_indicies_0() private static byte[] init__JSON_float_trans_targs_0() { return new byte [] { - 2, 0, 3, 9, 4, 6, 5, 10, 7, 8 + 2, 0, 3, 7, 4, 5, 8, 6, 10, 9 }; } @@ -1000,7 +1018,7 @@ private static final byte _JSON_float_trans_targs[] = init__JSON_float_trans_tar private static byte[] init__JSON_float_trans_actions_0() { return new byte [] { - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; } @@ -1008,28 +1026,28 @@ private static final byte _JSON_float_trans_actions[] = init__JSON_float_trans_a static final int JSON_float_start = 1; -static final int JSON_float_first_final = 10; +static final int JSON_float_first_final = 8; static final int JSON_float_error = 0; static final int JSON_float_en_main = 1; -// line 504 "Parser.rl" +// line 522 "Parser.rl" ParserResult parseFloat(int p, int pe) { int cs = EVIL; -// line 1025 "Parser.java" +// line 1043 "Parser.java" { cs = JSON_float_start; } -// line 510 "Parser.rl" +// line 528 "Parser.rl" int memo = p; -// line 1033 "Parser.java" +// line 1051 "Parser.java" { int _klen; int _trans = 0; @@ -1110,13 +1128,13 @@ case 1: switch ( _JSON_float_actions[_acts++] ) { case 0: -// line 495 "Parser.rl" +// line 513 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 1120 "Parser.java" +// line 1138 "Parser.java" } } } @@ -1136,7 +1154,7 @@ case 5: break; } } -// line 512 "Parser.rl" +// line 530 "Parser.rl" if (cs < JSON_float_first_final) { return null; @@ -1151,7 +1169,7 @@ case 5: } -// line 1155 "Parser.java" +// line 1173 "Parser.java" private static byte[] init__JSON_string_actions_0() { return new byte [] { @@ -1253,7 +1271,7 @@ static final int JSON_string_error = 0; static final int JSON_string_en_main = 1; -// line 556 "Parser.rl" +// line 574 "Parser.rl" ParserResult parseString(int p, int pe) { @@ -1261,15 +1279,15 @@ static final int JSON_string_en_main = 1; IRubyObject result = null; -// line 1265 "Parser.java" +// line 1283 "Parser.java" { cs = JSON_string_start; } -// line 563 "Parser.rl" +// line 581 "Parser.rl" int memo = p; -// line 1273 "Parser.java" +// line 1291 "Parser.java" { int _klen; int _trans = 0; @@ -1350,7 +1368,7 @@ case 1: switch ( _JSON_string_actions[_acts++] ) { case 0: -// line 531 "Parser.rl" +// line 549 "Parser.rl" { int offset = byteList.begin(); ByteList decoded = decoder.decode(byteList, memo + 1 - offset, @@ -1365,13 +1383,13 @@ case 1: } break; case 1: -// line 544 "Parser.rl" +// line 562 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 1375 "Parser.java" +// line 1393 "Parser.java" } } } @@ -1391,7 +1409,7 @@ case 5: break; } } -// line 565 "Parser.rl" +// line 583 "Parser.rl" if (parser.createAdditions) { RubyHash match_string = parser.match_string; @@ -1426,7 +1444,7 @@ case 5: } -// line 1430 "Parser.java" +// line 1448 "Parser.java" private static byte[] init__JSON_array_actions_0() { return new byte [] { @@ -1539,7 +1557,7 @@ static final int JSON_array_error = 0; static final int JSON_array_en_main = 1; -// line 635 "Parser.rl" +// line 653 "Parser.rl" ParserResult parseArray(int p, int pe) { @@ -1557,14 +1575,14 @@ static final int JSON_array_en_main = 1; IRubyObject.NULL_ARRAY, Block.NULL_BLOCK); -// line 1561 "Parser.java" +// line 1579 "Parser.java" { cs = JSON_array_start; } -// line 652 "Parser.rl" +// line 670 "Parser.rl" -// line 1568 "Parser.java" +// line 1586 "Parser.java" { int _klen; int _trans = 0; @@ -1645,7 +1663,7 @@ case 1: switch ( _JSON_array_actions[_acts++] ) { case 0: -// line 604 "Parser.rl" +// line 622 "Parser.rl" { ParserResult res = parseValue(p, pe); if (res == null) { @@ -1662,13 +1680,13 @@ case 1: } break; case 1: -// line 619 "Parser.rl" +// line 637 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 1672 "Parser.java" +// line 1690 "Parser.java" } } } @@ -1688,7 +1706,7 @@ case 5: break; } } -// line 653 "Parser.rl" +// line 671 "Parser.rl" if (cs >= JSON_array_first_final) { return new ParserResult(result, p + 1); @@ -1698,7 +1716,7 @@ case 5: } -// line 1702 "Parser.java" +// line 1720 "Parser.java" private static byte[] init__JSON_object_actions_0() { return new byte [] { @@ -1821,7 +1839,7 @@ static final int JSON_object_error = 0; static final int JSON_object_en_main = 1; -// line 713 "Parser.rl" +// line 730 "Parser.rl" ParserResult parseObject(int p, int pe) { @@ -1840,14 +1858,14 @@ static final int JSON_object_en_main = 1; IRubyObject.NULL_ARRAY, Block.NULL_BLOCK); -// line 1844 "Parser.java" +// line 1862 "Parser.java" { cs = JSON_object_start; } -// line 731 "Parser.rl" +// line 748 "Parser.rl" -// line 1851 "Parser.java" +// line 1869 "Parser.java" { int _klen; int _trans = 0; @@ -1928,7 +1946,7 @@ case 1: switch ( _JSON_object_actions[_acts++] ) { case 0: -// line 667 "Parser.rl" +// line 685 "Parser.rl" { ParserResult res = parseValue(p, pe); if (res == null) { @@ -1945,7 +1963,7 @@ case 1: } break; case 1: -// line 682 "Parser.rl" +// line 700 "Parser.rl" { ParserResult res = parseString(p, pe); if (res == null) { @@ -1965,13 +1983,13 @@ case 1: } break; case 2: -// line 700 "Parser.rl" +// line 718 "Parser.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 1975 "Parser.java" +// line 1993 "Parser.java" } } } @@ -1991,7 +2009,7 @@ case 5: break; } } -// line 732 "Parser.rl" +// line 749 "Parser.rl" if (cs < JSON_object_first_final) { return null; @@ -2017,7 +2035,7 @@ case 5: } -// line 2021 "Parser.java" +// line 2039 "Parser.java" private static byte[] init__JSON_actions_0() { return new byte [] { @@ -2121,25 +2139,25 @@ static final int JSON_error = 0; static final int JSON_en_main = 1; -// line 790 "Parser.rl" +// line 807 "Parser.rl" - public IRubyObject parse() { + public IRubyObject parseStrict() { int cs = EVIL; int p, pe; IRubyObject result = null; -// line 2134 "Parser.java" +// line 2152 "Parser.java" { cs = JSON_start; } -// line 798 "Parser.rl" +// line 815 "Parser.rl" p = byteList.begin(); pe = p + byteList.length(); -// line 2143 "Parser.java" +// line 2161 "Parser.java" { int _klen; int _trans = 0; @@ -2220,7 +2238,7 @@ case 1: switch ( _JSON_actions[_acts++] ) { case 0: -// line 762 "Parser.rl" +// line 779 "Parser.rl" { currentNesting = 1; ParserResult res = parseObject(p, pe); @@ -2234,7 +2252,7 @@ case 1: } break; case 1: -// line 774 "Parser.rl" +// line 791 "Parser.rl" { currentNesting = 1; ParserResult res = parseArray(p, pe); @@ -2247,7 +2265,7 @@ case 1: } } break; -// line 2251 "Parser.java" +// line 2269 "Parser.java" } } } @@ -2267,7 +2285,7 @@ case 5: break; } } -// line 801 "Parser.rl" +// line 818 "Parser.rl" if (cs >= JSON_first_final && p == pe) { return result; @@ -2276,6 +2294,259 @@ case 5: } } + +// line 2299 "Parser.java" +private static byte[] init__JSON_quirks_mode_actions_0() +{ + return new byte [] { + 0, 1, 0 + }; +} + +private static final byte _JSON_quirks_mode_actions[] = init__JSON_quirks_mode_actions_0(); + + +private static byte[] init__JSON_quirks_mode_key_offsets_0() +{ + return new byte [] { + 0, 0, 16, 18, 19, 21, 22, 24, 25, 27, 28 + }; +} + +private static final byte _JSON_quirks_mode_key_offsets[] = init__JSON_quirks_mode_key_offsets_0(); + + +private static char[] init__JSON_quirks_mode_trans_keys_0() +{ + return new char [] { + 13, 32, 34, 45, 47, 73, 78, 91, 102, 110, 116, 123, + 9, 10, 48, 57, 42, 47, 42, 42, 47, 10, 42, 47, + 42, 42, 47, 10, 13, 32, 47, 9, 10, 0 + }; +} + +private static final char _JSON_quirks_mode_trans_keys[] = init__JSON_quirks_mode_trans_keys_0(); + + +private static byte[] init__JSON_quirks_mode_single_lengths_0() +{ + return new byte [] { + 0, 12, 2, 1, 2, 1, 2, 1, 2, 1, 3 + }; +} + +private static final byte _JSON_quirks_mode_single_lengths[] = init__JSON_quirks_mode_single_lengths_0(); + + +private static byte[] init__JSON_quirks_mode_range_lengths_0() +{ + return new byte [] { + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1 + }; +} + +private static final byte _JSON_quirks_mode_range_lengths[] = init__JSON_quirks_mode_range_lengths_0(); + + +private static byte[] init__JSON_quirks_mode_index_offsets_0() +{ + return new byte [] { + 0, 0, 15, 18, 20, 23, 25, 28, 30, 33, 35 + }; +} + +private static final byte _JSON_quirks_mode_index_offsets[] = init__JSON_quirks_mode_index_offsets_0(); + + +private static byte[] init__JSON_quirks_mode_indicies_0() +{ + return new byte [] { + 0, 0, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, + 0, 2, 1, 4, 5, 1, 6, 4, 6, 7, 4, 7, + 5, 8, 9, 1, 10, 8, 10, 0, 8, 0, 9, 7, + 7, 11, 7, 1, 0 + }; +} + +private static final byte _JSON_quirks_mode_indicies[] = init__JSON_quirks_mode_indicies_0(); + + +private static byte[] init__JSON_quirks_mode_trans_targs_0() +{ + return new byte [] { + 1, 0, 10, 6, 3, 5, 4, 10, 7, 9, 8, 2 + }; +} + +private static final byte _JSON_quirks_mode_trans_targs[] = init__JSON_quirks_mode_trans_targs_0(); + + +private static byte[] init__JSON_quirks_mode_trans_actions_0() +{ + return new byte [] { + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; +} + +private static final byte _JSON_quirks_mode_trans_actions[] = init__JSON_quirks_mode_trans_actions_0(); + + +static final int JSON_quirks_mode_start = 1; +static final int JSON_quirks_mode_first_final = 10; +static final int JSON_quirks_mode_error = 0; + +static final int JSON_quirks_mode_en_main = 1; + + +// line 846 "Parser.rl" + + + public IRubyObject parseQuirksMode() { + int cs = EVIL; + int p, pe; + IRubyObject result = null; + + +// line 2411 "Parser.java" + { + cs = JSON_quirks_mode_start; + } + +// line 854 "Parser.rl" + p = byteList.begin(); + pe = p + byteList.length(); + +// line 2420 "Parser.java" + { + int _klen; + int _trans = 0; + int _acts; + int _nacts; + int _keys; + int _goto_targ = 0; + + _goto: while (true) { + switch ( _goto_targ ) { + case 0: + if ( p == pe ) { + _goto_targ = 4; + continue _goto; + } + if ( cs == 0 ) { + _goto_targ = 5; + continue _goto; + } +case 1: + _match: do { + _keys = _JSON_quirks_mode_key_offsets[cs]; + _trans = _JSON_quirks_mode_index_offsets[cs]; + _klen = _JSON_quirks_mode_single_lengths[cs]; + if ( _klen > 0 ) { + int _lower = _keys; + int _mid; + int _upper = _keys + _klen - 1; + while (true) { + if ( _upper < _lower ) + break; + + _mid = _lower + ((_upper-_lower) >> 1); + if ( data[p] < _JSON_quirks_mode_trans_keys[_mid] ) + _upper = _mid - 1; + else if ( data[p] > _JSON_quirks_mode_trans_keys[_mid] ) + _lower = _mid + 1; + else { + _trans += (_mid - _keys); + break _match; + } + } + _keys += _klen; + _trans += _klen; + } + + _klen = _JSON_quirks_mode_range_lengths[cs]; + if ( _klen > 0 ) { + int _lower = _keys; + int _mid; + int _upper = _keys + (_klen<<1) - 2; + while (true) { + if ( _upper < _lower ) + break; + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( data[p] < _JSON_quirks_mode_trans_keys[_mid] ) + _upper = _mid - 2; + else if ( data[p] > _JSON_quirks_mode_trans_keys[_mid+1] ) + _lower = _mid + 2; + else { + _trans += ((_mid - _keys)>>1); + break _match; + } + } + _trans += _klen; + } + } while (false); + + _trans = _JSON_quirks_mode_indicies[_trans]; + cs = _JSON_quirks_mode_trans_targs[_trans]; + + if ( _JSON_quirks_mode_trans_actions[_trans] != 0 ) { + _acts = _JSON_quirks_mode_trans_actions[_trans]; + _nacts = (int) _JSON_quirks_mode_actions[_acts++]; + while ( _nacts-- > 0 ) + { + switch ( _JSON_quirks_mode_actions[_acts++] ) + { + case 0: +// line 832 "Parser.rl" + { + ParserResult res = parseValue(p, pe); + if (res == null) { + p--; + { p += 1; _goto_targ = 5; if (true) continue _goto;} + } else { + result = res.result; + {p = (( res.p))-1;} + } + } + break; +// line 2513 "Parser.java" + } + } + } + +case 2: + if ( cs == 0 ) { + _goto_targ = 5; + continue _goto; + } + if ( ++p != pe ) { + _goto_targ = 1; + continue _goto; + } +case 4: +case 5: + } + break; } + } + +// line 857 "Parser.rl" + + if (cs >= JSON_quirks_mode_first_final && p == pe) { + return result; + } else { + throw unexpectedToken(p, pe); + } + } + + public IRubyObject parse() { + if (parser.quirksMode) { + return parseQuirksMode(); + } else { + return parseStrict(); + } + + } + /** * Returns a subsequence of the source ByteList, based on source * array byte offsets (i.e., the ByteList's own begin offset is not diff --git a/java/src/json/ext/Parser.rl b/java/src/json/ext/Parser.rl index 779d3f3..9cd134d 100644 --- a/java/src/json/ext/Parser.rl +++ b/java/src/json/ext/Parser.rl @@ -49,6 +49,7 @@ public class Parser extends RubyObject { private int maxNesting; private boolean allowNaN; private boolean symbolizeNames; + private boolean quirksMode; private RubyClass objectClass; private RubyClass arrayClass; private RubyHash match_string; @@ -118,6 +119,10 @@ public class Parser extends RubyObject { *

:symbolize_names *
If set to true, returns symbols for the names (keys) in * a JSON object. Otherwise strings are returned, which is also the default. + * + *
:quirks_mode? + *
If set to true, if the parse is in quirks_mode, false + * otherwise. * *
:create_additions *
If set to false, the Parser doesn't create additions @@ -146,19 +151,21 @@ public class Parser extends RubyObject { if (this.vSource != null) { throw runtime.newTypeError("already initialized instance"); } - RubyString source = convertEncoding(context, args[0].convertToString()); OptionsReader opts = new OptionsReader(context, args.length > 1 ? args[1] : null); this.maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING); this.allowNaN = opts.getBool("allow_nan", false); this.symbolizeNames = opts.getBool("symbolize_names", false); + this.quirksMode = opts.getBool("quirks_mode", false); this.createId = opts.getString("create_id", getCreateId(context)); this.createAdditions = opts.getBool("create_additions", true); this.objectClass = opts.getClass("object_class", runtime.getHash()); this.arrayClass = opts.getClass("array_class", runtime.getArray()); this.match_string = opts.getHash("match_string"); - this.vSource = source; + this.vSource = args[0].convertToString(); + if (!quirksMode) this.vSource = convertEncoding(context, vSource); + return this; } @@ -247,6 +254,17 @@ public class Parser extends RubyObject { return checkAndGetSource().dup(); } + /** + * Parser#quirks_mode?() + * + *

If set to true, if the parse is in quirks_mode, false + * otherwise. + */ + @JRubyMethod(name = "quirks_mode?") + public IRubyObject quirks_mode_p(ThreadContext context) { + return context.getRuntime().newBoolean(quirksMode); + } + public RubyString checkAndGetSource() { if (vSource != null) { return vSource; @@ -364,7 +382,7 @@ public class Parser extends RubyObject { } } action parse_number { - if (pe > fpc + 9 && + if (pe > fpc + 9 - (parser.quirksMode ? 1 : 0) && absSubSequence(fpc, fpc + 9).toString().equals(JSON_MINUS_INFINITY)) { if (parser.allowNaN) { @@ -464,7 +482,7 @@ public class Parser extends RubyObject { fbreak; } - main := '-'? ( '0' | [1-9][0-9]* ) ( ^[0-9] @exit ); + main := '-'? ( '0' | [1-9][0-9]* ) ( ^[0-9]? @exit ); }%% ParserResult parseInteger(int p, int pe) { @@ -500,7 +518,7 @@ public class Parser extends RubyObject { main := '-'? ( ( ( '0' | [1-9][0-9]* ) '.' [0-9]+ ( [Ee] [+\-]?[0-9]+ )? ) | ( ( '0' | [1-9][0-9]* ) ( [Ee] [+\-]? [0-9]+ ) ) ) - ( ^[0-9Ee.\-] @exit ); + ( ^[0-9Ee.\-]? @exit ); }%% ParserResult parseFloat(int p, int pe) { @@ -701,15 +719,14 @@ public class Parser extends RubyObject { fhold; fbreak; } + + pair = ignore* begin_name >parse_name ignore* name_separator + ignore* begin_value >parse_value; + next_pair = ignore* value_separator pair; - a_pair = ignore* - begin_name >parse_name - ignore* name_separator ignore* - begin_value >parse_value; - - main := begin_object - (a_pair (ignore* value_separator a_pair)*)? - ignore* end_object @exit; + main := ( + begin_object (pair (next_pair)*)? ignore* end_object + ) @exit; }%% ParserResult parseObject(int p, int pe) { @@ -789,7 +806,7 @@ public class Parser extends RubyObject { ignore*; }%% - public IRubyObject parse() { + public IRubyObject parseStrict() { int cs = EVIL; int p, pe; IRubyObject result = null; @@ -806,6 +823,54 @@ public class Parser extends RubyObject { } } + %%{ + machine JSON_quirks_mode; + include JSON_common; + + write data; + + action parse_value { + ParserResult res = parseValue(fpc, pe); + if (res == null) { + fhold; + fbreak; + } else { + result = res.result; + fexec res.p; + } + } + + main := ignore* + ( begin_value >parse_value) + ignore*; + }%% + + public IRubyObject parseQuirksMode() { + int cs = EVIL; + int p, pe; + IRubyObject result = null; + + %% write init; + p = byteList.begin(); + pe = p + byteList.length(); + %% write exec; + + if (cs >= JSON_quirks_mode_first_final && p == pe) { + return result; + } else { + throw unexpectedToken(p, pe); + } + } + + public IRubyObject parse() { + if (parser.quirksMode) { + return parseQuirksMode(); + } else { + return parseStrict(); + } + + } + /** * Returns a subsequence of the source ByteList, based on source * array byte offsets (i.e., the ByteList's own begin offset is not -- cgit v1.2.1