source: trip-planner-front/node_modules/json5/lib/parse.js@ 188ee53

Last change on this file since 188ee53 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 20.9 KB
RevLine 
[6a3a178]1const util = require('./util')
2
3let source
4let parseState
5let stack
6let pos
7let line
8let column
9let token
10let key
11let root
12
13module.exports = function parse (text, reviver) {
14 source = String(text)
15 parseState = 'start'
16 stack = []
17 pos = 0
18 line = 1
19 column = 0
20 token = undefined
21 key = undefined
22 root = undefined
23
24 do {
25 token = lex()
26
27 // This code is unreachable.
28 // if (!parseStates[parseState]) {
29 // throw invalidParseState()
30 // }
31
32 parseStates[parseState]()
33 } while (token.type !== 'eof')
34
35 if (typeof reviver === 'function') {
36 return internalize({'': root}, '', reviver)
37 }
38
39 return root
40}
41
42function internalize (holder, name, reviver) {
43 const value = holder[name]
44 if (value != null && typeof value === 'object') {
45 for (const key in value) {
46 const replacement = internalize(value, key, reviver)
47 if (replacement === undefined) {
48 delete value[key]
49 } else {
50 value[key] = replacement
51 }
52 }
53 }
54
55 return reviver.call(holder, name, value)
56}
57
58let lexState
59let buffer
60let doubleQuote
61let sign
62let c
63
64function lex () {
65 lexState = 'default'
66 buffer = ''
67 doubleQuote = false
68 sign = 1
69
70 for (;;) {
71 c = peek()
72
73 // This code is unreachable.
74 // if (!lexStates[lexState]) {
75 // throw invalidLexState(lexState)
76 // }
77
78 const token = lexStates[lexState]()
79 if (token) {
80 return token
81 }
82 }
83}
84
85function peek () {
86 if (source[pos]) {
87 return String.fromCodePoint(source.codePointAt(pos))
88 }
89}
90
91function read () {
92 const c = peek()
93
94 if (c === '\n') {
95 line++
96 column = 0
97 } else if (c) {
98 column += c.length
99 } else {
100 column++
101 }
102
103 if (c) {
104 pos += c.length
105 }
106
107 return c
108}
109
110const lexStates = {
111 default () {
112 switch (c) {
113 case '\t':
114 case '\v':
115 case '\f':
116 case ' ':
117 case '\u00A0':
118 case '\uFEFF':
119 case '\n':
120 case '\r':
121 case '\u2028':
122 case '\u2029':
123 read()
124 return
125
126 case '/':
127 read()
128 lexState = 'comment'
129 return
130
131 case undefined:
132 read()
133 return newToken('eof')
134 }
135
136 if (util.isSpaceSeparator(c)) {
137 read()
138 return
139 }
140
141 // This code is unreachable.
142 // if (!lexStates[parseState]) {
143 // throw invalidLexState(parseState)
144 // }
145
146 return lexStates[parseState]()
147 },
148
149 comment () {
150 switch (c) {
151 case '*':
152 read()
153 lexState = 'multiLineComment'
154 return
155
156 case '/':
157 read()
158 lexState = 'singleLineComment'
159 return
160 }
161
162 throw invalidChar(read())
163 },
164
165 multiLineComment () {
166 switch (c) {
167 case '*':
168 read()
169 lexState = 'multiLineCommentAsterisk'
170 return
171
172 case undefined:
173 throw invalidChar(read())
174 }
175
176 read()
177 },
178
179 multiLineCommentAsterisk () {
180 switch (c) {
181 case '*':
182 read()
183 return
184
185 case '/':
186 read()
187 lexState = 'default'
188 return
189
190 case undefined:
191 throw invalidChar(read())
192 }
193
194 read()
195 lexState = 'multiLineComment'
196 },
197
198 singleLineComment () {
199 switch (c) {
200 case '\n':
201 case '\r':
202 case '\u2028':
203 case '\u2029':
204 read()
205 lexState = 'default'
206 return
207
208 case undefined:
209 read()
210 return newToken('eof')
211 }
212
213 read()
214 },
215
216 value () {
217 switch (c) {
218 case '{':
219 case '[':
220 return newToken('punctuator', read())
221
222 case 'n':
223 read()
224 literal('ull')
225 return newToken('null', null)
226
227 case 't':
228 read()
229 literal('rue')
230 return newToken('boolean', true)
231
232 case 'f':
233 read()
234 literal('alse')
235 return newToken('boolean', false)
236
237 case '-':
238 case '+':
239 if (read() === '-') {
240 sign = -1
241 }
242
243 lexState = 'sign'
244 return
245
246 case '.':
247 buffer = read()
248 lexState = 'decimalPointLeading'
249 return
250
251 case '0':
252 buffer = read()
253 lexState = 'zero'
254 return
255
256 case '1':
257 case '2':
258 case '3':
259 case '4':
260 case '5':
261 case '6':
262 case '7':
263 case '8':
264 case '9':
265 buffer = read()
266 lexState = 'decimalInteger'
267 return
268
269 case 'I':
270 read()
271 literal('nfinity')
272 return newToken('numeric', Infinity)
273
274 case 'N':
275 read()
276 literal('aN')
277 return newToken('numeric', NaN)
278
279 case '"':
280 case "'":
281 doubleQuote = (read() === '"')
282 buffer = ''
283 lexState = 'string'
284 return
285 }
286
287 throw invalidChar(read())
288 },
289
290 identifierNameStartEscape () {
291 if (c !== 'u') {
292 throw invalidChar(read())
293 }
294
295 read()
296 const u = unicodeEscape()
297 switch (u) {
298 case '$':
299 case '_':
300 break
301
302 default:
303 if (!util.isIdStartChar(u)) {
304 throw invalidIdentifier()
305 }
306
307 break
308 }
309
310 buffer += u
311 lexState = 'identifierName'
312 },
313
314 identifierName () {
315 switch (c) {
316 case '$':
317 case '_':
318 case '\u200C':
319 case '\u200D':
320 buffer += read()
321 return
322
323 case '\\':
324 read()
325 lexState = 'identifierNameEscape'
326 return
327 }
328
329 if (util.isIdContinueChar(c)) {
330 buffer += read()
331 return
332 }
333
334 return newToken('identifier', buffer)
335 },
336
337 identifierNameEscape () {
338 if (c !== 'u') {
339 throw invalidChar(read())
340 }
341
342 read()
343 const u = unicodeEscape()
344 switch (u) {
345 case '$':
346 case '_':
347 case '\u200C':
348 case '\u200D':
349 break
350
351 default:
352 if (!util.isIdContinueChar(u)) {
353 throw invalidIdentifier()
354 }
355
356 break
357 }
358
359 buffer += u
360 lexState = 'identifierName'
361 },
362
363 sign () {
364 switch (c) {
365 case '.':
366 buffer = read()
367 lexState = 'decimalPointLeading'
368 return
369
370 case '0':
371 buffer = read()
372 lexState = 'zero'
373 return
374
375 case '1':
376 case '2':
377 case '3':
378 case '4':
379 case '5':
380 case '6':
381 case '7':
382 case '8':
383 case '9':
384 buffer = read()
385 lexState = 'decimalInteger'
386 return
387
388 case 'I':
389 read()
390 literal('nfinity')
391 return newToken('numeric', sign * Infinity)
392
393 case 'N':
394 read()
395 literal('aN')
396 return newToken('numeric', NaN)
397 }
398
399 throw invalidChar(read())
400 },
401
402 zero () {
403 switch (c) {
404 case '.':
405 buffer += read()
406 lexState = 'decimalPoint'
407 return
408
409 case 'e':
410 case 'E':
411 buffer += read()
412 lexState = 'decimalExponent'
413 return
414
415 case 'x':
416 case 'X':
417 buffer += read()
418 lexState = 'hexadecimal'
419 return
420 }
421
422 return newToken('numeric', sign * 0)
423 },
424
425 decimalInteger () {
426 switch (c) {
427 case '.':
428 buffer += read()
429 lexState = 'decimalPoint'
430 return
431
432 case 'e':
433 case 'E':
434 buffer += read()
435 lexState = 'decimalExponent'
436 return
437 }
438
439 if (util.isDigit(c)) {
440 buffer += read()
441 return
442 }
443
444 return newToken('numeric', sign * Number(buffer))
445 },
446
447 decimalPointLeading () {
448 if (util.isDigit(c)) {
449 buffer += read()
450 lexState = 'decimalFraction'
451 return
452 }
453
454 throw invalidChar(read())
455 },
456
457 decimalPoint () {
458 switch (c) {
459 case 'e':
460 case 'E':
461 buffer += read()
462 lexState = 'decimalExponent'
463 return
464 }
465
466 if (util.isDigit(c)) {
467 buffer += read()
468 lexState = 'decimalFraction'
469 return
470 }
471
472 return newToken('numeric', sign * Number(buffer))
473 },
474
475 decimalFraction () {
476 switch (c) {
477 case 'e':
478 case 'E':
479 buffer += read()
480 lexState = 'decimalExponent'
481 return
482 }
483
484 if (util.isDigit(c)) {
485 buffer += read()
486 return
487 }
488
489 return newToken('numeric', sign * Number(buffer))
490 },
491
492 decimalExponent () {
493 switch (c) {
494 case '+':
495 case '-':
496 buffer += read()
497 lexState = 'decimalExponentSign'
498 return
499 }
500
501 if (util.isDigit(c)) {
502 buffer += read()
503 lexState = 'decimalExponentInteger'
504 return
505 }
506
507 throw invalidChar(read())
508 },
509
510 decimalExponentSign () {
511 if (util.isDigit(c)) {
512 buffer += read()
513 lexState = 'decimalExponentInteger'
514 return
515 }
516
517 throw invalidChar(read())
518 },
519
520 decimalExponentInteger () {
521 if (util.isDigit(c)) {
522 buffer += read()
523 return
524 }
525
526 return newToken('numeric', sign * Number(buffer))
527 },
528
529 hexadecimal () {
530 if (util.isHexDigit(c)) {
531 buffer += read()
532 lexState = 'hexadecimalInteger'
533 return
534 }
535
536 throw invalidChar(read())
537 },
538
539 hexadecimalInteger () {
540 if (util.isHexDigit(c)) {
541 buffer += read()
542 return
543 }
544
545 return newToken('numeric', sign * Number(buffer))
546 },
547
548 string () {
549 switch (c) {
550 case '\\':
551 read()
552 buffer += escape()
553 return
554
555 case '"':
556 if (doubleQuote) {
557 read()
558 return newToken('string', buffer)
559 }
560
561 buffer += read()
562 return
563
564 case "'":
565 if (!doubleQuote) {
566 read()
567 return newToken('string', buffer)
568 }
569
570 buffer += read()
571 return
572
573 case '\n':
574 case '\r':
575 throw invalidChar(read())
576
577 case '\u2028':
578 case '\u2029':
579 separatorChar(c)
580 break
581
582 case undefined:
583 throw invalidChar(read())
584 }
585
586 buffer += read()
587 },
588
589 start () {
590 switch (c) {
591 case '{':
592 case '[':
593 return newToken('punctuator', read())
594
595 // This code is unreachable since the default lexState handles eof.
596 // case undefined:
597 // return newToken('eof')
598 }
599
600 lexState = 'value'
601 },
602
603 beforePropertyName () {
604 switch (c) {
605 case '$':
606 case '_':
607 buffer = read()
608 lexState = 'identifierName'
609 return
610
611 case '\\':
612 read()
613 lexState = 'identifierNameStartEscape'
614 return
615
616 case '}':
617 return newToken('punctuator', read())
618
619 case '"':
620 case "'":
621 doubleQuote = (read() === '"')
622 lexState = 'string'
623 return
624 }
625
626 if (util.isIdStartChar(c)) {
627 buffer += read()
628 lexState = 'identifierName'
629 return
630 }
631
632 throw invalidChar(read())
633 },
634
635 afterPropertyName () {
636 if (c === ':') {
637 return newToken('punctuator', read())
638 }
639
640 throw invalidChar(read())
641 },
642
643 beforePropertyValue () {
644 lexState = 'value'
645 },
646
647 afterPropertyValue () {
648 switch (c) {
649 case ',':
650 case '}':
651 return newToken('punctuator', read())
652 }
653
654 throw invalidChar(read())
655 },
656
657 beforeArrayValue () {
658 if (c === ']') {
659 return newToken('punctuator', read())
660 }
661
662 lexState = 'value'
663 },
664
665 afterArrayValue () {
666 switch (c) {
667 case ',':
668 case ']':
669 return newToken('punctuator', read())
670 }
671
672 throw invalidChar(read())
673 },
674
675 end () {
676 // This code is unreachable since it's handled by the default lexState.
677 // if (c === undefined) {
678 // read()
679 // return newToken('eof')
680 // }
681
682 throw invalidChar(read())
683 },
684}
685
686function newToken (type, value) {
687 return {
688 type,
689 value,
690 line,
691 column,
692 }
693}
694
695function literal (s) {
696 for (const c of s) {
697 const p = peek()
698
699 if (p !== c) {
700 throw invalidChar(read())
701 }
702
703 read()
704 }
705}
706
707function escape () {
708 const c = peek()
709 switch (c) {
710 case 'b':
711 read()
712 return '\b'
713
714 case 'f':
715 read()
716 return '\f'
717
718 case 'n':
719 read()
720 return '\n'
721
722 case 'r':
723 read()
724 return '\r'
725
726 case 't':
727 read()
728 return '\t'
729
730 case 'v':
731 read()
732 return '\v'
733
734 case '0':
735 read()
736 if (util.isDigit(peek())) {
737 throw invalidChar(read())
738 }
739
740 return '\0'
741
742 case 'x':
743 read()
744 return hexEscape()
745
746 case 'u':
747 read()
748 return unicodeEscape()
749
750 case '\n':
751 case '\u2028':
752 case '\u2029':
753 read()
754 return ''
755
756 case '\r':
757 read()
758 if (peek() === '\n') {
759 read()
760 }
761
762 return ''
763
764 case '1':
765 case '2':
766 case '3':
767 case '4':
768 case '5':
769 case '6':
770 case '7':
771 case '8':
772 case '9':
773 throw invalidChar(read())
774
775 case undefined:
776 throw invalidChar(read())
777 }
778
779 return read()
780}
781
782function hexEscape () {
783 let buffer = ''
784 let c = peek()
785
786 if (!util.isHexDigit(c)) {
787 throw invalidChar(read())
788 }
789
790 buffer += read()
791
792 c = peek()
793 if (!util.isHexDigit(c)) {
794 throw invalidChar(read())
795 }
796
797 buffer += read()
798
799 return String.fromCodePoint(parseInt(buffer, 16))
800}
801
802function unicodeEscape () {
803 let buffer = ''
804 let count = 4
805
806 while (count-- > 0) {
807 const c = peek()
808 if (!util.isHexDigit(c)) {
809 throw invalidChar(read())
810 }
811
812 buffer += read()
813 }
814
815 return String.fromCodePoint(parseInt(buffer, 16))
816}
817
818const parseStates = {
819 start () {
820 if (token.type === 'eof') {
821 throw invalidEOF()
822 }
823
824 push()
825 },
826
827 beforePropertyName () {
828 switch (token.type) {
829 case 'identifier':
830 case 'string':
831 key = token.value
832 parseState = 'afterPropertyName'
833 return
834
835 case 'punctuator':
836 // This code is unreachable since it's handled by the lexState.
837 // if (token.value !== '}') {
838 // throw invalidToken()
839 // }
840
841 pop()
842 return
843
844 case 'eof':
845 throw invalidEOF()
846 }
847
848 // This code is unreachable since it's handled by the lexState.
849 // throw invalidToken()
850 },
851
852 afterPropertyName () {
853 // This code is unreachable since it's handled by the lexState.
854 // if (token.type !== 'punctuator' || token.value !== ':') {
855 // throw invalidToken()
856 // }
857
858 if (token.type === 'eof') {
859 throw invalidEOF()
860 }
861
862 parseState = 'beforePropertyValue'
863 },
864
865 beforePropertyValue () {
866 if (token.type === 'eof') {
867 throw invalidEOF()
868 }
869
870 push()
871 },
872
873 beforeArrayValue () {
874 if (token.type === 'eof') {
875 throw invalidEOF()
876 }
877
878 if (token.type === 'punctuator' && token.value === ']') {
879 pop()
880 return
881 }
882
883 push()
884 },
885
886 afterPropertyValue () {
887 // This code is unreachable since it's handled by the lexState.
888 // if (token.type !== 'punctuator') {
889 // throw invalidToken()
890 // }
891
892 if (token.type === 'eof') {
893 throw invalidEOF()
894 }
895
896 switch (token.value) {
897 case ',':
898 parseState = 'beforePropertyName'
899 return
900
901 case '}':
902 pop()
903 }
904
905 // This code is unreachable since it's handled by the lexState.
906 // throw invalidToken()
907 },
908
909 afterArrayValue () {
910 // This code is unreachable since it's handled by the lexState.
911 // if (token.type !== 'punctuator') {
912 // throw invalidToken()
913 // }
914
915 if (token.type === 'eof') {
916 throw invalidEOF()
917 }
918
919 switch (token.value) {
920 case ',':
921 parseState = 'beforeArrayValue'
922 return
923
924 case ']':
925 pop()
926 }
927
928 // This code is unreachable since it's handled by the lexState.
929 // throw invalidToken()
930 },
931
932 end () {
933 // This code is unreachable since it's handled by the lexState.
934 // if (token.type !== 'eof') {
935 // throw invalidToken()
936 // }
937 },
938}
939
940function push () {
941 let value
942
943 switch (token.type) {
944 case 'punctuator':
945 switch (token.value) {
946 case '{':
947 value = {}
948 break
949
950 case '[':
951 value = []
952 break
953 }
954
955 break
956
957 case 'null':
958 case 'boolean':
959 case 'numeric':
960 case 'string':
961 value = token.value
962 break
963
964 // This code is unreachable.
965 // default:
966 // throw invalidToken()
967 }
968
969 if (root === undefined) {
970 root = value
971 } else {
972 const parent = stack[stack.length - 1]
973 if (Array.isArray(parent)) {
974 parent.push(value)
975 } else {
976 parent[key] = value
977 }
978 }
979
980 if (value !== null && typeof value === 'object') {
981 stack.push(value)
982
983 if (Array.isArray(value)) {
984 parseState = 'beforeArrayValue'
985 } else {
986 parseState = 'beforePropertyName'
987 }
988 } else {
989 const current = stack[stack.length - 1]
990 if (current == null) {
991 parseState = 'end'
992 } else if (Array.isArray(current)) {
993 parseState = 'afterArrayValue'
994 } else {
995 parseState = 'afterPropertyValue'
996 }
997 }
998}
999
1000function pop () {
1001 stack.pop()
1002
1003 const current = stack[stack.length - 1]
1004 if (current == null) {
1005 parseState = 'end'
1006 } else if (Array.isArray(current)) {
1007 parseState = 'afterArrayValue'
1008 } else {
1009 parseState = 'afterPropertyValue'
1010 }
1011}
1012
1013// This code is unreachable.
1014// function invalidParseState () {
1015// return new Error(`JSON5: invalid parse state '${parseState}'`)
1016// }
1017
1018// This code is unreachable.
1019// function invalidLexState (state) {
1020// return new Error(`JSON5: invalid lex state '${state}'`)
1021// }
1022
1023function invalidChar (c) {
1024 if (c === undefined) {
1025 return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
1026 }
1027
1028 return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
1029}
1030
1031function invalidEOF () {
1032 return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
1033}
1034
1035// This code is unreachable.
1036// function invalidToken () {
1037// if (token.type === 'eof') {
1038// return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
1039// }
1040
1041// const c = String.fromCodePoint(token.value.codePointAt(0))
1042// return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
1043// }
1044
1045function invalidIdentifier () {
1046 column -= 5
1047 return syntaxError(`JSON5: invalid identifier character at ${line}:${column}`)
1048}
1049
1050function separatorChar (c) {
1051 console.warn(`JSON5: '${formatChar(c)}' in strings is not valid ECMAScript; consider escaping`)
1052}
1053
1054function formatChar (c) {
1055 const replacements = {
1056 "'": "\\'",
1057 '"': '\\"',
1058 '\\': '\\\\',
1059 '\b': '\\b',
1060 '\f': '\\f',
1061 '\n': '\\n',
1062 '\r': '\\r',
1063 '\t': '\\t',
1064 '\v': '\\v',
1065 '\0': '\\0',
1066 '\u2028': '\\u2028',
1067 '\u2029': '\\u2029',
1068 }
1069
1070 if (replacements[c]) {
1071 return replacements[c]
1072 }
1073
1074 if (c < ' ') {
1075 const hexString = c.charCodeAt(0).toString(16)
1076 return '\\x' + ('00' + hexString).substring(hexString.length)
1077 }
1078
1079 return c
1080}
1081
1082function syntaxError (message) {
1083 const err = new SyntaxError(message)
1084 err.lineNumber = line
1085 err.columnNumber = column
1086 return err
1087}
Note: See TracBrowser for help on using the repository browser.