parser.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. (function (factory) {
  2. if (typeof module === "object" && typeof module.exports === "object") {
  3. var v = factory(require, exports);
  4. if (v !== undefined) module.exports = v;
  5. }
  6. else if (typeof define === "function" && define.amd) {
  7. define(["require", "exports", "./scanner"], factory);
  8. }
  9. })(function (require, exports) {
  10. /*---------------------------------------------------------------------------------------------
  11. * Copyright (c) Microsoft Corporation. All rights reserved.
  12. * Licensed under the MIT License. See License.txt in the project root for license information.
  13. *--------------------------------------------------------------------------------------------*/
  14. 'use strict';
  15. Object.defineProperty(exports, "__esModule", { value: true });
  16. exports.getNodeType = exports.stripComments = exports.visit = exports.findNodeAtOffset = exports.contains = exports.getNodeValue = exports.getNodePath = exports.findNodeAtLocation = exports.parseTree = exports.parse = exports.getLocation = void 0;
  17. const scanner_1 = require("./scanner");
  18. var ParseOptions;
  19. (function (ParseOptions) {
  20. ParseOptions.DEFAULT = {
  21. allowTrailingComma: false
  22. };
  23. })(ParseOptions || (ParseOptions = {}));
  24. /**
  25. * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.
  26. */
  27. function getLocation(text, position) {
  28. const segments = []; // strings or numbers
  29. const earlyReturnException = new Object();
  30. let previousNode = undefined;
  31. const previousNodeInst = {
  32. value: {},
  33. offset: 0,
  34. length: 0,
  35. type: 'object',
  36. parent: undefined
  37. };
  38. let isAtPropertyKey = false;
  39. function setPreviousNode(value, offset, length, type) {
  40. previousNodeInst.value = value;
  41. previousNodeInst.offset = offset;
  42. previousNodeInst.length = length;
  43. previousNodeInst.type = type;
  44. previousNodeInst.colonOffset = undefined;
  45. previousNode = previousNodeInst;
  46. }
  47. try {
  48. visit(text, {
  49. onObjectBegin: (offset, length) => {
  50. if (position <= offset) {
  51. throw earlyReturnException;
  52. }
  53. previousNode = undefined;
  54. isAtPropertyKey = position > offset;
  55. segments.push(''); // push a placeholder (will be replaced)
  56. },
  57. onObjectProperty: (name, offset, length) => {
  58. if (position < offset) {
  59. throw earlyReturnException;
  60. }
  61. setPreviousNode(name, offset, length, 'property');
  62. segments[segments.length - 1] = name;
  63. if (position <= offset + length) {
  64. throw earlyReturnException;
  65. }
  66. },
  67. onObjectEnd: (offset, length) => {
  68. if (position <= offset) {
  69. throw earlyReturnException;
  70. }
  71. previousNode = undefined;
  72. segments.pop();
  73. },
  74. onArrayBegin: (offset, length) => {
  75. if (position <= offset) {
  76. throw earlyReturnException;
  77. }
  78. previousNode = undefined;
  79. segments.push(0);
  80. },
  81. onArrayEnd: (offset, length) => {
  82. if (position <= offset) {
  83. throw earlyReturnException;
  84. }
  85. previousNode = undefined;
  86. segments.pop();
  87. },
  88. onLiteralValue: (value, offset, length) => {
  89. if (position < offset) {
  90. throw earlyReturnException;
  91. }
  92. setPreviousNode(value, offset, length, getNodeType(value));
  93. if (position <= offset + length) {
  94. throw earlyReturnException;
  95. }
  96. },
  97. onSeparator: (sep, offset, length) => {
  98. if (position <= offset) {
  99. throw earlyReturnException;
  100. }
  101. if (sep === ':' && previousNode && previousNode.type === 'property') {
  102. previousNode.colonOffset = offset;
  103. isAtPropertyKey = false;
  104. previousNode = undefined;
  105. }
  106. else if (sep === ',') {
  107. const last = segments[segments.length - 1];
  108. if (typeof last === 'number') {
  109. segments[segments.length - 1] = last + 1;
  110. }
  111. else {
  112. isAtPropertyKey = true;
  113. segments[segments.length - 1] = '';
  114. }
  115. previousNode = undefined;
  116. }
  117. }
  118. });
  119. }
  120. catch (e) {
  121. if (e !== earlyReturnException) {
  122. throw e;
  123. }
  124. }
  125. return {
  126. path: segments,
  127. previousNode,
  128. isAtPropertyKey,
  129. matches: (pattern) => {
  130. let k = 0;
  131. for (let i = 0; k < pattern.length && i < segments.length; i++) {
  132. if (pattern[k] === segments[i] || pattern[k] === '*') {
  133. k++;
  134. }
  135. else if (pattern[k] !== '**') {
  136. return false;
  137. }
  138. }
  139. return k === pattern.length;
  140. }
  141. };
  142. }
  143. exports.getLocation = getLocation;
  144. /**
  145. * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
  146. * Therefore always check the errors list to find out if the input was valid.
  147. */
  148. function parse(text, errors = [], options = ParseOptions.DEFAULT) {
  149. let currentProperty = null;
  150. let currentParent = [];
  151. const previousParents = [];
  152. function onValue(value) {
  153. if (Array.isArray(currentParent)) {
  154. currentParent.push(value);
  155. }
  156. else if (currentProperty !== null) {
  157. currentParent[currentProperty] = value;
  158. }
  159. }
  160. const visitor = {
  161. onObjectBegin: () => {
  162. const object = {};
  163. onValue(object);
  164. previousParents.push(currentParent);
  165. currentParent = object;
  166. currentProperty = null;
  167. },
  168. onObjectProperty: (name) => {
  169. currentProperty = name;
  170. },
  171. onObjectEnd: () => {
  172. currentParent = previousParents.pop();
  173. },
  174. onArrayBegin: () => {
  175. const array = [];
  176. onValue(array);
  177. previousParents.push(currentParent);
  178. currentParent = array;
  179. currentProperty = null;
  180. },
  181. onArrayEnd: () => {
  182. currentParent = previousParents.pop();
  183. },
  184. onLiteralValue: onValue,
  185. onError: (error, offset, length) => {
  186. errors.push({ error, offset, length });
  187. }
  188. };
  189. visit(text, visitor, options);
  190. return currentParent[0];
  191. }
  192. exports.parse = parse;
  193. /**
  194. * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
  195. */
  196. function parseTree(text, errors = [], options = ParseOptions.DEFAULT) {
  197. let currentParent = { type: 'array', offset: -1, length: -1, children: [], parent: undefined }; // artificial root
  198. function ensurePropertyComplete(endOffset) {
  199. if (currentParent.type === 'property') {
  200. currentParent.length = endOffset - currentParent.offset;
  201. currentParent = currentParent.parent;
  202. }
  203. }
  204. function onValue(valueNode) {
  205. currentParent.children.push(valueNode);
  206. return valueNode;
  207. }
  208. const visitor = {
  209. onObjectBegin: (offset) => {
  210. currentParent = onValue({ type: 'object', offset, length: -1, parent: currentParent, children: [] });
  211. },
  212. onObjectProperty: (name, offset, length) => {
  213. currentParent = onValue({ type: 'property', offset, length: -1, parent: currentParent, children: [] });
  214. currentParent.children.push({ type: 'string', value: name, offset, length, parent: currentParent });
  215. },
  216. onObjectEnd: (offset, length) => {
  217. ensurePropertyComplete(offset + length); // in case of a missing value for a property: make sure property is complete
  218. currentParent.length = offset + length - currentParent.offset;
  219. currentParent = currentParent.parent;
  220. ensurePropertyComplete(offset + length);
  221. },
  222. onArrayBegin: (offset, length) => {
  223. currentParent = onValue({ type: 'array', offset, length: -1, parent: currentParent, children: [] });
  224. },
  225. onArrayEnd: (offset, length) => {
  226. currentParent.length = offset + length - currentParent.offset;
  227. currentParent = currentParent.parent;
  228. ensurePropertyComplete(offset + length);
  229. },
  230. onLiteralValue: (value, offset, length) => {
  231. onValue({ type: getNodeType(value), offset, length, parent: currentParent, value });
  232. ensurePropertyComplete(offset + length);
  233. },
  234. onSeparator: (sep, offset, length) => {
  235. if (currentParent.type === 'property') {
  236. if (sep === ':') {
  237. currentParent.colonOffset = offset;
  238. }
  239. else if (sep === ',') {
  240. ensurePropertyComplete(offset);
  241. }
  242. }
  243. },
  244. onError: (error, offset, length) => {
  245. errors.push({ error, offset, length });
  246. }
  247. };
  248. visit(text, visitor, options);
  249. const result = currentParent.children[0];
  250. if (result) {
  251. delete result.parent;
  252. }
  253. return result;
  254. }
  255. exports.parseTree = parseTree;
  256. /**
  257. * Finds the node at the given path in a JSON DOM.
  258. */
  259. function findNodeAtLocation(root, path) {
  260. if (!root) {
  261. return undefined;
  262. }
  263. let node = root;
  264. for (let segment of path) {
  265. if (typeof segment === 'string') {
  266. if (node.type !== 'object' || !Array.isArray(node.children)) {
  267. return undefined;
  268. }
  269. let found = false;
  270. for (const propertyNode of node.children) {
  271. if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment && propertyNode.children.length === 2) {
  272. node = propertyNode.children[1];
  273. found = true;
  274. break;
  275. }
  276. }
  277. if (!found) {
  278. return undefined;
  279. }
  280. }
  281. else {
  282. const index = segment;
  283. if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {
  284. return undefined;
  285. }
  286. node = node.children[index];
  287. }
  288. }
  289. return node;
  290. }
  291. exports.findNodeAtLocation = findNodeAtLocation;
  292. /**
  293. * Gets the JSON path of the given JSON DOM node
  294. */
  295. function getNodePath(node) {
  296. if (!node.parent || !node.parent.children) {
  297. return [];
  298. }
  299. const path = getNodePath(node.parent);
  300. if (node.parent.type === 'property') {
  301. const key = node.parent.children[0].value;
  302. path.push(key);
  303. }
  304. else if (node.parent.type === 'array') {
  305. const index = node.parent.children.indexOf(node);
  306. if (index !== -1) {
  307. path.push(index);
  308. }
  309. }
  310. return path;
  311. }
  312. exports.getNodePath = getNodePath;
  313. /**
  314. * Evaluates the JavaScript object of the given JSON DOM node
  315. */
  316. function getNodeValue(node) {
  317. switch (node.type) {
  318. case 'array':
  319. return node.children.map(getNodeValue);
  320. case 'object':
  321. const obj = Object.create(null);
  322. for (let prop of node.children) {
  323. const valueNode = prop.children[1];
  324. if (valueNode) {
  325. obj[prop.children[0].value] = getNodeValue(valueNode);
  326. }
  327. }
  328. return obj;
  329. case 'null':
  330. case 'string':
  331. case 'number':
  332. case 'boolean':
  333. return node.value;
  334. default:
  335. return undefined;
  336. }
  337. }
  338. exports.getNodeValue = getNodeValue;
  339. function contains(node, offset, includeRightBound = false) {
  340. return (offset >= node.offset && offset < (node.offset + node.length)) || includeRightBound && (offset === (node.offset + node.length));
  341. }
  342. exports.contains = contains;
  343. /**
  344. * Finds the most inner node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.
  345. */
  346. function findNodeAtOffset(node, offset, includeRightBound = false) {
  347. if (contains(node, offset, includeRightBound)) {
  348. const children = node.children;
  349. if (Array.isArray(children)) {
  350. for (let i = 0; i < children.length && children[i].offset <= offset; i++) {
  351. const item = findNodeAtOffset(children[i], offset, includeRightBound);
  352. if (item) {
  353. return item;
  354. }
  355. }
  356. }
  357. return node;
  358. }
  359. return undefined;
  360. }
  361. exports.findNodeAtOffset = findNodeAtOffset;
  362. /**
  363. * Parses the given text and invokes the visitor functions for each object, array and literal reached.
  364. */
  365. function visit(text, visitor, options = ParseOptions.DEFAULT) {
  366. const _scanner = (0, scanner_1.createScanner)(text, false);
  367. // Important: Only pass copies of this to visitor functions to prevent accidental modification, and
  368. // to not affect visitor functions which stored a reference to a previous JSONPath
  369. const _jsonPath = [];
  370. // Depth of onXXXBegin() callbacks suppressed. onXXXEnd() decrements this if it isn't 0 already.
  371. // Callbacks are only called when this value is 0.
  372. let suppressedCallbacks = 0;
  373. function toNoArgVisit(visitFunction) {
  374. return visitFunction ? () => suppressedCallbacks === 0 && visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
  375. }
  376. function toOneArgVisit(visitFunction) {
  377. return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
  378. }
  379. function toOneArgVisitWithPath(visitFunction) {
  380. return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice()) : () => true;
  381. }
  382. function toBeginVisit(visitFunction) {
  383. return visitFunction ?
  384. () => {
  385. if (suppressedCallbacks > 0) {
  386. suppressedCallbacks++;
  387. }
  388. else {
  389. let cbReturn = visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice());
  390. if (cbReturn === false) {
  391. suppressedCallbacks = 1;
  392. }
  393. }
  394. }
  395. : () => true;
  396. }
  397. function toEndVisit(visitFunction) {
  398. return visitFunction ?
  399. () => {
  400. if (suppressedCallbacks > 0) {
  401. suppressedCallbacks--;
  402. }
  403. if (suppressedCallbacks === 0) {
  404. visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
  405. }
  406. }
  407. : () => true;
  408. }
  409. const onObjectBegin = toBeginVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisitWithPath(visitor.onObjectProperty), onObjectEnd = toEndVisit(visitor.onObjectEnd), onArrayBegin = toBeginVisit(visitor.onArrayBegin), onArrayEnd = toEndVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisitWithPath(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);
  410. const disallowComments = options && options.disallowComments;
  411. const allowTrailingComma = options && options.allowTrailingComma;
  412. function scanNext() {
  413. while (true) {
  414. const token = _scanner.scan();
  415. switch (_scanner.getTokenError()) {
  416. case 4 /* ScanError.InvalidUnicode */:
  417. handleError(14 /* ParseErrorCode.InvalidUnicode */);
  418. break;
  419. case 5 /* ScanError.InvalidEscapeCharacter */:
  420. handleError(15 /* ParseErrorCode.InvalidEscapeCharacter */);
  421. break;
  422. case 3 /* ScanError.UnexpectedEndOfNumber */:
  423. handleError(13 /* ParseErrorCode.UnexpectedEndOfNumber */);
  424. break;
  425. case 1 /* ScanError.UnexpectedEndOfComment */:
  426. if (!disallowComments) {
  427. handleError(11 /* ParseErrorCode.UnexpectedEndOfComment */);
  428. }
  429. break;
  430. case 2 /* ScanError.UnexpectedEndOfString */:
  431. handleError(12 /* ParseErrorCode.UnexpectedEndOfString */);
  432. break;
  433. case 6 /* ScanError.InvalidCharacter */:
  434. handleError(16 /* ParseErrorCode.InvalidCharacter */);
  435. break;
  436. }
  437. switch (token) {
  438. case 12 /* SyntaxKind.LineCommentTrivia */:
  439. case 13 /* SyntaxKind.BlockCommentTrivia */:
  440. if (disallowComments) {
  441. handleError(10 /* ParseErrorCode.InvalidCommentToken */);
  442. }
  443. else {
  444. onComment();
  445. }
  446. break;
  447. case 16 /* SyntaxKind.Unknown */:
  448. handleError(1 /* ParseErrorCode.InvalidSymbol */);
  449. break;
  450. case 15 /* SyntaxKind.Trivia */:
  451. case 14 /* SyntaxKind.LineBreakTrivia */:
  452. break;
  453. default:
  454. return token;
  455. }
  456. }
  457. }
  458. function handleError(error, skipUntilAfter = [], skipUntil = []) {
  459. onError(error);
  460. if (skipUntilAfter.length + skipUntil.length > 0) {
  461. let token = _scanner.getToken();
  462. while (token !== 17 /* SyntaxKind.EOF */) {
  463. if (skipUntilAfter.indexOf(token) !== -1) {
  464. scanNext();
  465. break;
  466. }
  467. else if (skipUntil.indexOf(token) !== -1) {
  468. break;
  469. }
  470. token = scanNext();
  471. }
  472. }
  473. }
  474. function parseString(isValue) {
  475. const value = _scanner.getTokenValue();
  476. if (isValue) {
  477. onLiteralValue(value);
  478. }
  479. else {
  480. onObjectProperty(value);
  481. // add property name afterwards
  482. _jsonPath.push(value);
  483. }
  484. scanNext();
  485. return true;
  486. }
  487. function parseLiteral() {
  488. switch (_scanner.getToken()) {
  489. case 11 /* SyntaxKind.NumericLiteral */:
  490. const tokenValue = _scanner.getTokenValue();
  491. let value = Number(tokenValue);
  492. if (isNaN(value)) {
  493. handleError(2 /* ParseErrorCode.InvalidNumberFormat */);
  494. value = 0;
  495. }
  496. onLiteralValue(value);
  497. break;
  498. case 7 /* SyntaxKind.NullKeyword */:
  499. onLiteralValue(null);
  500. break;
  501. case 8 /* SyntaxKind.TrueKeyword */:
  502. onLiteralValue(true);
  503. break;
  504. case 9 /* SyntaxKind.FalseKeyword */:
  505. onLiteralValue(false);
  506. break;
  507. default:
  508. return false;
  509. }
  510. scanNext();
  511. return true;
  512. }
  513. function parseProperty() {
  514. if (_scanner.getToken() !== 10 /* SyntaxKind.StringLiteral */) {
  515. handleError(3 /* ParseErrorCode.PropertyNameExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);
  516. return false;
  517. }
  518. parseString(false);
  519. if (_scanner.getToken() === 6 /* SyntaxKind.ColonToken */) {
  520. onSeparator(':');
  521. scanNext(); // consume colon
  522. if (!parseValue()) {
  523. handleError(4 /* ParseErrorCode.ValueExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);
  524. }
  525. }
  526. else {
  527. handleError(5 /* ParseErrorCode.ColonExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);
  528. }
  529. _jsonPath.pop(); // remove processed property name
  530. return true;
  531. }
  532. function parseObject() {
  533. onObjectBegin();
  534. scanNext(); // consume open brace
  535. let needsComma = false;
  536. while (_scanner.getToken() !== 2 /* SyntaxKind.CloseBraceToken */ && _scanner.getToken() !== 17 /* SyntaxKind.EOF */) {
  537. if (_scanner.getToken() === 5 /* SyntaxKind.CommaToken */) {
  538. if (!needsComma) {
  539. handleError(4 /* ParseErrorCode.ValueExpected */, [], []);
  540. }
  541. onSeparator(',');
  542. scanNext(); // consume comma
  543. if (_scanner.getToken() === 2 /* SyntaxKind.CloseBraceToken */ && allowTrailingComma) {
  544. break;
  545. }
  546. }
  547. else if (needsComma) {
  548. handleError(6 /* ParseErrorCode.CommaExpected */, [], []);
  549. }
  550. if (!parseProperty()) {
  551. handleError(4 /* ParseErrorCode.ValueExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);
  552. }
  553. needsComma = true;
  554. }
  555. onObjectEnd();
  556. if (_scanner.getToken() !== 2 /* SyntaxKind.CloseBraceToken */) {
  557. handleError(7 /* ParseErrorCode.CloseBraceExpected */, [2 /* SyntaxKind.CloseBraceToken */], []);
  558. }
  559. else {
  560. scanNext(); // consume close brace
  561. }
  562. return true;
  563. }
  564. function parseArray() {
  565. onArrayBegin();
  566. scanNext(); // consume open bracket
  567. let isFirstElement = true;
  568. let needsComma = false;
  569. while (_scanner.getToken() !== 4 /* SyntaxKind.CloseBracketToken */ && _scanner.getToken() !== 17 /* SyntaxKind.EOF */) {
  570. if (_scanner.getToken() === 5 /* SyntaxKind.CommaToken */) {
  571. if (!needsComma) {
  572. handleError(4 /* ParseErrorCode.ValueExpected */, [], []);
  573. }
  574. onSeparator(',');
  575. scanNext(); // consume comma
  576. if (_scanner.getToken() === 4 /* SyntaxKind.CloseBracketToken */ && allowTrailingComma) {
  577. break;
  578. }
  579. }
  580. else if (needsComma) {
  581. handleError(6 /* ParseErrorCode.CommaExpected */, [], []);
  582. }
  583. if (isFirstElement) {
  584. _jsonPath.push(0);
  585. isFirstElement = false;
  586. }
  587. else {
  588. _jsonPath[_jsonPath.length - 1]++;
  589. }
  590. if (!parseValue()) {
  591. handleError(4 /* ParseErrorCode.ValueExpected */, [], [4 /* SyntaxKind.CloseBracketToken */, 5 /* SyntaxKind.CommaToken */]);
  592. }
  593. needsComma = true;
  594. }
  595. onArrayEnd();
  596. if (!isFirstElement) {
  597. _jsonPath.pop(); // remove array index
  598. }
  599. if (_scanner.getToken() !== 4 /* SyntaxKind.CloseBracketToken */) {
  600. handleError(8 /* ParseErrorCode.CloseBracketExpected */, [4 /* SyntaxKind.CloseBracketToken */], []);
  601. }
  602. else {
  603. scanNext(); // consume close bracket
  604. }
  605. return true;
  606. }
  607. function parseValue() {
  608. switch (_scanner.getToken()) {
  609. case 3 /* SyntaxKind.OpenBracketToken */:
  610. return parseArray();
  611. case 1 /* SyntaxKind.OpenBraceToken */:
  612. return parseObject();
  613. case 10 /* SyntaxKind.StringLiteral */:
  614. return parseString(true);
  615. default:
  616. return parseLiteral();
  617. }
  618. }
  619. scanNext();
  620. if (_scanner.getToken() === 17 /* SyntaxKind.EOF */) {
  621. if (options.allowEmptyContent) {
  622. return true;
  623. }
  624. handleError(4 /* ParseErrorCode.ValueExpected */, [], []);
  625. return false;
  626. }
  627. if (!parseValue()) {
  628. handleError(4 /* ParseErrorCode.ValueExpected */, [], []);
  629. return false;
  630. }
  631. if (_scanner.getToken() !== 17 /* SyntaxKind.EOF */) {
  632. handleError(9 /* ParseErrorCode.EndOfFileExpected */, [], []);
  633. }
  634. return true;
  635. }
  636. exports.visit = visit;
  637. /**
  638. * Takes JSON with JavaScript-style comments and remove
  639. * them. Optionally replaces every none-newline character
  640. * of comments with a replaceCharacter
  641. */
  642. function stripComments(text, replaceCh) {
  643. let _scanner = (0, scanner_1.createScanner)(text), parts = [], kind, offset = 0, pos;
  644. do {
  645. pos = _scanner.getPosition();
  646. kind = _scanner.scan();
  647. switch (kind) {
  648. case 12 /* SyntaxKind.LineCommentTrivia */:
  649. case 13 /* SyntaxKind.BlockCommentTrivia */:
  650. case 17 /* SyntaxKind.EOF */:
  651. if (offset !== pos) {
  652. parts.push(text.substring(offset, pos));
  653. }
  654. if (replaceCh !== undefined) {
  655. parts.push(_scanner.getTokenValue().replace(/[^\r\n]/g, replaceCh));
  656. }
  657. offset = _scanner.getPosition();
  658. break;
  659. }
  660. } while (kind !== 17 /* SyntaxKind.EOF */);
  661. return parts.join('');
  662. }
  663. exports.stripComments = stripComments;
  664. function getNodeType(value) {
  665. switch (typeof value) {
  666. case 'boolean': return 'boolean';
  667. case 'number': return 'number';
  668. case 'string': return 'string';
  669. case 'object': {
  670. if (!value) {
  671. return 'null';
  672. }
  673. else if (Array.isArray(value)) {
  674. return 'array';
  675. }
  676. return 'object';
  677. }
  678. default: return 'null';
  679. }
  680. }
  681. exports.getNodeType = getNodeType;
  682. });