+++ /dev/null
-json_lexer.nit -diff
-json_parser.nit -diff
+++ /dev/null
-json.concrete_grammar.txt
-json.dfa.dot
-json.gram.dot
-json.lr.dot
-json.lr.txt
-json.nfa.dot
-json_test_parser.nit
+++ /dev/null
-NITCCDIR=../../contrib/nitcc/
-
-pre-build: $(NITCCDIR)src/nitcc
- $(NITCCDIR)src/nitcc $(NITCCDIR)examples/json.sablecc
-
-$(NITCCDIR)src/nitcc:
- make -C $(NITCCDIR)
# 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
+++ /dev/null
-# 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
+++ /dev/null
-# 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
import ::serialization::caching
private import ::serialization::engine_tools
private import static
-private import string_parser
import poset
# Deserializer from a Json string.
# 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
#
# 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
# 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
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
+++ /dev/null
-# 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