parse.js 22 KB

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