-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
json.ts
132 lines (114 loc) · 2.75 KB
/
json.ts
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// https://www.json.org/json-en.html
// Introducing a separate lexer for string contents
// is rather contrived. It is here to demonstrate
// how to compose lexers and get quotes as separate tokens if needed.
// Another option might be to use a capture group
// and replace the token contents but that would mean
// the token array can no longer be directly serialized
// without processing (adding quotes back to string tokens).
// Full JSON parser example comes with `peberminta` parser combinators package repo.
// There, I just left quotes as a part of a single token for the parser to handle.
import { inspect } from 'util';
import { createLexer, Options } from '../src/leac';
const options: Options = { lineNumbers: true };
const lexJson = createLexer([
{ name: '{' },
{ name: '}' },
{ name: '[' },
{ name: ']' },
{ name: ',' },
{ name: ':' },
{ name: 'null' },
{ name: 'true' },
{ name: 'false' },
{
name: 'space',
regex: /\s+/,
discard: true
},
{ name: 'number', regex: /-?(?:[0-9]|[1-9][0-9]+)(?:\.[0-9]+)?(?:[eE][-+]?[0-9]+)?\b/ },
{
name: 'openQuote',
str: '"',
push: createLexer([
// Following regex can match an empty string and no token will be emitted in that case -
// empty matches are considered as non-matches.
// Keep this in mind if you're thinking about discarding quotes.
{ name: 'string', regex: /(?:\\["bfnrt/\\]|\\u[a-fA-F0-9]{4}|[^"\\])*/ },
{
name: 'closeQuote',
str: '"',
pop: true
}
], 'string', options)
}
], 'root', options);
console.log(inspect(lexJson(`
{
"foo": true, "bar": "baz",
"qux": [1, 2, [3], [ ], { "quux": "quuz" }]
}
`)));
// Output
// {
// tokens: [
// {
// state: 'root',
// name: '{',
// text: '{',
// offset: 1,
// len: 1,
// line: 2,
// column: 1
// },
// {
// state: 'root',
// name: 'openQuote',
// text: '"',
// offset: 5,
// len: 1,
// line: 3,
// column: 3
// },
// {
// state: 'string',
// name: 'string',
// text: 'foo',
// offset: 6,
// len: 3,
// line: 3,
// column: 4
// },
// {
// state: 'string',
// name: 'closeQuote',
// text: '"',
// offset: 9,
// len: 1,
// line: 3,
// column: 7
// },
// {
// state: 'root',
// name: ':',
// text: ':',
// offset: 10,
// len: 1,
// line: 3,
// column: 8
// },
// ...
// {
// state: 'root',
// name: '}',
// text: '}',
// offset: 78,
// len: 1,
// line: 5,
// column: 1
// }
// ],
// offset: 80,
// complete: true
// }
// Complete output is in the test snapshot.