You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							621 lines
						
					
					
						
							23 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							621 lines
						
					
					
						
							23 KiB
						
					
					
				
								/*---------------------------------------------------------------------------------------------
							 | 
						|
								 *  Copyright (c) Microsoft Corporation. All rights reserved.
							 | 
						|
								 *  Licensed under the MIT License. See License.txt in the project root for license information.
							 | 
						|
								 *--------------------------------------------------------------------------------------------*/
							 | 
						|
								'use strict';
							 | 
						|
								import { createScanner } from './scanner';
							 | 
						|
								var ParseOptions;
							 | 
						|
								(function (ParseOptions) {
							 | 
						|
								    ParseOptions.DEFAULT = {
							 | 
						|
								        allowTrailingComma: false
							 | 
						|
								    };
							 | 
						|
								})(ParseOptions || (ParseOptions = {}));
							 | 
						|
								/**
							 | 
						|
								 * 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.
							 | 
						|
								 */
							 | 
						|
								export function getLocation(text, position) {
							 | 
						|
								    var segments = []; // strings or numbers
							 | 
						|
								    var earlyReturnException = new Object();
							 | 
						|
								    var previousNode = undefined;
							 | 
						|
								    var previousNodeInst = {
							 | 
						|
								        value: {},
							 | 
						|
								        offset: 0,
							 | 
						|
								        length: 0,
							 | 
						|
								        type: 'object',
							 | 
						|
								        parent: undefined
							 | 
						|
								    };
							 | 
						|
								    var isAtPropertyKey = false;
							 | 
						|
								    function setPreviousNode(value, offset, length, type) {
							 | 
						|
								        previousNodeInst.value = value;
							 | 
						|
								        previousNodeInst.offset = offset;
							 | 
						|
								        previousNodeInst.length = length;
							 | 
						|
								        previousNodeInst.type = type;
							 | 
						|
								        previousNodeInst.colonOffset = undefined;
							 | 
						|
								        previousNode = previousNodeInst;
							 | 
						|
								    }
							 | 
						|
								    try {
							 | 
						|
								        visit(text, {
							 | 
						|
								            onObjectBegin: function (offset, length) {
							 | 
						|
								                if (position <= offset) {
							 | 
						|
								                    throw earlyReturnException;
							 | 
						|
								                }
							 | 
						|
								                previousNode = undefined;
							 | 
						|
								                isAtPropertyKey = position > offset;
							 | 
						|
								                segments.push(''); // push a placeholder (will be replaced)
							 | 
						|
								            },
							 | 
						|
								            onObjectProperty: function (name, offset, length) {
							 | 
						|
								                if (position < offset) {
							 | 
						|
								                    throw earlyReturnException;
							 | 
						|
								                }
							 | 
						|
								                setPreviousNode(name, offset, length, 'property');
							 | 
						|
								                segments[segments.length - 1] = name;
							 | 
						|
								                if (position <= offset + length) {
							 | 
						|
								                    throw earlyReturnException;
							 | 
						|
								                }
							 | 
						|
								            },
							 | 
						|
								            onObjectEnd: function (offset, length) {
							 | 
						|
								                if (position <= offset) {
							 | 
						|
								                    throw earlyReturnException;
							 | 
						|
								                }
							 | 
						|
								                previousNode = undefined;
							 | 
						|
								                segments.pop();
							 | 
						|
								            },
							 | 
						|
								            onArrayBegin: function (offset, length) {
							 | 
						|
								                if (position <= offset) {
							 | 
						|
								                    throw earlyReturnException;
							 | 
						|
								                }
							 | 
						|
								                previousNode = undefined;
							 | 
						|
								                segments.push(0);
							 | 
						|
								            },
							 | 
						|
								            onArrayEnd: function (offset, length) {
							 | 
						|
								                if (position <= offset) {
							 | 
						|
								                    throw earlyReturnException;
							 | 
						|
								                }
							 | 
						|
								                previousNode = undefined;
							 | 
						|
								                segments.pop();
							 | 
						|
								            },
							 | 
						|
								            onLiteralValue: function (value, offset, length) {
							 | 
						|
								                if (position < offset) {
							 | 
						|
								                    throw earlyReturnException;
							 | 
						|
								                }
							 | 
						|
								                setPreviousNode(value, offset, length, getNodeType(value));
							 | 
						|
								                if (position <= offset + length) {
							 | 
						|
								                    throw earlyReturnException;
							 | 
						|
								                }
							 | 
						|
								            },
							 | 
						|
								            onSeparator: function (sep, offset, length) {
							 | 
						|
								                if (position <= offset) {
							 | 
						|
								                    throw earlyReturnException;
							 | 
						|
								                }
							 | 
						|
								                if (sep === ':' && previousNode && previousNode.type === 'property') {
							 | 
						|
								                    previousNode.colonOffset = offset;
							 | 
						|
								                    isAtPropertyKey = false;
							 | 
						|
								                    previousNode = undefined;
							 | 
						|
								                }
							 | 
						|
								                else if (sep === ',') {
							 | 
						|
								                    var last = segments[segments.length - 1];
							 | 
						|
								                    if (typeof last === 'number') {
							 | 
						|
								                        segments[segments.length - 1] = last + 1;
							 | 
						|
								                    }
							 | 
						|
								                    else {
							 | 
						|
								                        isAtPropertyKey = true;
							 | 
						|
								                        segments[segments.length - 1] = '';
							 | 
						|
								                    }
							 | 
						|
								                    previousNode = undefined;
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								        });
							 | 
						|
								    }
							 | 
						|
								    catch (e) {
							 | 
						|
								        if (e !== earlyReturnException) {
							 | 
						|
								            throw e;
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    return {
							 | 
						|
								        path: segments,
							 | 
						|
								        previousNode: previousNode,
							 | 
						|
								        isAtPropertyKey: isAtPropertyKey,
							 | 
						|
								        matches: function (pattern) {
							 | 
						|
								            var k = 0;
							 | 
						|
								            for (var i = 0; k < pattern.length && i < segments.length; i++) {
							 | 
						|
								                if (pattern[k] === segments[i] || pattern[k] === '*') {
							 | 
						|
								                    k++;
							 | 
						|
								                }
							 | 
						|
								                else if (pattern[k] !== '**') {
							 | 
						|
								                    return false;
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								            return k === pattern.length;
							 | 
						|
								        }
							 | 
						|
								    };
							 | 
						|
								}
							 | 
						|
								/**
							 | 
						|
								 * 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.
							 | 
						|
								 * Therefore always check the errors list to find out if the input was valid.
							 | 
						|
								 */
							 | 
						|
								export function parse(text, errors, options) {
							 | 
						|
								    if (errors === void 0) { errors = []; }
							 | 
						|
								    if (options === void 0) { options = ParseOptions.DEFAULT; }
							 | 
						|
								    var currentProperty = null;
							 | 
						|
								    var currentParent = [];
							 | 
						|
								    var previousParents = [];
							 | 
						|
								    function onValue(value) {
							 | 
						|
								        if (Array.isArray(currentParent)) {
							 | 
						|
								            currentParent.push(value);
							 | 
						|
								        }
							 | 
						|
								        else if (currentProperty !== null) {
							 | 
						|
								            currentParent[currentProperty] = value;
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    var visitor = {
							 | 
						|
								        onObjectBegin: function () {
							 | 
						|
								            var object = {};
							 | 
						|
								            onValue(object);
							 | 
						|
								            previousParents.push(currentParent);
							 | 
						|
								            currentParent = object;
							 | 
						|
								            currentProperty = null;
							 | 
						|
								        },
							 | 
						|
								        onObjectProperty: function (name) {
							 | 
						|
								            currentProperty = name;
							 | 
						|
								        },
							 | 
						|
								        onObjectEnd: function () {
							 | 
						|
								            currentParent = previousParents.pop();
							 | 
						|
								        },
							 | 
						|
								        onArrayBegin: function () {
							 | 
						|
								            var array = [];
							 | 
						|
								            onValue(array);
							 | 
						|
								            previousParents.push(currentParent);
							 | 
						|
								            currentParent = array;
							 | 
						|
								            currentProperty = null;
							 | 
						|
								        },
							 | 
						|
								        onArrayEnd: function () {
							 | 
						|
								            currentParent = previousParents.pop();
							 | 
						|
								        },
							 | 
						|
								        onLiteralValue: onValue,
							 | 
						|
								        onError: function (error, offset, length) {
							 | 
						|
								            errors.push({ error: error, offset: offset, length: length });
							 | 
						|
								        }
							 | 
						|
								    };
							 | 
						|
								    visit(text, visitor, options);
							 | 
						|
								    return currentParent[0];
							 | 
						|
								}
							 | 
						|
								/**
							 | 
						|
								 * 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.
							 | 
						|
								 */
							 | 
						|
								export function parseTree(text, errors, options) {
							 | 
						|
								    if (errors === void 0) { errors = []; }
							 | 
						|
								    if (options === void 0) { options = ParseOptions.DEFAULT; }
							 | 
						|
								    var currentParent = { type: 'array', offset: -1, length: -1, children: [], parent: undefined }; // artificial root
							 | 
						|
								    function ensurePropertyComplete(endOffset) {
							 | 
						|
								        if (currentParent.type === 'property') {
							 | 
						|
								            currentParent.length = endOffset - currentParent.offset;
							 | 
						|
								            currentParent = currentParent.parent;
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    function onValue(valueNode) {
							 | 
						|
								        currentParent.children.push(valueNode);
							 | 
						|
								        return valueNode;
							 | 
						|
								    }
							 | 
						|
								    var visitor = {
							 | 
						|
								        onObjectBegin: function (offset) {
							 | 
						|
								            currentParent = onValue({ type: 'object', offset: offset, length: -1, parent: currentParent, children: [] });
							 | 
						|
								        },
							 | 
						|
								        onObjectProperty: function (name, offset, length) {
							 | 
						|
								            currentParent = onValue({ type: 'property', offset: offset, length: -1, parent: currentParent, children: [] });
							 | 
						|
								            currentParent.children.push({ type: 'string', value: name, offset: offset, length: length, parent: currentParent });
							 | 
						|
								        },
							 | 
						|
								        onObjectEnd: function (offset, length) {
							 | 
						|
								            ensurePropertyComplete(offset + length); // in case of a missing value for a property: make sure property is complete
							 | 
						|
								            currentParent.length = offset + length - currentParent.offset;
							 | 
						|
								            currentParent = currentParent.parent;
							 | 
						|
								            ensurePropertyComplete(offset + length);
							 | 
						|
								        },
							 | 
						|
								        onArrayBegin: function (offset, length) {
							 | 
						|
								            currentParent = onValue({ type: 'array', offset: offset, length: -1, parent: currentParent, children: [] });
							 | 
						|
								        },
							 | 
						|
								        onArrayEnd: function (offset, length) {
							 | 
						|
								            currentParent.length = offset + length - currentParent.offset;
							 | 
						|
								            currentParent = currentParent.parent;
							 | 
						|
								            ensurePropertyComplete(offset + length);
							 | 
						|
								        },
							 | 
						|
								        onLiteralValue: function (value, offset, length) {
							 | 
						|
								            onValue({ type: getNodeType(value), offset: offset, length: length, parent: currentParent, value: value });
							 | 
						|
								            ensurePropertyComplete(offset + length);
							 | 
						|
								        },
							 | 
						|
								        onSeparator: function (sep, offset, length) {
							 | 
						|
								            if (currentParent.type === 'property') {
							 | 
						|
								                if (sep === ':') {
							 | 
						|
								                    currentParent.colonOffset = offset;
							 | 
						|
								                }
							 | 
						|
								                else if (sep === ',') {
							 | 
						|
								                    ensurePropertyComplete(offset);
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								        onError: function (error, offset, length) {
							 | 
						|
								            errors.push({ error: error, offset: offset, length: length });
							 | 
						|
								        }
							 | 
						|
								    };
							 | 
						|
								    visit(text, visitor, options);
							 | 
						|
								    var result = currentParent.children[0];
							 | 
						|
								    if (result) {
							 | 
						|
								        delete result.parent;
							 | 
						|
								    }
							 | 
						|
								    return result;
							 | 
						|
								}
							 | 
						|
								/**
							 | 
						|
								 * Finds the node at the given path in a JSON DOM.
							 | 
						|
								 */
							 | 
						|
								export function findNodeAtLocation(root, path) {
							 | 
						|
								    if (!root) {
							 | 
						|
								        return undefined;
							 | 
						|
								    }
							 | 
						|
								    var node = root;
							 | 
						|
								    for (var _i = 0, path_1 = path; _i < path_1.length; _i++) {
							 | 
						|
								        var segment = path_1[_i];
							 | 
						|
								        if (typeof segment === 'string') {
							 | 
						|
								            if (node.type !== 'object' || !Array.isArray(node.children)) {
							 | 
						|
								                return undefined;
							 | 
						|
								            }
							 | 
						|
								            var found = false;
							 | 
						|
								            for (var _a = 0, _b = node.children; _a < _b.length; _a++) {
							 | 
						|
								                var propertyNode = _b[_a];
							 | 
						|
								                if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment) {
							 | 
						|
								                    node = propertyNode.children[1];
							 | 
						|
								                    found = true;
							 | 
						|
								                    break;
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								            if (!found) {
							 | 
						|
								                return undefined;
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								        else {
							 | 
						|
								            var index = segment;
							 | 
						|
								            if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {
							 | 
						|
								                return undefined;
							 | 
						|
								            }
							 | 
						|
								            node = node.children[index];
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    return node;
							 | 
						|
								}
							 | 
						|
								/**
							 | 
						|
								 * Gets the JSON path of the given JSON DOM node
							 | 
						|
								 */
							 | 
						|
								export function getNodePath(node) {
							 | 
						|
								    if (!node.parent || !node.parent.children) {
							 | 
						|
								        return [];
							 | 
						|
								    }
							 | 
						|
								    var path = getNodePath(node.parent);
							 | 
						|
								    if (node.parent.type === 'property') {
							 | 
						|
								        var key = node.parent.children[0].value;
							 | 
						|
								        path.push(key);
							 | 
						|
								    }
							 | 
						|
								    else if (node.parent.type === 'array') {
							 | 
						|
								        var index = node.parent.children.indexOf(node);
							 | 
						|
								        if (index !== -1) {
							 | 
						|
								            path.push(index);
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    return path;
							 | 
						|
								}
							 | 
						|
								/**
							 | 
						|
								 * Evaluates the JavaScript object of the given JSON DOM node
							 | 
						|
								 */
							 | 
						|
								export function getNodeValue(node) {
							 | 
						|
								    switch (node.type) {
							 | 
						|
								        case 'array':
							 | 
						|
								            return node.children.map(getNodeValue);
							 | 
						|
								        case 'object':
							 | 
						|
								            var obj = Object.create(null);
							 | 
						|
								            for (var _i = 0, _a = node.children; _i < _a.length; _i++) {
							 | 
						|
								                var prop = _a[_i];
							 | 
						|
								                var valueNode = prop.children[1];
							 | 
						|
								                if (valueNode) {
							 | 
						|
								                    obj[prop.children[0].value] = getNodeValue(valueNode);
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								            return obj;
							 | 
						|
								        case 'null':
							 | 
						|
								        case 'string':
							 | 
						|
								        case 'number':
							 | 
						|
								        case 'boolean':
							 | 
						|
								            return node.value;
							 | 
						|
								        default:
							 | 
						|
								            return undefined;
							 | 
						|
								    }
							 | 
						|
								}
							 | 
						|
								export function contains(node, offset, includeRightBound) {
							 | 
						|
								    if (includeRightBound === void 0) { includeRightBound = false; }
							 | 
						|
								    return (offset >= node.offset && offset < (node.offset + node.length)) || includeRightBound && (offset === (node.offset + node.length));
							 | 
						|
								}
							 | 
						|
								/**
							 | 
						|
								 * Finds the most inner node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.
							 | 
						|
								 */
							 | 
						|
								export function findNodeAtOffset(node, offset, includeRightBound) {
							 | 
						|
								    if (includeRightBound === void 0) { includeRightBound = false; }
							 | 
						|
								    if (contains(node, offset, includeRightBound)) {
							 | 
						|
								        var children = node.children;
							 | 
						|
								        if (Array.isArray(children)) {
							 | 
						|
								            for (var i = 0; i < children.length && children[i].offset <= offset; i++) {
							 | 
						|
								                var item = findNodeAtOffset(children[i], offset, includeRightBound);
							 | 
						|
								                if (item) {
							 | 
						|
								                    return item;
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								        return node;
							 | 
						|
								    }
							 | 
						|
								    return undefined;
							 | 
						|
								}
							 | 
						|
								/**
							 | 
						|
								 * Parses the given text and invokes the visitor functions for each object, array and literal reached.
							 | 
						|
								 */
							 | 
						|
								export function visit(text, visitor, options) {
							 | 
						|
								    if (options === void 0) { options = ParseOptions.DEFAULT; }
							 | 
						|
								    var _scanner = createScanner(text, false);
							 | 
						|
								    function toNoArgVisit(visitFunction) {
							 | 
						|
								        return visitFunction ? function () { return visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()); } : function () { return true; };
							 | 
						|
								    }
							 | 
						|
								    function toOneArgVisit(visitFunction) {
							 | 
						|
								        return visitFunction ? function (arg) { return visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()); } : function () { return true; };
							 | 
						|
								    }
							 | 
						|
								    var onObjectBegin = toNoArgVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisit(visitor.onObjectProperty), onObjectEnd = toNoArgVisit(visitor.onObjectEnd), onArrayBegin = toNoArgVisit(visitor.onArrayBegin), onArrayEnd = toNoArgVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisit(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);
							 | 
						|
								    var disallowComments = options && options.disallowComments;
							 | 
						|
								    var allowTrailingComma = options && options.allowTrailingComma;
							 | 
						|
								    function scanNext() {
							 | 
						|
								        while (true) {
							 | 
						|
								            var token = _scanner.scan();
							 | 
						|
								            switch (_scanner.getTokenError()) {
							 | 
						|
								                case 4 /* InvalidUnicode */:
							 | 
						|
								                    handleError(14 /* InvalidUnicode */);
							 | 
						|
								                    break;
							 | 
						|
								                case 5 /* InvalidEscapeCharacter */:
							 | 
						|
								                    handleError(15 /* InvalidEscapeCharacter */);
							 | 
						|
								                    break;
							 | 
						|
								                case 3 /* UnexpectedEndOfNumber */:
							 | 
						|
								                    handleError(13 /* UnexpectedEndOfNumber */);
							 | 
						|
								                    break;
							 | 
						|
								                case 1 /* UnexpectedEndOfComment */:
							 | 
						|
								                    if (!disallowComments) {
							 | 
						|
								                        handleError(11 /* UnexpectedEndOfComment */);
							 | 
						|
								                    }
							 | 
						|
								                    break;
							 | 
						|
								                case 2 /* UnexpectedEndOfString */:
							 | 
						|
								                    handleError(12 /* UnexpectedEndOfString */);
							 | 
						|
								                    break;
							 | 
						|
								                case 6 /* InvalidCharacter */:
							 | 
						|
								                    handleError(16 /* InvalidCharacter */);
							 | 
						|
								                    break;
							 | 
						|
								            }
							 | 
						|
								            switch (token) {
							 | 
						|
								                case 12 /* LineCommentTrivia */:
							 | 
						|
								                case 13 /* BlockCommentTrivia */:
							 | 
						|
								                    if (disallowComments) {
							 | 
						|
								                        handleError(10 /* InvalidCommentToken */);
							 | 
						|
								                    }
							 | 
						|
								                    else {
							 | 
						|
								                        onComment();
							 | 
						|
								                    }
							 | 
						|
								                    break;
							 | 
						|
								                case 16 /* Unknown */:
							 | 
						|
								                    handleError(1 /* InvalidSymbol */);
							 | 
						|
								                    break;
							 | 
						|
								                case 15 /* Trivia */:
							 | 
						|
								                case 14 /* LineBreakTrivia */:
							 | 
						|
								                    break;
							 | 
						|
								                default:
							 | 
						|
								                    return token;
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    function handleError(error, skipUntilAfter, skipUntil) {
							 | 
						|
								        if (skipUntilAfter === void 0) { skipUntilAfter = []; }
							 | 
						|
								        if (skipUntil === void 0) { skipUntil = []; }
							 | 
						|
								        onError(error);
							 | 
						|
								        if (skipUntilAfter.length + skipUntil.length > 0) {
							 | 
						|
								            var token = _scanner.getToken();
							 | 
						|
								            while (token !== 17 /* EOF */) {
							 | 
						|
								                if (skipUntilAfter.indexOf(token) !== -1) {
							 | 
						|
								                    scanNext();
							 | 
						|
								                    break;
							 | 
						|
								                }
							 | 
						|
								                else if (skipUntil.indexOf(token) !== -1) {
							 | 
						|
								                    break;
							 | 
						|
								                }
							 | 
						|
								                token = scanNext();
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    function parseString(isValue) {
							 | 
						|
								        var value = _scanner.getTokenValue();
							 | 
						|
								        if (isValue) {
							 | 
						|
								            onLiteralValue(value);
							 | 
						|
								        }
							 | 
						|
								        else {
							 | 
						|
								            onObjectProperty(value);
							 | 
						|
								        }
							 | 
						|
								        scanNext();
							 | 
						|
								        return true;
							 | 
						|
								    }
							 | 
						|
								    function parseLiteral() {
							 | 
						|
								        switch (_scanner.getToken()) {
							 | 
						|
								            case 11 /* NumericLiteral */:
							 | 
						|
								                var tokenValue = _scanner.getTokenValue();
							 | 
						|
								                var value = Number(tokenValue);
							 | 
						|
								                if (isNaN(value)) {
							 | 
						|
								                    handleError(2 /* InvalidNumberFormat */);
							 | 
						|
								                    value = 0;
							 | 
						|
								                }
							 | 
						|
								                onLiteralValue(value);
							 | 
						|
								                break;
							 | 
						|
								            case 7 /* NullKeyword */:
							 | 
						|
								                onLiteralValue(null);
							 | 
						|
								                break;
							 | 
						|
								            case 8 /* TrueKeyword */:
							 | 
						|
								                onLiteralValue(true);
							 | 
						|
								                break;
							 | 
						|
								            case 9 /* FalseKeyword */:
							 | 
						|
								                onLiteralValue(false);
							 | 
						|
								                break;
							 | 
						|
								            default:
							 | 
						|
								                return false;
							 | 
						|
								        }
							 | 
						|
								        scanNext();
							 | 
						|
								        return true;
							 | 
						|
								    }
							 | 
						|
								    function parseProperty() {
							 | 
						|
								        if (_scanner.getToken() !== 10 /* StringLiteral */) {
							 | 
						|
								            handleError(3 /* PropertyNameExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
							 | 
						|
								            return false;
							 | 
						|
								        }
							 | 
						|
								        parseString(false);
							 | 
						|
								        if (_scanner.getToken() === 6 /* ColonToken */) {
							 | 
						|
								            onSeparator(':');
							 | 
						|
								            scanNext(); // consume colon
							 | 
						|
								            if (!parseValue()) {
							 | 
						|
								                handleError(4 /* ValueExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								        else {
							 | 
						|
								            handleError(5 /* ColonExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
							 | 
						|
								        }
							 | 
						|
								        return true;
							 | 
						|
								    }
							 | 
						|
								    function parseObject() {
							 | 
						|
								        onObjectBegin();
							 | 
						|
								        scanNext(); // consume open brace
							 | 
						|
								        var needsComma = false;
							 | 
						|
								        while (_scanner.getToken() !== 2 /* CloseBraceToken */ && _scanner.getToken() !== 17 /* EOF */) {
							 | 
						|
								            if (_scanner.getToken() === 5 /* CommaToken */) {
							 | 
						|
								                if (!needsComma) {
							 | 
						|
								                    handleError(4 /* ValueExpected */, [], []);
							 | 
						|
								                }
							 | 
						|
								                onSeparator(',');
							 | 
						|
								                scanNext(); // consume comma
							 | 
						|
								                if (_scanner.getToken() === 2 /* CloseBraceToken */ && allowTrailingComma) {
							 | 
						|
								                    break;
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								            else if (needsComma) {
							 | 
						|
								                handleError(6 /* CommaExpected */, [], []);
							 | 
						|
								            }
							 | 
						|
								            if (!parseProperty()) {
							 | 
						|
								                handleError(4 /* ValueExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
							 | 
						|
								            }
							 | 
						|
								            needsComma = true;
							 | 
						|
								        }
							 | 
						|
								        onObjectEnd();
							 | 
						|
								        if (_scanner.getToken() !== 2 /* CloseBraceToken */) {
							 | 
						|
								            handleError(7 /* CloseBraceExpected */, [2 /* CloseBraceToken */], []);
							 | 
						|
								        }
							 | 
						|
								        else {
							 | 
						|
								            scanNext(); // consume close brace
							 | 
						|
								        }
							 | 
						|
								        return true;
							 | 
						|
								    }
							 | 
						|
								    function parseArray() {
							 | 
						|
								        onArrayBegin();
							 | 
						|
								        scanNext(); // consume open bracket
							 | 
						|
								        var needsComma = false;
							 | 
						|
								        while (_scanner.getToken() !== 4 /* CloseBracketToken */ && _scanner.getToken() !== 17 /* EOF */) {
							 | 
						|
								            if (_scanner.getToken() === 5 /* CommaToken */) {
							 | 
						|
								                if (!needsComma) {
							 | 
						|
								                    handleError(4 /* ValueExpected */, [], []);
							 | 
						|
								                }
							 | 
						|
								                onSeparator(',');
							 | 
						|
								                scanNext(); // consume comma
							 | 
						|
								                if (_scanner.getToken() === 4 /* CloseBracketToken */ && allowTrailingComma) {
							 | 
						|
								                    break;
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								            else if (needsComma) {
							 | 
						|
								                handleError(6 /* CommaExpected */, [], []);
							 | 
						|
								            }
							 | 
						|
								            if (!parseValue()) {
							 | 
						|
								                handleError(4 /* ValueExpected */, [], [4 /* CloseBracketToken */, 5 /* CommaToken */]);
							 | 
						|
								            }
							 | 
						|
								            needsComma = true;
							 | 
						|
								        }
							 | 
						|
								        onArrayEnd();
							 | 
						|
								        if (_scanner.getToken() !== 4 /* CloseBracketToken */) {
							 | 
						|
								            handleError(8 /* CloseBracketExpected */, [4 /* CloseBracketToken */], []);
							 | 
						|
								        }
							 | 
						|
								        else {
							 | 
						|
								            scanNext(); // consume close bracket
							 | 
						|
								        }
							 | 
						|
								        return true;
							 | 
						|
								    }
							 | 
						|
								    function parseValue() {
							 | 
						|
								        switch (_scanner.getToken()) {
							 | 
						|
								            case 3 /* OpenBracketToken */:
							 | 
						|
								                return parseArray();
							 | 
						|
								            case 1 /* OpenBraceToken */:
							 | 
						|
								                return parseObject();
							 | 
						|
								            case 10 /* StringLiteral */:
							 | 
						|
								                return parseString(true);
							 | 
						|
								            default:
							 | 
						|
								                return parseLiteral();
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    scanNext();
							 | 
						|
								    if (_scanner.getToken() === 17 /* EOF */) {
							 | 
						|
								        if (options.allowEmptyContent) {
							 | 
						|
								            return true;
							 | 
						|
								        }
							 | 
						|
								        handleError(4 /* ValueExpected */, [], []);
							 | 
						|
								        return false;
							 | 
						|
								    }
							 | 
						|
								    if (!parseValue()) {
							 | 
						|
								        handleError(4 /* ValueExpected */, [], []);
							 | 
						|
								        return false;
							 | 
						|
								    }
							 | 
						|
								    if (_scanner.getToken() !== 17 /* EOF */) {
							 | 
						|
								        handleError(9 /* EndOfFileExpected */, [], []);
							 | 
						|
								    }
							 | 
						|
								    return true;
							 | 
						|
								}
							 | 
						|
								/**
							 | 
						|
								 * Takes JSON with JavaScript-style comments and remove
							 | 
						|
								 * them. Optionally replaces every none-newline character
							 | 
						|
								 * of comments with a replaceCharacter
							 | 
						|
								 */
							 | 
						|
								export function stripComments(text, replaceCh) {
							 | 
						|
								    var _scanner = createScanner(text), parts = [], kind, offset = 0, pos;
							 | 
						|
								    do {
							 | 
						|
								        pos = _scanner.getPosition();
							 | 
						|
								        kind = _scanner.scan();
							 | 
						|
								        switch (kind) {
							 | 
						|
								            case 12 /* LineCommentTrivia */:
							 | 
						|
								            case 13 /* BlockCommentTrivia */:
							 | 
						|
								            case 17 /* EOF */:
							 | 
						|
								                if (offset !== pos) {
							 | 
						|
								                    parts.push(text.substring(offset, pos));
							 | 
						|
								                }
							 | 
						|
								                if (replaceCh !== undefined) {
							 | 
						|
								                    parts.push(_scanner.getTokenValue().replace(/[^\r\n]/g, replaceCh));
							 | 
						|
								                }
							 | 
						|
								                offset = _scanner.getPosition();
							 | 
						|
								                break;
							 | 
						|
								        }
							 | 
						|
								    } while (kind !== 17 /* EOF */);
							 | 
						|
								    return parts.join('');
							 | 
						|
								}
							 | 
						|
								export function getNodeType(value) {
							 | 
						|
								    switch (typeof value) {
							 | 
						|
								        case 'boolean': return 'boolean';
							 | 
						|
								        case 'number': return 'number';
							 | 
						|
								        case 'string': return 'string';
							 | 
						|
								        case 'object': {
							 | 
						|
								            if (!value) {
							 | 
						|
								                return 'null';
							 | 
						|
								            }
							 | 
						|
								            else if (Array.isArray(value)) {
							 | 
						|
								                return 'array';
							 | 
						|
								            }
							 | 
						|
								            return 'object';
							 | 
						|
								        }
							 | 
						|
								        default: return 'null';
							 | 
						|
								    }
							 | 
						|
								}
							 |