From 9cc1ff7bd1a1080765cfb24d0c23b39b6bc91523 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alexis=20Laferri=C3=A8re?= Date: Thu, 3 Aug 2017 12:46:30 -0400 Subject: [PATCH] json: remove the old nitcc parser MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit And move the content of `string_parser` to `static` because of high coupling. Signed-off-by: Alexis Laferrière --- lib/json/.gitattributes | 2 - lib/json/.gitignore | 7 - lib/json/Makefile | 7 - lib/json/error.nit | 21 +- lib/json/json_lexer.nit | 470 --------------------- lib/json/json_parser.nit | 876 --------------------------------------- lib/json/serialization_read.nit | 1 - lib/json/static.nit | 444 ++++++++++++++------ lib/json/string_parser.nit | 351 ---------------- 9 files changed, 329 insertions(+), 1850 deletions(-) delete mode 100644 lib/json/.gitattributes delete mode 100644 lib/json/.gitignore delete mode 100644 lib/json/Makefile delete mode 100644 lib/json/json_lexer.nit delete mode 100644 lib/json/json_parser.nit delete mode 100644 lib/json/string_parser.nit diff --git a/lib/json/.gitattributes b/lib/json/.gitattributes deleted file mode 100644 index 041d62a..0000000 --- a/lib/json/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -json_lexer.nit -diff -json_parser.nit -diff diff --git a/lib/json/.gitignore b/lib/json/.gitignore deleted file mode 100644 index 0f08b2b..0000000 --- a/lib/json/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -json.concrete_grammar.txt -json.dfa.dot -json.gram.dot -json.lr.dot -json.lr.txt -json.nfa.dot -json_test_parser.nit diff --git a/lib/json/Makefile b/lib/json/Makefile deleted file mode 100644 index a8a5eb9..0000000 --- a/lib/json/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -NITCCDIR=../../contrib/nitcc/ - -pre-build: $(NITCCDIR)src/nitcc - $(NITCCDIR)src/nitcc $(NITCCDIR)examples/json.sablecc - -$(NITCCDIR)src/nitcc: - make -C $(NITCCDIR) diff --git a/lib/json/error.nit b/lib/json/error.nit index 26a9952..f13d2fc 100644 --- a/lib/json/error.nit +++ b/lib/json/error.nit @@ -8,25 +8,16 @@ # You are allowed to redistribute it and sell it, alone or is a part of # another product. -# Errors related to JSON parsing. -module json::error +# Intro `JsonParseError` which is exposed by all JSON reading APIs +module error -import nitcc_runtime +import parser_base -# Ill-formed JSON. +# JSON format error at parsing class JsonParseError super Error serialize - # The location of the error in the original text. - var position: nullable Position - - redef fun to_s do - var p = position - if p isa Position then - return "Error Parsing JSON: [{p}] {super}" - else - return super - end - end + # Location of the error in source + var location: nullable Location = null end diff --git a/lib/json/json_lexer.nit b/lib/json/json_lexer.nit deleted file mode 100644 index 32a82b2..0000000 --- a/lib/json/json_lexer.nit +++ /dev/null @@ -1,470 +0,0 @@ -# Lexer generated by nitcc for the grammar json -module json_lexer is generated, no_warning "missing-doc" -import nitcc_runtime -import json_parser -class Lexer_json - super Lexer - redef fun start_state do return dfastate_0 -end -private fun dfastate_0: DFAState0 do return once new DFAState0 -private fun dfastate_1: DFAState1 do return once new DFAState1 -private fun dfastate_2: DFAState2 do return once new DFAState2 -private fun dfastate_3: DFAState3 do return once new DFAState3 -private fun dfastate_4: DFAState4 do return once new DFAState4 -private fun dfastate_5: DFAState5 do return once new DFAState5 -private fun dfastate_6: DFAState6 do return once new DFAState6 -private fun dfastate_7: DFAState7 do return once new DFAState7 -private fun dfastate_8: DFAState8 do return once new DFAState8 -private fun dfastate_9: DFAState9 do return once new DFAState9 -private fun dfastate_10: DFAState10 do return once new DFAState10 -private fun dfastate_11: DFAState11 do return once new DFAState11 -private fun dfastate_12: DFAState12 do return once new DFAState12 -private fun dfastate_13: DFAState13 do return once new DFAState13 -private fun dfastate_14: DFAState14 do return once new DFAState14 -private fun dfastate_15: DFAState15 do return once new DFAState15 -private fun dfastate_16: DFAState16 do return once new DFAState16 -private fun dfastate_17: DFAState17 do return once new DFAState17 -private fun dfastate_18: DFAState18 do return once new DFAState18 -private fun dfastate_19: DFAState19 do return once new DFAState19 -private fun dfastate_20: DFAState20 do return once new DFAState20 -private fun dfastate_21: DFAState21 do return once new DFAState21 -private fun dfastate_22: DFAState22 do return once new DFAState22 -private fun dfastate_23: DFAState23 do return once new DFAState23 -private fun dfastate_24: DFAState24 do return once new DFAState24 -private fun dfastate_25: DFAState25 do return once new DFAState25 -private fun dfastate_26: DFAState26 do return once new DFAState26 -private fun dfastate_27: DFAState27 do return once new DFAState27 -private fun dfastate_28: DFAState28 do return once new DFAState28 -private fun dfastate_29: DFAState29 do return once new DFAState29 -private fun dfastate_30: DFAState30 do return once new DFAState30 -private fun dfastate_31: DFAState31 do return once new DFAState31 -private fun dfastate_32: DFAState32 do return once new DFAState32 -private fun dfastate_33: DFAState33 do return once new DFAState33 -private fun dfastate_34: DFAState34 do return once new DFAState34 -class MyNToken - super NToken -end -private class DFAState0 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 8 then return null - if c <= 10 then return dfastate_1 - if c <= 31 then return null - if c <= 32 then return dfastate_1 - if c <= 33 then return null - if c <= 34 then return dfastate_2 - if c <= 43 then return null - if c <= 44 then return dfastate_3 - if c <= 45 then return dfastate_4 - if c <= 47 then return null - if c <= 57 then return dfastate_5 - if c <= 58 then return dfastate_6 - if c <= 90 then return null - if c <= 91 then return dfastate_7 - if c <= 92 then return null - if c <= 93 then return dfastate_8 - if c <= 101 then return null - if c <= 102 then return dfastate_9 - if c <= 109 then return null - if c <= 110 then return dfastate_10 - if c <= 115 then return null - if c <= 116 then return dfastate_11 - if c <= 122 then return null - if c <= 123 then return dfastate_12 - if c <= 124 then return null - if c <= 125 then return dfastate_13 - return null - end -end -private class DFAState1 - super DFAState - redef fun is_accept do return true - redef fun is_ignored do return true - redef fun make_token(position, source) do - return null - end - redef fun trans(char) do - var c = char.code_point - if c <= 8 then return null - if c <= 10 then return dfastate_1 - if c <= 31 then return null - if c <= 32 then return dfastate_1 - return null - end -end -private class DFAState2 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c > 92 then return dfastate_2 - if c <= 33 then return dfastate_2 - if c <= 34 then return dfastate_29 - if c <= 91 then return dfastate_2 - return dfastate_30 - end -end -private class DFAState3 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new N_39d_44d_39d - t.text = "," - t.position = position - return t - end -end -private class DFAState4 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 47 then return null - if c <= 57 then return dfastate_5 - return null - end -end -private class DFAState5 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new Nnumber - t.text = position.extract(source) - t.position = position - return t - end - redef fun trans(char) do - var c = char.code_point - if c <= 45 then return null - if c <= 46 then return dfastate_24 - if c <= 47 then return null - if c <= 57 then return dfastate_5 - if c <= 68 then return null - if c <= 69 then return dfastate_25 - if c <= 100 then return null - if c <= 101 then return dfastate_25 - return null - end -end -private class DFAState6 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new N_39d_58d_39d - t.text = ":" - t.position = position - return t - end -end -private class DFAState7 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new N_39d_91d_39d - t.text = "[" - t.position = position - return t - end -end -private class DFAState8 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new N_39d_93d_39d - t.text = "]" - t.position = position - return t - end -end -private class DFAState9 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 96 then return null - if c <= 97 then return dfastate_20 - return null - end -end -private class DFAState10 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 116 then return null - if c <= 117 then return dfastate_17 - return null - end -end -private class DFAState11 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 113 then return null - if c <= 114 then return dfastate_14 - return null - end -end -private class DFAState12 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new N_39d_123d_39d - t.text = "\{" - t.position = position - return t - end -end -private class DFAState13 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new N_39d_125d_39d - t.text = "\}" - t.position = position - return t - end -end -private class DFAState14 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 116 then return null - if c <= 117 then return dfastate_15 - return null - end -end -private class DFAState15 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 100 then return null - if c <= 101 then return dfastate_16 - return null - end -end -private class DFAState16 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new N_39dtrue_39d - t.text = "true" - t.position = position - return t - end -end -private class DFAState17 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 107 then return null - if c <= 108 then return dfastate_18 - return null - end -end -private class DFAState18 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 107 then return null - if c <= 108 then return dfastate_19 - return null - end -end -private class DFAState19 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new N_39dnull_39d - t.text = "null" - t.position = position - return t - end -end -private class DFAState20 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 107 then return null - if c <= 108 then return dfastate_21 - return null - end -end -private class DFAState21 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 114 then return null - if c <= 115 then return dfastate_22 - return null - end -end -private class DFAState22 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 100 then return null - if c <= 101 then return dfastate_23 - return null - end -end -private class DFAState23 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new N_39dfalse_39d - t.text = "false" - t.position = position - return t - end -end -private class DFAState24 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 47 then return null - if c <= 57 then return dfastate_28 - return null - end -end -private class DFAState25 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 42 then return null - if c <= 43 then return dfastate_26 - if c <= 44 then return null - if c <= 45 then return dfastate_26 - if c <= 47 then return null - if c <= 57 then return dfastate_27 - return null - end -end -private class DFAState26 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 47 then return null - if c <= 57 then return dfastate_27 - return null - end -end -private class DFAState27 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new Nnumber - t.text = position.extract(source) - t.position = position - return t - end - redef fun trans(char) do - var c = char.code_point - if c <= 47 then return null - if c <= 57 then return dfastate_27 - return null - end -end -private class DFAState28 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new Nnumber - t.text = position.extract(source) - t.position = position - return t - end - redef fun trans(char) do - var c = char.code_point - if c <= 47 then return null - if c <= 57 then return dfastate_28 - if c <= 68 then return null - if c <= 69 then return dfastate_25 - if c <= 100 then return null - if c <= 101 then return dfastate_25 - return null - end -end -private class DFAState29 - super DFAState - redef fun is_accept do return true - redef fun make_token(position, source) do - var t = new Nstring - t.text = position.extract(source) - t.position = position - return t - end -end -private class DFAState30 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 33 then return null - if c <= 34 then return dfastate_2 - if c <= 46 then return null - if c <= 47 then return dfastate_2 - if c <= 91 then return null - if c <= 92 then return dfastate_2 - if c <= 97 then return null - if c <= 98 then return dfastate_2 - if c <= 101 then return null - if c <= 102 then return dfastate_2 - if c <= 109 then return null - if c <= 110 then return dfastate_2 - if c <= 113 then return null - if c <= 114 then return dfastate_2 - if c <= 115 then return null - if c <= 116 then return dfastate_2 - if c <= 117 then return dfastate_31 - return null - end -end -private class DFAState31 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 47 then return null - if c <= 57 then return dfastate_32 - if c <= 64 then return null - if c <= 90 then return dfastate_32 - if c <= 96 then return null - if c <= 122 then return dfastate_32 - return null - end -end -private class DFAState32 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 47 then return null - if c <= 57 then return dfastate_33 - if c <= 64 then return null - if c <= 90 then return dfastate_33 - if c <= 96 then return null - if c <= 122 then return dfastate_33 - return null - end -end -private class DFAState33 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 47 then return null - if c <= 57 then return dfastate_34 - if c <= 64 then return null - if c <= 90 then return dfastate_34 - if c <= 96 then return null - if c <= 122 then return dfastate_34 - return null - end -end -private class DFAState34 - super DFAState - redef fun trans(char) do - var c = char.code_point - if c <= 47 then return null - if c <= 57 then return dfastate_2 - if c <= 64 then return null - if c <= 90 then return dfastate_2 - if c <= 96 then return null - if c <= 122 then return dfastate_2 - return null - end -end diff --git a/lib/json/json_parser.nit b/lib/json/json_parser.nit deleted file mode 100644 index 28094c0..0000000 --- a/lib/json/json_parser.nit +++ /dev/null @@ -1,876 +0,0 @@ -# Parser generated by nitcc for the grammar json -module json_parser is generated, no_warning("missing-doc","old-init") -import nitcc_runtime -class Parser_json - super Parser - redef fun start_state do return state_Start -end -private fun state_Start: LRStateStart do return once new LRStateStart -private fun state_value: LRStatevalue do return once new LRStatevalue -private fun state_number: LRStatenumber do return once new LRStatenumber -private fun state_string: LRStatestring do return once new LRStatestring -private fun state__39dtrue_39d: LRState_39dtrue_39d do return once new LRState_39dtrue_39d -private fun state__39dfalse_39d: LRState_39dfalse_39d do return once new LRState_39dfalse_39d -private fun state__39dnull_39d: LRState_39dnull_39d do return once new LRState_39dnull_39d -private fun state__39d_123d_39d: LRState_39d_123d_39d do return once new LRState_39d_123d_39d -private fun state__39d_91d_39d: LRState_39d_91d_39d do return once new LRState_39d_91d_39d -private fun state_value_32dEof: LRStatevalue_32dEof do return once new LRStatevalue_32dEof -private fun state__39d_123d_39d_32dmembers: LRState_39d_123d_39d_32dmembers do return once new LRState_39d_123d_39d_32dmembers -private fun state__39d_123d_39d_32d_39d_125d_39d: LRState_39d_123d_39d_32d_39d_125d_39d do return once new LRState_39d_123d_39d_32d_39d_125d_39d -private fun state__39d_123d_39d_32dpair: LRState_39d_123d_39d_32dpair do return once new LRState_39d_123d_39d_32dpair -private fun state__39d_123d_39d_32dstring: LRState_39d_123d_39d_32dstring do return once new LRState_39d_123d_39d_32dstring -private fun state__39d_91d_39d_32delements: LRState_39d_91d_39d_32delements do return once new LRState_39d_91d_39d_32delements -private fun state__39d_91d_39d_32d_39d_93d_39d: LRState_39d_91d_39d_32d_39d_93d_39d do return once new LRState_39d_91d_39d_32d_39d_93d_39d -private fun state__39d_91d_39d_32dvalue: LRState_39d_91d_39d_32dvalue do return once new LRState_39d_91d_39d_32dvalue -private fun state__39d_123d_39d_32dmembers_32d_39d_125d_39d: LRState_39d_123d_39d_32dmembers_32d_39d_125d_39d do return once new LRState_39d_123d_39d_32dmembers_32d_39d_125d_39d -private fun state__39d_123d_39d_32dmembers_32d_39d_44d_39d: LRState_39d_123d_39d_32dmembers_32d_39d_44d_39d do return once new LRState_39d_123d_39d_32dmembers_32d_39d_44d_39d -private fun state__39d_123d_39d_32dstring_32d_39d_58d_39d: LRState_39d_123d_39d_32dstring_32d_39d_58d_39d do return once new LRState_39d_123d_39d_32dstring_32d_39d_58d_39d -private fun state__39d_91d_39d_32delements_32d_39d_93d_39d: LRState_39d_91d_39d_32delements_32d_39d_93d_39d do return once new LRState_39d_91d_39d_32delements_32d_39d_93d_39d -private fun state__39d_91d_39d_32delements_32d_39d_44d_39d: LRState_39d_91d_39d_32delements_32d_39d_44d_39d do return once new LRState_39d_91d_39d_32delements_32d_39d_44d_39d -private fun state__39d_123d_39d_32dmembers_32d_39d_44d_39d_32dpair: LRState_39d_123d_39d_32dmembers_32d_39d_44d_39d_32dpair do return once new LRState_39d_123d_39d_32dmembers_32d_39d_44d_39d_32dpair -private fun state__39d_123d_39d_32dstring_32d_39d_58d_39d_32dvalue: LRState_39d_123d_39d_32dstring_32d_39d_58d_39d_32dvalue do return once new LRState_39d_123d_39d_32dstring_32d_39d_58d_39d_32dvalue -private fun state__39d_91d_39d_32delements_32d_39d_44d_39d_32dvalue: LRState_39d_91d_39d_32delements_32d_39d_44d_39d_32dvalue do return once new LRState_39d_91d_39d_32delements_32d_39d_44d_39d_32dvalue -private fun goto_Nvalue: Goto_Nvalue do return once new Goto_Nvalue -private fun reduce_Nvalue_number(parser: Parser) do - # REDUCE value::value_number=number - var n0 = parser.pop.as(Nnumber) - var p1 = new Nvalue_number(n0) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nvalue) -end -private fun reduce_Nvalue_string(parser: Parser) do - # REDUCE value::value_string=string - var n0 = parser.pop.as(Nstring) - var p1 = new Nvalue_string(n0) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nvalue) -end -private fun reduce_Nvalue_true(parser: Parser) do - # REDUCE value::value_true='true' - var n0 = parser.pop.as(N_39dtrue_39d) - var p1 = new Nvalue_true(n0) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nvalue) -end -private fun reduce_Nvalue_false(parser: Parser) do - # REDUCE value::value_false='false' - var n0 = parser.pop.as(N_39dfalse_39d) - var p1 = new Nvalue_false(n0) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nvalue) -end -private fun reduce_Nvalue_null(parser: Parser) do - # REDUCE value::value_null='null' - var n0 = parser.pop.as(N_39dnull_39d) - var p1 = new Nvalue_null(n0) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nvalue) -end -private fun reduce_Nvalue_object_95d0(parser: Parser) do - # REDUCE value::value_object_0='{' members '}' - var n2 = parser.pop.as(N_39d_125d_39d) - var n1 = parser.pop.as(Nmembers) - var n0 = parser.pop.as(N_39d_123d_39d) - var p1 = new Nvalue_object(n0, n1, n2) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nvalue) -end -private fun reduce_Nvalue_object_95d1(parser: Parser) do - # REDUCE value::value_object_1='{' '}' - var n1 = parser.pop.as(N_39d_125d_39d) - var n0 = parser.pop.as(N_39d_123d_39d) - var p1 = new Nvalue_object(n0, null, n1) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nvalue) -end -private fun reduce_Nvalue_array_95d0(parser: Parser) do - # REDUCE value::value_array_0='[' elements ']' - var n2 = parser.pop.as(N_39d_93d_39d) - var n1 = parser.pop.as(Nelements) - var n0 = parser.pop.as(N_39d_91d_39d) - var p1 = new Nvalue_array(n0, n1, n2) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nvalue) -end -private fun reduce_Nvalue_array_95d1(parser: Parser) do - # REDUCE value::value_array_1='[' ']' - var n1 = parser.pop.as(N_39d_93d_39d) - var n0 = parser.pop.as(N_39d_91d_39d) - var p1 = new Nvalue_array(n0, null, n1) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nvalue) -end -private fun goto_Nmembers: Goto_Nmembers do return once new Goto_Nmembers -private fun reduce_Nmembers_tail(parser: Parser) do - # REDUCE members::members_tail=members ',' pair - var n2 = parser.pop.as(Npair) - var n1 = parser.pop.as(N_39d_44d_39d) - var n0 = parser.pop.as(Nmembers) - var p1 = new Nmembers_tail(n0, n1, n2) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nmembers) -end -private fun reduce_Nmembers_head(parser: Parser) do - # REDUCE members::members_head=pair - var n0 = parser.pop.as(Npair) - var p1 = new Nmembers_head(n0) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nmembers) -end -private fun goto_Npair: Goto_Npair do return once new Goto_Npair -private fun reduce_Npair(parser: Parser) do - # REDUCE pair::pair=string ':' value - var n2 = parser.pop.as(Nvalue) - var n1 = parser.pop.as(N_39d_58d_39d) - var n0 = parser.pop.as(Nstring) - var p1 = new Npair(n0, n1, n2) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Npair) -end -private fun goto_Nelements: Goto_Nelements do return once new Goto_Nelements -private fun reduce_Nelements_tail(parser: Parser) do - # REDUCE elements::elements_tail=elements ',' value - var n2 = parser.pop.as(Nvalue) - var n1 = parser.pop.as(N_39d_44d_39d) - var n0 = parser.pop.as(Nelements) - var p1 = new Nelements_tail(n0, n1, n2) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nelements) -end -private fun reduce_Nelements_head(parser: Parser) do - # REDUCE elements::elements_head=value - var n0 = parser.pop.as(Nvalue) - var p1 = new Nelements_head(n0) - var prod = p1 - parser.node_stack.push prod - parser.goto(goto_Nelements) -end -private fun goto_N_start: Goto_N_start do return once new Goto_N_start -private fun reduce_NStart(parser: Parser) do - # REDUCE _start::Start=value Eof - var n1 = parser.pop.as(NEof) - var n0 = parser.pop.as(Nvalue) - var p1 = new NStart(n0, n1) - var prod = p1 - parser.node_stack.push prod - parser.stop = true -end -redef class NToken - # guarded action for state Start - # 7 shift(s) and 0 reduce(s) - private fun action_sStart(parser: Parser) do - parser.parse_error - end - # guarded action for state value - # 1 shift(s) and 0 reduce(s) - private fun action_svalue(parser: Parser) do - parser.parse_error - end - # guarded action for state '{' - # 2 shift(s) and 0 reduce(s) - private fun action_s_39d_123d_39d(parser: Parser) do - parser.parse_error - end - # guarded action for state '[' - # 8 shift(s) and 0 reduce(s) - private fun action_s_39d_91d_39d(parser: Parser) do - parser.parse_error - end - # guarded action for state '{' members - # 2 shift(s) and 0 reduce(s) - private fun action_s_39d_123d_39d_32dmembers(parser: Parser) do - parser.parse_error - end - # guarded action for state '{' string - # 1 shift(s) and 0 reduce(s) - private fun action_s_39d_123d_39d_32dstring(parser: Parser) do - parser.parse_error - end - # guarded action for state '[' elements - # 2 shift(s) and 0 reduce(s) - private fun action_s_39d_91d_39d_32delements(parser: Parser) do - parser.parse_error - end - # guarded action for state '{' members ',' - # 1 shift(s) and 0 reduce(s) - private fun action_s_39d_123d_39d_32dmembers_32d_39d_44d_39d(parser: Parser) do - parser.parse_error - end - # guarded action for state '{' string ':' - # 7 shift(s) and 0 reduce(s) - private fun action_s_39d_123d_39d_32dstring_32d_39d_58d_39d(parser: Parser) do - parser.parse_error - end - # guarded action for state '[' elements ',' - # 7 shift(s) and 0 reduce(s) - private fun action_s_39d_91d_39d_32delements_32d_39d_44d_39d(parser: Parser) do - parser.parse_error - end -end -class N_39d_123d_39d - super NToken - redef fun action_sStart(parser) do - parser.shift(state__39d_123d_39d) - end - redef fun action_s_39d_91d_39d(parser) do - parser.shift(state__39d_123d_39d) - end - redef fun action_s_39d_123d_39d_32dstring_32d_39d_58d_39d(parser) do - parser.shift(state__39d_123d_39d) - end - redef fun action_s_39d_91d_39d_32delements_32d_39d_44d_39d(parser) do - parser.shift(state__39d_123d_39d) - end - redef fun node_name do return "\'\{\'" -end -class N_39d_125d_39d - super NToken - redef fun action_s_39d_123d_39d(parser) do - parser.shift(state__39d_123d_39d_32d_39d_125d_39d) - end - redef fun action_s_39d_123d_39d_32dmembers(parser) do - parser.shift(state__39d_123d_39d_32dmembers_32d_39d_125d_39d) - end - redef fun node_name do return "\'\}\'" -end -class N_39d_91d_39d - super NToken - redef fun action_sStart(parser) do - parser.shift(state__39d_91d_39d) - end - redef fun action_s_39d_91d_39d(parser) do - parser.shift(state__39d_91d_39d) - end - redef fun action_s_39d_123d_39d_32dstring_32d_39d_58d_39d(parser) do - parser.shift(state__39d_91d_39d) - end - redef fun action_s_39d_91d_39d_32delements_32d_39d_44d_39d(parser) do - parser.shift(state__39d_91d_39d) - end - redef fun node_name do return "\'[\'" -end -class N_39d_93d_39d - super NToken - redef fun action_s_39d_91d_39d(parser) do - parser.shift(state__39d_91d_39d_32d_39d_93d_39d) - end - redef fun action_s_39d_91d_39d_32delements(parser) do - parser.shift(state__39d_91d_39d_32delements_32d_39d_93d_39d) - end - redef fun node_name do return "\']\'" -end -class Nnumber - super NToken - redef fun action_sStart(parser) do - parser.shift(state_number) - end - redef fun action_s_39d_91d_39d(parser) do - parser.shift(state_number) - end - redef fun action_s_39d_123d_39d_32dstring_32d_39d_58d_39d(parser) do - parser.shift(state_number) - end - redef fun action_s_39d_91d_39d_32delements_32d_39d_44d_39d(parser) do - parser.shift(state_number) - end - redef fun node_name do return "number" -end -class Nstring - super NToken - redef fun action_sStart(parser) do - parser.shift(state_string) - end - redef fun action_s_39d_123d_39d(parser) do - parser.shift(state__39d_123d_39d_32dstring) - end - redef fun action_s_39d_91d_39d(parser) do - parser.shift(state_string) - end - redef fun action_s_39d_123d_39d_32dmembers_32d_39d_44d_39d(parser) do - parser.shift(state__39d_123d_39d_32dstring) - end - redef fun action_s_39d_123d_39d_32dstring_32d_39d_58d_39d(parser) do - parser.shift(state_string) - end - redef fun action_s_39d_91d_39d_32delements_32d_39d_44d_39d(parser) do - parser.shift(state_string) - end - redef fun node_name do return "string" -end -class N_39dtrue_39d - super NToken - redef fun action_sStart(parser) do - parser.shift(state__39dtrue_39d) - end - redef fun action_s_39d_91d_39d(parser) do - parser.shift(state__39dtrue_39d) - end - redef fun action_s_39d_123d_39d_32dstring_32d_39d_58d_39d(parser) do - parser.shift(state__39dtrue_39d) - end - redef fun action_s_39d_91d_39d_32delements_32d_39d_44d_39d(parser) do - parser.shift(state__39dtrue_39d) - end - redef fun node_name do return "\'true\'" -end -class N_39dfalse_39d - super NToken - redef fun action_sStart(parser) do - parser.shift(state__39dfalse_39d) - end - redef fun action_s_39d_91d_39d(parser) do - parser.shift(state__39dfalse_39d) - end - redef fun action_s_39d_123d_39d_32dstring_32d_39d_58d_39d(parser) do - parser.shift(state__39dfalse_39d) - end - redef fun action_s_39d_91d_39d_32delements_32d_39d_44d_39d(parser) do - parser.shift(state__39dfalse_39d) - end - redef fun node_name do return "\'false\'" -end -class N_39dnull_39d - super NToken - redef fun action_sStart(parser) do - parser.shift(state__39dnull_39d) - end - redef fun action_s_39d_91d_39d(parser) do - parser.shift(state__39dnull_39d) - end - redef fun action_s_39d_123d_39d_32dstring_32d_39d_58d_39d(parser) do - parser.shift(state__39dnull_39d) - end - redef fun action_s_39d_91d_39d_32delements_32d_39d_44d_39d(parser) do - parser.shift(state__39dnull_39d) - end - redef fun node_name do return "\'null\'" -end -class N_39d_44d_39d - super NToken - redef fun action_s_39d_123d_39d_32dmembers(parser) do - parser.shift(state__39d_123d_39d_32dmembers_32d_39d_44d_39d) - end - redef fun action_s_39d_91d_39d_32delements(parser) do - parser.shift(state__39d_91d_39d_32delements_32d_39d_44d_39d) - end - redef fun node_name do return "\',\'" -end -class N_39d_58d_39d - super NToken - redef fun action_s_39d_123d_39d_32dstring(parser) do - parser.shift(state__39d_123d_39d_32dstring_32d_39d_58d_39d) - end - redef fun node_name do return "\':\'" -end -redef class NEof - super NToken - redef fun action_svalue(parser) do - parser.shift(state_value_32dEof) - end - redef fun node_name do return "Eof" -end -redef class LRGoto - private fun goto_s_39d_123d_39d(parser: Parser) do abort - private fun goto_s_39d_91d_39d(parser: Parser) do abort -end -class Goto_Nvalue - super LRGoto - redef fun goto_s_39d_91d_39d(parser) do - parser.push(state__39d_91d_39d_32dvalue) - end -end -class Goto_Nmembers - super LRGoto - redef fun goto_s_39d_123d_39d(parser) do - parser.push(state__39d_123d_39d_32dmembers) - end -end -class Goto_Npair - super LRGoto - redef fun goto_s_39d_123d_39d(parser) do - parser.push(state__39d_123d_39d_32dpair) - end -end -class Goto_Nelements - super LRGoto - redef fun goto_s_39d_91d_39d(parser) do - parser.push(state__39d_91d_39d_32delements) - end -end -class Goto_N_start - super LRGoto -end -class Nvalue - super NProd - redef fun node_name do return "value" -end -class Nvalue_number - super Nvalue - redef fun node_name do return "value_number" - var n_number: Nnumber - init(n_number: Nnumber) do - self.n_number = n_number - end - redef fun number_of_children do return 1 - redef fun child(i) do - if i == 0 then return n_number - abort - end -end -class Nvalue_string - super Nvalue - redef fun node_name do return "value_string" - var n_string: Nstring - init(n_string: Nstring) do - self.n_string = n_string - end - redef fun number_of_children do return 1 - redef fun child(i) do - if i == 0 then return n_string - abort - end -end -class Nvalue_true - super Nvalue - redef fun node_name do return "value_true" - var n_0: N_39dtrue_39d - init(n_0: N_39dtrue_39d) do - self.n_0 = n_0 - end - redef fun number_of_children do return 1 - redef fun child(i) do - if i == 0 then return n_0 - abort - end -end -class Nvalue_false - super Nvalue - redef fun node_name do return "value_false" - var n_0: N_39dfalse_39d - init(n_0: N_39dfalse_39d) do - self.n_0 = n_0 - end - redef fun number_of_children do return 1 - redef fun child(i) do - if i == 0 then return n_0 - abort - end -end -class Nvalue_null - super Nvalue - redef fun node_name do return "value_null" - var n_0: N_39dnull_39d - init(n_0: N_39dnull_39d) do - self.n_0 = n_0 - end - redef fun number_of_children do return 1 - redef fun child(i) do - if i == 0 then return n_0 - abort - end -end -class Nvalue_object - super Nvalue - redef fun node_name do return "value_object" - var n_0: N_39d_123d_39d - var n_members: nullable Nmembers - var n_2: N_39d_125d_39d - init(n_0: N_39d_123d_39d, n_members: nullable Nmembers, n_2: N_39d_125d_39d) do - self.n_0 = n_0 - self.n_members = n_members - self.n_2 = n_2 - end - redef fun number_of_children do return 3 - redef fun child(i) do - if i == 0 then return n_0 - if i == 1 then return n_members - if i == 2 then return n_2 - abort - end -end -class Nvalue_array - super Nvalue - redef fun node_name do return "value_array" - var n_0: N_39d_91d_39d - var n_elements: nullable Nelements - var n_2: N_39d_93d_39d - init(n_0: N_39d_91d_39d, n_elements: nullable Nelements, n_2: N_39d_93d_39d) do - self.n_0 = n_0 - self.n_elements = n_elements - self.n_2 = n_2 - end - redef fun number_of_children do return 3 - redef fun child(i) do - if i == 0 then return n_0 - if i == 1 then return n_elements - if i == 2 then return n_2 - abort - end -end -class Nmembers - super NProd - redef fun node_name do return "members" -end -class Nmembers_tail - super Nmembers - redef fun node_name do return "members_tail" - var n_members: Nmembers - var n_1: N_39d_44d_39d - var n_pair: Npair - init(n_members: Nmembers, n_1: N_39d_44d_39d, n_pair: Npair) do - self.n_members = n_members - self.n_1 = n_1 - self.n_pair = n_pair - end - redef fun number_of_children do return 3 - redef fun child(i) do - if i == 0 then return n_members - if i == 1 then return n_1 - if i == 2 then return n_pair - abort - end -end -class Nmembers_head - super Nmembers - redef fun node_name do return "members_head" - var n_pair: Npair - init(n_pair: Npair) do - self.n_pair = n_pair - end - redef fun number_of_children do return 1 - redef fun child(i) do - if i == 0 then return n_pair - abort - end -end -class Npair - super NProd - redef fun node_name do return "pair" - var n_string: Nstring - var n_1: N_39d_58d_39d - var n_value: Nvalue - init(n_string: Nstring, n_1: N_39d_58d_39d, n_value: Nvalue) do - self.n_string = n_string - self.n_1 = n_1 - self.n_value = n_value - end - redef fun number_of_children do return 3 - redef fun child(i) do - if i == 0 then return n_string - if i == 1 then return n_1 - if i == 2 then return n_value - abort - end -end -class Nelements - super NProd - redef fun node_name do return "elements" -end -class Nelements_tail - super Nelements - redef fun node_name do return "elements_tail" - var n_elements: Nelements - var n_1: N_39d_44d_39d - var n_value: Nvalue - init(n_elements: Nelements, n_1: N_39d_44d_39d, n_value: Nvalue) do - self.n_elements = n_elements - self.n_1 = n_1 - self.n_value = n_value - end - redef fun number_of_children do return 3 - redef fun child(i) do - if i == 0 then return n_elements - if i == 1 then return n_1 - if i == 2 then return n_value - abort - end -end -class Nelements_head - super Nelements - redef fun node_name do return "elements_head" - var n_value: Nvalue - init(n_value: Nvalue) do - self.n_value = n_value - end - redef fun number_of_children do return 1 - redef fun child(i) do - if i == 0 then return n_value - abort - end -end -class N_start - super NProd - redef fun node_name do return "_start" -end -class NStart - super N_start - redef fun node_name do return "Start" - var n_0: Nvalue - var n_1: NEof - init(n_0: Nvalue, n_1: NEof) do - self.n_0 = n_0 - self.n_1 = n_1 - end - redef fun number_of_children do return 2 - redef fun child(i) do - if i == 0 then return n_0 - if i == 1 then return n_1 - abort - end -end -# State Start -private class LRStateStart - super LRState - redef fun to_s do return "Start" - redef fun error_msg do return "value" - redef fun action(parser) do - parser.peek_token.action_sStart(parser) - end - redef fun goto(parser, goto) do - parser.push(state_value) - end -end -# State value -private class LRStatevalue - super LRState - redef fun to_s do return "value" - redef fun error_msg do return "Eof" - redef fun action(parser) do - parser.peek_token.action_svalue(parser) - end -end -# State number -private class LRStatenumber - super LRState - redef fun to_s do return "number" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nvalue_number(parser) - end -end -# State string -private class LRStatestring - super LRState - redef fun to_s do return "string" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nvalue_string(parser) - end -end -# State 'true' -private class LRState_39dtrue_39d - super LRState - redef fun to_s do return "\'true\'" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nvalue_true(parser) - end -end -# State 'false' -private class LRState_39dfalse_39d - super LRState - redef fun to_s do return "\'false\'" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nvalue_false(parser) - end -end -# State 'null' -private class LRState_39dnull_39d - super LRState - redef fun to_s do return "\'null\'" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nvalue_null(parser) - end -end -# State '{' -private class LRState_39d_123d_39d - super LRState - redef fun to_s do return "\'\{\'" - redef fun error_msg do return "members, pair" - redef fun action(parser) do - parser.peek_token.action_s_39d_123d_39d(parser) - end - redef fun goto(parser, goto) do - goto.goto_s_39d_123d_39d(parser) - end -end -# State '[' -private class LRState_39d_91d_39d - super LRState - redef fun to_s do return "\'[\'" - redef fun error_msg do return "elements, value" - redef fun action(parser) do - parser.peek_token.action_s_39d_91d_39d(parser) - end - redef fun goto(parser, goto) do - goto.goto_s_39d_91d_39d(parser) - end -end -# State value Eof -private class LRStatevalue_32dEof - super LRState - redef fun to_s do return "value Eof" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_NStart(parser) - end -end -# State '{' members -private class LRState_39d_123d_39d_32dmembers - super LRState - redef fun to_s do return "\'\{\' members" - redef fun error_msg do return "\'\}\', \',\'" - redef fun action(parser) do - parser.peek_token.action_s_39d_123d_39d_32dmembers(parser) - end -end -# State '{' '}' -private class LRState_39d_123d_39d_32d_39d_125d_39d - super LRState - redef fun to_s do return "\'\{\' \'\}\'" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nvalue_object_95d1(parser) - end -end -# State '{' pair -private class LRState_39d_123d_39d_32dpair - super LRState - redef fun to_s do return "\'\{\' pair" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nmembers_head(parser) - end -end -# State '{' string -private class LRState_39d_123d_39d_32dstring - super LRState - redef fun to_s do return "\'\{\' string" - redef fun error_msg do return "\':\'" - redef fun action(parser) do - parser.peek_token.action_s_39d_123d_39d_32dstring(parser) - end -end -# State '[' elements -private class LRState_39d_91d_39d_32delements - super LRState - redef fun to_s do return "\'[\' elements" - redef fun error_msg do return "\']\', \',\'" - redef fun action(parser) do - parser.peek_token.action_s_39d_91d_39d_32delements(parser) - end -end -# State '[' ']' -private class LRState_39d_91d_39d_32d_39d_93d_39d - super LRState - redef fun to_s do return "\'[\' \']\'" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nvalue_array_95d1(parser) - end -end -# State '[' value -private class LRState_39d_91d_39d_32dvalue - super LRState - redef fun to_s do return "\'[\' value" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nelements_head(parser) - end -end -# State '{' members '}' -private class LRState_39d_123d_39d_32dmembers_32d_39d_125d_39d - super LRState - redef fun to_s do return "\'\{\' members \'\}\'" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nvalue_object_95d0(parser) - end -end -# State '{' members ',' -private class LRState_39d_123d_39d_32dmembers_32d_39d_44d_39d - super LRState - redef fun to_s do return "\'\{\' members \',\'" - redef fun error_msg do return "pair" - redef fun action(parser) do - parser.peek_token.action_s_39d_123d_39d_32dmembers_32d_39d_44d_39d(parser) - end - redef fun goto(parser, goto) do - parser.push(state__39d_123d_39d_32dmembers_32d_39d_44d_39d_32dpair) - end -end -# State '{' string ':' -private class LRState_39d_123d_39d_32dstring_32d_39d_58d_39d - super LRState - redef fun to_s do return "\'\{\' string \':\'" - redef fun error_msg do return "value" - redef fun action(parser) do - parser.peek_token.action_s_39d_123d_39d_32dstring_32d_39d_58d_39d(parser) - end - redef fun goto(parser, goto) do - parser.push(state__39d_123d_39d_32dstring_32d_39d_58d_39d_32dvalue) - end -end -# State '[' elements ']' -private class LRState_39d_91d_39d_32delements_32d_39d_93d_39d - super LRState - redef fun to_s do return "\'[\' elements \']\'" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nvalue_array_95d0(parser) - end -end -# State '[' elements ',' -private class LRState_39d_91d_39d_32delements_32d_39d_44d_39d - super LRState - redef fun to_s do return "\'[\' elements \',\'" - redef fun error_msg do return "value" - redef fun action(parser) do - parser.peek_token.action_s_39d_91d_39d_32delements_32d_39d_44d_39d(parser) - end - redef fun goto(parser, goto) do - parser.push(state__39d_91d_39d_32delements_32d_39d_44d_39d_32dvalue) - end -end -# State '{' members ',' pair -private class LRState_39d_123d_39d_32dmembers_32d_39d_44d_39d_32dpair - super LRState - redef fun to_s do return "\'\{\' members \',\' pair" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nmembers_tail(parser) - end -end -# State '{' string ':' value -private class LRState_39d_123d_39d_32dstring_32d_39d_58d_39d_32dvalue - super LRState - redef fun to_s do return "\'\{\' string \':\' value" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Npair(parser) - end -end -# State '[' elements ',' value -private class LRState_39d_91d_39d_32delements_32d_39d_44d_39d_32dvalue - super LRState - redef fun to_s do return "\'[\' elements \',\' value" - redef fun error_msg do return "" - redef fun action(parser) do - reduce_Nelements_tail(parser) - end -end diff --git a/lib/json/serialization_read.nit b/lib/json/serialization_read.nit index 0ac2bea..03b1267 100644 --- a/lib/json/serialization_read.nit +++ b/lib/json/serialization_read.nit @@ -18,7 +18,6 @@ module serialization_read import ::serialization::caching private import ::serialization::engine_tools private import static -private import string_parser import poset # Deserializer from a Json string. diff --git a/lib/json/static.nit b/lib/json/static.nit index 9b68f31..09d463d 100644 --- a/lib/json/static.nit +++ b/lib/json/static.nit @@ -22,9 +22,8 @@ # This object can then be type checked as usual with `isa` and `as`. module static -import error -private import json_parser -private import json_lexer +import parser_base +intrude import error redef class Text @@ -42,14 +41,14 @@ redef class Text # # assert not "string".json_need_escape # assert "\\\"string\\\"".json_need_escape - protected fun json_need_escape: Bool do return has('\\') + private fun json_need_escape: Bool do return has('\\') # Escapes `self` from a JSON string to a Nit string # # assert "\\\"string\\\"".json_to_nit_string == "\"string\"" # assert "\\nEscape\\t\\n".json_to_nit_string == "\nEscape\t\n" # assert "\\u0041zu\\uD800\\uDFD3".json_to_nit_string == "Azu𐏓" - protected fun json_to_nit_string: String do + private fun json_to_nit_string: String do var res = new FlatBuffer.with_capacity(byte_length) var i = 0 var ln = self.length @@ -122,18 +121,7 @@ redef class Text # var bad = "\{foo: \"bar\"\}".parse_json # assert bad isa JsonParseError # assert bad.position.col_start == 2 - fun parse_json: nullable Serializable do - var lexer = new Lexer_json(to_s) - var parser = new Parser_json - var tokens = lexer.lex - parser.tokens.add_all(tokens) - var root_node = parser.parse - if root_node isa NStart then - return root_node.n_0.to_nit_object - else if root_node isa NError then - return new JsonParseError(root_node.message, root_node.position) - else abort - end + fun parse_json: nullable Serializable do return (new JSONStringParser(self.to_s)).parse_entity end redef class FlatText @@ -146,133 +134,347 @@ redef class FlatText end end -# A map that can be translated into a JSON object. -interface JsonMapRead[K: String, V: nullable Serializable] - super MapRead[K, V] - super Serializable -end - -# A JSON Object. -class JsonObject - super JsonMapRead[String, nullable Serializable] - super HashMap[String, nullable Serializable] -end - -# A sequence that can be translated into a JSON array. -class JsonSequenceRead[E: nullable Serializable] - super Serializable - super SequenceRead[E] -end - -# A JSON array. -class JsonArray - super JsonSequenceRead[nullable Serializable] - super Array[nullable Serializable] -end - -################################################################################ -# Redef parser - -redef class Nvalue - # The represented value. - private fun to_nit_object: nullable Serializable is abstract -end - -redef class Nvalue_number - redef fun to_nit_object - do - var text = n_number.text - if text.chars.has('.') or text.chars.has('e') or text.chars.has('E') then return text.to_f - return text.to_i +redef class Char + # Is `self` a valid number start ? + private fun is_json_num_start: Bool do + if self == '-' then return true + if self.is_numeric then return true + return false end -end -redef class Nvalue_string - redef fun to_nit_object do return n_string.to_nit_string -end - -redef class Nvalue_true - redef fun to_nit_object do return true + # Is `self` a valid JSON separator ? + private fun is_json_separator: Bool do + if self == ':' then return true + if self == ',' then return true + if self == '{' then return true + if self == '}' then return true + if self == '[' then return true + if self == ']' then return true + if self == '"' then return true + if self.is_whitespace then return true + return false + end end -redef class Nvalue_false - redef fun to_nit_object do return false -end +# A simple ad-hoc JSON parser +# +# To parse a simple JSON document, read it as a String and give it to `parse_entity` +# NOTE: if your document contains several non-nested entities, use `parse_entity` for each +# JSON entity to parse +class JSONStringParser + super StringProcessor -redef class Nvalue_null - redef fun to_nit_object do return null -end + # Parses a JSON Entity + # + # ~~~nit + # var p = new JSONStringParser("""{"numbers": [1,23,3], "string": "string"}""") + # assert p.parse_entity isa JsonObject + # ~~~ + fun parse_entity: nullable Serializable do + var srclen = len + ignore_whitespaces + if pos >= srclen then return make_parse_error("Empty JSON") + var c = src[pos] + if c == '[' then + pos += 1 + return parse_json_array + else if c == '"' then + var s = parse_json_string + return s + else if c == '{' then + pos += 1 + return parse_json_object + else if c == 'f' then + if pos + 4 >= srclen then make_parse_error("Error: bad JSON entity") + if src[pos + 1] == 'a' and src[pos + 2] == 'l' and src[pos + 3] == 's' and src[pos + 4] == 'e' then + pos += 5 + return false + end + return make_parse_error("Error: bad JSON entity") + else if c == 't' then + if pos + 3 >= srclen then make_parse_error("Error: bad JSON entity") + if src[pos + 1] == 'r' and src[pos + 2] == 'u' and src[pos + 3] == 'e' then + pos += 4 + return true + end + return make_parse_error("Error: bad JSON entity") + else if c == 'n' then + if pos + 3 >= srclen then make_parse_error("Error: bad JSON entity") + if src[pos + 1] == 'u' and src[pos + 2] == 'l' and src[pos + 3] == 'l' then + pos += 4 + return null + end + return make_parse_error("Error: bad JSON entity") + end + if not c.is_json_num_start then return make_parse_error("Bad JSON character") + return parse_json_number + end -redef class Nstring - # The represented string. - private fun to_nit_string: String do return text.substring(1, text.length - 2).unescape_json.to_s -end + # Parses a JSON Array + fun parse_json_array: Serializable do + var max = len + if pos >= max then return make_parse_error("Incomplete JSON array") + var arr = new JsonArray + var c = src[pos] + while not c == ']' do + ignore_whitespaces + if pos >= max then return make_parse_error("Incomplete JSON array") + if src[pos] == ']' then break + var ent = parse_entity + #print "Parsed an entity {ent} for a JSON array" + if ent isa JsonParseError then return ent + arr.add ent + ignore_whitespaces + if pos >= max then return make_parse_error("Incomplete JSON array") + c = src[pos] + if c == ']' then break + if c != ',' then return make_parse_error("Bad array separator {c}") + pos += 1 + end + pos += 1 + return arr + end -redef class Nvalue_object - redef fun to_nit_object do + # Parses a JSON Object + fun parse_json_object: Serializable do + var max = len + if pos >= max then return make_parse_error("Incomplete JSON object") var obj = new JsonObject - var members = n_members - if members != null then - var pairs = members.pairs - for pair in pairs do obj[pair.name] = pair.value + var c = src[pos] + while not c == '}' do + ignore_whitespaces + if pos >= max then return make_parse_error("Malformed JSON object") + if src[pos] == '}' then break + var key = parse_entity + #print "Parsed key {key} for JSON object" + if not key isa String then return make_parse_error("Bad key format {key or else "null"}") + ignore_whitespaces + if pos >= max then return make_parse_error("Incomplete JSON object") + if not src[pos] == ':' then return make_parse_error("Bad key/value separator {src[pos]}") + pos += 1 + ignore_whitespaces + var value = parse_entity + #print "Parsed value {value} for JSON object" + if value isa JsonParseError then return value + obj[key] = value + ignore_whitespaces + if pos >= max then return make_parse_error("Incomplete JSON object") + c = src[pos] + if c == '}' then break + if c != ',' then return make_parse_error("Bad object separator {src[pos]}") + pos += 1 end + pos += 1 return obj end -end - -redef class Nmembers - # All the key-value pairs. - private fun pairs: Array[Npair] is abstract -end -redef class Nmembers_tail - redef fun pairs - do - var arr = n_members.pairs - arr.add n_pair - return arr + # Creates a `JsonParseError` with the right message and location + protected fun make_parse_error(message: String): JsonParseError do + var err = new JsonParseError(message) + err.location = hot_location + return err end -end -redef class Nmembers_head - redef fun pairs do return [n_pair] -end + # Parses an Int or Float + fun parse_json_number: Serializable do + var max = len + var p = pos + var c = src[p] + var is_neg = false + if c == '-' then + is_neg = true + p += 1 + if p >= max then return make_parse_error("Bad JSON number") + c = src[p] + end + var val = 0 + while c.is_numeric do + val *= 10 + val += c.to_i + p += 1 + if p >= max then break + c = src[p] + end + if c == '.' then + p += 1 + if p >= max then return make_parse_error("Bad JSON number") + c = src[p] + var fl = val.to_f + var frac = 0.1 + while c.is_numeric do + fl += c.to_i.to_f * frac + frac /= 10.0 + p += 1 + if p >= max then break + c = src[p] + end + if c == 'e' or c == 'E' then + p += 1 + var exp = 0 + if p >= max then return make_parse_error("Malformed JSON number") + c = src[p] + while c.is_numeric do + exp *= 10 + exp += c.to_i + p += 1 + if p >= max then break + c = src[p] + end + fl *= (10 ** exp).to_f + end + if p < max and not c.is_json_separator then return make_parse_error("Malformed JSON number") + pos = p + if is_neg then return -fl + return fl + end + if c == 'e' or c == 'E' then + p += 1 + if p >= max then return make_parse_error("Bad JSON number") + var exp = src[p].to_i + c = src[p] + while c.is_numeric do + exp *= 10 + exp += c.to_i + p += 1 + if p >= max then break + c = src[p] + end + val *= (10 ** exp) + end + if p < max and not src[p].is_json_separator then return make_parse_error("Malformed JSON number") + pos = p + if is_neg then return -val + return val + end -redef class Npair - # The represented key. - private fun name: String do return n_string.to_nit_string + private var parse_str_buf = new FlatBuffer - # The represented value. - private fun value: nullable Serializable do return n_value.to_nit_object -end + # Parses and returns a Nit string from a JSON String + fun parse_json_string: Serializable do + var src = src + var ln = src.length + var p = pos + p += 1 + if p > ln then return make_parse_error("Malformed JSON String") + var c = src[p] + var ret = parse_str_buf + var chunk_st = p + while c != '"' do + if c != '\\' then + p += 1 + if p >= ln then return make_parse_error("Malformed JSON string") + c = src[p] + continue + end + ret.append_substring_impl(src, chunk_st, p - chunk_st) + p += 1 + if p >= ln then return make_parse_error("Malformed Escape sequence in JSON string") + c = src[p] + if c == 'r' then + ret.add '\r' + p += 1 + else if c == 'n' then + ret.add '\n' + p += 1 + else if c == 't' then + ret.add '\t' + p += 1 + else if c == 'u' then + var cp = 0 + p += 1 + for i in [0 .. 4[ do + cp <<= 4 + if p >= ln then make_parse_error("Malformed \uXXXX Escape sequence in JSON string") + c = src[p] + if c >= '0' and c <= '9' then + cp += c.code_point - '0'.code_point + else if c >= 'a' and c <= 'f' then + cp += c.code_point - 'a'.code_point + 10 + else if c >= 'A' and c <= 'F' then + cp += c.code_point - 'A'.code_point + 10 + else + make_parse_error("Malformed \uXXXX Escape sequence in JSON string") + end + p += 1 + end + c = cp.code_point + if cp >= 0xD800 and cp <= 0xDBFF then + if p >= ln then make_parse_error("Malformed \uXXXX Escape sequence in JSON string") + c = src[p] + if c != '\\' then make_parse_error("Malformed \uXXXX Escape sequence in JSON string") + p += 1 + c = src[p] + if c != 'u' then make_parse_error("Malformed \uXXXX Escape sequence in JSON string") + var locp = 0 + p += 1 + for i in [0 .. 4[ do + locp <<= 4 + if p > ln then make_parse_error("Malformed \uXXXX Escape sequence in JSON string") + c = src[p] + if c >= '0' and c <= '9' then + locp += c.code_point - '0'.code_point + else if c >= 'a' and c <= 'f' then + locp += c.code_point - 'a'.code_point + 10 + else if c >= 'A' and c <= 'F' then + locp += c.code_point - 'A'.code_point + 10 + else + make_parse_error("Malformed \uXXXX Escape sequence in JSON string") + end + p += 1 + end + c = (((locp & 0x3FF) | ((cp & 0x3FF) << 10)) + 0x10000).code_point + end + ret.add c + else if c == 'b' then + ret.add 8.code_point + p += 1 + else if c == 'f' then + ret.add '\f' + p += 1 + else + p += 1 + ret.add c + end + chunk_st = p + c = src[p] + end + pos = p + 1 + if ret.is_empty then return src.substring(chunk_st, p - chunk_st) + ret.append_substring_impl(src, chunk_st, p - chunk_st) + var rets = ret.to_s + ret.clear + return rets + end -redef class Nvalue_array - redef fun to_nit_object - do - var arr = new JsonArray - var elements = n_elements - if elements != null then - var items = elements.items - for item in items do arr.add(item.to_nit_object) + # Ignores any character until a JSON separator is encountered + fun ignore_until_separator do + var max = len + while pos < max do + if not src[pos].is_json_separator then return end - return arr end end -redef class Nelements - # All the items. - private fun items: Array[Nvalue] is abstract +# A map that can be translated into a JSON object. +interface JsonMapRead[K: String, V: nullable Serializable] + super MapRead[K, V] + super Serializable end -redef class Nelements_tail - redef fun items - do - var items = n_elements.items - items.add(n_value) - return items - end +# A JSON Object. +class JsonObject + super JsonMapRead[String, nullable Serializable] + super HashMap[String, nullable Serializable] end -redef class Nelements_head - redef fun items do return [n_value] +# A sequence that can be translated into a JSON array. +class JsonSequenceRead[E: nullable Serializable] + super Serializable + super SequenceRead[E] +end + +# A JSON array. +class JsonArray + super JsonSequenceRead[nullable Serializable] + super Array[nullable Serializable] end diff --git a/lib/json/string_parser.nit b/lib/json/string_parser.nit deleted file mode 100644 index 5015754..0000000 --- a/lib/json/string_parser.nit +++ /dev/null @@ -1,351 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Simple ad-hoc implementation of a JSON parser for String inputs -module string_parser - -import parser_base -import static - -redef class Char - # Is `self` a valid number start ? - private fun is_json_num_start: Bool do - if self == '-' then return true - if self.is_numeric then return true - return false - end - - # Is `self` a valid JSON separator ? - private fun is_json_separator: Bool do - if self == ':' then return true - if self == ',' then return true - if self == '{' then return true - if self == '}' then return true - if self == '[' then return true - if self == ']' then return true - if self == '"' then return true - if self.is_whitespace then return true - return false - end -end - -# A simple ad-hoc JSON parser -# -# To parse a simple JSON document, read it as a String and give it to `parse_entity` -# NOTE: if your document contains several non-nested entities, use `parse_entity` for each -# JSON entity to parse -class JSONStringParser - super StringProcessor - - # Parses a JSON Entity - # - # ~~~nit - # var p = new JSONStringParser("""{"numbers": [1,23,3], "string": "string"}""") - # assert p.parse_entity isa JsonObject - # ~~~ - fun parse_entity: nullable Serializable do - var srclen = len - ignore_whitespaces - if pos >= srclen then return make_parse_error("Empty JSON") - var c = src[pos] - if c == '[' then - pos += 1 - return parse_json_array - else if c == '"' then - var s = parse_json_string - return s - else if c == '{' then - pos += 1 - return parse_json_object - else if c == 'f' then - if pos + 4 >= srclen then make_parse_error("Error: bad JSON entity") - if src[pos + 1] == 'a' and src[pos + 2] == 'l' and src[pos + 3] == 's' and src[pos + 4] == 'e' then - pos += 5 - return false - end - return make_parse_error("Error: bad JSON entity") - else if c == 't' then - if pos + 3 >= srclen then make_parse_error("Error: bad JSON entity") - if src[pos + 1] == 'r' and src[pos + 2] == 'u' and src[pos + 3] == 'e' then - pos += 4 - return true - end - return make_parse_error("Error: bad JSON entity") - else if c == 'n' then - if pos + 3 >= srclen then make_parse_error("Error: bad JSON entity") - if src[pos + 1] == 'u' and src[pos + 2] == 'l' and src[pos + 3] == 'l' then - pos += 4 - return null - end - return make_parse_error("Error: bad JSON entity") - end - if not c.is_json_num_start then return make_parse_error("Bad JSON character") - return parse_json_number - end - - # Parses a JSON Array - fun parse_json_array: Serializable do - var max = len - if pos >= max then return make_parse_error("Incomplete JSON array") - var arr = new JsonArray - var c = src[pos] - while not c == ']' do - ignore_whitespaces - if pos >= max then return make_parse_error("Incomplete JSON array") - if src[pos] == ']' then break - var ent = parse_entity - #print "Parsed an entity {ent} for a JSON array" - if ent isa JsonParseError then return ent - arr.add ent - ignore_whitespaces - if pos >= max then return make_parse_error("Incomplete JSON array") - c = src[pos] - if c == ']' then break - if c != ',' then return make_parse_error("Bad array separator {c}") - pos += 1 - end - pos += 1 - return arr - end - - # Parses a JSON Object - fun parse_json_object: Serializable do - var max = len - if pos >= max then return make_parse_error("Incomplete JSON object") - var obj = new JsonObject - var c = src[pos] - while not c == '}' do - ignore_whitespaces - if pos >= max then return make_parse_error("Malformed JSON object") - if src[pos] == '}' then break - var key = parse_entity - #print "Parsed key {key} for JSON object" - if not key isa String then return make_parse_error("Bad key format {key or else "null"}") - ignore_whitespaces - if pos >= max then return make_parse_error("Incomplete JSON object") - if not src[pos] == ':' then return make_parse_error("Bad key/value separator {src[pos]}") - pos += 1 - ignore_whitespaces - var value = parse_entity - #print "Parsed value {value} for JSON object" - if value isa JsonParseError then return value - obj[key] = value - ignore_whitespaces - if pos >= max then return make_parse_error("Incomplete JSON object") - c = src[pos] - if c == '}' then break - if c != ',' then return make_parse_error("Bad object separator {src[pos]}") - pos += 1 - end - pos += 1 - return obj - end - - # Creates a `JsonParseError` with the right message and location - protected fun make_parse_error(message: String): JsonParseError do - var err = new JsonParseError(message) - err.location = hot_location - return err - end - - # Parses an Int or Float - fun parse_json_number: Serializable do - var max = len - var p = pos - var c = src[p] - var is_neg = false - if c == '-' then - is_neg = true - p += 1 - if p >= max then return make_parse_error("Bad JSON number") - c = src[p] - end - var val = 0 - while c.is_numeric do - val *= 10 - val += c.to_i - p += 1 - if p >= max then break - c = src[p] - end - if c == '.' then - p += 1 - if p >= max then return make_parse_error("Bad JSON number") - c = src[p] - var fl = val.to_f - var frac = 0.1 - while c.is_numeric do - fl += c.to_i.to_f * frac - frac /= 10.0 - p += 1 - if p >= max then break - c = src[p] - end - if c == 'e' or c == 'E' then - p += 1 - var exp = 0 - if p >= max then return make_parse_error("Malformed JSON number") - c = src[p] - while c.is_numeric do - exp *= 10 - exp += c.to_i - p += 1 - if p >= max then break - c = src[p] - end - fl *= (10 ** exp).to_f - end - if p < max and not c.is_json_separator then return make_parse_error("Malformed JSON number") - pos = p - if is_neg then return -fl - return fl - end - if c == 'e' or c == 'E' then - p += 1 - if p >= max then return make_parse_error("Bad JSON number") - var exp = src[p].to_i - c = src[p] - while c.is_numeric do - exp *= 10 - exp += c.to_i - p += 1 - if p >= max then break - c = src[p] - end - val *= (10 ** exp) - end - if p < max and not src[p].is_json_separator then return make_parse_error("Malformed JSON number") - pos = p - if is_neg then return -val - return val - end - - private var parse_str_buf = new FlatBuffer - - # Parses and returns a Nit string from a JSON String - fun parse_json_string: Serializable do - var src = src - var ln = src.length - var p = pos - p += 1 - if p > ln then return make_parse_error("Malformed JSON String") - var c = src[p] - var ret = parse_str_buf - var chunk_st = p - while c != '"' do - if c != '\\' then - p += 1 - if p >= ln then return make_parse_error("Malformed JSON string") - c = src[p] - continue - end - ret.append_substring_impl(src, chunk_st, p - chunk_st) - p += 1 - if p >= ln then return make_parse_error("Malformed Escape sequence in JSON string") - c = src[p] - if c == 'r' then - ret.add '\r' - p += 1 - else if c == 'n' then - ret.add '\n' - p += 1 - else if c == 't' then - ret.add '\t' - p += 1 - else if c == 'u' then - var cp = 0 - p += 1 - for i in [0 .. 4[ do - cp <<= 4 - if p >= ln then make_parse_error("Malformed \uXXXX Escape sequence in JSON string") - c = src[p] - if c >= '0' and c <= '9' then - cp += c.code_point - '0'.code_point - else if c >= 'a' and c <= 'f' then - cp += c.code_point - 'a'.code_point + 10 - else if c >= 'A' and c <= 'F' then - cp += c.code_point - 'A'.code_point + 10 - else - make_parse_error("Malformed \uXXXX Escape sequence in JSON string") - end - p += 1 - end - c = cp.code_point - if cp >= 0xD800 and cp <= 0xDBFF then - if p >= ln then make_parse_error("Malformed \uXXXX Escape sequence in JSON string") - c = src[p] - if c != '\\' then make_parse_error("Malformed \uXXXX Escape sequence in JSON string") - p += 1 - c = src[p] - if c != 'u' then make_parse_error("Malformed \uXXXX Escape sequence in JSON string") - var locp = 0 - p += 1 - for i in [0 .. 4[ do - locp <<= 4 - if p > ln then make_parse_error("Malformed \uXXXX Escape sequence in JSON string") - c = src[p] - if c >= '0' and c <= '9' then - locp += c.code_point - '0'.code_point - else if c >= 'a' and c <= 'f' then - locp += c.code_point - 'a'.code_point + 10 - else if c >= 'A' and c <= 'F' then - locp += c.code_point - 'A'.code_point + 10 - else - make_parse_error("Malformed \uXXXX Escape sequence in JSON string") - end - p += 1 - end - c = (((locp & 0x3FF) | ((cp & 0x3FF) << 10)) + 0x10000).code_point - end - ret.add c - else if c == 'b' then - ret.add 8.code_point - p += 1 - else if c == 'f' then - ret.add '\f' - p += 1 - else - p += 1 - ret.add c - end - chunk_st = p - c = src[p] - end - pos = p + 1 - if ret.is_empty then return src.substring(chunk_st, p - chunk_st) - ret.append_substring_impl(src, chunk_st, p - chunk_st) - var rets = ret.to_s - ret.clear - return rets - end - - # Ignores any character until a JSON separator is encountered - fun ignore_until_separator do - var max = len - while pos < max do - if not src[pos].is_json_separator then return - end - end -end - -redef class Text - redef fun parse_json do return (new JSONStringParser(self.to_s)).parse_entity -end - -redef class JsonParseError - serialize - - # Location of the error in source - var location: nullable Location = null -end -- 1.7.9.5