-
Notifications
You must be signed in to change notification settings - Fork 1
/
json_parser.js
91 lines (81 loc) · 3.32 KB
/
json_parser.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
const parsers = [[/^\s*n/, parseNull], [/^\s*(t|f)/, parseBool], [/^\s*(-?(0|[1-9]))/, parseNumber], [/^\s*"/, parseString], [/^\s*\[/, parseArray], [/^\s*\{/, parseObject], [null, null]]
// return [null || data:string, remainning_string: string]
function parseString (string) {
const exp = /^\s*"((\\(["\\\/bfnrt]|u[a-fA-F0-9]{4})|[^"\\\0-\x1F\x7F]+)*)"\s*/
let match = exp.exec(string)
if (match === null) return null
return [match[1], string.slice(match[0].length)]
}
// return [null || data:number, remainning_string: string]
function parseNumber (string) {
const exp = /^\s*(-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?)\s*/
let match = exp.exec(string)
if (match === null) return null
return [parseFloat(match[1]), string.slice(match[0].length)]
}
// return [null || data:null, remainning_string: string]
function parseNull (string) {
let match = /^\s*(null)\s*/.exec(string)
if (match === null) return null
return [null, string.slice(match[0].length)]
}
// return [null || data:null, remainning_string: string]
function parseBool (string) {
let match = /^\s*(true)\s*/.exec(string)
if (match !== null) return [true, string.slice(match[0].length)]
match = /^\s*(false)\s*/.exec(string)
if (match !== null) return [false, string.slice(match[0].length)]
return null
}
// return [null || data:object, remainning_string: string]
function parseObject (string) {
let match = /^\s*\{\s*/.exec(string)
if (match !== null) {
string = string.slice(match[0].length)
if (string[0] === '}') return [[], string.slice(/^\}\s*/.exec(string)[0].length)]
let [data, key, value] = [{}, '', parseString(string.slice(0))]
if (value === null || !value[1] || value[1][0] !== ':') return null
key = value[0]; value = parseValue(value[1].slice(1))
while (value !== null && value[1] && value[1][0] === ',') {
data[key] = value[0]
value = parseString(value[1].slice(1))
if (value === null || !value[1] || value[1][0] !== ':') return null
key = value[0]; value = parseValue(value[1].slice(1))
}
if (value === null || !value[1] || value[1][0] !== '}') return null
data[key] = value[0]
return [data, value[1].slice(/^\}\s*/.exec(value[1])[0].length)]
}
return null
}
// return [null || data:array, remainning_string: string]
function parseArray (string) {
let match = /^\s*\[\s*/.exec(string)
if (match !== null) {
string = string.slice(match[0].length)
if (string[0] === ']') return [[], string.slice(/^\]\s*/.exec(string)[0].length)]
let [data, value] = [[], parseValue(string)]
while (value !== null && value[1] && value[1][0] === ',') {
data.push(value[0])
value = parseValue(value[1].slice(1))
}
if (value === null || !value[1] || value[1][0] !== ']') return null
data.push(value[0])
return [data, value[1].slice(/^\]\s*/.exec(value[1])[0].length)]
}
return null
}
// return [null || data:array, remainning_string: string]
function parseValue (string) {
let parser = factoryParser(string)
return parser === null ? null : parser(string)
}
function factoryParser (string) {
return parsers.reduce((a, f) => (a[0].exec(string) === null ? f : a))[1]
}
// return [null || data:mapped data]
function parseJson (string) {
let data = parseValue(string)
return (data !== null && !data[1]) ? [true, data[0]] : [false, string]
}
module.exports = parseJson