var global = Function("return this;")();
/*jshint strict:true node:true es5:true onevar:true laxcomma:true laxbreak:true eqeqeq:true immed:true latedef:true*/
(function () {
  "use strict";

  var oldRequire = require
    , modules = {}
    ;

  function newRequire(modulename) {
    var err
      , mod
      , metamod
      ;

    try {
      mod = oldRequire(modulename);
    } catch(e) {
      err = e;
    }

    if (mod) {
      return mod;
    }

    metamod = modules[modulename];

    if (metamod) {
      mod = metamod();
      return mod;
    }

    // make it possible to require 'process', etc
    mod = global[modulename];

    if (mod) {
      return mod;
    }

    console.error(modulename);
    throw err;
  }

  function provide(modulename, factory) {
    var modReal
      ;

    function metamod() {
      if (modReal) {
        return modReal;
      }

      if (!factory.__pakmanager_factory__) {
        modReal = factory;
        return factory;
      }

      if (factory.__factoryIsResolving) {
        console.error('Your circular dependencies are too powerful!');
        return factory.__moduleExports;
      }

      factory.__factoryIsResolving = true;
      factory.__moduleExports = {};
      modReal = factory(factory.__moduleExports);
      factory.__factoryIsResolving = false;

      return modReal;
    }

    modules[modulename] = metamod;
    // somewhat of a dirty hack since I don't have a plug for loading the "main" module otherwise
    modules['pakmanager.main'] = metamod;
  }

  require = newRequire;
  global.require = newRequire;
  global.provide = provide;
}());

// pakmanager:pinkie-promise
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';

    module.exports = global.Promise || require('pinkie');

  provide("pinkie-promise", module.exports);
}(global));

// pakmanager:pinkie
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';

    var PENDING = 'pending';
    var SETTLED = 'settled';
    var FULFILLED = 'fulfilled';
    var REJECTED = 'rejected';
    var NOOP = function () {};

    // async calls
    var asyncSetTimer = typeof setImmediate !== 'undefined' ? setImmediate : setTimeout;
    var asyncQueue = [];
    var asyncTimer;

    function asyncFlush() {
    	// run promise callbacks
    	for (var i = 0; i < asyncQueue.length; i++) {
    		asyncQueue[i][0](asyncQueue[i][1]);
    	}

    	// reset async asyncQueue
    	asyncQueue = [];
    	asyncTimer = false;
    }

    function asyncCall(callback, arg) {
    	asyncQueue.push([callback, arg]);

    	if (!asyncTimer) {
    		asyncTimer = true;
    		asyncSetTimer(asyncFlush, 0);
    	}
    }

    function invokeResolver(resolver, promise) {
    	function resolvePromise(value) {
    		resolve(promise, value);
    	}

    	function rejectPromise(reason) {
    		reject(promise, reason);
    	}

    	try {
    		resolver(resolvePromise, rejectPromise);
    	} catch (e) {
    		rejectPromise(e);
    	}
    }

    function invokeCallback(subscriber) {
    	var owner = subscriber.owner;
    	var settled = owner._state;
    	var value = owner._data;
    	var callback = subscriber[settled];
    	var promise = subscriber.then;

    	if (typeof callback === 'function') {
    		settled = FULFILLED;
    		try {
    			value = callback(value);
    		} catch (e) {
    			reject(promise, e);
    		}
    	}

    	if (!handleThenable(promise, value)) {
    		if (settled === FULFILLED) {
    			resolve(promise, value);
    		}

    		if (settled === REJECTED) {
    			reject(promise, value);
    		}
    	}
    }

    function handleThenable(promise, value) {
    	var resolved;

    	try {
    		if (promise === value) {
    			throw new TypeError('A promises callback cannot return that same promise.');
    		}

    		if (value && (typeof value === 'function' || typeof value === 'object')) {
    			var then = value.then; // then should be retrived only once

    			if (typeof then === 'function') {
    				then.call(value, function (val) {
    					if (!resolved) {
    						resolved = true;

    						if (value !== val) {
    							resolve(promise, val);
    						} else {
    							fulfill(promise, val);
    						}
    					}
    				}, function (reason) {
    					if (!resolved) {
    						resolved = true;

    						reject(promise, reason);
    					}
    				});

    				return true;
    			}
    		}
    	} catch (e) {
    		if (!resolved) {
    			reject(promise, e);
    		}

    		return true;
    	}

    	return false;
    }

    function resolve(promise, value) {
    	if (promise === value || !handleThenable(promise, value)) {
    		fulfill(promise, value);
    	}
    }

    function fulfill(promise, value) {
    	if (promise._state === PENDING) {
    		promise._state = SETTLED;
    		promise._data = value;

    		asyncCall(publishFulfillment, promise);
    	}
    }

    function reject(promise, reason) {
    	if (promise._state === PENDING) {
    		promise._state = SETTLED;
    		promise._data = reason;

    		asyncCall(publishRejection, promise);
    	}
    }

    function publish(promise) {
    	promise._then = promise._then.forEach(invokeCallback);
    }

    function publishFulfillment(promise) {
    	promise._state = FULFILLED;
    	publish(promise);
    }

    function publishRejection(promise) {
    	promise._state = REJECTED;
    	publish(promise);
    }

    /**
     * @class
     */
    function Promise(resolver) {
    	if (typeof resolver !== 'function') {
    		throw new TypeError('Promise resolver ' + resolver + ' is not a function');
    	}

    	if (this instanceof Promise === false) {
    		throw new TypeError('Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.');
    	}

    	this._then = [];

    	invokeResolver(resolver, this);
    }

    Promise.prototype = {
    	constructor: Promise,

    	_state: PENDING,
    	_then: null,
    	_data: undefined,

    	then: function (onFulfillment, onRejection) {
    		var subscriber = {
    			owner: this,
    			then: new this.constructor(NOOP),
    			fulfilled: onFulfillment,
    			rejected: onRejection
    		};

    		if (this._state === FULFILLED || this._state === REJECTED) {
    			// already resolved, call callback async
    			asyncCall(invokeCallback, subscriber);
    		} else {
    			// subscribe
    			this._then.push(subscriber);
    		}

    		return subscriber.then;
    	},

    	'catch': function (onRejection) {
    		return this.then(null, onRejection);
    	}
    };

    Promise.all = function (promises) {
    	if (!Array.isArray(promises)) {
    		throw new TypeError('You must pass an array to Promise.all().');
    	}

    	return new Promise(function (resolve, reject) {
    		var results = [];
    		var remaining = 0;

    		function resolver(index) {
    			remaining++;
    			return function (value) {
    				results[index] = value;
    				if (!--remaining) {
    					resolve(results);
    				}
    			};
    		}

    		for (var i = 0, promise; i < promises.length; i++) {
    			promise = promises[i];

    			if (promise && typeof promise.then === 'function') {
    				promise.then(resolver(i), reject);
    			} else {
    				results[i] = promise;
    			}
    		}

    		if (!remaining) {
    			resolve(results);
    		}
    	});
    };

    Promise.race = function (promises) {
    	if (!Array.isArray(promises)) {
    		throw new TypeError('You must pass an array to Promise.race().');
    	}

    	return new Promise(function (resolve, reject) {
    		for (var i = 0, promise; i < promises.length; i++) {
    			promise = promises[i];

    			if (promise && typeof promise.then === 'function') {
    				promise.then(resolve, reject);
    			} else {
    				resolve(promise);
    			}
    		}
    	});
    };

    Promise.resolve = function (value) {
    	if (value && typeof value === 'object' && value.constructor === Promise) {
    		return value;
    	}

    	return new Promise(function (resolve) {
    		resolve(value);
    	});
    };

    Promise.reject = function (reason) {
    	return new Promise(function (resolve, reject) {
    		reject(reason);
    	});
    };

    module.exports = Promise;

  provide("pinkie", module.exports);
}(global));

// pakmanager:graceful-fs/fs.js
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict'

    var fs = require('fs')

    module.exports = clone(fs)

    function clone (obj) {
      if (obj === null || typeof obj !== 'object')
        return obj

      if (obj instanceof Object)
        var copy = { __proto__: obj.__proto__ }
      else
        var copy = Object.create(null)

      Object.getOwnPropertyNames(obj).forEach(function (key) {
        Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key))
      })

      return copy
    }

  provide("graceful-fs/fs.js", module.exports);
}(global));

// pakmanager:graceful-fs/polyfills.js
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  var fs =  require('graceful-fs/fs.js')
    var constants = require('constants')

    var origCwd = process.cwd
    var cwd = null
    process.cwd = function() {
      if (!cwd)
        cwd = origCwd.call(process)
      return cwd
    }
    try {
      process.cwd()
    } catch (er) {}

    var chdir = process.chdir
    process.chdir = function(d) {
      cwd = null
      chdir.call(process, d)
    }

    module.exports = patch

    function patch (fs) {
      // (re-)implement some things that are known busted or missing.

      // lchmod, broken prior to 0.6.2
      // back-port the fix here.
      if (constants.hasOwnProperty('O_SYMLINK') &&
          process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
        patchLchmod(fs)
      }

      // lutimes implementation, or no-op
      if (!fs.lutimes) {
        patchLutimes(fs)
      }

      // https://github.com/isaacs/node-graceful-fs/issues/4
      // Chown should not fail on einval or eperm if non-root.
      // It should not fail on enosys ever, as this just indicates
      // that a fs doesn't support the intended operation.

      fs.chown = chownFix(fs.chown)
      fs.fchown = chownFix(fs.fchown)
      fs.lchown = chownFix(fs.lchown)

      fs.chmod = chownFix(fs.chmod)
      fs.fchmod = chownFix(fs.fchmod)
      fs.lchmod = chownFix(fs.lchmod)

      fs.chownSync = chownFixSync(fs.chownSync)
      fs.fchownSync = chownFixSync(fs.fchownSync)
      fs.lchownSync = chownFixSync(fs.lchownSync)

      fs.chmodSync = chownFix(fs.chmodSync)
      fs.fchmodSync = chownFix(fs.fchmodSync)
      fs.lchmodSync = chownFix(fs.lchmodSync)

      // if lchmod/lchown do not exist, then make them no-ops
      if (!fs.lchmod) {
        fs.lchmod = function (path, mode, cb) {
          process.nextTick(cb)
        }
        fs.lchmodSync = function () {}
      }
      if (!fs.lchown) {
        fs.lchown = function (path, uid, gid, cb) {
          process.nextTick(cb)
        }
        fs.lchownSync = function () {}
      }

      // on Windows, A/V software can lock the directory, causing this
      // to fail with an EACCES or EPERM if the directory contains newly
      // created files.  Try again on failure, for up to 1 second.
      if (process.platform === "win32") {
        fs.rename = (function (fs$rename) { return function (from, to, cb) {
          var start = Date.now()
          fs$rename(from, to, function CB (er) {
            if (er
                && (er.code === "EACCES" || er.code === "EPERM")
                && Date.now() - start < 1000) {
              return fs$rename(from, to, CB)
            }
            if (cb) cb(er)
          })
        }})(fs.rename)
      }

      // if read() returns EAGAIN, then just try it again.
      fs.read = (function (fs$read) { return function (fd, buffer, offset, length, position, callback_) {
        var callback
        if (callback_ && typeof callback_ === 'function') {
          var eagCounter = 0
          callback = function (er, _, __) {
            if (er && er.code === 'EAGAIN' && eagCounter < 10) {
              eagCounter ++
              return fs$read.call(fs, fd, buffer, offset, length, position, callback)
            }
            callback_.apply(this, arguments)
          }
        }
        return fs$read.call(fs, fd, buffer, offset, length, position, callback)
      }})(fs.read)

      fs.readSync = (function (fs$readSync) { return function (fd, buffer, offset, length, position) {
        var eagCounter = 0
        while (true) {
          try {
            return fs$readSync.call(fs, fd, buffer, offset, length, position)
          } catch (er) {
            if (er.code === 'EAGAIN' && eagCounter < 10) {
              eagCounter ++
              continue
            }
            throw er
          }
        }
      }})(fs.readSync)
    }

    function patchLchmod (fs) {
      fs.lchmod = function (path, mode, callback) {
        callback = callback || noop
        fs.open( path
               , constants.O_WRONLY | constants.O_SYMLINK
               , mode
               , function (err, fd) {
          if (err) {
            callback(err)
            return
          }
          // prefer to return the chmod error, if one occurs,
          // but still try to close, and report closing errors if they occur.
          fs.fchmod(fd, mode, function (err) {
            fs.close(fd, function(err2) {
              callback(err || err2)
            })
          })
        })
      }

      fs.lchmodSync = function (path, mode) {
        var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)

        // prefer to return the chmod error, if one occurs,
        // but still try to close, and report closing errors if they occur.
        var threw = true
        var ret
        try {
          ret = fs.fchmodSync(fd, mode)
          threw = false
        } finally {
          if (threw) {
            try {
              fs.closeSync(fd)
            } catch (er) {}
          } else {
            fs.closeSync(fd)
          }
        }
        return ret
      }
    }

    function patchLutimes (fs) {
      if (constants.hasOwnProperty("O_SYMLINK")) {
        fs.lutimes = function (path, at, mt, cb) {
          fs.open(path, constants.O_SYMLINK, function (er, fd) {
            cb = cb || noop
            if (er) return cb(er)
            fs.futimes(fd, at, mt, function (er) {
              fs.close(fd, function (er2) {
                return cb(er || er2)
              })
            })
          })
        }

        fs.lutimesSync = function (path, at, mt) {
          var fd = fs.openSync(path, constants.O_SYMLINK)
          var ret
          var threw = true
          try {
            ret = fs.futimesSync(fd, at, mt)
            threw = false
          } finally {
            if (threw) {
              try {
                fs.closeSync(fd)
              } catch (er) {}
            } else {
              fs.closeSync(fd)
            }
          }
          return ret
        }

      } else {
        fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) }
        fs.lutimesSync = function () {}
      }
    }

    function chownFix (orig) {
      if (!orig) return orig
      return function (target, uid, gid, cb) {
        return orig.call(fs, target, uid, gid, function (er, res) {
          if (chownErOk(er)) er = null
          cb(er, res)
        })
      }
    }

    function chownFixSync (orig) {
      if (!orig) return orig
      return function (target, uid, gid) {
        try {
          return orig.call(fs, target, uid, gid)
        } catch (er) {
          if (!chownErOk(er)) throw er
        }
      }
    }

    // ENOSYS means that the fs doesn't support the op. Just ignore
    // that, because it doesn't matter.
    //
    // if there's no getuid, or if getuid() is something other
    // than 0, and the error is EINVAL or EPERM, then just ignore
    // it.
    //
    // This specific case is a silent failure in cp, install, tar,
    // and most other unix tools that manage permissions.
    //
    // When running as root, or if other types of errors are
    // encountered, then it's strict.
    function chownErOk (er) {
      if (!er)
        return true

      if (er.code === "ENOSYS")
        return true

      var nonroot = !process.getuid || process.getuid() !== 0
      if (nonroot) {
        if (er.code === "EINVAL" || er.code === "EPERM")
          return true
      }

      return false
    }

  provide("graceful-fs/polyfills.js", module.exports);
}(global));

// pakmanager:graceful-fs/legacy-streams.js
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  var Stream = require('stream').Stream

    module.exports = legacy

    function legacy (fs) {
      return {
        ReadStream: ReadStream,
        WriteStream: WriteStream
      }

      function ReadStream (path, options) {
        if (!(this instanceof ReadStream)) return new ReadStream(path, options);

        Stream.call(this);

        var self = this;

        this.path = path;
        this.fd = null;
        this.readable = true;
        this.paused = false;

        this.flags = 'r';
        this.mode = 438; /*=0666*/
        this.bufferSize = 64 * 1024;

        options = options || {};

        // Mixin options into this
        var keys = Object.keys(options);
        for (var index = 0, length = keys.length; index < length; index++) {
          var key = keys[index];
          this[key] = options[key];
        }

        if (this.encoding) this.setEncoding(this.encoding);

        if (this.start !== undefined) {
          if ('number' !== typeof this.start) {
            throw TypeError('start must be a Number');
          }
          if (this.end === undefined) {
            this.end = Infinity;
          } else if ('number' !== typeof this.end) {
            throw TypeError('end must be a Number');
          }

          if (this.start > this.end) {
            throw new Error('start must be <= end');
          }

          this.pos = this.start;
        }

        if (this.fd !== null) {
          process.nextTick(function() {
            self._read();
          });
          return;
        }

        fs.open(this.path, this.flags, this.mode, function (err, fd) {
          if (err) {
            self.emit('error', err);
            self.readable = false;
            return;
          }

          self.fd = fd;
          self.emit('open', fd);
          self._read();
        })
      }

      function WriteStream (path, options) {
        if (!(this instanceof WriteStream)) return new WriteStream(path, options);

        Stream.call(this);

        this.path = path;
        this.fd = null;
        this.writable = true;

        this.flags = 'w';
        this.encoding = 'binary';
        this.mode = 438; /*=0666*/
        this.bytesWritten = 0;

        options = options || {};

        // Mixin options into this
        var keys = Object.keys(options);
        for (var index = 0, length = keys.length; index < length; index++) {
          var key = keys[index];
          this[key] = options[key];
        }

        if (this.start !== undefined) {
          if ('number' !== typeof this.start) {
            throw TypeError('start must be a Number');
          }
          if (this.start < 0) {
            throw new Error('start must be >= zero');
          }

          this.pos = this.start;
        }

        this.busy = false;
        this._queue = [];

        if (this.fd === null) {
          this._open = fs.open;
          this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
          this.flush();
        }
      }
    }

  provide("graceful-fs/legacy-streams.js", module.exports);
}(global));

// pakmanager:graceful-fs
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  var fs = require('fs')
    var polyfills =  require('graceful-fs/polyfills.js')
    var legacy =  require('graceful-fs/legacy-streams.js')
    var queue = []

    var util = require('util')

    function noop () {}

    var debug = noop
    if (util.debuglog)
      debug = util.debuglog('gfs4')
    else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || ''))
      debug = function() {
        var m = util.format.apply(util, arguments)
        m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ')
        console.error(m)
      }

    if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
      process.on('exit', function() {
        debug(queue)
        require('assert').equal(queue.length, 0)
      })
    }

    module.exports = patch( require('graceful-fs/fs.js'))
    if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH) {
      module.exports = patch(fs)
    }

    // Always patch fs.close/closeSync, because we want to
    // retry() whenever a close happens *anywhere* in the program.
    // This is essential when multiple graceful-fs instances are
    // in play at the same time.
    fs.close = (function (fs$close) { return function (fd, cb) {
      return fs$close.call(fs, fd, function (err) {
        if (!err)
          retry()

        if (typeof cb === 'function')
          cb.apply(this, arguments)
      })
    }})(fs.close)

    fs.closeSync = (function (fs$closeSync) { return function (fd) {
      // Note that graceful-fs also retries when fs.closeSync() fails.
      // Looks like a bug to me, although it's probably a harmless one.
      var rval = fs$closeSync.apply(fs, arguments)
      retry()
      return rval
    }})(fs.closeSync)

    function patch (fs) {
      // Everything that references the open() function needs to be in here
      polyfills(fs)
      fs.gracefulify = patch
      fs.FileReadStream = ReadStream;  // Legacy name.
      fs.FileWriteStream = WriteStream;  // Legacy name.
      fs.createReadStream = createReadStream
      fs.createWriteStream = createWriteStream
      var fs$readFile = fs.readFile
      fs.readFile = readFile
      function readFile (path, options, cb) {
        if (typeof options === 'function')
          cb = options, options = null

        return go$readFile(path, options, cb)

        function go$readFile (path, options, cb) {
          return fs$readFile(path, options, function (err) {
            if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
              enqueue([go$readFile, [path, options, cb]])
            else {
              if (typeof cb === 'function')
                cb.apply(this, arguments)
              retry()
            }
          })
        }
      }

      var fs$writeFile = fs.writeFile
      fs.writeFile = writeFile
      function writeFile (path, data, options, cb) {
        if (typeof options === 'function')
          cb = options, options = null

        return go$writeFile(path, data, options, cb)

        function go$writeFile (path, data, options, cb) {
          return fs$writeFile(path, data, options, function (err) {
            if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
              enqueue([go$writeFile, [path, data, options, cb]])
            else {
              if (typeof cb === 'function')
                cb.apply(this, arguments)
              retry()
            }
          })
        }
      }

      var fs$appendFile = fs.appendFile
      if (fs$appendFile)
        fs.appendFile = appendFile
      function appendFile (path, data, options, cb) {
        if (typeof options === 'function')
          cb = options, options = null

        return go$appendFile(path, data, options, cb)

        function go$appendFile (path, data, options, cb) {
          return fs$appendFile(path, data, options, function (err) {
            if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
              enqueue([go$appendFile, [path, data, options, cb]])
            else {
              if (typeof cb === 'function')
                cb.apply(this, arguments)
              retry()
            }
          })
        }
      }

      var fs$readdir = fs.readdir
      fs.readdir = readdir
      function readdir (path, cb) {
        return go$readdir(path, cb)

        function go$readdir () {
          return fs$readdir(path, function (err, files) {
            if (files && files.sort)
              files.sort();  // Backwards compatibility with graceful-fs.

            if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
              enqueue([go$readdir, [path, cb]])
            else {
              if (typeof cb === 'function')
                cb.apply(this, arguments)
              retry()
            }
          })
        }
      }

      if (process.version.substr(0, 4) === 'v0.8') {
        var legStreams = legacy(fs)
        ReadStream = legStreams.ReadStream
        WriteStream = legStreams.WriteStream
      }

      var fs$ReadStream = fs.ReadStream
      ReadStream.prototype = Object.create(fs$ReadStream.prototype)
      ReadStream.prototype.open = ReadStream$open

      var fs$WriteStream = fs.WriteStream
      WriteStream.prototype = Object.create(fs$WriteStream.prototype)
      WriteStream.prototype.open = WriteStream$open

      fs.ReadStream = ReadStream
      fs.WriteStream = WriteStream

      function ReadStream (path, options) {
        if (this instanceof ReadStream)
          return fs$ReadStream.apply(this, arguments), this
        else
          return ReadStream.apply(Object.create(ReadStream.prototype), arguments)
      }

      function ReadStream$open () {
        var that = this
        open(that.path, that.flags, that.mode, function (err, fd) {
          if (err) {
            if (that.autoClose)
              that.destroy()

            that.emit('error', err)
          } else {
            that.fd = fd
            that.emit('open', fd)
            that.read()
          }
        })
      }

      function WriteStream (path, options) {
        if (this instanceof WriteStream)
          return fs$WriteStream.apply(this, arguments), this
        else
          return WriteStream.apply(Object.create(WriteStream.prototype), arguments)
      }

      function WriteStream$open () {
        var that = this
        open(that.path, that.flags, that.mode, function (err, fd) {
          if (err) {
            that.destroy()
            that.emit('error', err)
          } else {
            that.fd = fd
            that.emit('open', fd)
          }
        })
      }

      function createReadStream (path, options) {
        return new ReadStream(path, options)
      }

      function createWriteStream (path, options) {
        return new WriteStream(path, options)
      }

      var fs$open = fs.open
      fs.open = open
      function open (path, flags, mode, cb) {
        if (typeof mode === 'function')
          cb = mode, mode = null

        return go$open(path, flags, mode, cb)

        function go$open (path, flags, mode, cb) {
          return fs$open(path, flags, mode, function (err, fd) {
            if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
              enqueue([go$open, [path, flags, mode, cb]])
            else {
              if (typeof cb === 'function')
                cb.apply(this, arguments)
              retry()
            }
          })
        }
      }

      return fs
    }

    function enqueue (elem) {
      debug('ENQUEUE', elem[0].name, elem[1])
      queue.push(elem)
    }

    function retry () {
      var elem = queue.shift()
      if (elem) {
        debug('RETRY', elem[0].name, elem[1])
        elem[0].apply(null, elem[1])
      }
    }

  provide("graceful-fs", module.exports);
}(global));

// pakmanager:parse-json/vendor/unicode
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

    // This is autogenerated with esprima tools, see:
    // https://github.com/ariya/esprima/blob/master/esprima.js
    //
    // PS: oh God, I hate Unicode

    // ECMAScript 5.1/Unicode v6.3.0 NonAsciiIdentifierStart:

    var Uni = module.exports

    module.exports.isWhiteSpace = function isWhiteSpace(x) {
      // section 7.2, table 2
      return x === '\u0020'
          || x === '\u00A0'
          || x === '\uFEFF' // <-- this is not a Unicode WS, only a JS one
          || (x >= '\u0009' && x <= '\u000D') // 9 A B C D

          // + whitespace characters from unicode, category Zs
          || x === '\u1680'
          || x === '\u180E'
          || (x >= '\u2000' && x <= '\u200A') // 0 1 2 3 4 5 6 7 8 9 A
          || x === '\u2028'
          || x === '\u2029'
          || x === '\u202F'
          || x === '\u205F'
          || x === '\u3000'
    }

    module.exports.isWhiteSpaceJSON = function isWhiteSpaceJSON(x) {
      return x === '\u0020'
          || x === '\u0009'
          || x === '\u000A'
          || x === '\u000D'
    }

    module.exports.isLineTerminator = function isLineTerminator(x) {
      // ok, here is the part when JSON is wrong
      // section 7.3, table 3
      return x === '\u000A'
          || x === '\u000D'
          || x === '\u2028'
          || x === '\u2029'
    }

    module.exports.isLineTerminatorJSON = function isLineTerminatorJSON(x) {
      return x === '\u000A'
          || x === '\u000D'
    }

    module.exports.isIdentifierStart = function isIdentifierStart(x) {
      return x === '$'
          || x === '_'
          || (x >= 'A' && x <= 'Z')
          || (x >= 'a' && x <= 'z')
          || (x >= '\u0080' && Uni.NonAsciiIdentifierStart.test(x))
    }

    module.exports.isIdentifierPart = function isIdentifierPart(x) {
      return x === '$'
          || x === '_'
          || (x >= 'A' && x <= 'Z')
          || (x >= 'a' && x <= 'z')
          || (x >= '0' && x <= '9') // <-- addition to Start
          || (x >= '\u0080' && Uni.NonAsciiIdentifierPart.test(x))
    }

    module.exports.NonAsciiIdentifierStart = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/

    // ECMAScript 5.1/Unicode v6.3.0 NonAsciiIdentifierPart:

    module.exports.NonAsciiIdentifierPart = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0\u08A2-\u08AC\u08E4-\u08FE\u0900-\u0963\u0966-\u096F\u0971-\u0977\u0979-\u097F\u0981-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C01-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C82\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191C\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1D00-\u1DE6\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA697\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7B\uAA80-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE26\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/

  provide("parse-json/vendor/unicode", module.exports);
}(global));

// pakmanager:parse-json/vendor/parse
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  /*
     * Author: Alex Kocharin <alex@kocharin.ru>
     * GIT: https://github.com/rlidwka/jju
     * License: WTFPL, grab your copy here: http://www.wtfpl.net/txt/copying/
     */

    // RTFM: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf

    var Uni =  require('parse-json/vendor/unicode')

    function isHexDigit(x) {
      return (x >= '0' && x <= '9')
          || (x >= 'A' && x <= 'F')
          || (x >= 'a' && x <= 'f')
    }

    function isOctDigit(x) {
      return x >= '0' && x <= '7'
    }

    function isDecDigit(x) {
      return x >= '0' && x <= '9'
    }

    var unescapeMap = {
      '\'': '\'',
      '"' : '"',
      '\\': '\\',
      'b' : '\b',
      'f' : '\f',
      'n' : '\n',
      'r' : '\r',
      't' : '\t',
      'v' : '\v',
      '/' : '/',
    }

    function formatError(input, msg, position, lineno, column, json5) {
      var result = msg + ' at ' + (lineno + 1) + ':' + (column + 1)
        , tmppos = position - column - 1
        , srcline = ''
        , underline = ''

      var isLineTerminator = json5 ? Uni.isLineTerminator : Uni.isLineTerminatorJSON

      // output no more than 70 characters before the wrong ones
      if (tmppos < position - 70) {
        tmppos = position - 70
      }

      while (1) {
        var chr = input[++tmppos]

        if (isLineTerminator(chr) || tmppos === input.length) {
          if (position >= tmppos) {
            // ending line error, so show it after the last char
            underline += '^'
          }
          break
        }
        srcline += chr

        if (position === tmppos) {
          underline += '^'
        } else if (position > tmppos) {
          underline += input[tmppos] === '\t' ? '\t' : ' '
        }

        // output no more than 78 characters on the string
        if (srcline.length > 78) break
      }

      return result + '\n' + srcline + '\n' + underline
    }

    function parse(input, options) {
      // parse as a standard JSON mode
      var json5 = !(options.mode === 'json' || options.legacy)
      var isLineTerminator = json5 ? Uni.isLineTerminator : Uni.isLineTerminatorJSON
      var isWhiteSpace = json5 ? Uni.isWhiteSpace : Uni.isWhiteSpaceJSON

      var length = input.length
        , lineno = 0
        , linestart = 0
        , position = 0
        , stack = []

      var tokenStart = function() {}
      var tokenEnd = function(v) {return v}

      /* tokenize({
           raw: '...',
           type: 'whitespace'|'comment'|'key'|'literal'|'separator'|'newline',
           value: 'number'|'string'|'whatever',
           path: [...],
         })
      */
      if (options._tokenize) {
        ;(function() {
          var start = null
          tokenStart = function() {
            if (start !== null) throw Error('internal error, token overlap')
            start = position
          }

          tokenEnd = function(v, type) {
            if (start != position) {
              var hash = {
                raw: input.substr(start, position-start),
                type: type,
                stack: stack.slice(0),
              }
              if (v !== undefined) hash.value = v
              options._tokenize.call(null, hash)
            }
            start = null
            return v
          }
        })()
      }

      function fail(msg) {
        var column = position - linestart

        if (!msg) {
          if (position < length) {
            var token = '\'' +
              JSON
                .stringify(input[position])
                .replace(/^"|"$/g, '')
                .replace(/'/g, "\\'")
                .replace(/\\"/g, '"')
              + '\''

            if (!msg) msg = 'Unexpected token ' + token
          } else {
            if (!msg) msg = 'Unexpected end of input'
          }
        }

        var error = SyntaxError(formatError(input, msg, position, lineno, column, json5))
        error.row = lineno + 1
        error.column = column + 1
        throw error
      }

      function newline(chr) {
        // account for <cr><lf>
        if (chr === '\r' && input[position] === '\n') position++
        linestart = position
        lineno++
      }

      function parseGeneric() {
        var result

        while (position < length) {
          tokenStart()
          var chr = input[position++]

          if (chr === '"' || (chr === '\'' && json5)) {
            return tokenEnd(parseString(chr), 'literal')

          } else if (chr === '{') {
            tokenEnd(undefined, 'separator')
            return parseObject()

          } else if (chr === '[') {
            tokenEnd(undefined, 'separator')
            return parseArray()

          } else if (chr === '-'
                 ||  chr === '.'
                 ||  isDecDigit(chr)
                     //           + number       Infinity          NaN
                 ||  (json5 && (chr === '+' || chr === 'I' || chr === 'N'))
          ) {
            return tokenEnd(parseNumber(), 'literal')

          } else if (chr === 'n') {
            parseKeyword('null')
            return tokenEnd(null, 'literal')

          } else if (chr === 't') {
            parseKeyword('true')
            return tokenEnd(true, 'literal')

          } else if (chr === 'f') {
            parseKeyword('false')
            return tokenEnd(false, 'literal')

          } else {
            position--
            return tokenEnd(undefined)
          }
        }
      }

      function parseKey() {
        var result

        while (position < length) {
          tokenStart()
          var chr = input[position++]

          if (chr === '"' || (chr === '\'' && json5)) {
            return tokenEnd(parseString(chr), 'key')

          } else if (chr === '{') {
            tokenEnd(undefined, 'separator')
            return parseObject()

          } else if (chr === '[') {
            tokenEnd(undefined, 'separator')
            return parseArray()

          } else if (chr === '.'
                 ||  isDecDigit(chr)
          ) {
            return tokenEnd(parseNumber(true), 'key')

          } else if (json5
                 &&  Uni.isIdentifierStart(chr) || (chr === '\\' && input[position] === 'u')) {
            // unicode char or a unicode sequence
            var rollback = position - 1
            var result = parseIdentifier()

            if (result === undefined) {
              position = rollback
              return tokenEnd(undefined)
            } else {
              return tokenEnd(result, 'key')
            }

          } else {
            position--
            return tokenEnd(undefined)
          }
        }
      }

      function skipWhiteSpace() {
        tokenStart()
        while (position < length) {
          var chr = input[position++]

          if (isLineTerminator(chr)) {
            position--
            tokenEnd(undefined, 'whitespace')
            tokenStart()
            position++
            newline(chr)
            tokenEnd(undefined, 'newline')
            tokenStart()

          } else if (isWhiteSpace(chr)) {
            // nothing

          } else if (chr === '/'
                 && json5
                 && (input[position] === '/' || input[position] === '*')
          ) {
            position--
            tokenEnd(undefined, 'whitespace')
            tokenStart()
            position++
            skipComment(input[position++] === '*')
            tokenEnd(undefined, 'comment')
            tokenStart()

          } else {
            position--
            break
          }
        }
        return tokenEnd(undefined, 'whitespace')
      }

      function skipComment(multi) {
        while (position < length) {
          var chr = input[position++]

          if (isLineTerminator(chr)) {
            // LineTerminator is an end of singleline comment
            if (!multi) {
              // let parent function deal with newline
              position--
              return
            }

            newline(chr)

          } else if (chr === '*' && multi) {
            // end of multiline comment
            if (input[position] === '/') {
              position++
              return
            }

          } else {
            // nothing
          }
        }

        if (multi) {
          fail('Unclosed multiline comment')
        }
      }

      function parseKeyword(keyword) {
        // keyword[0] is not checked because it should've checked earlier
        var _pos = position
        var len = keyword.length
        for (var i=1; i<len; i++) {
          if (position >= length || keyword[i] != input[position]) {
            position = _pos-1
            fail()
          }
          position++
        }
      }

      function parseObject() {
        var result = options.null_prototype ? Object.create(null) : {}
          , empty_object = {}
          , is_non_empty = false

        while (position < length) {
          skipWhiteSpace()
          var item1 = parseKey()
          skipWhiteSpace()
          tokenStart()
          var chr = input[position++]
          tokenEnd(undefined, 'separator')

          if (chr === '}' && item1 === undefined) {
            if (!json5 && is_non_empty) {
              position--
              fail('Trailing comma in object')
            }
            return result

          } else if (chr === ':' && item1 !== undefined) {
            skipWhiteSpace()
            stack.push(item1)
            var item2 = parseGeneric()
            stack.pop()

            if (item2 === undefined) fail('No value found for key ' + item1)
            if (typeof(item1) !== 'string') {
              if (!json5 || typeof(item1) !== 'number') {
                fail('Wrong key type: ' + item1)
              }
            }

            if ((item1 in empty_object || empty_object[item1] != null) && options.reserved_keys !== 'replace') {
              if (options.reserved_keys === 'throw') {
                fail('Reserved key: ' + item1)
              } else {
                // silently ignore it
              }
            } else {
              if (typeof(options.reviver) === 'function') {
                item2 = options.reviver.call(null, item1, item2)
              }

              if (item2 !== undefined) {
                is_non_empty = true
                Object.defineProperty(result, item1, {
                  value: item2,
                  enumerable: true,
                  configurable: true,
                  writable: true,
                })
              }
            }

            skipWhiteSpace()

            tokenStart()
            var chr = input[position++]
            tokenEnd(undefined, 'separator')

            if (chr === ',') {
              continue

            } else if (chr === '}') {
              return result

            } else {
              fail()
            }

          } else {
            position--
            fail()
          }
        }

        fail()
      }

      function parseArray() {
        var result = []

        while (position < length) {
          skipWhiteSpace()
          stack.push(result.length)
          var item = parseGeneric()
          stack.pop()
          skipWhiteSpace()
          tokenStart()
          var chr = input[position++]
          tokenEnd(undefined, 'separator')

          if (item !== undefined) {
            if (typeof(options.reviver) === 'function') {
              item = options.reviver.call(null, String(result.length), item)
            }
            if (item === undefined) {
              result.length++
              item = true // hack for check below, not included into result
            } else {
              result.push(item)
            }
          }

          if (chr === ',') {
            if (item === undefined) {
              fail('Elisions are not supported')
            }

          } else if (chr === ']') {
            if (!json5 && item === undefined && result.length) {
              position--
              fail('Trailing comma in array')
            }
            return result

          } else {
            position--
            fail()
          }
        }
      }

      function parseNumber() {
        // rewind because we don't know first char
        position--

        var start = position
          , chr = input[position++]
          , t

        var to_num = function(is_octal) {
          var str = input.substr(start, position - start)

          if (is_octal) {
            var result = parseInt(str.replace(/^0o?/, ''), 8)
          } else {
            var result = Number(str)
          }

          if (Number.isNaN(result)) {
            position--
            fail('Bad numeric literal - "' + input.substr(start, position - start + 1) + '"')
          } else if (!json5 && !str.match(/^-?(0|[1-9][0-9]*)(\.[0-9]+)?(e[+-]?[0-9]+)?$/i)) {
            // additional restrictions imposed by json
            position--
            fail('Non-json numeric literal - "' + input.substr(start, position - start + 1) + '"')
          } else {
            return result
          }
        }

        // ex: -5982475.249875e+29384
        //     ^ skipping this
        if (chr === '-' || (chr === '+' && json5)) chr = input[position++]

        if (chr === 'N' && json5) {
          parseKeyword('NaN')
          return NaN
        }

        if (chr === 'I' && json5) {
          parseKeyword('Infinity')

          // returning +inf or -inf
          return to_num()
        }

        if (chr >= '1' && chr <= '9') {
          // ex: -5982475.249875e+29384
          //        ^^^ skipping these
          while (position < length && isDecDigit(input[position])) position++
          chr = input[position++]
        }

        // special case for leading zero: 0.123456
        if (chr === '0') {
          chr = input[position++]

          //             new syntax, "0o777"           old syntax, "0777"
          var is_octal = chr === 'o' || chr === 'O' || isOctDigit(chr)
          var is_hex = chr === 'x' || chr === 'X'

          if (json5 && (is_octal || is_hex)) {
            while (position < length
               &&  (is_hex ? isHexDigit : isOctDigit)( input[position] )
            ) position++

            var sign = 1
            if (input[start] === '-') {
              sign = -1
              start++
            } else if (input[start] === '+') {
              start++
            }

            return sign * to_num(is_octal)
          }
        }

        if (chr === '.') {
          // ex: -5982475.249875e+29384
          //                ^^^ skipping these
          while (position < length && isDecDigit(input[position])) position++
          chr = input[position++]
        }

        if (chr === 'e' || chr === 'E') {
          chr = input[position++]
          if (chr === '-' || chr === '+') position++
          // ex: -5982475.249875e+29384
          //                       ^^^ skipping these
          while (position < length && isDecDigit(input[position])) position++
          chr = input[position++]
        }

        // we have char in the buffer, so count for it
        position--
        return to_num()
      }

      function parseIdentifier() {
        // rewind because we don't know first char
        position--

        var result = ''

        while (position < length) {
          var chr = input[position++]

          if (chr === '\\'
          &&  input[position] === 'u'
          &&  isHexDigit(input[position+1])
          &&  isHexDigit(input[position+2])
          &&  isHexDigit(input[position+3])
          &&  isHexDigit(input[position+4])
          ) {
            // UnicodeEscapeSequence
            chr = String.fromCharCode(parseInt(input.substr(position+1, 4), 16))
            position += 5
          }

          if (result.length) {
            // identifier started
            if (Uni.isIdentifierPart(chr)) {
              result += chr
            } else {
              position--
              return result
            }

          } else {
            if (Uni.isIdentifierStart(chr)) {
              result += chr
            } else {
              return undefined
            }
          }
        }

        fail()
      }

      function parseString(endChar) {
        // 7.8.4 of ES262 spec
        var result = ''

        while (position < length) {
          var chr = input[position++]

          if (chr === endChar) {
            return result

          } else if (chr === '\\') {
            if (position >= length) fail()
            chr = input[position++]

            if (unescapeMap[chr] && (json5 || (chr != 'v' && chr != "'"))) {
              result += unescapeMap[chr]

            } else if (json5 && isLineTerminator(chr)) {
              // line continuation
              newline(chr)

            } else if (chr === 'u' || (chr === 'x' && json5)) {
              // unicode/character escape sequence
              var off = chr === 'u' ? 4 : 2

              // validation for \uXXXX
              for (var i=0; i<off; i++) {
                if (position >= length) fail()
                if (!isHexDigit(input[position])) fail('Bad escape sequence')
                position++
              }

              result += String.fromCharCode(parseInt(input.substr(position-off, off), 16))
            } else if (json5 && isOctDigit(chr)) {
              if (chr < '4' && isOctDigit(input[position]) && isOctDigit(input[position+1])) {
                // three-digit octal
                var digits = 3
              } else if (isOctDigit(input[position])) {
                // two-digit octal
                var digits = 2
              } else {
                var digits = 1
              }
              position += digits - 1
              result += String.fromCharCode(parseInt(input.substr(position-digits, digits), 8))
              /*if (!isOctDigit(input[position])) {
                // \0 is allowed still
                result += '\0'
              } else {
                fail('Octal literals are not supported')
              }*/

            } else if (json5) {
              // \X -> x
              result += chr

            } else {
              position--
              fail()
            }

          } else if (isLineTerminator(chr)) {
            fail()

          } else {
            if (!json5 && chr.charCodeAt(0) < 32) {
              position--
              fail('Unexpected control character')
            }

            // SourceCharacter but not one of " or \ or LineTerminator
            result += chr
          }
        }

        fail()
      }

      skipWhiteSpace()
      var return_value = parseGeneric()
      if (return_value !== undefined || position < length) {
        skipWhiteSpace()

        if (position >= length) {
          if (typeof(options.reviver) === 'function') {
            return_value = options.reviver.call(null, '', return_value)
          }
          return return_value
        } else {
          fail()
        }

      } else {
        if (position) {
          fail('No data, only a whitespace')
        } else {
          fail('No data, empty input')
        }
      }
    }

    /*
     * parse(text, options)
     * or
     * parse(text, reviver)
     *
     * where:
     * text - string
     * options - object
     * reviver - function
     */
    module.exports.parse = function parseJSON(input, options) {
      // support legacy functions
      if (typeof(options) === 'function') {
        options = {
          reviver: options
        }
      }

      if (input === undefined) {
        // parse(stringify(x)) should be equal x
        // with JSON functions it is not 'cause of undefined
        // so we're fixing it
        return undefined
      }

      // JSON.parse compat
      if (typeof(input) !== 'string') input = String(input)
      if (options == null) options = {}
      if (options.reserved_keys == null) options.reserved_keys = 'ignore'

      if (options.reserved_keys === 'throw' || options.reserved_keys === 'ignore') {
        if (options.null_prototype == null) {
          options.null_prototype = true
        }
      }

      try {
        return parse(input, options)
      } catch(err) {
        // jju is a recursive parser, so JSON.parse("{{{{{{{") could blow up the stack
        //
        // this catch is used to skip all those internal calls
        if (err instanceof SyntaxError && err.row != null && err.column != null) {
          var old_err = err
          err = SyntaxError(old_err.message)
          err.column = old_err.column
          err.row = old_err.row
        }
        throw err
      }
    }

    module.exports.tokenize = function tokenizeJSON(input, options) {
      if (options == null) options = {}

      options._tokenize = function(smth) {
        if (options._addstack) smth.stack.unshift.apply(smth.stack, options._addstack)
        tokens.push(smth)
      }

      var tokens = []
      tokens.data = module.exports.parse(input, options)
      return tokens
    }

  provide("parse-json/vendor/parse", module.exports);
}(global));

// pakmanager:parse-json
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    var errorEx = require('error-ex');
    var fallback =  require('parse-json/vendor/parse');

    var JSONError = errorEx('JSONError', {
    	fileName: errorEx.append('in %s')
    });

    module.exports = function (x, reviver, filename) {
    	if (typeof reviver === 'string') {
    		filename = reviver;
    		reviver = null;
    	}

    	try {
    		try {
    			return JSON.parse(x, reviver);
    		} catch (err) {
    			fallback.parse(x, {
    				mode: 'json',
    				reviver: reviver
    			});

    			throw err;
    		}
    	} catch (err) {
    		var jsonErr = new JSONError(err);

    		if (filename) {
    			jsonErr.fileName = filename;
    		}

    		throw jsonErr;
    	}
    };

  provide("parse-json", module.exports);
}(global));

// pakmanager:pify
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';

    var pify = module.exports = function (fn, P, opts) {
    	if (typeof P !== 'function') {
    		opts = P;
    		P = Promise;
    	}

    	opts = opts || {};

    	if (typeof fn !== 'function') {
    		return P.reject(new TypeError('Expected a function'));
    	}

    	return function () {
    		var that = this;
    		var args = [].slice.call(arguments);

    		return new P(function (resolve, reject) {
    			args.push(function (err, result) {
    				if (err) {
    					reject(err);
    				} else if (opts.multiArgs) {
    					resolve([].slice.call(arguments, 1));
    				} else {
    					resolve(result);
    				}
    			});

    			fn.apply(that, args);
    		});
    	};
    };

    pify.all = function (obj, P, opts) {
    	if (typeof P !== 'function') {
    		opts = P;
    		P = Promise;
    	}

    	opts = opts || {};

    	var filter = function (key) {
    		if (opts.include) {
    			return opts.include.indexOf(key) !== -1;
    		}

    		if (opts.exclude) {
    			return opts.exclude.indexOf(key) === -1;
    		}

    		return true;
    	};

    	var ret = (typeof obj === 'function') ? function () {
    		if (opts.excludeMain) {
    			return obj.apply(this, arguments);
    		}

    		return pify(obj, P, opts).apply(this, arguments);
    	} : {};

    	return Object.keys(obj).reduce(function (ret, key) {
    		var x = obj[key];
    		ret[key] = (typeof x === 'function') && filter(key) ? pify(x, P, opts) : x;
    		return ret;
    	}, ret);
    };

  provide("pify", module.exports);
}(global));

// pakmanager:strip-bom
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    var isUtf8 = require('is-utf8');

    module.exports = function (x) {
    	// Catches EFBBBF (UTF-8 BOM) because the buffer-to-string
    	// conversion translates it to FEFF (UTF-16 BOM)
    	if (typeof x === 'string' && x.charCodeAt(0) === 0xFEFF) {
    		return x.slice(1);
    	}

    	if (Buffer.isBuffer(x) && isUtf8(x) &&
    		x[0] === 0xEF && x[1] === 0xBB && x[2] === 0xBF) {
    		return x.slice(3);
    	}

    	return x;
    };

  provide("strip-bom", module.exports);
}(global));

// pakmanager:hosted-git-info/git-host-info.js
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict'

    var gitHosts = module.exports = {
      github: {
        // First two are insecure and generally shouldn't be used any more, but
        // they are still supported.
        'protocols': [ 'git', 'http', 'git+ssh', 'git+https', 'ssh', 'https' ],
        'domain': 'github.com',
        'treepath': 'tree',
        'filetemplate': 'https://{auth@}raw.githubusercontent.com/{user}/{project}/{committish}/{path}',
        'bugstemplate': 'https://{domain}/{user}/{project}/issues',
        'gittemplate': 'git://{auth@}{domain}/{user}/{project}.git{#committish}'
      },
      bitbucket: {
        'protocols': [ 'git+ssh', 'git+https', 'ssh', 'https' ],
        'domain': 'bitbucket.org',
        'treepath': 'src'
      },
      gitlab: {
        'protocols': [ 'git+ssh', 'git+https', 'ssh', 'https' ],
        'domain': 'gitlab.com',
        'treepath': 'tree',
        'docstemplate': 'https://{domain}/{user}/{project}{/tree/committish}#README',
        'bugstemplate': 'https://{domain}/{user}/{project}/issues'
      },
      gist: {
        'protocols': [ 'git', 'git+ssh', 'git+https', 'ssh', 'https' ],
        'domain': 'gist.github.com',
        'pathmatch': /^[/](?:([^/]+)[/])?([a-z0-9]+)(?:[.]git)?$/,
        'filetemplate': 'https://gist.githubusercontent.com/{user}/{project}/raw{/committish}/{path}',
        'bugstemplate': 'https://{domain}/{project}',
        'gittemplate': 'git://{domain}/{project}.git{#committish}',
        'sshtemplate': 'git@{domain}:/{project}.git{#committish}',
        'sshurltemplate': 'git+ssh://git@{domain}/{project}.git{#committish}',
        'browsetemplate': 'https://{domain}/{project}{/committish}',
        'docstemplate': 'https://{domain}/{project}{/committish}',
        'httpstemplate': 'git+https://{domain}/{project}.git{#committish}',
        'shortcuttemplate': '{type}:{project}{#committish}',
        'pathtemplate': '{project}{#committish}'
      }
    }

    var gitHostDefaults = {
      'sshtemplate': 'git@{domain}:{user}/{project}.git{#committish}',
      'sshurltemplate': 'git+ssh://git@{domain}/{user}/{project}.git{#committish}',
      'browsetemplate': 'https://{domain}/{user}/{project}{/tree/committish}',
      'docstemplate': 'https://{domain}/{user}/{project}{/tree/committish}#readme',
      'httpstemplate': 'git+https://{auth@}{domain}/{user}/{project}.git{#committish}',
      'filetemplate': 'https://{domain}/{user}/{project}/raw/{committish}/{path}',
      'shortcuttemplate': '{type}:{user}/{project}{#committish}',
      'pathtemplate': '{user}/{project}{#committish}',
      'pathmatch': /^[/]([^/]+)[/]([^/]+?)(?:[.]git)?$/
    }

    Object.keys(gitHosts).forEach(function (name) {
      Object.keys(gitHostDefaults).forEach(function (key) {
        if (gitHosts[name][key]) return
        gitHosts[name][key] = gitHostDefaults[key]
      })
      gitHosts[name].protocols_re = RegExp('^(' +
        gitHosts[name].protocols.map(function (protocol) {
          return protocol.replace(/([\\+*{}()\[\]$^|])/g, '\\$1')
        }).join('|') + '):$')
    })

  provide("hosted-git-info/git-host-info.js", module.exports);
}(global));

// pakmanager:hosted-git-info/git-host.js
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict'
    var gitHosts =  require('hosted-git-info/git-host-info.js')

    var GitHost = module.exports = function (type, user, auth, project, committish, defaultRepresentation) {
      var gitHostInfo = this
      gitHostInfo.type = type
      Object.keys(gitHosts[type]).forEach(function (key) {
        gitHostInfo[key] = gitHosts[type][key]
      })
      gitHostInfo.user = user
      gitHostInfo.auth = auth
      gitHostInfo.project = project
      gitHostInfo.committish = committish
      gitHostInfo.default = defaultRepresentation
    }
    GitHost.prototype = {}

    GitHost.prototype.hash = function () {
      return this.committish ? '#' + this.committish : ''
    }

    GitHost.prototype._fill = function (template, vars) {
      if (!template) return
      if (!vars) vars = {}
      var self = this
      Object.keys(this).forEach(function (key) {
        if (self[key] != null && vars[key] == null) vars[key] = self[key]
      })
      var rawAuth = vars.auth
      var rawComittish = vars.committish
      Object.keys(vars).forEach(function (key) {
        vars[key] = encodeURIComponent(vars[key])
      })
      vars['auth@'] = rawAuth ? rawAuth + '@' : ''
      vars['#committish'] = rawComittish ? '#' + rawComittish : ''
      vars['/tree/committish'] = vars.committish
                              ? '/' + vars.treepath + '/' + vars.committish
                              : ''
      vars['/committish'] = vars.committish ? '/' + vars.committish : ''
      vars.committish = vars.committish || 'master'
      var res = template
      Object.keys(vars).forEach(function (key) {
        res = res.replace(new RegExp('[{]' + key + '[}]', 'g'), vars[key])
      })
      return res
    }

    GitHost.prototype.ssh = function () {
      return this._fill(this.sshtemplate)
    }

    GitHost.prototype.sshurl = function () {
      return this._fill(this.sshurltemplate)
    }

    GitHost.prototype.browse = function () {
      return this._fill(this.browsetemplate)
    }

    GitHost.prototype.docs = function () {
      return this._fill(this.docstemplate)
    }

    GitHost.prototype.bugs = function () {
      return this._fill(this.bugstemplate)
    }

    GitHost.prototype.https = function () {
      return this._fill(this.httpstemplate)
    }

    GitHost.prototype.git = function () {
      return this._fill(this.gittemplate)
    }

    GitHost.prototype.shortcut = function () {
      return this._fill(this.shortcuttemplate)
    }

    GitHost.prototype.path = function () {
      return this._fill(this.pathtemplate)
    }

    GitHost.prototype.file = function (P) {
      return this._fill(this.filetemplate, {
        path: P.replace(/^[/]+/g, '')
      })
    }

    GitHost.prototype.getDefaultRepresentation = function () {
      return this.default
    }

    GitHost.prototype.toString = function () {
      return (this[this.default] || this.sshurl).call(this)
    }

  provide("hosted-git-info/git-host.js", module.exports);
}(global));

// pakmanager:hosted-git-info
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict'
    var url = require('url')
    var gitHosts =  require('hosted-git-info/git-host-info.js')
    var GitHost = module.exports =  require('hosted-git-info/git-host.js')

    var protocolToRepresentationMap = {
      'git+ssh': 'sshurl',
      'git+https': 'https',
      'ssh': 'sshurl',
      'git': 'git'
    }

    function protocolToRepresentation (protocol) {
      if (protocol.substr(-1) === ':') protocol = protocol.slice(0, -1)
      return protocolToRepresentationMap[protocol] || protocol
    }

    var authProtocols = {
      'git:': true,
      'https:': true,
      'git+https:': true,
      'http:': true,
      'git+http:': true
    }

    module.exports.fromUrl = function (giturl) {
      if (giturl == null || giturl === '') return
      var url = fixupUnqualifiedGist(
        isGitHubShorthand(giturl) ? 'github:' + giturl : giturl
      )
      var parsed = parseGitUrl(url)
      var matches = Object.keys(gitHosts).map(function (gitHostName) {
        var gitHostInfo = gitHosts[gitHostName]
        var auth = null
        if (parsed.auth && authProtocols[parsed.protocol]) {
          auth = decodeURIComponent(parsed.auth)
        }
        var committish = parsed.hash ? decodeURIComponent(parsed.hash.substr(1)) : null
        var user = null
        var project = null
        var defaultRepresentation = null
        if (parsed.protocol === gitHostName + ':') {
          user = decodeURIComponent(parsed.host)
          project = parsed.path && decodeURIComponent(parsed.path.replace(/^[/](.*?)(?:[.]git)?$/, '$1'))
          defaultRepresentation = 'shortcut'
        } else {
          if (parsed.host !== gitHostInfo.domain) return
          if (!gitHostInfo.protocols_re.test(parsed.protocol)) return
          var pathmatch = gitHostInfo.pathmatch
          var matched = parsed.path.match(pathmatch)
          if (!matched) return
          if (matched[1] != null) user = decodeURIComponent(matched[1])
          if (matched[2] != null) project = decodeURIComponent(matched[2])
          defaultRepresentation = protocolToRepresentation(parsed.protocol)
        }
        return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation)
      }).filter(function (gitHostInfo) { return gitHostInfo })
      if (matches.length !== 1) return
      return matches[0]
    }

    function isGitHubShorthand (arg) {
      // Note: This does not fully test the git ref format.
      // See https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
      //
      // The only way to do this properly would be to shell out to
      // git-check-ref-format, and as this is a fast sync function,
      // we don't want to do that.  Just let git fail if it turns
      // out that the commit-ish is invalid.
      // GH usernames cannot start with . or -
      return /^[^:@%/\s.-][^:@%/\s]*[/][^:@\s/%]+(?:#.*)?$/.test(arg)
    }

    function fixupUnqualifiedGist (giturl) {
      // necessary for round-tripping gists
      var parsed = url.parse(giturl)
      if (parsed.protocol === 'gist:' && parsed.host && !parsed.path) {
        return parsed.protocol + '/' + parsed.host
      } else {
        return giturl
      }
    }

    function parseGitUrl (giturl) {
      if (typeof giturl !== 'string') giturl = '' + giturl
      var matched = giturl.match(/^([^@]+)@([^:]+):[/]?((?:[^/]+[/])?[^/]+?)(?:[.]git)?(#.*)?$/)
      if (!matched) return url.parse(giturl)
      return {
        protocol: 'git+ssh:',
        slashes: true,
        auth: matched[1],
        host: matched[2],
        port: null,
        hostname: matched[2],
        hash: matched[4],
        search: null,
        query: null,
        pathname: '/' + matched[3],
        path: '/' + matched[3],
        href: 'git+ssh://' + matched[1] + '@' + matched[2] +
              '/' + matched[3] + (matched[4] || '')
      }
    }

  provide("hosted-git-info", module.exports);
}(global));

// pakmanager:is-builtin-module
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    var builtinModules = require('builtin-modules');

    module.exports = function (str) {
    	if (typeof str !== 'string') {
    		throw new TypeError('Expected a string');
    	}

    	return builtinModules.indexOf(str) !== -1;
    };

  provide("is-builtin-module", module.exports);
}(global));

// pakmanager:semver
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  exports = module.exports = SemVer;

    // The debug function is excluded entirely from the minified version.
    /* nomin */ var debug;
    /* nomin */ if (typeof process === 'object' &&
        /* nomin */ process.env &&
        /* nomin */ process.env.NODE_DEBUG &&
        /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG))
      /* nomin */ debug = function() {
        /* nomin */ var args = Array.prototype.slice.call(arguments, 0);
        /* nomin */ args.unshift('SEMVER');
        /* nomin */ console.log.apply(console, args);
        /* nomin */ };
    /* nomin */ else
      /* nomin */ debug = function() {};

    // Note: this is the semver.org version of the spec that it implements
    // Not necessarily the package version of this code.
    exports.SEMVER_SPEC_VERSION = '2.0.0';

    var MAX_LENGTH = 256;
    var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;

    // The actual regexps go on exports.re
    var re = exports.re = [];
    var src = exports.src = [];
    var R = 0;

    // The following Regular Expressions can be used for tokenizing,
    // validating, and parsing SemVer version strings.

    // ## Numeric Identifier
    // A single `0`, or a non-zero digit followed by zero or more digits.

    var NUMERICIDENTIFIER = R++;
    src[NUMERICIDENTIFIER] = '0|[1-9]\\d*';
    var NUMERICIDENTIFIERLOOSE = R++;
    src[NUMERICIDENTIFIERLOOSE] = '[0-9]+';

    // ## Non-numeric Identifier
    // Zero or more digits, followed by a letter or hyphen, and then zero or
    // more letters, digits, or hyphens.

    var NONNUMERICIDENTIFIER = R++;
    src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*';

    // ## Main Version
    // Three dot-separated numeric identifiers.

    var MAINVERSION = R++;
    src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' +
                       '(' + src[NUMERICIDENTIFIER] + ')\\.' +
                       '(' + src[NUMERICIDENTIFIER] + ')';

    var MAINVERSIONLOOSE = R++;
    src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
                            '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
                            '(' + src[NUMERICIDENTIFIERLOOSE] + ')';

    // ## Pre-release Version Identifier
    // A numeric identifier, or a non-numeric identifier.

    var PRERELEASEIDENTIFIER = R++;
    src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] +
                                '|' + src[NONNUMERICIDENTIFIER] + ')';

    var PRERELEASEIDENTIFIERLOOSE = R++;
    src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] +
                                     '|' + src[NONNUMERICIDENTIFIER] + ')';

    // ## Pre-release Version
    // Hyphen, followed by one or more dot-separated pre-release version
    // identifiers.

    var PRERELEASE = R++;
    src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] +
                      '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))';

    var PRERELEASELOOSE = R++;
    src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] +
                           '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))';

    // ## Build Metadata Identifier
    // Any combination of digits, letters, or hyphens.

    var BUILDIDENTIFIER = R++;
    src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+';

    // ## Build Metadata
    // Plus sign, followed by one or more period-separated build metadata
    // identifiers.

    var BUILD = R++;
    src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] +
                 '(?:\\.' + src[BUILDIDENTIFIER] + ')*))';

    // ## Full Version String
    // A main version, followed optionally by a pre-release version and
    // build metadata.

    // Note that the only major, minor, patch, and pre-release sections of
    // the version string are capturing groups.  The build metadata is not a
    // capturing group, because it should not ever be used in version
    // comparison.

    var FULL = R++;
    var FULLPLAIN = 'v?' + src[MAINVERSION] +
                    src[PRERELEASE] + '?' +
                    src[BUILD] + '?';

    src[FULL] = '^' + FULLPLAIN + '$';

    // like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
    // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
    // common in the npm registry.
    var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] +
                     src[PRERELEASELOOSE] + '?' +
                     src[BUILD] + '?';

    var LOOSE = R++;
    src[LOOSE] = '^' + LOOSEPLAIN + '$';

    var GTLT = R++;
    src[GTLT] = '((?:<|>)?=?)';

    // Something like "2.*" or "1.2.x".
    // Note that "x.x" is a valid xRange identifer, meaning "any version"
    // Only the first item is strictly required.
    var XRANGEIDENTIFIERLOOSE = R++;
    src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*';
    var XRANGEIDENTIFIER = R++;
    src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*';

    var XRANGEPLAIN = R++;
    src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' +
                       '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
                       '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
                       '(?:' + src[PRERELEASE] + ')?' +
                       src[BUILD] + '?' +
                       ')?)?';

    var XRANGEPLAINLOOSE = R++;
    src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
                            '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
                            '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
                            '(?:' + src[PRERELEASELOOSE] + ')?' +
                            src[BUILD] + '?' +
                            ')?)?';

    var XRANGE = R++;
    src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$';
    var XRANGELOOSE = R++;
    src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$';

    // Tilde ranges.
    // Meaning is "reasonably at or greater than"
    var LONETILDE = R++;
    src[LONETILDE] = '(?:~>?)';

    var TILDETRIM = R++;
    src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+';
    re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g');
    var tildeTrimReplace = '$1~';

    var TILDE = R++;
    src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$';
    var TILDELOOSE = R++;
    src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$';

    // Caret ranges.
    // Meaning is "at least and backwards compatible with"
    var LONECARET = R++;
    src[LONECARET] = '(?:\\^)';

    var CARETTRIM = R++;
    src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+';
    re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g');
    var caretTrimReplace = '$1^';

    var CARET = R++;
    src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$';
    var CARETLOOSE = R++;
    src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$';

    // A simple gt/lt/eq thing, or just "" to indicate "any version"
    var COMPARATORLOOSE = R++;
    src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$';
    var COMPARATOR = R++;
    src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$';

    // An expression to strip any whitespace between the gtlt and the thing
    // it modifies, so that `> 1.2.3` ==> `>1.2.3`
    var COMPARATORTRIM = R++;
    src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] +
                          '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')';

    // this one has to use the /g flag
    re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g');
    var comparatorTrimReplace = '$1$2$3';

    // Something like `1.2.3 - 1.2.4`
    // Note that these all use the loose form, because they'll be
    // checked against either the strict or loose comparator form
    // later.
    var HYPHENRANGE = R++;
    src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' +
                       '\\s+-\\s+' +
                       '(' + src[XRANGEPLAIN] + ')' +
                       '\\s*$';

    var HYPHENRANGELOOSE = R++;
    src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' +
                            '\\s+-\\s+' +
                            '(' + src[XRANGEPLAINLOOSE] + ')' +
                            '\\s*$';

    // Star ranges basically just allow anything at all.
    var STAR = R++;
    src[STAR] = '(<|>)?=?\\s*\\*';

    // Compile to actual regexp objects.
    // All are flag-free, unless they were created above with a flag.
    for (var i = 0; i < R; i++) {
      debug(i, src[i]);
      if (!re[i])
        re[i] = new RegExp(src[i]);
    }

    exports.parse = parse;
    function parse(version, loose) {
      if (version instanceof SemVer)
        return version;

      if (typeof version !== 'string')
        return null;

      if (version.length > MAX_LENGTH)
        return null;

      var r = loose ? re[LOOSE] : re[FULL];
      if (!r.test(version))
        return null;

      try {
        return new SemVer(version, loose);
      } catch (er) {
        return null;
      }
    }

    exports.valid = valid;
    function valid(version, loose) {
      var v = parse(version, loose);
      return v ? v.version : null;
    }

    exports.clean = clean;
    function clean(version, loose) {
      var s = parse(version.trim().replace(/^[=v]+/, ''), loose);
      return s ? s.version : null;
    }

    exports.SemVer = SemVer;

    function SemVer(version, loose) {
      if (version instanceof SemVer) {
        if (version.loose === loose)
          return version;
        else
          version = version.version;
      } else if (typeof version !== 'string') {
        throw new TypeError('Invalid Version: ' + version);
      }

      if (version.length > MAX_LENGTH)
        throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters')

      if (!(this instanceof SemVer))
        return new SemVer(version, loose);

      debug('SemVer', version, loose);
      this.loose = loose;
      var m = version.trim().match(loose ? re[LOOSE] : re[FULL]);

      if (!m)
        throw new TypeError('Invalid Version: ' + version);

      this.raw = version;

      // these are actually numbers
      this.major = +m[1];
      this.minor = +m[2];
      this.patch = +m[3];

      if (this.major > MAX_SAFE_INTEGER || this.major < 0)
        throw new TypeError('Invalid major version')

      if (this.minor > MAX_SAFE_INTEGER || this.minor < 0)
        throw new TypeError('Invalid minor version')

      if (this.patch > MAX_SAFE_INTEGER || this.patch < 0)
        throw new TypeError('Invalid patch version')

      // numberify any prerelease numeric ids
      if (!m[4])
        this.prerelease = [];
      else
        this.prerelease = m[4].split('.').map(function(id) {
          if (/^[0-9]+$/.test(id)) {
            var num = +id
            if (num >= 0 && num < MAX_SAFE_INTEGER)
              return num
          }
          return id;
        });

      this.build = m[5] ? m[5].split('.') : [];
      this.format();
    }

    SemVer.prototype.format = function() {
      this.version = this.major + '.' + this.minor + '.' + this.patch;
      if (this.prerelease.length)
        this.version += '-' + this.prerelease.join('.');
      return this.version;
    };

    SemVer.prototype.inspect = function() {
      return '<SemVer "' + this + '">';
    };

    SemVer.prototype.toString = function() {
      return this.version;
    };

    SemVer.prototype.compare = function(other) {
      debug('SemVer.compare', this.version, this.loose, other);
      if (!(other instanceof SemVer))
        other = new SemVer(other, this.loose);

      return this.compareMain(other) || this.comparePre(other);
    };

    SemVer.prototype.compareMain = function(other) {
      if (!(other instanceof SemVer))
        other = new SemVer(other, this.loose);

      return compareIdentifiers(this.major, other.major) ||
             compareIdentifiers(this.minor, other.minor) ||
             compareIdentifiers(this.patch, other.patch);
    };

    SemVer.prototype.comparePre = function(other) {
      if (!(other instanceof SemVer))
        other = new SemVer(other, this.loose);

      // NOT having a prerelease is > having one
      if (this.prerelease.length && !other.prerelease.length)
        return -1;
      else if (!this.prerelease.length && other.prerelease.length)
        return 1;
      else if (!this.prerelease.length && !other.prerelease.length)
        return 0;

      var i = 0;
      do {
        var a = this.prerelease[i];
        var b = other.prerelease[i];
        debug('prerelease compare', i, a, b);
        if (a === undefined && b === undefined)
          return 0;
        else if (b === undefined)
          return 1;
        else if (a === undefined)
          return -1;
        else if (a === b)
          continue;
        else
          return compareIdentifiers(a, b);
      } while (++i);
    };

    // preminor will bump the version up to the next minor release, and immediately
    // down to pre-release. premajor and prepatch work the same way.
    SemVer.prototype.inc = function(release, identifier) {
      switch (release) {
        case 'premajor':
          this.prerelease.length = 0;
          this.patch = 0;
          this.minor = 0;
          this.major++;
          this.inc('pre', identifier);
          break;
        case 'preminor':
          this.prerelease.length = 0;
          this.patch = 0;
          this.minor++;
          this.inc('pre', identifier);
          break;
        case 'prepatch':
          // If this is already a prerelease, it will bump to the next version
          // drop any prereleases that might already exist, since they are not
          // relevant at this point.
          this.prerelease.length = 0;
          this.inc('patch', identifier);
          this.inc('pre', identifier);
          break;
        // If the input is a non-prerelease version, this acts the same as
        // prepatch.
        case 'prerelease':
          if (this.prerelease.length === 0)
            this.inc('patch', identifier);
          this.inc('pre', identifier);
          break;

        case 'major':
          // If this is a pre-major version, bump up to the same major version.
          // Otherwise increment major.
          // 1.0.0-5 bumps to 1.0.0
          // 1.1.0 bumps to 2.0.0
          if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0)
            this.major++;
          this.minor = 0;
          this.patch = 0;
          this.prerelease = [];
          break;
        case 'minor':
          // If this is a pre-minor version, bump up to the same minor version.
          // Otherwise increment minor.
          // 1.2.0-5 bumps to 1.2.0
          // 1.2.1 bumps to 1.3.0
          if (this.patch !== 0 || this.prerelease.length === 0)
            this.minor++;
          this.patch = 0;
          this.prerelease = [];
          break;
        case 'patch':
          // If this is not a pre-release version, it will increment the patch.
          // If it is a pre-release it will bump up to the same patch version.
          // 1.2.0-5 patches to 1.2.0
          // 1.2.0 patches to 1.2.1
          if (this.prerelease.length === 0)
            this.patch++;
          this.prerelease = [];
          break;
        // This probably shouldn't be used publicly.
        // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction.
        case 'pre':
          if (this.prerelease.length === 0)
            this.prerelease = [0];
          else {
            var i = this.prerelease.length;
            while (--i >= 0) {
              if (typeof this.prerelease[i] === 'number') {
                this.prerelease[i]++;
                i = -2;
              }
            }
            if (i === -1) // didn't increment anything
              this.prerelease.push(0);
          }
          if (identifier) {
            // 1.2.0-beta.1 bumps to 1.2.0-beta.2,
            // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
            if (this.prerelease[0] === identifier) {
              if (isNaN(this.prerelease[1]))
                this.prerelease = [identifier, 0];
            } else
              this.prerelease = [identifier, 0];
          }
          break;

        default:
          throw new Error('invalid increment argument: ' + release);
      }
      this.format();
      this.raw = this.version;
      return this;
    };

    exports.inc = inc;
    function inc(version, release, loose, identifier) {
      if (typeof(loose) === 'string') {
        identifier = loose;
        loose = undefined;
      }

      try {
        return new SemVer(version, loose).inc(release, identifier).version;
      } catch (er) {
        return null;
      }
    }

    exports.diff = diff;
    function diff(version1, version2) {
      if (eq(version1, version2)) {
        return null;
      } else {
        var v1 = parse(version1);
        var v2 = parse(version2);
        if (v1.prerelease.length || v2.prerelease.length) {
          for (var key in v1) {
            if (key === 'major' || key === 'minor' || key === 'patch') {
              if (v1[key] !== v2[key]) {
                return 'pre'+key;
              }
            }
          }
          return 'prerelease';
        }
        for (var key in v1) {
          if (key === 'major' || key === 'minor' || key === 'patch') {
            if (v1[key] !== v2[key]) {
              return key;
            }
          }
        }
      }
    }

    exports.compareIdentifiers = compareIdentifiers;

    var numeric = /^[0-9]+$/;
    function compareIdentifiers(a, b) {
      var anum = numeric.test(a);
      var bnum = numeric.test(b);

      if (anum && bnum) {
        a = +a;
        b = +b;
      }

      return (anum && !bnum) ? -1 :
             (bnum && !anum) ? 1 :
             a < b ? -1 :
             a > b ? 1 :
             0;
    }

    exports.rcompareIdentifiers = rcompareIdentifiers;
    function rcompareIdentifiers(a, b) {
      return compareIdentifiers(b, a);
    }

    exports.major = major;
    function major(a, loose) {
      return new SemVer(a, loose).major;
    }

    exports.minor = minor;
    function minor(a, loose) {
      return new SemVer(a, loose).minor;
    }

    exports.patch = patch;
    function patch(a, loose) {
      return new SemVer(a, loose).patch;
    }

    exports.compare = compare;
    function compare(a, b, loose) {
      return new SemVer(a, loose).compare(b);
    }

    exports.compareLoose = compareLoose;
    function compareLoose(a, b) {
      return compare(a, b, true);
    }

    exports.rcompare = rcompare;
    function rcompare(a, b, loose) {
      return compare(b, a, loose);
    }

    exports.sort = sort;
    function sort(list, loose) {
      return list.sort(function(a, b) {
        return exports.compare(a, b, loose);
      });
    }

    exports.rsort = rsort;
    function rsort(list, loose) {
      return list.sort(function(a, b) {
        return exports.rcompare(a, b, loose);
      });
    }

    exports.gt = gt;
    function gt(a, b, loose) {
      return compare(a, b, loose) > 0;
    }

    exports.lt = lt;
    function lt(a, b, loose) {
      return compare(a, b, loose) < 0;
    }

    exports.eq = eq;
    function eq(a, b, loose) {
      return compare(a, b, loose) === 0;
    }

    exports.neq = neq;
    function neq(a, b, loose) {
      return compare(a, b, loose) !== 0;
    }

    exports.gte = gte;
    function gte(a, b, loose) {
      return compare(a, b, loose) >= 0;
    }

    exports.lte = lte;
    function lte(a, b, loose) {
      return compare(a, b, loose) <= 0;
    }

    exports.cmp = cmp;
    function cmp(a, op, b, loose) {
      var ret;
      switch (op) {
        case '===':
          if (typeof a === 'object') a = a.version;
          if (typeof b === 'object') b = b.version;
          ret = a === b;
          break;
        case '!==':
          if (typeof a === 'object') a = a.version;
          if (typeof b === 'object') b = b.version;
          ret = a !== b;
          break;
        case '': case '=': case '==': ret = eq(a, b, loose); break;
        case '!=': ret = neq(a, b, loose); break;
        case '>': ret = gt(a, b, loose); break;
        case '>=': ret = gte(a, b, loose); break;
        case '<': ret = lt(a, b, loose); break;
        case '<=': ret = lte(a, b, loose); break;
        default: throw new TypeError('Invalid operator: ' + op);
      }
      return ret;
    }

    exports.Comparator = Comparator;
    function Comparator(comp, loose) {
      if (comp instanceof Comparator) {
        if (comp.loose === loose)
          return comp;
        else
          comp = comp.value;
      }

      if (!(this instanceof Comparator))
        return new Comparator(comp, loose);

      debug('comparator', comp, loose);
      this.loose = loose;
      this.parse(comp);

      if (this.semver === ANY)
        this.value = '';
      else
        this.value = this.operator + this.semver.version;

      debug('comp', this);
    }

    var ANY = {};
    Comparator.prototype.parse = function(comp) {
      var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
      var m = comp.match(r);

      if (!m)
        throw new TypeError('Invalid comparator: ' + comp);

      this.operator = m[1];
      if (this.operator === '=')
        this.operator = '';

      // if it literally is just '>' or '' then allow anything.
      if (!m[2])
        this.semver = ANY;
      else
        this.semver = new SemVer(m[2], this.loose);
    };

    Comparator.prototype.inspect = function() {
      return '<SemVer Comparator "' + this + '">';
    };

    Comparator.prototype.toString = function() {
      return this.value;
    };

    Comparator.prototype.test = function(version) {
      debug('Comparator.test', version, this.loose);

      if (this.semver === ANY)
        return true;

      if (typeof version === 'string')
        version = new SemVer(version, this.loose);

      return cmp(version, this.operator, this.semver, this.loose);
    };

    exports.Range = Range;
    function Range(range, loose) {
      if ((range instanceof Range) && range.loose === loose)
        return range;

      if (!(this instanceof Range))
        return new Range(range, loose);

      this.loose = loose;

      // First, split based on boolean or ||
      this.raw = range;
      this.set = range.split(/\s*\|\|\s*/).map(function(range) {
        return this.parseRange(range.trim());
      }, this).filter(function(c) {
        // throw out any that are not relevant for whatever reason
        return c.length;
      });

      if (!this.set.length) {
        throw new TypeError('Invalid SemVer Range: ' + range);
      }

      this.format();
    }

    Range.prototype.inspect = function() {
      return '<SemVer Range "' + this.range + '">';
    };

    Range.prototype.format = function() {
      this.range = this.set.map(function(comps) {
        return comps.join(' ').trim();
      }).join('||').trim();
      return this.range;
    };

    Range.prototype.toString = function() {
      return this.range;
    };

    Range.prototype.parseRange = function(range) {
      var loose = this.loose;
      range = range.trim();
      debug('range', range, loose);
      // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
      var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE];
      range = range.replace(hr, hyphenReplace);
      debug('hyphen replace', range);
      // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
      range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace);
      debug('comparator trim', range, re[COMPARATORTRIM]);

      // `~ 1.2.3` => `~1.2.3`
      range = range.replace(re[TILDETRIM], tildeTrimReplace);

      // `^ 1.2.3` => `^1.2.3`
      range = range.replace(re[CARETTRIM], caretTrimReplace);

      // normalize spaces
      range = range.split(/\s+/).join(' ');

      // At this point, the range is completely trimmed and
      // ready to be split into comparators.

      var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
      var set = range.split(' ').map(function(comp) {
        return parseComparator(comp, loose);
      }).join(' ').split(/\s+/);
      if (this.loose) {
        // in loose mode, throw out any that are not valid comparators
        set = set.filter(function(comp) {
          return !!comp.match(compRe);
        });
      }
      set = set.map(function(comp) {
        return new Comparator(comp, loose);
      });

      return set;
    };

    // Mostly just for testing and legacy API reasons
    exports.toComparators = toComparators;
    function toComparators(range, loose) {
      return new Range(range, loose).set.map(function(comp) {
        return comp.map(function(c) {
          return c.value;
        }).join(' ').trim().split(' ');
      });
    }

    // comprised of xranges, tildes, stars, and gtlt's at this point.
    // already replaced the hyphen ranges
    // turn into a set of JUST comparators.
    function parseComparator(comp, loose) {
      debug('comp', comp);
      comp = replaceCarets(comp, loose);
      debug('caret', comp);
      comp = replaceTildes(comp, loose);
      debug('tildes', comp);
      comp = replaceXRanges(comp, loose);
      debug('xrange', comp);
      comp = replaceStars(comp, loose);
      debug('stars', comp);
      return comp;
    }

    function isX(id) {
      return !id || id.toLowerCase() === 'x' || id === '*';
    }

    // ~, ~> --> * (any, kinda silly)
    // ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0
    // ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0
    // ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0
    // ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0
    // ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0
    function replaceTildes(comp, loose) {
      return comp.trim().split(/\s+/).map(function(comp) {
        return replaceTilde(comp, loose);
      }).join(' ');
    }

    function replaceTilde(comp, loose) {
      var r = loose ? re[TILDELOOSE] : re[TILDE];
      return comp.replace(r, function(_, M, m, p, pr) {
        debug('tilde', comp, _, M, m, p, pr);
        var ret;

        if (isX(M))
          ret = '';
        else if (isX(m))
          ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
        else if (isX(p))
          // ~1.2 == >=1.2.0- <1.3.0-
          ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
        else if (pr) {
          debug('replaceTilde pr', pr);
          if (pr.charAt(0) !== '-')
            pr = '-' + pr;
          ret = '>=' + M + '.' + m + '.' + p + pr +
                ' <' + M + '.' + (+m + 1) + '.0';
        } else
          // ~1.2.3 == >=1.2.3 <1.3.0
          ret = '>=' + M + '.' + m + '.' + p +
                ' <' + M + '.' + (+m + 1) + '.0';

        debug('tilde return', ret);
        return ret;
      });
    }

    // ^ --> * (any, kinda silly)
    // ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0
    // ^2.0, ^2.0.x --> >=2.0.0 <3.0.0
    // ^1.2, ^1.2.x --> >=1.2.0 <2.0.0
    // ^1.2.3 --> >=1.2.3 <2.0.0
    // ^1.2.0 --> >=1.2.0 <2.0.0
    function replaceCarets(comp, loose) {
      return comp.trim().split(/\s+/).map(function(comp) {
        return replaceCaret(comp, loose);
      }).join(' ');
    }

    function replaceCaret(comp, loose) {
      debug('caret', comp, loose);
      var r = loose ? re[CARETLOOSE] : re[CARET];
      return comp.replace(r, function(_, M, m, p, pr) {
        debug('caret', comp, _, M, m, p, pr);
        var ret;

        if (isX(M))
          ret = '';
        else if (isX(m))
          ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
        else if (isX(p)) {
          if (M === '0')
            ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
          else
            ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0';
        } else if (pr) {
          debug('replaceCaret pr', pr);
          if (pr.charAt(0) !== '-')
            pr = '-' + pr;
          if (M === '0') {
            if (m === '0')
              ret = '>=' + M + '.' + m + '.' + p + pr +
                    ' <' + M + '.' + m + '.' + (+p + 1);
            else
              ret = '>=' + M + '.' + m + '.' + p + pr +
                    ' <' + M + '.' + (+m + 1) + '.0';
          } else
            ret = '>=' + M + '.' + m + '.' + p + pr +
                  ' <' + (+M + 1) + '.0.0';
        } else {
          debug('no pr');
          if (M === '0') {
            if (m === '0')
              ret = '>=' + M + '.' + m + '.' + p +
                    ' <' + M + '.' + m + '.' + (+p + 1);
            else
              ret = '>=' + M + '.' + m + '.' + p +
                    ' <' + M + '.' + (+m + 1) + '.0';
          } else
            ret = '>=' + M + '.' + m + '.' + p +
                  ' <' + (+M + 1) + '.0.0';
        }

        debug('caret return', ret);
        return ret;
      });
    }

    function replaceXRanges(comp, loose) {
      debug('replaceXRanges', comp, loose);
      return comp.split(/\s+/).map(function(comp) {
        return replaceXRange(comp, loose);
      }).join(' ');
    }

    function replaceXRange(comp, loose) {
      comp = comp.trim();
      var r = loose ? re[XRANGELOOSE] : re[XRANGE];
      return comp.replace(r, function(ret, gtlt, M, m, p, pr) {
        debug('xRange', comp, ret, gtlt, M, m, p, pr);
        var xM = isX(M);
        var xm = xM || isX(m);
        var xp = xm || isX(p);
        var anyX = xp;

        if (gtlt === '=' && anyX)
          gtlt = '';

        if (xM) {
          if (gtlt === '>' || gtlt === '<') {
            // nothing is allowed
            ret = '<0.0.0';
          } else {
            // nothing is forbidden
            ret = '*';
          }
        } else if (gtlt && anyX) {
          // replace X with 0
          if (xm)
            m = 0;
          if (xp)
            p = 0;

          if (gtlt === '>') {
            // >1 => >=2.0.0
            // >1.2 => >=1.3.0
            // >1.2.3 => >= 1.2.4
            gtlt = '>=';
            if (xm) {
              M = +M + 1;
              m = 0;
              p = 0;
            } else if (xp) {
              m = +m + 1;
              p = 0;
            }
          } else if (gtlt === '<=') {
            // <=0.7.x is actually <0.8.0, since any 0.7.x should
            // pass.  Similarly, <=7.x is actually <8.0.0, etc.
            gtlt = '<'
            if (xm)
              M = +M + 1
            else
              m = +m + 1
          }

          ret = gtlt + M + '.' + m + '.' + p;
        } else if (xm) {
          ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
        } else if (xp) {
          ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
        }

        debug('xRange return', ret);

        return ret;
      });
    }

    // Because * is AND-ed with everything else in the comparator,
    // and '' means "any version", just remove the *s entirely.
    function replaceStars(comp, loose) {
      debug('replaceStars', comp, loose);
      // Looseness is ignored here.  star is always as loose as it gets!
      return comp.trim().replace(re[STAR], '');
    }

    // This function is passed to string.replace(re[HYPHENRANGE])
    // M, m, patch, prerelease, build
    // 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
    // 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do
    // 1.2 - 3.4 => >=1.2.0 <3.5.0
    function hyphenReplace($0,
                           from, fM, fm, fp, fpr, fb,
                           to, tM, tm, tp, tpr, tb) {

      if (isX(fM))
        from = '';
      else if (isX(fm))
        from = '>=' + fM + '.0.0';
      else if (isX(fp))
        from = '>=' + fM + '.' + fm + '.0';
      else
        from = '>=' + from;

      if (isX(tM))
        to = '';
      else if (isX(tm))
        to = '<' + (+tM + 1) + '.0.0';
      else if (isX(tp))
        to = '<' + tM + '.' + (+tm + 1) + '.0';
      else if (tpr)
        to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr;
      else
        to = '<=' + to;

      return (from + ' ' + to).trim();
    }

    // if ANY of the sets match ALL of its comparators, then pass
    Range.prototype.test = function(version) {
      if (!version)
        return false;

      if (typeof version === 'string')
        version = new SemVer(version, this.loose);

      for (var i = 0; i < this.set.length; i++) {
        if (testSet(this.set[i], version))
          return true;
      }
      return false;
    };

    function testSet(set, version) {
      for (var i = 0; i < set.length; i++) {
        if (!set[i].test(version))
          return false;
      }

      if (version.prerelease.length) {
        // Find the set of versions that are allowed to have prereleases
        // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0
        // That should allow `1.2.3-pr.2` to pass.
        // However, `1.2.4-alpha.notready` should NOT be allowed,
        // even though it's within the range set by the comparators.
        for (var i = 0; i < set.length; i++) {
          debug(set[i].semver);
          if (set[i].semver === ANY)
            continue;

          if (set[i].semver.prerelease.length > 0) {
            var allowed = set[i].semver;
            if (allowed.major === version.major &&
                allowed.minor === version.minor &&
                allowed.patch === version.patch)
              return true;
          }
        }

        // Version has a -pre, but it's not one of the ones we like.
        return false;
      }

      return true;
    }

    exports.satisfies = satisfies;
    function satisfies(version, range, loose) {
      try {
        range = new Range(range, loose);
      } catch (er) {
        return false;
      }
      return range.test(version);
    }

    exports.maxSatisfying = maxSatisfying;
    function maxSatisfying(versions, range, loose) {
      return versions.filter(function(version) {
        return satisfies(version, range, loose);
      }).sort(function(a, b) {
        return rcompare(a, b, loose);
      })[0] || null;
    }

    exports.validRange = validRange;
    function validRange(range, loose) {
      try {
        // Return '*' instead of '' so that truthiness works.
        // This will throw if it's invalid anyway
        return new Range(range, loose).range || '*';
      } catch (er) {
        return null;
      }
    }

    // Determine if version is less than all the versions possible in the range
    exports.ltr = ltr;
    function ltr(version, range, loose) {
      return outside(version, range, '<', loose);
    }

    // Determine if version is greater than all the versions possible in the range.
    exports.gtr = gtr;
    function gtr(version, range, loose) {
      return outside(version, range, '>', loose);
    }

    exports.outside = outside;
    function outside(version, range, hilo, loose) {
      version = new SemVer(version, loose);
      range = new Range(range, loose);

      var gtfn, ltefn, ltfn, comp, ecomp;
      switch (hilo) {
        case '>':
          gtfn = gt;
          ltefn = lte;
          ltfn = lt;
          comp = '>';
          ecomp = '>=';
          break;
        case '<':
          gtfn = lt;
          ltefn = gte;
          ltfn = gt;
          comp = '<';
          ecomp = '<=';
          break;
        default:
          throw new TypeError('Must provide a hilo val of "<" or ">"');
      }

      // If it satisifes the range it is not outside
      if (satisfies(version, range, loose)) {
        return false;
      }

      // From now on, variable terms are as if we're in "gtr" mode.
      // but note that everything is flipped for the "ltr" function.

      for (var i = 0; i < range.set.length; ++i) {
        var comparators = range.set[i];

        var high = null;
        var low = null;

        comparators.forEach(function(comparator) {
          if (comparator.semver === ANY) {
            comparator = new Comparator('>=0.0.0')
          }
          high = high || comparator;
          low = low || comparator;
          if (gtfn(comparator.semver, high.semver, loose)) {
            high = comparator;
          } else if (ltfn(comparator.semver, low.semver, loose)) {
            low = comparator;
          }
        });

        // If the edge version comparator has a operator then our version
        // isn't outside it
        if (high.operator === comp || high.operator === ecomp) {
          return false;
        }

        // If the lowest version comparator has an operator and our version
        // is less than it then it isn't higher than the range
        if ((!low.operator || low.operator === comp) &&
            ltefn(version, low.semver)) {
          return false;
        } else if (low.operator === ecomp && ltfn(version, low.semver)) {
          return false;
        }
      }
      return true;
    }

  provide("semver", module.exports);
}(global));

// pakmanager:validate-npm-package-license
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  var parse = require('spdx-expression-parse');
    var correct = require('spdx-correct');

    var genericWarning = (
      'license should be ' +
      'a valid SPDX license expression (without "LicenseRef"), ' +
      '"UNLICENSED", or ' +
      '"SEE LICENSE IN <filename>"'
    );

    var fileReferenceRE = /^SEE LICEN[CS]E IN (.+)$/;

    function startsWith(prefix, string) {
      return string.slice(0, prefix.length) === prefix;
    }

    function usesLicenseRef(ast) {
      if (ast.hasOwnProperty('license')) {
        var license = ast.license;
        return (
          startsWith('LicenseRef', license) ||
          startsWith('DocumentRef', license)
        );
      } else {
        return (
          usesLicenseRef(ast.left) ||
          usesLicenseRef(ast.right)
        );
      }
    }

    module.exports = function(argument) {
      var ast;

      try {
        ast = parse(argument);
      } catch (e) {
        var match
        if (
          argument === 'UNLICENSED' ||
          argument === 'UNLICENCED'
        ) {
          return {
            validForOldPackages: true,
            validForNewPackages: true,
            unlicensed: true
          };
        } else if (match = fileReferenceRE.exec(argument)) {
          return {
            validForOldPackages: true,
            validForNewPackages: true,
            inFile: match[1]
          };
        } else {
          var result = {
            validForOldPackages: false,
            validForNewPackages: false,
            warnings: [genericWarning]
          };
          var corrected = correct(argument);
          if (corrected) {
            result.warnings.push(
              'license is similar to the valid expression "' + corrected + '"'
            );
          }
          return result;
        }
      }

      if (usesLicenseRef(ast)) {
        return {
          validForNewPackages: false,
          validForOldPackages: false,
          spdx: true,
          warnings: [genericWarning]
        };
      } else {
        return {
          validForNewPackages: true,
          validForOldPackages: true,
          spdx: true
        };
      }
    };

  provide("validate-npm-package-license", module.exports);
}(global));

// pakmanager:is-finite
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    var numberIsNan = require('number-is-nan');

    module.exports = Number.isFinite || function (val) {
    	return !(typeof val !== 'number' || numberIsNan(val) || val === Infinity || val === -Infinity);
    };

  provide("is-finite", module.exports);
}(global));

// pakmanager:lodash._getnative
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  /**
     * lodash 3.9.1 (Custom Build) <https://lodash.com/>
     * Build: `lodash modern modularize exports="npm" -o ./`
     * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
     * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
     * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
     * Available under MIT license <https://lodash.com/license>
     */

    /** `Object#toString` result references. */
    var funcTag = '[object Function]';

    /** Used to detect host constructors (Safari > 5). */
    var reIsHostCtor = /^\[object .+?Constructor\]$/;

    /**
     * Checks if `value` is object-like.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
     */
    function isObjectLike(value) {
      return !!value && typeof value == 'object';
    }

    /** Used for native method references. */
    var objectProto = Object.prototype;

    /** Used to resolve the decompiled source of functions. */
    var fnToString = Function.prototype.toString;

    /** Used to check objects for own properties. */
    var hasOwnProperty = objectProto.hasOwnProperty;

    /**
     * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
     * of values.
     */
    var objToString = objectProto.toString;

    /** Used to detect if a method is native. */
    var reIsNative = RegExp('^' +
      fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
      .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
    );

    /**
     * Gets the native function at `key` of `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @param {string} key The key of the method to get.
     * @returns {*} Returns the function if it's native, else `undefined`.
     */
    function getNative(object, key) {
      var value = object == null ? undefined : object[key];
      return isNative(value) ? value : undefined;
    }

    /**
     * Checks if `value` is classified as a `Function` object.
     *
     * @static
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
     * @example
     *
     * _.isFunction(_);
     * // => true
     *
     * _.isFunction(/abc/);
     * // => false
     */
    function isFunction(value) {
      // The use of `Object#toString` avoids issues with the `typeof` operator
      // in older versions of Chrome and Safari which return 'function' for regexes
      // and Safari 8 equivalents which return 'object' for typed array constructors.
      return isObject(value) && objToString.call(value) == funcTag;
    }

    /**
     * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
     *
     * @static
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an object, else `false`.
     * @example
     *
     * _.isObject({});
     * // => true
     *
     * _.isObject([1, 2, 3]);
     * // => true
     *
     * _.isObject(1);
     * // => false
     */
    function isObject(value) {
      // Avoid a V8 JIT bug in Chrome 19-20.
      // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
      var type = typeof value;
      return !!value && (type == 'object' || type == 'function');
    }

    /**
     * Checks if `value` is a native function.
     *
     * @static
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
     * @example
     *
     * _.isNative(Array.prototype.push);
     * // => true
     *
     * _.isNative(_);
     * // => false
     */
    function isNative(value) {
      if (value == null) {
        return false;
      }
      if (isFunction(value)) {
        return reIsNative.test(fnToString.call(value));
      }
      return isObjectLike(value) && reIsHostCtor.test(value);
    }

    module.exports = getNative;

  provide("lodash._getnative", module.exports);
}(global));

// pakmanager:lodash.isarguments
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  /**
     * lodash 3.0.4 (Custom Build) <https://lodash.com/>
     * Build: `lodash modern modularize exports="npm" -o ./`
     * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
     * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
     * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
     * Available under MIT license <https://lodash.com/license>
     */

    /**
     * Checks if `value` is object-like.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
     */
    function isObjectLike(value) {
      return !!value && typeof value == 'object';
    }

    /** Used for native method references. */
    var objectProto = Object.prototype;

    /** Used to check objects for own properties. */
    var hasOwnProperty = objectProto.hasOwnProperty;

    /** Native method references. */
    var propertyIsEnumerable = objectProto.propertyIsEnumerable;

    /**
     * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
     * of an array-like value.
     */
    var MAX_SAFE_INTEGER = 9007199254740991;

    /**
     * The base implementation of `_.property` without support for deep paths.
     *
     * @private
     * @param {string} key The key of the property to get.
     * @returns {Function} Returns the new function.
     */
    function baseProperty(key) {
      return function(object) {
        return object == null ? undefined : object[key];
      };
    }

    /**
     * Gets the "length" property value of `object`.
     *
     * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
     * that affects Safari on at least iOS 8.1-8.3 ARM64.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {*} Returns the "length" value.
     */
    var getLength = baseProperty('length');

    /**
     * Checks if `value` is array-like.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
     */
    function isArrayLike(value) {
      return value != null && isLength(getLength(value));
    }

    /**
     * Checks if `value` is a valid array-like length.
     *
     * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
     */
    function isLength(value) {
      return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
    }

    /**
     * Checks if `value` is classified as an `arguments` object.
     *
     * @static
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
     * @example
     *
     * _.isArguments(function() { return arguments; }());
     * // => true
     *
     * _.isArguments([1, 2, 3]);
     * // => false
     */
    function isArguments(value) {
      return isObjectLike(value) && isArrayLike(value) &&
        hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
    }

    module.exports = isArguments;

  provide("lodash.isarguments", module.exports);
}(global));

// pakmanager:lodash.isarray
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  /**
     * lodash 3.0.4 (Custom Build) <https://lodash.com/>
     * Build: `lodash modern modularize exports="npm" -o ./`
     * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
     * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
     * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
     * Available under MIT license <https://lodash.com/license>
     */

    /** `Object#toString` result references. */
    var arrayTag = '[object Array]',
        funcTag = '[object Function]';

    /** Used to detect host constructors (Safari > 5). */
    var reIsHostCtor = /^\[object .+?Constructor\]$/;

    /**
     * Checks if `value` is object-like.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
     */
    function isObjectLike(value) {
      return !!value && typeof value == 'object';
    }

    /** Used for native method references. */
    var objectProto = Object.prototype;

    /** Used to resolve the decompiled source of functions. */
    var fnToString = Function.prototype.toString;

    /** Used to check objects for own properties. */
    var hasOwnProperty = objectProto.hasOwnProperty;

    /**
     * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
     * of values.
     */
    var objToString = objectProto.toString;

    /** Used to detect if a method is native. */
    var reIsNative = RegExp('^' +
      fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
      .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
    );

    /* Native method references for those with the same name as other `lodash` methods. */
    var nativeIsArray = getNative(Array, 'isArray');

    /**
     * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
     * of an array-like value.
     */
    var MAX_SAFE_INTEGER = 9007199254740991;

    /**
     * Gets the native function at `key` of `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @param {string} key The key of the method to get.
     * @returns {*} Returns the function if it's native, else `undefined`.
     */
    function getNative(object, key) {
      var value = object == null ? undefined : object[key];
      return isNative(value) ? value : undefined;
    }

    /**
     * Checks if `value` is a valid array-like length.
     *
     * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
     */
    function isLength(value) {
      return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
    }

    /**
     * Checks if `value` is classified as an `Array` object.
     *
     * @static
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
     * @example
     *
     * _.isArray([1, 2, 3]);
     * // => true
     *
     * _.isArray(function() { return arguments; }());
     * // => false
     */
    var isArray = nativeIsArray || function(value) {
      return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
    };

    /**
     * Checks if `value` is classified as a `Function` object.
     *
     * @static
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
     * @example
     *
     * _.isFunction(_);
     * // => true
     *
     * _.isFunction(/abc/);
     * // => false
     */
    function isFunction(value) {
      // The use of `Object#toString` avoids issues with the `typeof` operator
      // in older versions of Chrome and Safari which return 'function' for regexes
      // and Safari 8 equivalents which return 'object' for typed array constructors.
      return isObject(value) && objToString.call(value) == funcTag;
    }

    /**
     * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
     *
     * @static
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an object, else `false`.
     * @example
     *
     * _.isObject({});
     * // => true
     *
     * _.isObject([1, 2, 3]);
     * // => true
     *
     * _.isObject(1);
     * // => false
     */
    function isObject(value) {
      // Avoid a V8 JIT bug in Chrome 19-20.
      // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
      var type = typeof value;
      return !!value && (type == 'object' || type == 'function');
    }

    /**
     * Checks if `value` is a native function.
     *
     * @static
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
     * @example
     *
     * _.isNative(Array.prototype.push);
     * // => true
     *
     * _.isNative(_);
     * // => false
     */
    function isNative(value) {
      if (value == null) {
        return false;
      }
      if (isFunction(value)) {
        return reIsNative.test(fnToString.call(value));
      }
      return isObjectLike(value) && reIsHostCtor.test(value);
    }

    module.exports = isArray;

  provide("lodash.isarray", module.exports);
}(global));

// pakmanager:error-ex
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';

    var util = require('util');

    var errorEx = function errorEx(name, properties) {
    	if (!name || name.constructor !== String) {
    		properties = name || {};
    		name = Error.name;
    	}

    	var errorExError = function ErrorEXError(message) {
    		if (!this) {
    			return new ErrorEXError(message);
    		}

    		message = message instanceof Error
    			? message.message
    			: (message || this.message);

    		Error.call(this, message);
    		Error.captureStackTrace(this, errorExError);
    		this.name = name;

    		delete this.message;

    		Object.defineProperty(this, 'message', {
    			configurable: true,
    			enumerable: false,
    			get: function () {
    				var newMessage = message.split(/\r?\n/g);

    				for (var key in properties) {
    					if (properties.hasOwnProperty(key) && 'message' in properties[key]) {
    						newMessage = properties[key].message(this[key], newMessage) ||
    							newMessage;
    					}
    				}

    				return newMessage.join('\n');
    			},
    			set: function (v) {
    				message = v;
    			}
    		});

    		var stackDescriptor = Object.getOwnPropertyDescriptor(this, 'stack');
    		var stackGetter = stackDescriptor.get;

    		stackDescriptor.get = function () {
    			var stack = stackGetter.call(this).split(/\r?\n+/g);

    			var lineCount = 1;
    			for (var key in properties) {
    				if (!properties.hasOwnProperty(key)) {
    					continue;
    				}

    				var modifier = properties[key];

    				if ('line' in modifier) {
    					var line = modifier.line(this[key]);
    					if (line) {
    						stack.splice(lineCount, 0, '    ' + line);
    					}
    				}

    				if ('stack' in modifier) {
    					modifier.stack(this[key], stack);
    				}
    			}

    			return stack.join('\n');
    		};

    		Object.defineProperty(this, 'stack', stackDescriptor);
    	};

    	util.inherits(errorExError, Error);

    	return errorExError;
    };

    errorEx.append = function (str, def) {
    	return {
    		message: function (v, message) {
    			v = v || def;

    			if (v) {
    				message[0] += ' ' + str.replace('%s', v.toString());
    			}

    			return message;
    		}
    	};
    };

    errorEx.line = function (str, def) {
    	return {
    		line: function (v) {
    			v = v || def;

    			if (v) {
    				return str.replace('%s', v.toString());
    			}

    			return null;
    		}
    	};
    };

    module.exports = errorEx;

  provide("error-ex", module.exports);
}(global));

// pakmanager:is-utf8
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

    exports = module.exports = function(bytes)
    {
        var i = 0;
        while(i < bytes.length)
        {
            if(     (// ASCII
                        bytes[i] == 0x09 ||
                        bytes[i] == 0x0A ||
                        bytes[i] == 0x0D ||
                        (0x20 <= bytes[i] && bytes[i] <= 0x7E)
                    )
              ) {
                  i += 1;
                  continue;
              }

            if(     (// non-overlong 2-byte
                        (0xC2 <= bytes[i] && bytes[i] <= 0xDF) &&
                        (0x80 <= bytes[i+1] && bytes[i+1] <= 0xBF)
                    )
              ) {
                  i += 2;
                  continue;
              }

            if(     (// excluding overlongs
                        bytes[i] == 0xE0 &&
                        (0xA0 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
                        (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF)
                    ) ||
                    (// straight 3-byte
                     ((0xE1 <= bytes[i] && bytes[i] <= 0xEC) ||
                      bytes[i] == 0xEE ||
                      bytes[i] == 0xEF) &&
                     (0x80 <= bytes[i + 1] && bytes[i+1] <= 0xBF) &&
                     (0x80 <= bytes[i+2] && bytes[i+2] <= 0xBF)
                    ) ||
                    (// excluding surrogates
                     bytes[i] == 0xED &&
                     (0x80 <= bytes[i+1] && bytes[i+1] <= 0x9F) &&
                     (0x80 <= bytes[i+2] && bytes[i+2] <= 0xBF)
                    )
              ) {
                  i += 3;
                  continue;
              }

            if(     (// planes 1-3
                        bytes[i] == 0xF0 &&
                        (0x90 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
                        (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
                        (0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
                    ) ||
                    (// planes 4-15
                     (0xF1 <= bytes[i] && bytes[i] <= 0xF3) &&
                     (0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
                     (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
                     (0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
                    ) ||
                    (// plane 16
                     bytes[i] == 0xF4 &&
                     (0x80 <= bytes[i + 1] && bytes[i + 1] <= 0x8F) &&
                     (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
                     (0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
                    )
              ) {
                  i += 4;
                  continue;
              }

            return false;
        }

        return true;
    }

  provide("is-utf8", module.exports);
}(global));

// pakmanager:builtin-modules
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';

    var blacklist = [
    	'freelist',
    	'sys'
    ];

    module.exports = Object.keys(process.binding('natives')).filter(function (el) {
    	return !/^_|^internal/.test(el) && blacklist.indexOf(el) === -1;
    }).sort();

  provide("builtin-modules", module.exports);
}(global));

// pakmanager:spdx-correct
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  var licenseIDs = require('spdx-license-ids');

    function valid(string) {
      return licenseIDs.indexOf(string) > -1;
    }

    // Common transpositions of license identifier acronyms
    var transpositions = [
      ['APGL', 'AGPL'],
      ['Gpl', 'GPL'],
      ['GLP', 'GPL'],
      ['APL', 'Apache'],
      ['ISD', 'ISC'],
      ['GLP', 'GPL'],
      ['IST', 'ISC'],
      ['Claude', 'Clause'],
      [' or later', '+'],
      [' International', ''],
      ['GNU', 'GPL'],
      ['GUN', 'GPL'],
      ['+', ''],
      ['GNU GPL', 'GPL'],
      ['GNU/GPL', 'GPL'],
      ['GNU GLP', 'GPL'],
      ['GNU General Public License', 'GPL'],
      ['Gnu public license', 'GPL'],
      ['GNU Public License', 'GPL'],
      ['GNU GENERAL PUBLIC LICENSE', 'GPL'],
      ['MTI', 'MIT'],
      ['Mozilla Public License', 'MPL'],
      ['WTH', 'WTF'],
      ['-License', '']
    ];

    var TRANSPOSED = 0;
    var CORRECT = 1;

    // Simple corrections to nearly valid identifiers.
    var transforms = [
      // e.g. 'mit'
      function(argument) {
        return argument.toUpperCase();
      },
      // e.g. 'MIT '
      function(argument) {
        return argument.trim();
      },
      // e.g. 'M.I.T.'
      function(argument) {
        return argument.replace(/\./g, '');
      },
      // e.g. 'Apache- 2.0'
      function(argument) {
        return argument.replace(/\s+/g, '');
      },
      // e.g. 'CC BY 4.0''
      function(argument) {
        return argument.replace(/\s+/g, '-');
      },
      // e.g. 'LGPLv2.1'
      function(argument) {
        return argument.replace('v', '-');
      },
      // e.g. 'Apache 2.0'
      function(argument) {
        return argument.replace(/,?\s*(\d)/, '-$1');
      },
      // e.g. 'GPL 2'
      function(argument) {
        return argument.replace(/,?\s*(\d)/, '-$1.0');
      },
      // e.g. 'Apache Version 2.0'
      function(argument) {
        return argument.replace(/,?\s*(V\.|v\.|V|v|Version|version)\s*(\d)/, '-$2');
      },
      // e.g. 'Apache Version 2'
      function(argument) {
        return argument.replace(/,?\s*(V\.|v\.|V|v|Version|version)\s*(\d)/, '-$2.0');
      },
      // e.g. 'ZLIB'
      function(argument) {
        return argument[0].toUpperCase() + argument.slice(1);
      },
      // e.g. 'MPL/2.0'
      function(argument) {
        return argument.replace('/', '-');
      },
      // e.g. 'Apache 2'
      function(argument) {
        return argument
          .replace(/\s*V\s*(\d)/, '-$1')
          .replace(/(\d)$/, '$1.0');
      },
      // e.g. 'GPL-2.0-'
      function(argument) {
        return argument.slice(0, argument.length - 1);
      },
      // e.g. 'GPL2'
      function(argument) {
        return argument.replace(/(\d)$/, '-$1.0');
      },
      // e.g. 'BSD 3'
      function(argument) {
        return argument.replace(/(-| )?(\d)$/, '-$2-Clause');
      },
      // e.g. 'BSD clause 3'
      function(argument) {
        return argument.replace(/(-| )clause(-| )(\d)/, '-$3-Clause');
      },
      // e.g. 'BY-NC-4.0'
      function(argument) {
        return 'CC-' + argument;
      },
      // e.g. 'BY-NC'
      function(argument) {
        return 'CC-' + argument + '-4.0';
      },
      // e.g. 'Attribution-NonCommercial'
      function(argument) {
        return argument
          .replace('Attribution', 'BY')
          .replace('NonCommercial', 'NC')
          .replace('NoDerivatives', 'ND')
          .replace(/ (\d)/, '-$1')
          .replace(/ ?International/, '');
      },
      // e.g. 'Attribution-NonCommercial'
      function(argument) {
        return 'CC-' +
          argument
          .replace('Attribution', 'BY')
          .replace('NonCommercial', 'NC')
          .replace('NoDerivatives', 'ND')
          .replace(/ (\d)/, '-$1')
          .replace(/ ?International/, '') +
          '-4.0';
      }
    ];

    // If all else fails, guess that strings containing certain substrings
    // meant to identify certain licenses.
    var lastResorts = [
      ['UNLI', 'Unlicense'],
      ['WTF', 'WTFPL'],
      ['2 CLAUSE', 'BSD-2-Clause'],
      ['2-CLAUSE', 'BSD-2-Clause'],
      ['3 CLAUSE', 'BSD-3-Clause'],
      ['3-CLAUSE', 'BSD-3-Clause'],
      ['AFFERO', 'AGPL-3.0'],
      ['AGPL', 'AGPL-3.0'],
      ['APACHE', 'Apache-2.0'],
      ['ARTISTIC', 'Artistic-2.0'],
      ['Affero', 'AGPL-3.0'],
      ['BEER', 'Beerware'],
      ['BOOST', 'BSL-1.0'],
      ['BSD', 'BSD-2-Clause'],
      ['ECLIPSE', 'EPL-1.0'],
      ['FUCK', 'WTFPL'],
      ['GNU', 'GPL-3.0'],
      ['LGPL', 'LGPL-3.0'],
      ['GPL', 'GPL-3.0'],
      ['MIT', 'MIT'],
      ['MPL', 'MPL-2.0'],
      ['X11', 'X11'],
      ['ZLIB', 'Zlib']
    ];

    var SUBSTRING = 0;
    var IDENTIFIER = 1;

    var validTransformation = function(identifier) {
      for (var i = 0; i < transforms.length; i++) {
        var transformed = transforms[i](identifier);
        if (transformed !== identifier && valid(transformed)) {
          return transformed;
        }
      }
      return null;
    };

    var validLastResort = function(identifier) {
      var upperCased = identifier.toUpperCase();
      for (var i = 0; i < lastResorts.length; i++) {
        var lastResort = lastResorts[i];
        if (upperCased.indexOf(lastResort[SUBSTRING]) > -1) {
          return lastResort[IDENTIFIER];
        }
      }
      return null;
    };

    var anyCorrection = function(identifier, check) {
      for (var i = 0; i < transpositions.length; i++) {
        var transposition = transpositions[i];
        var transposed = transposition[TRANSPOSED];
        if (identifier.indexOf(transposed) > -1) {
          var corrected = identifier.replace(
            transposed,
            transposition[CORRECT]
          );
          var checked = check(corrected);
          if (checked !== null) {
            return checked;
          }
        }
      }
      return null;
    };

    module.exports = function(identifier) {
      identifier = identifier.replace(/\+$/, '');
      if (valid(identifier)) {
        return identifier;
      }
      var transformed = validTransformation(identifier);
      if (transformed !== null) {
        return transformed;
      }
      transformed = anyCorrection(identifier, function(argument) {
        if (valid(argument)) {
          return argument;
        }
        return validTransformation(argument);
      });
      if (transformed !== null) {
        return transformed;
      }
      transformed = validLastResort(identifier);
      if (transformed !== null) {
        return transformed;
      }
      transformed = anyCorrection(identifier, validLastResort);
      if (transformed !== null) {
        return transformed;
      }
      return null;
    };

  provide("spdx-correct", module.exports);
}(global));

// pakmanager:spdx-expression-parse/parser.generated.js
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  /* parser generated by jison 0.4.15 */
    /*
      Returns a Parser object of the following structure:

      Parser: {
        yy: {}
      }

      Parser.prototype: {
        yy: {},
        trace: function(),
        symbols_: {associative list: name ==> number},
        terminals_: {associative list: number ==> name},
        productions_: [...],
        performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
        table: [...],
        defaultActions: {...},
        parseError: function(str, hash),
        parse: function(input),

        lexer: {
            EOF: 1,
            parseError: function(str, hash),
            setInput: function(input),
            input: function(),
            unput: function(str),
            more: function(),
            less: function(n),
            pastInput: function(),
            upcomingInput: function(),
            showPosition: function(),
            test_match: function(regex_match_array, rule_index),
            next: function(),
            lex: function(),
            begin: function(condition),
            popState: function(),
            _currentRules: function(),
            topState: function(),
            pushState: function(condition),

            options: {
                ranges: boolean           (optional: true ==> token location info will include a .range[] member)
                flex: boolean             (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
                backtrack_lexer: boolean  (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
            },

            performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
            rules: [...],
            conditions: {associative list: name ==> set},
        }
      }

      token location info (@$, _$, etc.): {
        first_line: n,
        last_line: n,
        first_column: n,
        last_column: n,
        range: [start_number, end_number]       (where the numbers are indexes into the input string, regular zero-based)
      }

      the parseError function receives a 'hash' object with these members for lexer and parser errors: {
        text:        (matched text)
        token:       (the produced terminal token, if any)
        line:        (yylineno)
      }
      while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
        loc:         (yylloc)
        expected:    (string describing the set of expected tokens)
        recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
      }
    */
    var spdxparse = (function(){
    var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,5],$V1=[1,6],$V2=[1,7],$V3=[1,4],$V4=[1,9],$V5=[1,10],$V6=[5,14,15,17],$V7=[5,12,14,15,17];
    var parser = {trace: function trace() { },
    yy: {},
    symbols_: {"error":2,"start":3,"expression":4,"EOS":5,"simpleExpression":6,"LICENSE":7,"PLUS":8,"LICENSEREF":9,"DOCUMENTREF":10,"COLON":11,"WITH":12,"EXCEPTION":13,"AND":14,"OR":15,"OPEN":16,"CLOSE":17,"$accept":0,"$end":1},
    terminals_: {2:"error",5:"EOS",7:"LICENSE",8:"PLUS",9:"LICENSEREF",10:"DOCUMENTREF",11:"COLON",12:"WITH",13:"EXCEPTION",14:"AND",15:"OR",16:"OPEN",17:"CLOSE"},
    productions_: [0,[3,2],[6,1],[6,2],[6,1],[6,3],[4,1],[4,3],[4,3],[4,3],[4,3]],
    performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
    /* this == yyval */

    var $0 = $$.length - 1;
    switch (yystate) {
    case 1:
    return this.$ = $$[$0-1];
    break;
    case 2: case 4: case 5:
    this.$ = { license: yytext };
    break;
    case 3:
    this.$ = { license: $$[$0-1], plus: true };
    break;
    case 6:
    this.$ = $$[$0];
    break;
    case 7:
    this.$ = { exception: $$[$0] };
    this.$.license = $$[$0-2].license;
    if ($$[$0-2].hasOwnProperty('plus')) {
      this.$.plus = $$[$0-2].plus;
    }
    break;
    case 8:
    this.$ = { conjunction: 'and', left: $$[$0-2], right: $$[$0] };
    break;
    case 9:
    this.$ = { conjunction: 'or', left: $$[$0-2], right: $$[$0] };
    break;
    case 10:
    this.$ = $$[$0-1]
    break;
    }
    },
    table: [{3:1,4:2,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{1:[3]},{5:[1,8],14:$V4,15:$V5},o($V6,[2,6],{12:[1,11]}),{4:12,6:3,7:$V0,9:$V1,10:$V2,16:$V3},o($V7,[2,2],{8:[1,13]}),o($V7,[2,4]),{11:[1,14]},{1:[2,1]},{4:15,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{4:16,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{13:[1,17]},{14:$V4,15:$V5,17:[1,18]},o($V7,[2,3]),{9:[1,19]},o($V6,[2,8]),o([5,15,17],[2,9],{14:$V4}),o($V6,[2,7]),o($V6,[2,10]),o($V7,[2,5])],
    defaultActions: {8:[2,1]},
    parseError: function parseError(str, hash) {
        if (hash.recoverable) {
            this.trace(str);
        } else {
            throw new Error(str);
        }
    },
    parse: function parse(input) {
        var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
        var args = lstack.slice.call(arguments, 1);
        var lexer = Object.create(this.lexer);
        var sharedState = { yy: {} };
        for (var k in this.yy) {
            if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
                sharedState.yy[k] = this.yy[k];
            }
        }
        lexer.setInput(input, sharedState.yy);
        sharedState.yy.lexer = lexer;
        sharedState.yy.parser = this;
        if (typeof lexer.yylloc == 'undefined') {
            lexer.yylloc = {};
        }
        var yyloc = lexer.yylloc;
        lstack.push(yyloc);
        var ranges = lexer.options && lexer.options.ranges;
        if (typeof sharedState.yy.parseError === 'function') {
            this.parseError = sharedState.yy.parseError;
        } else {
            this.parseError = Object.getPrototypeOf(this).parseError;
        }
        function popStack(n) {
            stack.length = stack.length - 2 * n;
            vstack.length = vstack.length - n;
            lstack.length = lstack.length - n;
        }
        _token_stack:
            function lex() {
                var token;
                token = lexer.lex() || EOF;
                if (typeof token !== 'number') {
                    token = self.symbols_[token] || token;
                }
                return token;
            }
        var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
        while (true) {
            state = stack[stack.length - 1];
            if (this.defaultActions[state]) {
                action = this.defaultActions[state];
            } else {
                if (symbol === null || typeof symbol == 'undefined') {
                    symbol = lex();
                }
                action = table[state] && table[state][symbol];
            }
                        if (typeof action === 'undefined' || !action.length || !action[0]) {
                    var errStr = '';
                    expected = [];
                    for (p in table[state]) {
                        if (this.terminals_[p] && p > TERROR) {
                            expected.push('\'' + this.terminals_[p] + '\'');
                        }
                    }
                    if (lexer.showPosition) {
                        errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
                    } else {
                        errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
                    }
                    this.parseError(errStr, {
                        text: lexer.match,
                        token: this.terminals_[symbol] || symbol,
                        line: lexer.yylineno,
                        loc: yyloc,
                        expected: expected
                    });
                }
            if (action[0] instanceof Array && action.length > 1) {
                throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
            }
            switch (action[0]) {
            case 1:
                stack.push(symbol);
                vstack.push(lexer.yytext);
                lstack.push(lexer.yylloc);
                stack.push(action[1]);
                symbol = null;
                if (!preErrorSymbol) {
                    yyleng = lexer.yyleng;
                    yytext = lexer.yytext;
                    yylineno = lexer.yylineno;
                    yyloc = lexer.yylloc;
                    if (recovering > 0) {
                        recovering--;
                    }
                } else {
                    symbol = preErrorSymbol;
                    preErrorSymbol = null;
                }
                break;
            case 2:
                len = this.productions_[action[1]][1];
                yyval.$ = vstack[vstack.length - len];
                yyval._$ = {
                    first_line: lstack[lstack.length - (len || 1)].first_line,
                    last_line: lstack[lstack.length - 1].last_line,
                    first_column: lstack[lstack.length - (len || 1)].first_column,
                    last_column: lstack[lstack.length - 1].last_column
                };
                if (ranges) {
                    yyval._$.range = [
                        lstack[lstack.length - (len || 1)].range[0],
                        lstack[lstack.length - 1].range[1]
                    ];
                }
                r = this.performAction.apply(yyval, [
                    yytext,
                    yyleng,
                    yylineno,
                    sharedState.yy,
                    action[1],
                    vstack,
                    lstack
                ].concat(args));
                if (typeof r !== 'undefined') {
                    return r;
                }
                if (len) {
                    stack = stack.slice(0, -1 * len * 2);
                    vstack = vstack.slice(0, -1 * len);
                    lstack = lstack.slice(0, -1 * len);
                }
                stack.push(this.productions_[action[1]][0]);
                vstack.push(yyval.$);
                lstack.push(yyval._$);
                newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
                stack.push(newState);
                break;
            case 3:
                return true;
            }
        }
        return true;
    }};
    /* generated by jison-lex 0.3.4 */
    var lexer = (function(){
    var lexer = ({

    EOF:1,

    parseError:function parseError(str, hash) {
            if (this.yy.parser) {
                this.yy.parser.parseError(str, hash);
            } else {
                throw new Error(str);
            }
        },

    // resets the lexer, sets new input
    setInput:function (input, yy) {
            this.yy = yy || this.yy || {};
            this._input = input;
            this._more = this._backtrack = this.done = false;
            this.yylineno = this.yyleng = 0;
            this.yytext = this.matched = this.match = '';
            this.conditionStack = ['INITIAL'];
            this.yylloc = {
                first_line: 1,
                first_column: 0,
                last_line: 1,
                last_column: 0
            };
            if (this.options.ranges) {
                this.yylloc.range = [0,0];
            }
            this.offset = 0;
            return this;
        },

    // consumes and returns one char from the input
    input:function () {
            var ch = this._input[0];
            this.yytext += ch;
            this.yyleng++;
            this.offset++;
            this.match += ch;
            this.matched += ch;
            var lines = ch.match(/(?:\r\n?|\n).*/g);
            if (lines) {
                this.yylineno++;
                this.yylloc.last_line++;
            } else {
                this.yylloc.last_column++;
            }
            if (this.options.ranges) {
                this.yylloc.range[1]++;
            }

            this._input = this._input.slice(1);
            return ch;
        },

    // unshifts one char (or a string) into the input
    unput:function (ch) {
            var len = ch.length;
            var lines = ch.split(/(?:\r\n?|\n)/g);

            this._input = ch + this._input;
            this.yytext = this.yytext.substr(0, this.yytext.length - len);
            //this.yyleng -= len;
            this.offset -= len;
            var oldLines = this.match.split(/(?:\r\n?|\n)/g);
            this.match = this.match.substr(0, this.match.length - 1);
            this.matched = this.matched.substr(0, this.matched.length - 1);

            if (lines.length - 1) {
                this.yylineno -= lines.length - 1;
            }
            var r = this.yylloc.range;

            this.yylloc = {
                first_line: this.yylloc.first_line,
                last_line: this.yylineno + 1,
                first_column: this.yylloc.first_column,
                last_column: lines ?
                    (lines.length === oldLines.length ? this.yylloc.first_column : 0)
                     + oldLines[oldLines.length - lines.length].length - lines[0].length :
                  this.yylloc.first_column - len
            };

            if (this.options.ranges) {
                this.yylloc.range = [r[0], r[0] + this.yyleng - len];
            }
            this.yyleng = this.yytext.length;
            return this;
        },

    // When called from action, caches matched text and appends it on next action
    more:function () {
            this._more = true;
            return this;
        },

    // When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
    reject:function () {
            if (this.options.backtrack_lexer) {
                this._backtrack = true;
            } else {
                return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
                    text: "",
                    token: null,
                    line: this.yylineno
                });

            }
            return this;
        },

    // retain first n characters of the match
    less:function (n) {
            this.unput(this.match.slice(n));
        },

    // displays already matched input, i.e. for error messages
    pastInput:function () {
            var past = this.matched.substr(0, this.matched.length - this.match.length);
            return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
        },

    // displays upcoming input, i.e. for error messages
    upcomingInput:function () {
            var next = this.match;
            if (next.length < 20) {
                next += this._input.substr(0, 20-next.length);
            }
            return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
        },

    // displays the character position where the lexing error occurred, i.e. for error messages
    showPosition:function () {
            var pre = this.pastInput();
            var c = new Array(pre.length + 1).join("-");
            return pre + this.upcomingInput() + "\n" + c + "^";
        },

    // test the lexed token: return FALSE when not a match, otherwise return token
    test_match:function (match, indexed_rule) {
            var token,
                lines,
                backup;

            if (this.options.backtrack_lexer) {
                // save context
                backup = {
                    yylineno: this.yylineno,
                    yylloc: {
                        first_line: this.yylloc.first_line,
                        last_line: this.last_line,
                        first_column: this.yylloc.first_column,
                        last_column: this.yylloc.last_column
                    },
                    yytext: this.yytext,
                    match: this.match,
                    matches: this.matches,
                    matched: this.matched,
                    yyleng: this.yyleng,
                    offset: this.offset,
                    _more: this._more,
                    _input: this._input,
                    yy: this.yy,
                    conditionStack: this.conditionStack.slice(0),
                    done: this.done
                };
                if (this.options.ranges) {
                    backup.yylloc.range = this.yylloc.range.slice(0);
                }
            }

            lines = match[0].match(/(?:\r\n?|\n).*/g);
            if (lines) {
                this.yylineno += lines.length;
            }
            this.yylloc = {
                first_line: this.yylloc.last_line,
                last_line: this.yylineno + 1,
                first_column: this.yylloc.last_column,
                last_column: lines ?
                             lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
                             this.yylloc.last_column + match[0].length
            };
            this.yytext += match[0];
            this.match += match[0];
            this.matches = match;
            this.yyleng = this.yytext.length;
            if (this.options.ranges) {
                this.yylloc.range = [this.offset, this.offset += this.yyleng];
            }
            this._more = false;
            this._backtrack = false;
            this._input = this._input.slice(match[0].length);
            this.matched += match[0];
            token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
            if (this.done && this._input) {
                this.done = false;
            }
            if (token) {
                return token;
            } else if (this._backtrack) {
                // recover context
                for (var k in backup) {
                    this[k] = backup[k];
                }
                return false; // rule action called reject() implying the next rule should be tested instead.
            }
            return false;
        },

    // return next match in input
    next:function () {
            if (this.done) {
                return this.EOF;
            }
            if (!this._input) {
                this.done = true;
            }

            var token,
                match,
                tempMatch,
                index;
            if (!this._more) {
                this.yytext = '';
                this.match = '';
            }
            var rules = this._currentRules();
            for (var i = 0; i < rules.length; i++) {
                tempMatch = this._input.match(this.rules[rules[i]]);
                if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
                    match = tempMatch;
                    index = i;
                    if (this.options.backtrack_lexer) {
                        token = this.test_match(tempMatch, rules[i]);
                        if (token !== false) {
                            return token;
                        } else if (this._backtrack) {
                            match = false;
                            continue; // rule action called reject() implying a rule MISmatch.
                        } else {
                            // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
                            return false;
                        }
                    } else if (!this.options.flex) {
                        break;
                    }
                }
            }
            if (match) {
                token = this.test_match(match, rules[index]);
                if (token !== false) {
                    return token;
                }
                // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
                return false;
            }
            if (this._input === "") {
                return this.EOF;
            } else {
                return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
                    text: "",
                    token: null,
                    line: this.yylineno
                });
            }
        },

    // return next match that has a token
    lex:function lex() {
            var r = this.next();
            if (r) {
                return r;
            } else {
                return this.lex();
            }
        },

    // activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
    begin:function begin(condition) {
            this.conditionStack.push(condition);
        },

    // pop the previously active lexer condition state off the condition stack
    popState:function popState() {
            var n = this.conditionStack.length - 1;
            if (n > 0) {
                return this.conditionStack.pop();
            } else {
                return this.conditionStack[0];
            }
        },

    // produce the lexer rule set which is active for the currently active lexer condition state
    _currentRules:function _currentRules() {
            if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
                return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
            } else {
                return this.conditions["INITIAL"].rules;
            }
        },

    // return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
    topState:function topState(n) {
            n = this.conditionStack.length - 1 - Math.abs(n || 0);
            if (n >= 0) {
                return this.conditionStack[n];
            } else {
                return "INITIAL";
            }
        },

    // alias for begin(condition)
    pushState:function pushState(condition) {
            this.begin(condition);
        },

    // return the number of states currently on the stack
    stateStackSize:function stateStackSize() {
            return this.conditionStack.length;
        },
    options: {},
    performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
    var YYSTATE=YY_START;
    switch($avoiding_name_collisions) {
    case 0:return 5;
    break;
    case 1:/* skip whitespace */
    break;
    case 2:return 8;
    break;
    case 3:return 16;
    break;
    case 4:return 17;
    break;
    case 5:return 11;
    break;
    case 6:return 10;
    break;
    case 7:return 9;
    break;
    case 8:return 14;
    break;
    case 9:return 15;
    break;
    case 10:return 12;
    break;
    case 11:return 7
    break;
    case 12:return 7
    break;
    case 13:return 7
    break;
    case 14:return 7
    break;
    case 15:return 7
    break;
    case 16:return 7
    break;
    case 17:return 7
    break;
    case 18:return 7
    break;
    case 19:return 7
    break;
    case 20:return 7
    break;
    case 21:return 7
    break;
    case 22:return 7
    break;
    case 23:return 7
    break;
    case 24:return 7
    break;
    case 25:return 7
    break;
    case 26:return 7
    break;
    case 27:return 7
    break;
    case 28:return 7
    break;
    case 29:return 7
    break;
    case 30:return 7
    break;
    case 31:return 7
    break;
    case 32:return 7
    break;
    case 33:return 7
    break;
    case 34:return 7
    break;
    case 35:return 7
    break;
    case 36:return 7
    break;
    case 37:return 7
    break;
    case 38:return 7
    break;
    case 39:return 7
    break;
    case 40:return 7
    break;
    case 41:return 7
    break;
    case 42:return 7
    break;
    case 43:return 7
    break;
    case 44:return 7
    break;
    case 45:return 7
    break;
    case 46:return 7
    break;
    case 47:return 7
    break;
    case 48:return 7
    break;
    case 49:return 7
    break;
    case 50:return 7
    break;
    case 51:return 7
    break;
    case 52:return 7
    break;
    case 53:return 7
    break;
    case 54:return 7
    break;
    case 55:return 7
    break;
    case 56:return 7
    break;
    case 57:return 7
    break;
    case 58:return 7
    break;
    case 59:return 7
    break;
    case 60:return 7
    break;
    case 61:return 7
    break;
    case 62:return 7
    break;
    case 63:return 7
    break;
    case 64:return 7
    break;
    case 65:return 7
    break;
    case 66:return 7
    break;
    case 67:return 7
    break;
    case 68:return 7
    break;
    case 69:return 7
    break;
    case 70:return 7
    break;
    case 71:return 7
    break;
    case 72:return 7
    break;
    case 73:return 7
    break;
    case 74:return 7
    break;
    case 75:return 7
    break;
    case 76:return 7
    break;
    case 77:return 7
    break;
    case 78:return 7
    break;
    case 79:return 7
    break;
    case 80:return 7
    break;
    case 81:return 7
    break;
    case 82:return 7
    break;
    case 83:return 7
    break;
    case 84:return 7
    break;
    case 85:return 7
    break;
    case 86:return 7
    break;
    case 87:return 7
    break;
    case 88:return 7
    break;
    case 89:return 7
    break;
    case 90:return 7
    break;
    case 91:return 7
    break;
    case 92:return 7
    break;
    case 93:return 7
    break;
    case 94:return 7
    break;
    case 95:return 7
    break;
    case 96:return 7
    break;
    case 97:return 7
    break;
    case 98:return 7
    break;
    case 99:return 7
    break;
    case 100:return 7
    break;
    case 101:return 7
    break;
    case 102:return 7
    break;
    case 103:return 7
    break;
    case 104:return 7
    break;
    case 105:return 7
    break;
    case 106:return 7
    break;
    case 107:return 7
    break;
    case 108:return 7
    break;
    case 109:return 7
    break;
    case 110:return 7
    break;
    case 111:return 7
    break;
    case 112:return 7
    break;
    case 113:return 7
    break;
    case 114:return 7
    break;
    case 115:return 7
    break;
    case 116:return 7
    break;
    case 117:return 7
    break;
    case 118:return 7
    break;
    case 119:return 7
    break;
    case 120:return 7
    break;
    case 121:return 7
    break;
    case 122:return 7
    break;
    case 123:return 7
    break;
    case 124:return 7
    break;
    case 125:return 7
    break;
    case 126:return 7
    break;
    case 127:return 7
    break;
    case 128:return 7
    break;
    case 129:return 7
    break;
    case 130:return 7
    break;
    case 131:return 7
    break;
    case 132:return 7
    break;
    case 133:return 7
    break;
    case 134:return 7
    break;
    case 135:return 7
    break;
    case 136:return 7
    break;
    case 137:return 7
    break;
    case 138:return 7
    break;
    case 139:return 7
    break;
    case 140:return 7
    break;
    case 141:return 7
    break;
    case 142:return 7
    break;
    case 143:return 7
    break;
    case 144:return 7
    break;
    case 145:return 7
    break;
    case 146:return 7
    break;
    case 147:return 7
    break;
    case 148:return 7
    break;
    case 149:return 7
    break;
    case 150:return 7
    break;
    case 151:return 7
    break;
    case 152:return 7
    break;
    case 153:return 7
    break;
    case 154:return 7
    break;
    case 155:return 7
    break;
    case 156:return 7
    break;
    case 157:return 7
    break;
    case 158:return 7
    break;
    case 159:return 7
    break;
    case 160:return 7
    break;
    case 161:return 7
    break;
    case 162:return 7
    break;
    case 163:return 7
    break;
    case 164:return 7
    break;
    case 165:return 7
    break;
    case 166:return 7
    break;
    case 167:return 7
    break;
    case 168:return 7
    break;
    case 169:return 7
    break;
    case 170:return 7
    break;
    case 171:return 7
    break;
    case 172:return 7
    break;
    case 173:return 7
    break;
    case 174:return 7
    break;
    case 175:return 7
    break;
    case 176:return 7
    break;
    case 177:return 7
    break;
    case 178:return 7
    break;
    case 179:return 7
    break;
    case 180:return 7
    break;
    case 181:return 7
    break;
    case 182:return 7
    break;
    case 183:return 7
    break;
    case 184:return 7
    break;
    case 185:return 7
    break;
    case 186:return 7
    break;
    case 187:return 7
    break;
    case 188:return 7
    break;
    case 189:return 7
    break;
    case 190:return 7
    break;
    case 191:return 7
    break;
    case 192:return 7
    break;
    case 193:return 7
    break;
    case 194:return 7
    break;
    case 195:return 7
    break;
    case 196:return 7
    break;
    case 197:return 7
    break;
    case 198:return 7
    break;
    case 199:return 7
    break;
    case 200:return 7
    break;
    case 201:return 7
    break;
    case 202:return 7
    break;
    case 203:return 7
    break;
    case 204:return 7
    break;
    case 205:return 7
    break;
    case 206:return 7
    break;
    case 207:return 7
    break;
    case 208:return 7
    break;
    case 209:return 7
    break;
    case 210:return 7
    break;
    case 211:return 7
    break;
    case 212:return 7
    break;
    case 213:return 7
    break;
    case 214:return 7
    break;
    case 215:return 7
    break;
    case 216:return 7
    break;
    case 217:return 7
    break;
    case 218:return 7
    break;
    case 219:return 7
    break;
    case 220:return 7
    break;
    case 221:return 7
    break;
    case 222:return 7
    break;
    case 223:return 7
    break;
    case 224:return 7
    break;
    case 225:return 7
    break;
    case 226:return 7
    break;
    case 227:return 7
    break;
    case 228:return 7
    break;
    case 229:return 7
    break;
    case 230:return 7
    break;
    case 231:return 7
    break;
    case 232:return 7
    break;
    case 233:return 7
    break;
    case 234:return 7
    break;
    case 235:return 7
    break;
    case 236:return 7
    break;
    case 237:return 7
    break;
    case 238:return 7
    break;
    case 239:return 7
    break;
    case 240:return 7
    break;
    case 241:return 7
    break;
    case 242:return 7
    break;
    case 243:return 7
    break;
    case 244:return 7
    break;
    case 245:return 7
    break;
    case 246:return 7
    break;
    case 247:return 7
    break;
    case 248:return 7
    break;
    case 249:return 7
    break;
    case 250:return 7
    break;
    case 251:return 7
    break;
    case 252:return 7
    break;
    case 253:return 7
    break;
    case 254:return 7
    break;
    case 255:return 7
    break;
    case 256:return 7
    break;
    case 257:return 7
    break;
    case 258:return 7
    break;
    case 259:return 7
    break;
    case 260:return 7
    break;
    case 261:return 7
    break;
    case 262:return 7
    break;
    case 263:return 7
    break;
    case 264:return 7
    break;
    case 265:return 7
    break;
    case 266:return 7
    break;
    case 267:return 7
    break;
    case 268:return 7
    break;
    case 269:return 7
    break;
    case 270:return 7
    break;
    case 271:return 7
    break;
    case 272:return 7
    break;
    case 273:return 7
    break;
    case 274:return 7
    break;
    case 275:return 7
    break;
    case 276:return 7
    break;
    case 277:return 7
    break;
    case 278:return 7
    break;
    case 279:return 7
    break;
    case 280:return 7
    break;
    case 281:return 7
    break;
    case 282:return 7
    break;
    case 283:return 7
    break;
    case 284:return 7
    break;
    case 285:return 7
    break;
    case 286:return 7
    break;
    case 287:return 7
    break;
    case 288:return 7
    break;
    case 289:return 7
    break;
    case 290:return 7
    break;
    case 291:return 7
    break;
    case 292:return 7
    break;
    case 293:return 7
    break;
    case 294:return 7
    break;
    case 295:return 7
    break;
    case 296:return 7
    break;
    case 297:return 7
    break;
    case 298:return 7
    break;
    case 299:return 7
    break;
    case 300:return 7
    break;
    case 301:return 7
    break;
    case 302:return 7
    break;
    case 303:return 7
    break;
    case 304:return 7
    break;
    case 305:return 7
    break;
    case 306:return 7
    break;
    case 307:return 7
    break;
    case 308:return 7
    break;
    case 309:return 7
    break;
    case 310:return 7
    break;
    case 311:return 7
    break;
    case 312:return 13
    break;
    case 313:return 13
    break;
    case 314:return 13
    break;
    case 315:return 13
    break;
    case 316:return 13
    break;
    case 317:return 13
    break;
    case 318:return 13
    break;
    case 319:return 13
    break;
    case 320:return 13
    break;
    case 321:return 13
    break;
    case 322:return 13
    break;
    case 323:return 13
    break;
    case 324:return 13
    break;
    case 325:return 13
    break;
    case 326:return 13
    break;
    case 327:return 13
    break;
    case 328:return 13
    break;
    case 329:return 13
    break;
    case 330:return 13
    break;
    case 331:return 13
    break;
    case 332:return 13
    break;
    case 333:return 13
    break;
    }
    },
    rules: [/^(?:$)/,/^(?:\s+)/,/^(?:\+)/,/^(?:\()/,/^(?:\))/,/^(?::)/,/^(?:DocumentRef-([0-9A-Za-z-+.]+))/,/^(?:LicenseRef-([0-9A-Za-z-+.]+))/,/^(?:AND)/,/^(?:OR)/,/^(?:WITH)/,/^(?:Glide)/,/^(?:Abstyles)/,/^(?:AFL-1.1)/,/^(?:AFL-1.2)/,/^(?:AFL-2.0)/,/^(?:AFL-2.1)/,/^(?:AFL-3.0)/,/^(?:AMPAS)/,/^(?:APL-1.0)/,/^(?:Adobe-Glyph)/,/^(?:APAFML)/,/^(?:Adobe-2006)/,/^(?:AGPL-1.0)/,/^(?:Afmparse)/,/^(?:Aladdin)/,/^(?:ADSL)/,/^(?:AMDPLPA)/,/^(?:ANTLR-PD)/,/^(?:Apache-1.0)/,/^(?:Apache-1.1)/,/^(?:Apache-2.0)/,/^(?:AML)/,/^(?:APSL-1.0)/,/^(?:APSL-1.1)/,/^(?:APSL-1.2)/,/^(?:APSL-2.0)/,/^(?:Artistic-1.0)/,/^(?:Artistic-1.0-Perl)/,/^(?:Artistic-1.0-cl8)/,/^(?:Artistic-2.0)/,/^(?:AAL)/,/^(?:Bahyph)/,/^(?:Barr)/,/^(?:Beerware)/,/^(?:BitTorrent-1.0)/,/^(?:BitTorrent-1.1)/,/^(?:BSL-1.0)/,/^(?:Borceux)/,/^(?:BSD-2-Clause)/,/^(?:BSD-2-Clause-FreeBSD)/,/^(?:BSD-2-Clause-NetBSD)/,/^(?:BSD-3-Clause)/,/^(?:BSD-3-Clause-Clear)/,/^(?:BSD-4-Clause)/,/^(?:BSD-Protection)/,/^(?:BSD-3-Clause-Attribution)/,/^(?:BSD-4-Clause-UC)/,/^(?:bzip2-1.0.5)/,/^(?:bzip2-1.0.6)/,/^(?:Caldera)/,/^(?:CECILL-1.0)/,/^(?:CECILL-1.1)/,/^(?:CECILL-2.0)/,/^(?:CECILL-B)/,/^(?:CECILL-C)/,/^(?:ClArtistic)/,/^(?:MIT-CMU)/,/^(?:CNRI-Jython)/,/^(?:CNRI-Python)/,/^(?:CNRI-Python-GPL-Compatible)/,/^(?:CPOL-1.02)/,/^(?:CDDL-1.0)/,/^(?:CDDL-1.1)/,/^(?:CPAL-1.0)/,/^(?:CPL-1.0)/,/^(?:CATOSL-1.1)/,/^(?:Condor-1.1)/,/^(?:CC-BY-1.0)/,/^(?:CC-BY-2.0)/,/^(?:CC-BY-2.5)/,/^(?:CC-BY-3.0)/,/^(?:CC-BY-4.0)/,/^(?:CC-BY-ND-1.0)/,/^(?:CC-BY-ND-2.0)/,/^(?:CC-BY-ND-2.5)/,/^(?:CC-BY-ND-3.0)/,/^(?:CC-BY-ND-4.0)/,/^(?:CC-BY-NC-1.0)/,/^(?:CC-BY-NC-2.0)/,/^(?:CC-BY-NC-2.5)/,/^(?:CC-BY-NC-3.0)/,/^(?:CC-BY-NC-4.0)/,/^(?:CC-BY-NC-ND-1.0)/,/^(?:CC-BY-NC-ND-2.0)/,/^(?:CC-BY-NC-ND-2.5)/,/^(?:CC-BY-NC-ND-3.0)/,/^(?:CC-BY-NC-ND-4.0)/,/^(?:CC-BY-NC-SA-1.0)/,/^(?:CC-BY-NC-SA-2.0)/,/^(?:CC-BY-NC-SA-2.5)/,/^(?:CC-BY-NC-SA-3.0)/,/^(?:CC-BY-NC-SA-4.0)/,/^(?:CC-BY-SA-1.0)/,/^(?:CC-BY-SA-2.0)/,/^(?:CC-BY-SA-2.5)/,/^(?:CC-BY-SA-3.0)/,/^(?:CC-BY-SA-4.0)/,/^(?:CC0-1.0)/,/^(?:Crossword)/,/^(?:CUA-OPL-1.0)/,/^(?:Cube)/,/^(?:D-FSL-1.0)/,/^(?:diffmark)/,/^(?:WTFPL)/,/^(?:DOC)/,/^(?:Dotseqn)/,/^(?:DSDP)/,/^(?:dvipdfm)/,/^(?:EPL-1.0)/,/^(?:ECL-1.0)/,/^(?:ECL-2.0)/,/^(?:eGenix)/,/^(?:EFL-1.0)/,/^(?:EFL-2.0)/,/^(?:MIT-advertising)/,/^(?:MIT-enna)/,/^(?:Entessa)/,/^(?:ErlPL-1.1)/,/^(?:EUDatagrid)/,/^(?:EUPL-1.0)/,/^(?:EUPL-1.1)/,/^(?:Eurosym)/,/^(?:Fair)/,/^(?:MIT-feh)/,/^(?:Frameworx-1.0)/,/^(?:FreeImage)/,/^(?:FTL)/,/^(?:FSFUL)/,/^(?:FSFULLR)/,/^(?:Giftware)/,/^(?:GL2PS)/,/^(?:Glulxe)/,/^(?:AGPL-3.0)/,/^(?:GFDL-1.1)/,/^(?:GFDL-1.2)/,/^(?:GFDL-1.3)/,/^(?:GPL-1.0)/,/^(?:GPL-2.0)/,/^(?:GPL-3.0)/,/^(?:LGPL-2.1)/,/^(?:LGPL-3.0)/,/^(?:LGPL-2.0)/,/^(?:gnuplot)/,/^(?:gSOAP-1.3b)/,/^(?:HaskellReport)/,/^(?:HPND)/,/^(?:IBM-pibs)/,/^(?:IPL-1.0)/,/^(?:ICU)/,/^(?:ImageMagick)/,/^(?:iMatix)/,/^(?:Imlib2)/,/^(?:IJG)/,/^(?:Intel-ACPI)/,/^(?:Intel)/,/^(?:IPA)/,/^(?:ISC)/,/^(?:JasPer-2.0)/,/^(?:JSON)/,/^(?:LPPL-1.3a)/,/^(?:LPPL-1.0)/,/^(?:LPPL-1.1)/,/^(?:LPPL-1.2)/,/^(?:LPPL-1.3c)/,/^(?:Latex2e)/,/^(?:BSD-3-Clause-LBNL)/,/^(?:Leptonica)/,/^(?:LGPLLR)/,/^(?:Libpng)/,/^(?:libtiff)/,/^(?:LPL-1.02)/,/^(?:LPL-1.0)/,/^(?:MakeIndex)/,/^(?:MTLL)/,/^(?:MS-PL)/,/^(?:MS-RL)/,/^(?:MirOS)/,/^(?:MITNFA)/,/^(?:MIT)/,/^(?:Motosoto)/,/^(?:MPL-1.0)/,/^(?:MPL-1.1)/,/^(?:MPL-2.0)/,/^(?:MPL-2.0-no-copyleft-exception)/,/^(?:mpich2)/,/^(?:Multics)/,/^(?:Mup)/,/^(?:NASA-1.3)/,/^(?:Naumen)/,/^(?:NBPL-1.0)/,/^(?:NetCDF)/,/^(?:NGPL)/,/^(?:NOSL)/,/^(?:NPL-1.0)/,/^(?:NPL-1.1)/,/^(?:Newsletr)/,/^(?:NLPL)/,/^(?:Nokia)/,/^(?:NPOSL-3.0)/,/^(?:Noweb)/,/^(?:NRL)/,/^(?:NTP)/,/^(?:Nunit)/,/^(?:OCLC-2.0)/,/^(?:ODbL-1.0)/,/^(?:PDDL-1.0)/,/^(?:OGTSL)/,/^(?:OLDAP-2.2.2)/,/^(?:OLDAP-1.1)/,/^(?:OLDAP-1.2)/,/^(?:OLDAP-1.3)/,/^(?:OLDAP-1.4)/,/^(?:OLDAP-2.0)/,/^(?:OLDAP-2.0.1)/,/^(?:OLDAP-2.1)/,/^(?:OLDAP-2.2)/,/^(?:OLDAP-2.2.1)/,/^(?:OLDAP-2.3)/,/^(?:OLDAP-2.4)/,/^(?:OLDAP-2.5)/,/^(?:OLDAP-2.6)/,/^(?:OLDAP-2.7)/,/^(?:OLDAP-2.8)/,/^(?:OML)/,/^(?:OPL-1.0)/,/^(?:OSL-1.0)/,/^(?:OSL-1.1)/,/^(?:OSL-2.0)/,/^(?:OSL-2.1)/,/^(?:OSL-3.0)/,/^(?:OpenSSL)/,/^(?:PHP-3.0)/,/^(?:PHP-3.01)/,/^(?:Plexus)/,/^(?:PostgreSQL)/,/^(?:psfrag)/,/^(?:psutils)/,/^(?:Python-2.0)/,/^(?:QPL-1.0)/,/^(?:Qhull)/,/^(?:Rdisc)/,/^(?:RPSL-1.0)/,/^(?:RPL-1.1)/,/^(?:RPL-1.5)/,/^(?:RHeCos-1.1)/,/^(?:RSCPL)/,/^(?:RSA-MD)/,/^(?:Ruby)/,/^(?:SAX-PD)/,/^(?:Saxpath)/,/^(?:SCEA)/,/^(?:SWL)/,/^(?:SGI-B-1.0)/,/^(?:SGI-B-1.1)/,/^(?:SGI-B-2.0)/,/^(?:OFL-1.0)/,/^(?:OFL-1.1)/,/^(?:SimPL-2.0)/,/^(?:Sleepycat)/,/^(?:SNIA)/,/^(?:Spencer-86)/,/^(?:Spencer-94)/,/^(?:Spencer-99)/,/^(?:SMLNJ)/,/^(?:SugarCRM-1.1.3)/,/^(?:SISSL)/,/^(?:SISSL-1.2)/,/^(?:SPL-1.0)/,/^(?:Watcom-1.0)/,/^(?:TCL)/,/^(?:Unlicense)/,/^(?:TMate)/,/^(?:TORQUE-1.1)/,/^(?:TOSL)/,/^(?:Unicode-TOU)/,/^(?:UPL-1.0)/,/^(?:NCSA)/,/^(?:Vim)/,/^(?:VOSTROM)/,/^(?:VSL-1.0)/,/^(?:W3C-19980720)/,/^(?:W3C)/,/^(?:Wsuipa)/,/^(?:Xnet)/,/^(?:X11)/,/^(?:Xerox)/,/^(?:XFree86-1.1)/,/^(?:xinetd)/,/^(?:xpp)/,/^(?:XSkat)/,/^(?:YPL-1.0)/,/^(?:YPL-1.1)/,/^(?:Zed)/,/^(?:Zend-2.0)/,/^(?:Zimbra-1.3)/,/^(?:Zimbra-1.4)/,/^(?:Zlib)/,/^(?:zlib-acknowledgement)/,/^(?:ZPL-1.1)/,/^(?:ZPL-2.0)/,/^(?:ZPL-2.1)/,/^(?:389-exception)/,/^(?:Autoconf-exception-2.0 )/,/^(?:Autoconf-exception-3.0 )/,/^(?:Bison-exception-2.2)/,/^(?:CLISP-exception-2.0)/,/^(?:Classpath-exception-2.0)/,/^(?:FLTK-exception )/,/^(?:FLTK-exception-2.0 )/,/^(?:Font-exception-2.0 )/,/^(?:GCC-exception-2.0)/,/^(?:GCC-exception-3.1)/,/^(?:LZMA-exception )/,/^(?:Libtool-exception)/,/^(?:Nokia-Qt-exception-1.1 )/,/^(?:Qwt-exception-1.0)/,/^(?:WxWindows-exception-3.1)/,/^(?:eCos-exception-2.0 )/,/^(?:freertos-exception-2.0 )/,/^(?:gnu-javamail-exception )/,/^(?:i2p-gpl-java-exception )/,/^(?:mif-exception)/,/^(?:u-boot-exception-2.0 )/],
    conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333],"inclusive":true}}
    });
    return lexer;
    })();
    parser.lexer = lexer;
    function Parser () {
      this.yy = {};
    }
    Parser.prototype = parser;parser.Parser = Parser;
    return new Parser;
    })();

    if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
    exports.parser = spdxparse;
    exports.Parser = spdxparse.Parser;
    exports.parse = function () { return spdxparse.parse.apply(spdxparse, arguments); };
    exports.main = function commonjsMain(args) {
        if (!args[1]) {
            console.log('Usage: '+args[0]+' FILE');
            process.exit(1);
        }
        var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
        return exports.parser.parse(source);
    };
    if (typeof module !== 'undefined' && require.main === module) {
      exports.main(process.argv.slice(1));
    }
    }

  provide("spdx-expression-parse/parser.generated.js", module.exports);
}(global));

// pakmanager:spdx-expression-parse
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  var parser =  require('spdx-expression-parse/parser.generated.js').parser

    module.exports = function(argument) {
      return parser.parse(argument) }

  provide("spdx-expression-parse", module.exports);
}(global));

// pakmanager:number-is-nan
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    module.exports = Number.isNaN || function (x) {
    	return x !== x;
    };

  provide("number-is-nan", module.exports);
}(global));

// pakmanager:path-exists
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    var fs = require('fs');
    var Promise = require('pinkie-promise');

    module.exports = function (fp) {
    	var fn = typeof fs.access === 'function' ? fs.access : fs.stat;

    	return new Promise(function (resolve) {
    		fn(fp, function (err) {
    			resolve(!err);
    		});
    	});
    };

    module.exports.sync = function (fp) {
    	var fn = typeof fs.accessSync === 'function' ? fs.accessSync : fs.statSync;

    	try {
    		fn(fp);
    		return true;
    	} catch (err) {
    		return false;
    	}
    };

  provide("path-exists", module.exports);
}(global));

// pakmanager:load-json-file
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    var path = require('path');
    var fs = require('graceful-fs');
    var stripBom = require('strip-bom');
    var parseJson = require('parse-json');
    var Promise = require('pinkie-promise');
    var pify = require('pify');

    function parse(x, fp) {
    	return parseJson(stripBom(x), path.relative(process.cwd(), fp));
    }

    module.exports = function (fp) {
    	return pify(fs.readFile, Promise)(fp, 'utf8').then(function (data) {
    		return parse(data, fp);
    	});
    };

    module.exports.sync = function (fp) {
    	return parse(fs.readFileSync(fp, 'utf8'), fp);
    };

  provide("load-json-file", module.exports);
}(global));

// pakmanager:normalize-package-data/lib/extract_description
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  module.exports = extractDescription

    // Extracts description from contents of a readme file in markdown format
    function extractDescription (d) {
      if (!d) return;
      if (d === "ERROR: No README data found!") return;
      // the first block of text before the first heading
      // that isn't the first line heading
      d = d.trim().split('\n')
      for (var s = 0; d[s] && d[s].trim().match(/^(#|$)/); s ++);
      var l = d.length
      for (var e = s + 1; e < l && d[e].trim(); e ++);
      return d.slice(s, e).join(' ').trim()
    }

  provide("normalize-package-data/lib/extract_description", module.exports);
}(global));

// pakmanager:normalize-package-data/lib/fixer
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  var semver = require("semver")
    var validateLicense = require('validate-npm-package-license');
    var hostedGitInfo = require("hosted-git-info")
    var isBuiltinModule = require("is-builtin-module")
    var depTypes = ["dependencies","devDependencies","optionalDependencies"]
    var extractDescription =  require('normalize-package-data/lib/extract_description')
    var url = require("url")
    var typos = require("./typos")

    var fixer = module.exports = {
      // default warning function
      warn: function() {},

      fixRepositoryField: function(data) {
        if (data.repositories) {
          this.warn("repositories");
          data.repository = data.repositories[0]
        }
        if (!data.repository) return this.warn("missingRepository")
        if (typeof data.repository === "string") {
          data.repository = {
            type: "git",
            url: data.repository
          }
        }
        var r = data.repository.url || ""
        if (r) {
          var hosted = hostedGitInfo.fromUrl(r)
          if (hosted) {
            r = data.repository.url
              = hosted.getDefaultRepresentation() == "shortcut" ? hosted.https() : hosted.toString()
          }
        }

        if (r.match(/github.com\/[^\/]+\/[^\/]+\.git\.git$/)) {
          this.warn("brokenGitUrl", r)
        }
      }

    , fixTypos: function(data) {
        Object.keys(typos.topLevel).forEach(function (d) {
          if (data.hasOwnProperty(d)) {
            this.warn("typo", d, typos.topLevel[d])
          }
        }, this)
      }

    , fixScriptsField: function(data) {
        if (!data.scripts) return
        if (typeof data.scripts !== "object") {
          this.warn("nonObjectScripts")
          delete data.scripts
          return
        }
        Object.keys(data.scripts).forEach(function (k) {
          if (typeof data.scripts[k] !== "string") {
            this.warn("nonStringScript")
            delete data.scripts[k]
          } else if (typos.script[k] && !data.scripts[typos.script[k]]) {
            this.warn("typo", k, typos.script[k], "scripts")
          }
        }, this)
      }

    , fixFilesField: function(data) {
        var files = data.files
        if (files && !Array.isArray(files)) {
          this.warn("nonArrayFiles")
          delete data.files
        } else if (data.files) {
          data.files = data.files.filter(function(file) {
            if (!file || typeof file !== "string") {
              this.warn("invalidFilename", file)
              return false
            } else {
              return true
            }
          }, this)
        }
      }

    , fixBinField: function(data) {
        if (!data.bin) return;
        if (typeof data.bin === "string") {
          var b = {}
          b[data.name] = data.bin
          data.bin = b
        }
      }

    , fixManField: function(data) {
        if (!data.man) return;
        if (typeof data.man === "string") {
          data.man = [ data.man ]
        }
      }
    , fixBundleDependenciesField: function(data) {
        var bdd = "bundledDependencies"
        var bd = "bundleDependencies"
        if (data[bdd] && !data[bd]) {
          data[bd] = data[bdd]
          delete data[bdd]
        }
        if (data[bd] && !Array.isArray(data[bd])) {
          this.warn("nonArrayBundleDependencies")
          delete data[bd]
        } else if (data[bd]) {
          data[bd] = data[bd].filter(function(bd) {
            if (!bd || typeof bd !== 'string') {
              this.warn("nonStringBundleDependency", bd)
              return false
            } else {
              if (!data.dependencies) {
                data.dependencies = {}
              }
              if (!data.dependencies.hasOwnProperty(bd)) {
                this.warn("nonDependencyBundleDependency", bd)
                data.dependencies[bd] = "*"
              }
              return true
            }
          }, this)
        }
      }

    , fixDependencies: function(data, strict) {
        var loose = !strict
        objectifyDeps(data, this.warn)
        addOptionalDepsToDeps(data, this.warn)
        this.fixBundleDependenciesField(data)

        ;['dependencies','devDependencies'].forEach(function(deps) {
          if (!(deps in data)) return
          if (!data[deps] || typeof data[deps] !== "object") {
            this.warn("nonObjectDependencies", deps)
            delete data[deps]
            return
          }
          Object.keys(data[deps]).forEach(function (d) {
            var r = data[deps][d]
            if (typeof r !== 'string') {
              this.warn("nonStringDependency", d, JSON.stringify(r))
              delete data[deps][d]
            }
            var hosted = hostedGitInfo.fromUrl(data[deps][d])
            if (hosted) data[deps][d] = hosted.toString()
          }, this)
        }, this)
      }

    , fixModulesField: function (data) {
        if (data.modules) {
          this.warn("deprecatedModules")
          delete data.modules
        }
      }

    , fixKeywordsField: function (data) {
        if (typeof data.keywords === "string") {
          data.keywords = data.keywords.split(/,\s+/)
        }
        if (data.keywords && !Array.isArray(data.keywords)) {
          delete data.keywords
          this.warn("nonArrayKeywords")
        } else if (data.keywords) {
          data.keywords = data.keywords.filter(function(kw) {
            if (typeof kw !== "string" || !kw) {
              this.warn("nonStringKeyword");
              return false
            } else {
              return true
            }
          }, this)
        }
      }

    , fixVersionField: function(data, strict) {
        // allow "loose" semver 1.0 versions in non-strict mode
        // enforce strict semver 2.0 compliance in strict mode
        var loose = !strict
        if (!data.version) {
          data.version = ""
          return true
        }
        if (!semver.valid(data.version, loose)) {
          throw new Error('Invalid version: "'+ data.version + '"')
        }
        data.version = semver.clean(data.version, loose)
        return true
      }

    , fixPeople: function(data) {
        modifyPeople(data, unParsePerson)
        modifyPeople(data, parsePerson)
      }

    , fixNameField: function(data, options) {
        if (typeof options === "boolean") options = {strict: options}
        else if (typeof options === "undefined") options = {}
        var strict = options.strict
        if (!data.name && !strict) {
          data.name = ""
          return
        }
        if (typeof data.name !== "string") {
          throw new Error("name field must be a string.")
        }
        if (!strict)
          data.name = data.name.trim()
        ensureValidName(data.name, strict, options.allowLegacyCase)
        if (isBuiltinModule(data.name))
          this.warn("conflictingName", data.name)
      }

    , fixDescriptionField: function (data) {
        if (data.description && typeof data.description !== 'string') {
          this.warn("nonStringDescription")
          delete data.description
        }
        if (data.readme && !data.description)
          data.description = extractDescription(data.readme)
          if(data.description === undefined) delete data.description;
        if (!data.description) this.warn("missingDescription")
      }

    , fixReadmeField: function (data) {
        if (!data.readme) {
          this.warn("missingReadme")
          data.readme = "ERROR: No README data found!"
        }
      }

    , fixBugsField: function(data) {
        if (!data.bugs && data.repository && data.repository.url) {
          var hosted = hostedGitInfo.fromUrl(data.repository.url)
          if(hosted && hosted.bugs()) {
            data.bugs = {url: hosted.bugs()}
          }
        }
        else if(data.bugs) {
          var emailRe = /^.+@.*\..+$/
          if(typeof data.bugs == "string") {
            if(emailRe.test(data.bugs))
              data.bugs = {email:data.bugs}
            else if(url.parse(data.bugs).protocol)
              data.bugs = {url: data.bugs}
            else
              this.warn("nonEmailUrlBugsString")
          }
          else {
            bugsTypos(data.bugs, this.warn)
            var oldBugs = data.bugs
            data.bugs = {}
            if(oldBugs.url) {
              if(typeof(oldBugs.url) == "string" && url.parse(oldBugs.url).protocol)
                data.bugs.url = oldBugs.url
              else
                this.warn("nonUrlBugsUrlField")
            }
            if(oldBugs.email) {
              if(typeof(oldBugs.email) == "string" && emailRe.test(oldBugs.email))
                data.bugs.email = oldBugs.email
              else
                this.warn("nonEmailBugsEmailField")
            }
          }
          if(!data.bugs.email && !data.bugs.url) {
            delete data.bugs
            this.warn("emptyNormalizedBugs")
          }
        }
      }

    , fixHomepageField: function(data) {
        if (!data.homepage && data.repository && data.repository.url) {
          var hosted = hostedGitInfo.fromUrl(data.repository.url)
          if (hosted && hosted.docs()) data.homepage = hosted.docs()
        }
        if (!data.homepage) return

        if(typeof data.homepage !== "string") {
          this.warn("nonUrlHomepage")
          return delete data.homepage
        }
        if(!url.parse(data.homepage).protocol) {
          this.warn("missingProtocolHomepage")
          data.homepage = "http://" + data.homepage
        }
      }

    , fixLicenseField: function(data) {
        if (!data.license) {
          return this.warn("missingLicense")
        } else{
          if (
            typeof(data.license) !== 'string' ||
            data.license.length < 1
          ) {
            this.warn("invalidLicense")
          } else {
            if (!validateLicense(data.license).validForNewPackages)
              this.warn("invalidLicense")
          }
        }
      }
    }

    function isValidScopedPackageName(spec) {
      if (spec.charAt(0) !== '@') return false

      var rest = spec.slice(1).split('/')
      if (rest.length !== 2) return false

      return rest[0] && rest[1] &&
        rest[0] === encodeURIComponent(rest[0]) &&
        rest[1] === encodeURIComponent(rest[1])
    }

    function isCorrectlyEncodedName(spec) {
      return !spec.match(/[\/@\s\+%:]/) &&
        spec === encodeURIComponent(spec)
    }

    function ensureValidName (name, strict, allowLegacyCase) {
      if (name.charAt(0) === "." ||
          !(isValidScopedPackageName(name) || isCorrectlyEncodedName(name)) ||
          (strict && (!allowLegacyCase) && name !== name.toLowerCase()) ||
          name.toLowerCase() === "node_modules" ||
          name.toLowerCase() === "favicon.ico") {
            throw new Error("Invalid name: " + JSON.stringify(name))
      }
    }

    function modifyPeople (data, fn) {
      if (data.author) data.author = fn(data.author)
      ;["maintainers", "contributors"].forEach(function (set) {
        if (!Array.isArray(data[set])) return;
        data[set] = data[set].map(fn)
      })
      return data
    }

    function unParsePerson (person) {
      if (typeof person === "string") return person
      var name = person.name || ""
      var u = person.url || person.web
      var url = u ? (" ("+u+")") : ""
      var e = person.email || person.mail
      var email = e ? (" <"+e+">") : ""
      return name+email+url
    }

    function parsePerson (person) {
      if (typeof person !== "string") return person
      var name = person.match(/^([^\(<]+)/)
      var url = person.match(/\(([^\)]+)\)/)
      var email = person.match(/<([^>]+)>/)
      var obj = {}
      if (name && name[0].trim()) obj.name = name[0].trim()
      if (email) obj.email = email[1];
      if (url) obj.url = url[1];
      return obj
    }

    function addOptionalDepsToDeps (data, warn) {
      var o = data.optionalDependencies
      if (!o) return;
      var d = data.dependencies || {}
      Object.keys(o).forEach(function (k) {
        d[k] = o[k]
      })
      data.dependencies = d
    }

    function depObjectify (deps, type, warn) {
      if (!deps) return {}
      if (typeof deps === "string") {
        deps = deps.trim().split(/[\n\r\s\t ,]+/)
      }
      if (!Array.isArray(deps)) return deps
      warn("deprecatedArrayDependencies", type)
      var o = {}
      deps.filter(function (d) {
        return typeof d === "string"
      }).forEach(function(d) {
        d = d.trim().split(/(:?[@\s><=])/)
        var dn = d.shift()
        var dv = d.join("")
        dv = dv.trim()
        dv = dv.replace(/^@/, "")
        o[dn] = dv
      })
      return o
    }

    function objectifyDeps (data, warn) {
      depTypes.forEach(function (type) {
        if (!data[type]) return;
        data[type] = depObjectify(data[type], type, warn)
      })
    }

    function bugsTypos(bugs, warn) {
      if (!bugs) return
      Object.keys(bugs).forEach(function (k) {
        if (typos.bugs[k]) {
          warn("typo", k, typos.bugs[k], "bugs")
          bugs[typos.bugs[k]] = bugs[k]
          delete bugs[k]
        }
      })
    }

  provide("normalize-package-data/lib/fixer", module.exports);
}(global));

// pakmanager:normalize-package-data/lib/make_warning
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  var util = require("util")
    var messages = require("./warning_messages.json")

    module.exports = function() {
      var args = Array.prototype.slice.call(arguments, 0)
      var warningName = args.shift()
      if (warningName == "typo") {
        return makeTypoWarning.apply(null,args)
      }
      else {
        var msgTemplate = messages[warningName] ? messages[warningName] : warningName + ": '%s'"
        args.unshift(msgTemplate)
        return util.format.apply(null, args)
      }
    }

    function makeTypoWarning (providedName, probableName, field) {
      if (field) {
        providedName = field + "['" + providedName + "']"
        probableName = field + "['" + probableName + "']"
      }
      return util.format(messages.typo, providedName, probableName)
    }
  provide("normalize-package-data/lib/make_warning", module.exports);
}(global));

// pakmanager:normalize-package-data
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  module.exports = normalize

    var fixer =  require('normalize-package-data/lib/fixer')
    normalize.fixer = fixer

    var makeWarning =  require('normalize-package-data/lib/make_warning')

    var fieldsToFix = ['name','version','description','repository','modules','scripts'
                      ,'files','bin','man','bugs','keywords','readme','homepage','license']
    var otherThingsToFix = ['dependencies','people', 'typos']

    var thingsToFix = fieldsToFix.map(function(fieldName) {
      return ucFirst(fieldName) + "Field"
    })
    // two ways to do this in CoffeeScript on only one line, sub-70 chars:
    // thingsToFix = fieldsToFix.map (name) -> ucFirst(name) + "Field"
    // thingsToFix = (ucFirst(name) + "Field" for name in fieldsToFix)
    thingsToFix = thingsToFix.concat(otherThingsToFix)

    function normalize (data, warn, strict) {
      if(warn === true) warn = null, strict = true
      if(!strict) strict = false
      if(!warn || data.private) warn = function(msg) { /* noop */ }

      if (data.scripts &&
          data.scripts.install === "node-gyp rebuild" &&
          !data.scripts.preinstall) {
        data.gypfile = true
      }
      fixer.warn = function() { warn(makeWarning.apply(null, arguments)) }
      thingsToFix.forEach(function(thingName) {
        fixer["fix" + ucFirst(thingName)](data, strict)
      })
      data._id = data.name + "@" + data.version
    }

    function ucFirst (string) {
      return string.charAt(0).toUpperCase() + string.slice(1);
    }

  provide("normalize-package-data", module.exports);
}(global));

// pakmanager:path-type
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    var fs = require('graceful-fs');
    var Promise = require('pinkie-promise');
    var pify = require('pify');

    function type(fn, fn2, fp) {
    	if (typeof fp !== 'string') {
    		return Promise.reject(new TypeError('Expected a string'));
    	}

    	return pify(fs[fn], Promise)(fp).then(function (stats) {
    		return stats[fn2]();
    	});
    }

    function typeSync(fn, fn2, fp) {
    	if (typeof fp !== 'string') {
    		throw new TypeError('Expected a string');
    	}

    	return fs[fn](fp)[fn2]();
    }

    exports.file = type.bind(null, 'stat', 'isFile');
    exports.dir = type.bind(null, 'stat', 'isDirectory');
    exports.symlink = type.bind(null, 'lstat', 'isSymbolicLink');
    exports.fileSync = typeSync.bind(null, 'statSync', 'isFile');
    exports.dirSync = typeSync.bind(null, 'statSync', 'isDirectory');
    exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink');

  provide("path-type", module.exports);
}(global));

// pakmanager:repeating
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    var isFinite = require('is-finite');

    module.exports = function (str, n) {
    	if (typeof str !== 'string') {
    		throw new TypeError('Expected `input` to be a string');
    	}

    	if (n < 0 || !isFinite(n)) {
    		throw new TypeError('Expected `count` to be a positive finite number');
    	}

    	var ret = '';

    	do {
    		if (n & 1) {
    			ret += str;
    		}

    		str += str;
    	} while ((n >>= 1));

    	return ret;
    };

  provide("repeating", module.exports);
}(global));

// pakmanager:get-stdin
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    var stdin = process.stdin;

    module.exports = function () {
    	var ret = '';

    	return new Promise(function (resolve) {
    		if (stdin.isTTY) {
    			resolve(ret);
    			return;
    		}

    		stdin.setEncoding('utf8');

    		stdin.on('readable', function () {
    			var chunk;

    			while ((chunk = stdin.read())) {
    				ret += chunk;
    			}
    		});

    		stdin.on('end', function () {
    			resolve(ret);
    		});
    	});
    };

    module.exports.buffer = function () {
    	var ret = [];
    	var len = 0;

    	return new Promise(function (resolve) {
    		if (stdin.isTTY) {
    			resolve(new Buffer(''));
    			return;
    		}

    		stdin.on('readable', function () {
    			var chunk;

    			while ((chunk = stdin.read())) {
    				ret.push(chunk);
    				len += chunk.length;
    			}
    		});

    		stdin.on('end', function () {
    			resolve(Buffer.concat(ret, len));
    		});
    	});
    };

  provide("get-stdin", module.exports);
}(global));

// pakmanager:wrappy
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  // Returns a wrapper function that returns a wrapped callback
    // The wrapper function should do some stuff, and return a
    // presumably different callback function.
    // This makes sure that own properties are retained, so that
    // decorations and such are not lost along the way.
    module.exports = wrappy
    function wrappy (fn, cb) {
      if (fn && cb) return wrappy(fn)(cb)

      if (typeof fn !== 'function')
        throw new TypeError('need wrapper function')

      Object.keys(fn).forEach(function (k) {
        wrapper[k] = fn[k]
      })

      return wrapper

      function wrapper() {
        var args = new Array(arguments.length)
        for (var i = 0; i < args.length; i++) {
          args[i] = arguments[i]
        }
        var ret = fn.apply(this, args)
        var cb = args[args.length-1]
        if (typeof ret === 'function' && ret !== cb) {
          Object.keys(cb).forEach(function (k) {
            ret[k] = cb[k]
          })
        }
        return ret
      }
    }

  provide("wrappy", module.exports);
}(global));

// pakmanager:balanced-match
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  module.exports = balanced;
    function balanced(a, b, str) {
      var bal = 0;
      var m = {};
      var ended = false;

      for (var i = 0; i < str.length; i++) {
        if (a == str.substr(i, a.length)) {
          if (!('start' in m)) m.start = i;
          bal++;
        }
        else if (b == str.substr(i, b.length) && 'start' in m) {
          ended = true;
          bal--;
          if (!bal) {
            m.end = i;
            m.pre = str.substr(0, m.start);
            m.body = (m.end - m.start > 1)
              ? str.substring(m.start + a.length, m.end)
              : '';
            m.post = str.slice(m.end + b.length);
            return m;
          }
        }
      }

      // if we opened more than we closed, find the one we closed
      if (bal && ended) {
        var start = m.start + a.length;
        m = balanced(a, b, str.substr(start));
        if (m) {
          m.start += start;
          m.end += start;
          m.pre = str.slice(0, start) + m.pre;
        }
        return m;
      }
    }

  provide("balanced-match", module.exports);
}(global));

// pakmanager:concat-map
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  module.exports = function (xs, fn) {
        var res = [];
        for (var i = 0; i < xs.length; i++) {
            var x = fn(xs[i], i);
            if (isArray(x)) res.push.apply(res, x);
            else res.push(x);
        }
        return res;
    };

    var isArray = Array.isArray || function (xs) {
        return Object.prototype.toString.call(xs) === '[object Array]';
    };

  provide("concat-map", module.exports);
}(global));

// pakmanager:esprima-fb
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  /*
      Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
      Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
      Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
      Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
      Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
      Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
      Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
      Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
      Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>

      Redistribution and use in source and binary forms, with or without
      modification, are permitted provided that the following conditions are met:

        * Redistributions of source code must retain the above copyright
          notice, this list of conditions and the following disclaimer.
        * Redistributions in binary form must reproduce the above copyright
          notice, this list of conditions and the following disclaimer in the
          documentation and/or other materials provided with the distribution.

      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
      DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
      (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
      ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */

    (function (root, factory) {
        'use strict';

        // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
        // Rhino, and plain browser loading.

        /* istanbul ignore next */
        if (typeof define === 'function' && define.amd) {
            define(['exports'], factory);
        } else if (typeof exports !== 'undefined') {
            factory(exports);
        } else {
            factory((root.esprima = {}));
        }
    }(this, function (exports) {
        'use strict';

        var Token,
            TokenName,
            FnExprTokens,
            Syntax,
            PropertyKind,
            Messages,
            Regex,
            SyntaxTreeDelegate,
            XHTMLEntities,
            ClassPropertyType,
            source,
            strict,
            index,
            lineNumber,
            lineStart,
            length,
            delegate,
            lookahead,
            state,
            extra;

        Token = {
            BooleanLiteral: 1,
            EOF: 2,
            Identifier: 3,
            Keyword: 4,
            NullLiteral: 5,
            NumericLiteral: 6,
            Punctuator: 7,
            StringLiteral: 8,
            RegularExpression: 9,
            Template: 10,
            JSXIdentifier: 11,
            JSXText: 12
        };

        TokenName = {};
        TokenName[Token.BooleanLiteral] = 'Boolean';
        TokenName[Token.EOF] = '<end>';
        TokenName[Token.Identifier] = 'Identifier';
        TokenName[Token.Keyword] = 'Keyword';
        TokenName[Token.NullLiteral] = 'Null';
        TokenName[Token.NumericLiteral] = 'Numeric';
        TokenName[Token.Punctuator] = 'Punctuator';
        TokenName[Token.StringLiteral] = 'String';
        TokenName[Token.JSXIdentifier] = 'JSXIdentifier';
        TokenName[Token.JSXText] = 'JSXText';
        TokenName[Token.RegularExpression] = 'RegularExpression';
        TokenName[Token.Template] = 'Template';

        // A function following one of those tokens is an expression.
        FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
                        'return', 'case', 'delete', 'throw', 'void',
                        // assignment operators
                        '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=',
                        '&=', '|=', '^=', ',',
                        // binary/unary operators
                        '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&',
                        '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=',
                        '<=', '<', '>', '!=', '!=='];

        Syntax = {
            AnyTypeAnnotation: 'AnyTypeAnnotation',
            ArrayExpression: 'ArrayExpression',
            ArrayPattern: 'ArrayPattern',
            ArrayTypeAnnotation: 'ArrayTypeAnnotation',
            ArrowFunctionExpression: 'ArrowFunctionExpression',
            AssignmentExpression: 'AssignmentExpression',
            BinaryExpression: 'BinaryExpression',
            BlockStatement: 'BlockStatement',
            BooleanTypeAnnotation: 'BooleanTypeAnnotation',
            BreakStatement: 'BreakStatement',
            CallExpression: 'CallExpression',
            CatchClause: 'CatchClause',
            ClassBody: 'ClassBody',
            ClassDeclaration: 'ClassDeclaration',
            ClassExpression: 'ClassExpression',
            ClassImplements: 'ClassImplements',
            ClassProperty: 'ClassProperty',
            ComprehensionBlock: 'ComprehensionBlock',
            ComprehensionExpression: 'ComprehensionExpression',
            ConditionalExpression: 'ConditionalExpression',
            ContinueStatement: 'ContinueStatement',
            DebuggerStatement: 'DebuggerStatement',
            DeclareClass: 'DeclareClass',
            DeclareFunction: 'DeclareFunction',
            DeclareModule: 'DeclareModule',
            DeclareVariable: 'DeclareVariable',
            DoWhileStatement: 'DoWhileStatement',
            EmptyStatement: 'EmptyStatement',
            ExportDeclaration: 'ExportDeclaration',
            ExportBatchSpecifier: 'ExportBatchSpecifier',
            ExportSpecifier: 'ExportSpecifier',
            ExpressionStatement: 'ExpressionStatement',
            ForInStatement: 'ForInStatement',
            ForOfStatement: 'ForOfStatement',
            ForStatement: 'ForStatement',
            FunctionDeclaration: 'FunctionDeclaration',
            FunctionExpression: 'FunctionExpression',
            FunctionTypeAnnotation: 'FunctionTypeAnnotation',
            FunctionTypeParam: 'FunctionTypeParam',
            GenericTypeAnnotation: 'GenericTypeAnnotation',
            Identifier: 'Identifier',
            IfStatement: 'IfStatement',
            ImportDeclaration: 'ImportDeclaration',
            ImportDefaultSpecifier: 'ImportDefaultSpecifier',
            ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
            ImportSpecifier: 'ImportSpecifier',
            InterfaceDeclaration: 'InterfaceDeclaration',
            InterfaceExtends: 'InterfaceExtends',
            IntersectionTypeAnnotation: 'IntersectionTypeAnnotation',
            LabeledStatement: 'LabeledStatement',
            Literal: 'Literal',
            LogicalExpression: 'LogicalExpression',
            MemberExpression: 'MemberExpression',
            MethodDefinition: 'MethodDefinition',
            NewExpression: 'NewExpression',
            NullableTypeAnnotation: 'NullableTypeAnnotation',
            NumberTypeAnnotation: 'NumberTypeAnnotation',
            ObjectExpression: 'ObjectExpression',
            ObjectPattern: 'ObjectPattern',
            ObjectTypeAnnotation: 'ObjectTypeAnnotation',
            ObjectTypeCallProperty: 'ObjectTypeCallProperty',
            ObjectTypeIndexer: 'ObjectTypeIndexer',
            ObjectTypeProperty: 'ObjectTypeProperty',
            Program: 'Program',
            Property: 'Property',
            QualifiedTypeIdentifier: 'QualifiedTypeIdentifier',
            ReturnStatement: 'ReturnStatement',
            SequenceExpression: 'SequenceExpression',
            SpreadElement: 'SpreadElement',
            SpreadProperty: 'SpreadProperty',
            StringLiteralTypeAnnotation: 'StringLiteralTypeAnnotation',
            StringTypeAnnotation: 'StringTypeAnnotation',
            SwitchCase: 'SwitchCase',
            SwitchStatement: 'SwitchStatement',
            TaggedTemplateExpression: 'TaggedTemplateExpression',
            TemplateElement: 'TemplateElement',
            TemplateLiteral: 'TemplateLiteral',
            ThisExpression: 'ThisExpression',
            ThrowStatement: 'ThrowStatement',
            TupleTypeAnnotation: 'TupleTypeAnnotation',
            TryStatement: 'TryStatement',
            TypeAlias: 'TypeAlias',
            TypeAnnotation: 'TypeAnnotation',
            TypeCastExpression: 'TypeCastExpression',
            TypeofTypeAnnotation: 'TypeofTypeAnnotation',
            TypeParameterDeclaration: 'TypeParameterDeclaration',
            TypeParameterInstantiation: 'TypeParameterInstantiation',
            UnaryExpression: 'UnaryExpression',
            UnionTypeAnnotation: 'UnionTypeAnnotation',
            UpdateExpression: 'UpdateExpression',
            VariableDeclaration: 'VariableDeclaration',
            VariableDeclarator: 'VariableDeclarator',
            VoidTypeAnnotation: 'VoidTypeAnnotation',
            WhileStatement: 'WhileStatement',
            WithStatement: 'WithStatement',
            JSXIdentifier: 'JSXIdentifier',
            JSXNamespacedName: 'JSXNamespacedName',
            JSXMemberExpression: 'JSXMemberExpression',
            JSXEmptyExpression: 'JSXEmptyExpression',
            JSXExpressionContainer: 'JSXExpressionContainer',
            JSXElement: 'JSXElement',
            JSXClosingElement: 'JSXClosingElement',
            JSXOpeningElement: 'JSXOpeningElement',
            JSXAttribute: 'JSXAttribute',
            JSXSpreadAttribute: 'JSXSpreadAttribute',
            JSXText: 'JSXText',
            YieldExpression: 'YieldExpression',
            AwaitExpression: 'AwaitExpression'
        };

        PropertyKind = {
            Data: 1,
            Get: 2,
            Set: 4
        };

        ClassPropertyType = {
            'static': 'static',
            prototype: 'prototype'
        };

        // Error messages should be identical to V8.
        Messages = {
            UnexpectedToken: 'Unexpected token %0',
            UnexpectedNumber: 'Unexpected number',
            UnexpectedString: 'Unexpected string',
            UnexpectedIdentifier: 'Unexpected identifier',
            UnexpectedReserved: 'Unexpected reserved word',
            UnexpectedTemplate: 'Unexpected quasi %0',
            UnexpectedEOS: 'Unexpected end of input',
            NewlineAfterThrow: 'Illegal newline after throw',
            InvalidRegExp: 'Invalid regular expression',
            UnterminatedRegExp: 'Invalid regular expression: missing /',
            InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
            InvalidLHSInFormalsList: 'Invalid left-hand side in formals list',
            InvalidLHSInForIn: 'Invalid left-hand side in for-in',
            MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
            NoCatchOrFinally: 'Missing catch or finally after try',
            UnknownLabel: 'Undefined label \'%0\'',
            Redeclaration: '%0 \'%1\' has already been declared',
            IllegalContinue: 'Illegal continue statement',
            IllegalBreak: 'Illegal break statement',
            IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition',
            IllegalClassConstructorProperty: 'Illegal constructor property in class definition',
            IllegalReturn: 'Illegal return statement',
            IllegalSpread: 'Illegal spread element',
            StrictModeWith: 'Strict mode code may not include a with statement',
            StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
            StrictVarName: 'Variable name may not be eval or arguments in strict mode',
            StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
            StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
            ParameterAfterRestParameter: 'Rest parameter must be final parameter of an argument list',
            DefaultRestParameter: 'Rest parameter can not have a default value',
            ElementAfterSpreadElement: 'Spread must be the final element of an element list',
            PropertyAfterSpreadProperty: 'A rest property must be the final property of an object literal',
            ObjectPatternAsRestParameter: 'Invalid rest parameter',
            ObjectPatternAsSpread: 'Invalid spread argument',
            StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
            StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
            StrictDelete: 'Delete of an unqualified identifier in strict mode.',
            StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
            AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
            AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
            StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
            StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
            StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
            StrictReservedWord: 'Use of future reserved word in strict mode',
            MissingFromClause: 'Missing from clause',
            NoAsAfterImportNamespace: 'Missing as after import *',
            InvalidModuleSpecifier: 'Invalid module specifier',
            IllegalImportDeclaration: 'Illegal import declaration',
            IllegalExportDeclaration: 'Illegal export declaration',
            NoUninitializedConst: 'Const must be initialized',
            ComprehensionRequiresBlock: 'Comprehension must have at least one block',
            ComprehensionError: 'Comprehension Error',
            EachNotAllowed: 'Each is not supported',
            InvalidJSXAttributeValue: 'JSX value should be either an expression or a quoted JSX text',
            ExpectedJSXClosingTag: 'Expected corresponding JSX closing tag for %0',
            AdjacentJSXElements: 'Adjacent JSX elements must be wrapped in an enclosing tag',
            ConfusedAboutFunctionType: 'Unexpected token =>. It looks like ' +
                'you are trying to write a function type, but you ended up ' +
                'writing a grouped type followed by an =>, which is a syntax ' +
                'error. Remember, function type parameters are named so function ' +
                'types look like (name1: type1, name2: type2) => returnType. You ' +
                'probably wrote (type1) => returnType'
        };

        // See also tools/generate-unicode-regex.py.
        Regex = {
            NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'),
            NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'),
            LeadingZeros: new RegExp('^0+(?!$)')
        };

        // Ensure the condition is true, otherwise throw an error.
        // This is only to have a better contract semantic, i.e. another safety net
        // to catch a logic error. The condition shall be fulfilled in normal case.
        // Do NOT use this to enforce a certain condition on any user input.

        function assert(condition, message) {
            /* istanbul ignore if */
            if (!condition) {
                throw new Error('ASSERT: ' + message);
            }
        }

        function StringMap() {
            this.$data = {};
        }

        StringMap.prototype.get = function (key) {
            key = '$' + key;
            return this.$data[key];
        };

        StringMap.prototype.set = function (key, value) {
            key = '$' + key;
            this.$data[key] = value;
            return this;
        };

        StringMap.prototype.has = function (key) {
            key = '$' + key;
            return Object.prototype.hasOwnProperty.call(this.$data, key);
        };

        StringMap.prototype.delete = function (key) {
            key = '$' + key;
            return delete this.$data[key];
        };

        function isDecimalDigit(ch) {
            return (ch >= 48 && ch <= 57);   // 0..9
        }

        function isHexDigit(ch) {
            return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
        }

        function isOctalDigit(ch) {
            return '01234567'.indexOf(ch) >= 0;
        }

        // 7.2 White Space

        function isWhiteSpace(ch) {
            return (ch === 32) ||  // space
                (ch === 9) ||      // tab
                (ch === 0xB) ||
                (ch === 0xC) ||
                (ch === 0xA0) ||
                (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0);
        }

        // 7.3 Line Terminators

        function isLineTerminator(ch) {
            return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029);
        }

        // 7.6 Identifier Names and Identifiers

        function isIdentifierStart(ch) {
            return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)
                (ch >= 65 && ch <= 90) ||         // A..Z
                (ch >= 97 && ch <= 122) ||        // a..z
                (ch === 92) ||                    // \ (backslash)
                ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch)));
        }

        function isIdentifierPart(ch) {
            return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)
                (ch >= 65 && ch <= 90) ||         // A..Z
                (ch >= 97 && ch <= 122) ||        // a..z
                (ch >= 48 && ch <= 57) ||         // 0..9
                (ch === 92) ||                    // \ (backslash)
                ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch)));
        }

        // 7.6.1.2 Future Reserved Words

        function isFutureReservedWord(id) {
            switch (id) {
            case 'class':
            case 'enum':
            case 'export':
            case 'extends':
            case 'import':
            case 'super':
                return true;
            default:
                return false;
            }
        }

        function isStrictModeReservedWord(id) {
            switch (id) {
            case 'implements':
            case 'interface':
            case 'package':
            case 'private':
            case 'protected':
            case 'public':
            case 'static':
            case 'yield':
            case 'let':
                return true;
            default:
                return false;
            }
        }

        function isRestrictedWord(id) {
            return id === 'eval' || id === 'arguments';
        }

        // 7.6.1.1 Keywords

        function isKeyword(id) {
            if (strict && isStrictModeReservedWord(id)) {
                return true;
            }

            // 'const' is specialized as Keyword in V8.
            // 'yield' is only treated as a keyword in strict mode.
            // 'let' is for compatiblity with SpiderMonkey and ES.next.
            // Some others are from future reserved words.

            switch (id.length) {
            case 2:
                return (id === 'if') || (id === 'in') || (id === 'do');
            case 3:
                return (id === 'var') || (id === 'for') || (id === 'new') ||
                    (id === 'try') || (id === 'let');
            case 4:
                return (id === 'this') || (id === 'else') || (id === 'case') ||
                    (id === 'void') || (id === 'with') || (id === 'enum');
            case 5:
                return (id === 'while') || (id === 'break') || (id === 'catch') ||
                    (id === 'throw') || (id === 'const') ||
                    (id === 'class') || (id === 'super');
            case 6:
                return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
                    (id === 'switch') || (id === 'export') || (id === 'import');
            case 7:
                return (id === 'default') || (id === 'finally') || (id === 'extends');
            case 8:
                return (id === 'function') || (id === 'continue') || (id === 'debugger');
            case 10:
                return (id === 'instanceof');
            default:
                return false;
            }
        }

        // 7.4 Comments

        function addComment(type, value, start, end, loc) {
            var comment;
            assert(typeof start === 'number', 'Comment must have valid position');

            // Because the way the actual token is scanned, often the comments
            // (if any) are skipped twice during the lexical analysis.
            // Thus, we need to skip adding a comment if the comment array already
            // handled it.
            if (state.lastCommentStart >= start) {
                return;
            }
            state.lastCommentStart = start;

            comment = {
                type: type,
                value: value
            };
            if (extra.range) {
                comment.range = [start, end];
            }
            if (extra.loc) {
                comment.loc = loc;
            }
            extra.comments.push(comment);
            if (extra.attachComment) {
                extra.leadingComments.push(comment);
                extra.trailingComments.push(comment);
            }
        }

        function skipSingleLineComment() {
            var start, loc, ch, comment;

            start = index - 2;
            loc = {
                start: {
                    line: lineNumber,
                    column: index - lineStart - 2
                }
            };

            while (index < length) {
                ch = source.charCodeAt(index);
                ++index;
                if (isLineTerminator(ch)) {
                    if (extra.comments) {
                        comment = source.slice(start + 2, index - 1);
                        loc.end = {
                            line: lineNumber,
                            column: index - lineStart - 1
                        };
                        addComment('Line', comment, start, index - 1, loc);
                    }
                    if (ch === 13 && source.charCodeAt(index) === 10) {
                        ++index;
                    }
                    ++lineNumber;
                    lineStart = index;
                    return;
                }
            }

            if (extra.comments) {
                comment = source.slice(start + 2, index);
                loc.end = {
                    line: lineNumber,
                    column: index - lineStart
                };
                addComment('Line', comment, start, index, loc);
            }
        }

        function skipMultiLineComment() {
            var start, loc, ch, comment;

            if (extra.comments) {
                start = index - 2;
                loc = {
                    start: {
                        line: lineNumber,
                        column: index - lineStart - 2
                    }
                };
            }

            while (index < length) {
                ch = source.charCodeAt(index);
                if (isLineTerminator(ch)) {
                    if (ch === 13 && source.charCodeAt(index + 1) === 10) {
                        ++index;
                    }
                    ++lineNumber;
                    ++index;
                    lineStart = index;
                    if (index >= length) {
                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
                    }
                } else if (ch === 42) {
                    // Block comment ends with '*/' (char #42, char #47).
                    if (source.charCodeAt(index + 1) === 47) {
                        ++index;
                        ++index;
                        if (extra.comments) {
                            comment = source.slice(start + 2, index - 2);
                            loc.end = {
                                line: lineNumber,
                                column: index - lineStart
                            };
                            addComment('Block', comment, start, index, loc);
                        }
                        return;
                    }
                    ++index;
                } else {
                    ++index;
                }
            }

            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
        }

        function skipComment() {
            var ch;

            while (index < length) {
                ch = source.charCodeAt(index);

                if (isWhiteSpace(ch)) {
                    ++index;
                } else if (isLineTerminator(ch)) {
                    ++index;
                    if (ch === 13 && source.charCodeAt(index) === 10) {
                        ++index;
                    }
                    ++lineNumber;
                    lineStart = index;
                } else if (ch === 47) { // 47 is '/'
                    ch = source.charCodeAt(index + 1);
                    if (ch === 47) {
                        ++index;
                        ++index;
                        skipSingleLineComment();
                    } else if (ch === 42) {  // 42 is '*'
                        ++index;
                        ++index;
                        skipMultiLineComment();
                    } else {
                        break;
                    }
                } else {
                    break;
                }
            }
        }

        function scanHexEscape(prefix) {
            var i, len, ch, code = 0;

            len = (prefix === 'u') ? 4 : 2;
            for (i = 0; i < len; ++i) {
                if (index < length && isHexDigit(source[index])) {
                    ch = source[index++];
                    code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
                } else {
                    return '';
                }
            }
            return String.fromCharCode(code);
        }

        function scanUnicodeCodePointEscape() {
            var ch, code, cu1, cu2;

            ch = source[index];
            code = 0;

            // At least, one hex digit is required.
            if (ch === '}') {
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            while (index < length) {
                ch = source[index++];
                if (!isHexDigit(ch)) {
                    break;
                }
                code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
            }

            if (code > 0x10FFFF || ch !== '}') {
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            // UTF-16 Encoding
            if (code <= 0xFFFF) {
                return String.fromCharCode(code);
            }
            cu1 = ((code - 0x10000) >> 10) + 0xD800;
            cu2 = ((code - 0x10000) & 1023) + 0xDC00;
            return String.fromCharCode(cu1, cu2);
        }

        function getEscapedIdentifier() {
            var ch, id;

            ch = source.charCodeAt(index++);
            id = String.fromCharCode(ch);

            // '\u' (char #92, char #117) denotes an escaped character.
            if (ch === 92) {
                if (source.charCodeAt(index) !== 117) {
                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
                }
                ++index;
                ch = scanHexEscape('u');
                if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) {
                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
                }
                id = ch;
            }

            while (index < length) {
                ch = source.charCodeAt(index);
                if (!isIdentifierPart(ch)) {
                    break;
                }
                ++index;
                id += String.fromCharCode(ch);

                // '\u' (char #92, char #117) denotes an escaped character.
                if (ch === 92) {
                    id = id.substr(0, id.length - 1);
                    if (source.charCodeAt(index) !== 117) {
                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
                    }
                    ++index;
                    ch = scanHexEscape('u');
                    if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) {
                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
                    }
                    id += ch;
                }
            }

            return id;
        }

        function getIdentifier() {
            var start, ch;

            start = index++;
            while (index < length) {
                ch = source.charCodeAt(index);
                if (ch === 92) {
                    // Blackslash (char #92) marks Unicode escape sequence.
                    index = start;
                    return getEscapedIdentifier();
                }
                if (isIdentifierPart(ch)) {
                    ++index;
                } else {
                    break;
                }
            }

            return source.slice(start, index);
        }

        function scanIdentifier() {
            var start, id, type;

            start = index;

            // Backslash (char #92) starts an escaped character.
            id = (source.charCodeAt(index) === 92) ? getEscapedIdentifier() : getIdentifier();

            // There is no keyword or literal with only one character.
            // Thus, it must be an identifier.
            if (id.length === 1) {
                type = Token.Identifier;
            } else if (isKeyword(id)) {
                type = Token.Keyword;
            } else if (id === 'null') {
                type = Token.NullLiteral;
            } else if (id === 'true' || id === 'false') {
                type = Token.BooleanLiteral;
            } else {
                type = Token.Identifier;
            }

            return {
                type: type,
                value: id,
                lineNumber: lineNumber,
                lineStart: lineStart,
                range: [start, index]
            };
        }

        // 7.7 Punctuators

        function scanPunctuator() {
            var start = index,
                code = source.charCodeAt(index),
                code2,
                ch1 = source[index],
                ch2,
                ch3,
                ch4;

            if (state.inJSXTag || state.inJSXChild) {
                // Don't need to check for '{' and '}' as it's already handled
                // correctly by default.
                switch (code) {
                case 60:  // <
                case 62:  // >
                    ++index;
                    return {
                        type: Token.Punctuator,
                        value: String.fromCharCode(code),
                        lineNumber: lineNumber,
                        lineStart: lineStart,
                        range: [start, index]
                    };
                }
            }

            switch (code) {
            // Check for most common single-character punctuators.
            case 40:   // ( open bracket
            case 41:   // ) close bracket
            case 59:   // ; semicolon
            case 44:   // , comma
            case 91:   // [
            case 93:   // ]
            case 58:   // :
            case 63:   // ?
            case 126:  // ~
                ++index;
                if (extra.tokenize && code === 40) {
                    extra.openParenToken = extra.tokens.length;
                }

                return {
                    type: Token.Punctuator,
                    value: String.fromCharCode(code),
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [start, index]
                };

            case 123:  // { open curly brace
            case 125:  // } close curly brace
                ++index;
                if (extra.tokenize && code === 123) {
                    extra.openCurlyToken = extra.tokens.length;
                }

                // lookahead2 function can cause tokens to be scanned twice and in doing so
                // would wreck the curly stack by pushing the same token onto the stack twice.
                // curlyLastIndex ensures each token is pushed or popped exactly once
                if (index > state.curlyLastIndex) {
                    state.curlyLastIndex = index;
                    if (code === 123) {
                        state.curlyStack.push('{');
                    } else {
                        state.curlyStack.pop();
                    }
                }

                return {
                    type: Token.Punctuator,
                    value: String.fromCharCode(code),
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [start, index]
                };

            default:
                code2 = source.charCodeAt(index + 1);

                // '=' (char #61) marks an assignment or comparison operator.
                if (code2 === 61) {
                    switch (code) {
                    case 37:  // %
                    case 38:  // &
                    case 42:  // *:
                    case 43:  // +
                    case 45:  // -
                    case 47:  // /
                    case 60:  // <
                    case 62:  // >
                    case 94:  // ^
                    case 124: // |
                        index += 2;
                        return {
                            type: Token.Punctuator,
                            value: String.fromCharCode(code) + String.fromCharCode(code2),
                            lineNumber: lineNumber,
                            lineStart: lineStart,
                            range: [start, index]
                        };

                    case 33: // !
                    case 61: // =
                        index += 2;

                        // !== and ===
                        if (source.charCodeAt(index) === 61) {
                            ++index;
                        }
                        return {
                            type: Token.Punctuator,
                            value: source.slice(start, index),
                            lineNumber: lineNumber,
                            lineStart: lineStart,
                            range: [start, index]
                        };
                    default:
                        break;
                    }
                }
                break;
            }

            // Peek more characters.

            ch2 = source[index + 1];
            ch3 = source[index + 2];
            ch4 = source[index + 3];

            // 4-character punctuator: >>>=

            if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
                if (ch4 === '=') {
                    index += 4;
                    return {
                        type: Token.Punctuator,
                        value: '>>>=',
                        lineNumber: lineNumber,
                        lineStart: lineStart,
                        range: [start, index]
                    };
                }
            }

            // 3-character punctuators: === !== >>> <<= >>=

            if (ch1 === '>' && ch2 === '>' && ch3 === '>' && !state.inType) {
                index += 3;
                return {
                    type: Token.Punctuator,
                    value: '>>>',
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [start, index]
                };
            }

            if (ch1 === '<' && ch2 === '<' && ch3 === '=') {
                index += 3;
                return {
                    type: Token.Punctuator,
                    value: '<<=',
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [start, index]
                };
            }

            if (ch1 === '>' && ch2 === '>' && ch3 === '=') {
                index += 3;
                return {
                    type: Token.Punctuator,
                    value: '>>=',
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [start, index]
                };
            }

            if (ch1 === '.' && ch2 === '.' && ch3 === '.') {
                index += 3;
                return {
                    type: Token.Punctuator,
                    value: '...',
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [start, index]
                };
            }

            // Other 2-character punctuators: ++ -- << >> && ||

            // Don't match these tokens if we're in a type, since they never can
            // occur and can mess up types like Map<string, Array<string>>
            if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0) && !state.inType) {
                index += 2;
                return {
                    type: Token.Punctuator,
                    value: ch1 + ch2,
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [start, index]
                };
            }

            if (ch1 === '=' && ch2 === '>') {
                index += 2;
                return {
                    type: Token.Punctuator,
                    value: '=>',
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [start, index]
                };
            }

            if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
                ++index;
                return {
                    type: Token.Punctuator,
                    value: ch1,
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [start, index]
                };
            }

            if (ch1 === '.') {
                ++index;
                return {
                    type: Token.Punctuator,
                    value: ch1,
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [start, index]
                };
            }

            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
        }

        // 7.8.3 Numeric Literals

        function scanHexLiteral(start) {
            var number = '';

            while (index < length) {
                if (!isHexDigit(source[index])) {
                    break;
                }
                number += source[index++];
            }

            if (number.length === 0) {
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            if (isIdentifierStart(source.charCodeAt(index))) {
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            return {
                type: Token.NumericLiteral,
                value: parseInt('0x' + number, 16),
                lineNumber: lineNumber,
                lineStart: lineStart,
                range: [start, index]
            };
        }

        function scanBinaryLiteral(start) {
            var ch, number;

            number = '';

            while (index < length) {
                ch = source[index];
                if (ch !== '0' && ch !== '1') {
                    break;
                }
                number += source[index++];
            }

            if (number.length === 0) {
                // only 0b or 0B
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            if (index < length) {
                ch = source.charCodeAt(index);
                /* istanbul ignore else */
                if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
                }
            }

            return {
                type: Token.NumericLiteral,
                value: parseInt(number, 2),
                lineNumber: lineNumber,
                lineStart: lineStart,
                range: [start, index]
            };
        }

        function scanOctalLiteral(prefix, start) {
            var number, octal;

            if (isOctalDigit(prefix)) {
                octal = true;
                number = '0' + source[index++];
            } else {
                octal = false;
                ++index;
                number = '';
            }

            while (index < length) {
                if (!isOctalDigit(source[index])) {
                    break;
                }
                number += source[index++];
            }

            if (!octal && number.length === 0) {
                // only 0o or 0O
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            return {
                type: Token.NumericLiteral,
                value: parseInt(number, 8),
                octal: octal,
                lineNumber: lineNumber,
                lineStart: lineStart,
                range: [start, index]
            };
        }

        function scanNumericLiteral() {
            var number, start, ch;

            ch = source[index];
            assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
                'Numeric literal must start with a decimal digit or a decimal point');

            start = index;
            number = '';
            if (ch !== '.') {
                number = source[index++];
                ch = source[index];

                // Hex number starts with '0x'.
                // Octal number starts with '0'.
                // Octal number in ES6 starts with '0o'.
                // Binary number in ES6 starts with '0b'.
                if (number === '0') {
                    if (ch === 'x' || ch === 'X') {
                        ++index;
                        return scanHexLiteral(start);
                    }
                    if (ch === 'b' || ch === 'B') {
                        ++index;
                        return scanBinaryLiteral(start);
                    }
                    if (ch === 'o' || ch === 'O' || isOctalDigit(ch)) {
                        return scanOctalLiteral(ch, start);
                    }
                    // decimal number starts with '0' such as '09' is illegal.
                    if (ch && isDecimalDigit(ch.charCodeAt(0))) {
                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
                    }
                }

                while (isDecimalDigit(source.charCodeAt(index))) {
                    number += source[index++];
                }
                ch = source[index];
            }

            if (ch === '.') {
                number += source[index++];
                while (isDecimalDigit(source.charCodeAt(index))) {
                    number += source[index++];
                }
                ch = source[index];
            }

            if (ch === 'e' || ch === 'E') {
                number += source[index++];

                ch = source[index];
                if (ch === '+' || ch === '-') {
                    number += source[index++];
                }
                if (isDecimalDigit(source.charCodeAt(index))) {
                    while (isDecimalDigit(source.charCodeAt(index))) {
                        number += source[index++];
                    }
                } else {
                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
                }
            }

            if (isIdentifierStart(source.charCodeAt(index))) {
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            return {
                type: Token.NumericLiteral,
                value: parseFloat(number),
                lineNumber: lineNumber,
                lineStart: lineStart,
                range: [start, index]
            };
        }

        // 7.8.4 String Literals

        function scanStringLiteral() {
            var str = '', quote, start, ch, code, unescaped, restore, octal = false;

            quote = source[index];
            assert((quote === '\'' || quote === '"'),
                'String literal must starts with a quote');

            start = index;
            ++index;

            while (index < length) {
                ch = source[index++];

                if (ch === quote) {
                    quote = '';
                    break;
                } else if (ch === '\\') {
                    ch = source[index++];
                    if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
                        switch (ch) {
                        case 'n':
                            str += '\n';
                            break;
                        case 'r':
                            str += '\r';
                            break;
                        case 't':
                            str += '\t';
                            break;
                        case 'u':
                        case 'x':
                            if (source[index] === '{') {
                                ++index;
                                str += scanUnicodeCodePointEscape();
                            } else {
                                restore = index;
                                unescaped = scanHexEscape(ch);
                                if (unescaped) {
                                    str += unescaped;
                                } else {
                                    index = restore;
                                    str += ch;
                                }
                            }
                            break;
                        case 'b':
                            str += '\b';
                            break;
                        case 'f':
                            str += '\f';
                            break;
                        case 'v':
                            str += '\x0B';
                            break;

                        default:
                            if (isOctalDigit(ch)) {
                                code = '01234567'.indexOf(ch);

                                // \0 is not octal escape sequence
                                if (code !== 0) {
                                    octal = true;
                                }

                                /* istanbul ignore else */
                                if (index < length && isOctalDigit(source[index])) {
                                    octal = true;
                                    code = code * 8 + '01234567'.indexOf(source[index++]);

                                    // 3 digits are only allowed when string starts
                                    // with 0, 1, 2, 3
                                    if ('0123'.indexOf(ch) >= 0 &&
                                            index < length &&
                                            isOctalDigit(source[index])) {
                                        code = code * 8 + '01234567'.indexOf(source[index++]);
                                    }
                                }
                                str += String.fromCharCode(code);
                            } else {
                                str += ch;
                            }
                            break;
                        }
                    } else {
                        ++lineNumber;
                        if (ch === '\r' && source[index] === '\n') {
                            ++index;
                        }
                        lineStart = index;
                    }
                } else if (isLineTerminator(ch.charCodeAt(0))) {
                    break;
                } else {
                    str += ch;
                }
            }

            if (quote !== '') {
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            return {
                type: Token.StringLiteral,
                value: str,
                octal: octal,
                lineNumber: lineNumber,
                lineStart: lineStart,
                range: [start, index]
            };
        }

        function scanTemplate() {
            var cooked = '', ch, start, terminated, head, tail, restore, unescaped, code, octal;

            terminated = false;
            tail = false;
            start = index;
            head = (source[index] === '`');

            ++index;

            while (index < length) {
                ch = source[index++];
                if (ch === '`') {
                    tail = true;
                    terminated = true;
                    break;
                } else if (ch === '$') {
                    if (source[index] === '{') {
                        ++index;
                        terminated = true;
                        break;
                    }
                    cooked += ch;
                } else if (ch === '\\') {
                    ch = source[index++];
                    if (!isLineTerminator(ch.charCodeAt(0))) {
                        switch (ch) {
                        case 'n':
                            cooked += '\n';
                            break;
                        case 'r':
                            cooked += '\r';
                            break;
                        case 't':
                            cooked += '\t';
                            break;
                        case 'u':
                        case 'x':
                            if (source[index] === '{') {
                                ++index;
                                cooked += scanUnicodeCodePointEscape();
                            } else {
                                restore = index;
                                unescaped = scanHexEscape(ch);
                                if (unescaped) {
                                    cooked += unescaped;
                                } else {
                                    index = restore;
                                    cooked += ch;
                                }
                            }
                            break;
                        case 'b':
                            cooked += '\b';
                            break;
                        case 'f':
                            cooked += '\f';
                            break;
                        case 'v':
                            cooked += '\v';
                            break;

                        default:
                            if (isOctalDigit(ch)) {
                                code = '01234567'.indexOf(ch);

                                // \0 is not octal escape sequence
                                if (code !== 0) {
                                    octal = true;
                                }

                                /* istanbul ignore else */
                                if (index < length && isOctalDigit(source[index])) {
                                    octal = true;
                                    code = code * 8 + '01234567'.indexOf(source[index++]);

                                    // 3 digits are only allowed when string starts
                                    // with 0, 1, 2, 3
                                    if ('0123'.indexOf(ch) >= 0 &&
                                            index < length &&
                                            isOctalDigit(source[index])) {
                                        code = code * 8 + '01234567'.indexOf(source[index++]);
                                    }
                                }
                                cooked += String.fromCharCode(code);
                            } else {
                                cooked += ch;
                            }
                            break;
                        }
                    } else {
                        ++lineNumber;
                        if (ch === '\r' && source[index] === '\n') {
                            ++index;
                        }
                        lineStart = index;
                    }
                } else if (isLineTerminator(ch.charCodeAt(0))) {
                    ++lineNumber;
                    if (ch === '\r' && source[index] === '\n') {
                        ++index;
                    }
                    lineStart = index;
                    cooked += '\n';
                } else {
                    cooked += ch;
                }
            }

            if (!terminated) {
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            if (index > state.curlyLastIndex) {
                state.curlyLastIndex = index;
                if (!tail) {
                    state.curlyStack.push('template');
                }

                if (!head) {
                    state.curlyStack.pop();
                }
            }

            return {
                type: Token.Template,
                value: {
                    cooked: cooked,
                    raw: source.slice(start + 1, index - ((tail) ? 1 : 2))
                },
                head: head,
                tail: tail,
                octal: octal,
                lineNumber: lineNumber,
                lineStart: lineStart,
                range: [start, index]
            };
        }

        function testRegExp(pattern, flags) {
            var tmp = pattern,
                value;

            if (flags.indexOf('u') >= 0) {
                // Replace each astral symbol and every Unicode code point
                // escape sequence with a single ASCII symbol to avoid throwing on
                // regular expressions that are only valid in combination with the
                // `/u` flag.
                // Note: replacing with the ASCII symbol `x` might cause false
                // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
                // perfectly valid pattern that is equivalent to `[a-b]`, but it
                // would be replaced by `[x-b]` which throws an error.
                tmp = tmp
                    .replace(/\\u\{([0-9a-fA-F]+)\}/g, function ($0, $1) {
                        if (parseInt($1, 16) <= 0x10FFFF) {
                            return 'x';
                        }
                        throwError({}, Messages.InvalidRegExp);
                    })
                    .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x');
            }

            // First, detect invalid regular expressions.
            try {
                value = new RegExp(tmp);
            } catch (e) {
                throwError({}, Messages.InvalidRegExp);
            }

            // Return a regular expression object for this pattern-flag pair, or
            // `null` in case the current environment doesn't support the flags it
            // uses.
            try {
                return new RegExp(pattern, flags);
            } catch (exception) {
                return null;
            }
        }

        function scanRegExpBody() {
            var ch, str, classMarker, terminated, body;

            ch = source[index];
            assert(ch === '/', 'Regular expression literal must start with a slash');
            str = source[index++];

            classMarker = false;
            terminated = false;
            while (index < length) {
                ch = source[index++];
                str += ch;
                if (ch === '\\') {
                    ch = source[index++];
                    // ECMA-262 7.8.5
                    if (isLineTerminator(ch.charCodeAt(0))) {
                        throwError({}, Messages.UnterminatedRegExp);
                    }
                    str += ch;
                } else if (isLineTerminator(ch.charCodeAt(0))) {
                    throwError({}, Messages.UnterminatedRegExp);
                } else if (classMarker) {
                    if (ch === ']') {
                        classMarker = false;
                    }
                } else {
                    if (ch === '/') {
                        terminated = true;
                        break;
                    } else if (ch === '[') {
                        classMarker = true;
                    }
                }
            }

            if (!terminated) {
                throwError({}, Messages.UnterminatedRegExp);
            }

            // Exclude leading and trailing slash.
            body = str.substr(1, str.length - 2);
            return {
                value: body,
                literal: str
            };
        }

        function scanRegExpFlags() {
            var ch, str, flags, restore;

            str = '';
            flags = '';
            while (index < length) {
                ch = source[index];
                if (!isIdentifierPart(ch.charCodeAt(0))) {
                    break;
                }

                ++index;
                if (ch === '\\' && index < length) {
                    ch = source[index];
                    if (ch === 'u') {
                        ++index;
                        restore = index;
                        ch = scanHexEscape('u');
                        if (ch) {
                            flags += ch;
                            for (str += '\\u'; restore < index; ++restore) {
                                str += source[restore];
                            }
                        } else {
                            index = restore;
                            flags += 'u';
                            str += '\\u';
                        }
                        throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
                    } else {
                        str += '\\';
                        throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
                    }
                } else {
                    flags += ch;
                    str += ch;
                }
            }

            return {
                value: flags,
                literal: str
            };
        }

        function scanRegExp() {
            var start, body, flags, value;

            lookahead = null;
            skipComment();
            start = index;

            body = scanRegExpBody();
            flags = scanRegExpFlags();
            value = testRegExp(body.value, flags.value);

            if (extra.tokenize) {
                return {
                    type: Token.RegularExpression,
                    value: value,
                    regex: {
                        pattern: body.value,
                        flags: flags.value
                    },
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [start, index]
                };
            }

            return {
                literal: body.literal + flags.literal,
                value: value,
                regex: {
                    pattern: body.value,
                    flags: flags.value
                },
                range: [start, index]
            };
        }

        function isIdentifierName(token) {
            return token.type === Token.Identifier ||
                token.type === Token.Keyword ||
                token.type === Token.BooleanLiteral ||
                token.type === Token.NullLiteral;
        }

        function advanceSlash() {
            var prevToken,
                checkToken;
            // Using the following algorithm:
            // https://github.com/mozilla/sweet.js/wiki/design
            prevToken = extra.tokens[extra.tokens.length - 1];
            if (!prevToken) {
                // Nothing before that: it cannot be a division.
                return scanRegExp();
            }
            if (prevToken.type === 'Punctuator') {
                if (prevToken.value === ')') {
                    checkToken = extra.tokens[extra.openParenToken - 1];
                    if (checkToken &&
                            checkToken.type === 'Keyword' &&
                            (checkToken.value === 'if' ||
                             checkToken.value === 'while' ||
                             checkToken.value === 'for' ||
                             checkToken.value === 'with')) {
                        return scanRegExp();
                    }
                    return scanPunctuator();
                }
                if (prevToken.value === '}') {
                    // Dividing a function by anything makes little sense,
                    // but we have to check for that.
                    if (extra.tokens[extra.openCurlyToken - 3] &&
                            extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') {
                        // Anonymous function.
                        checkToken = extra.tokens[extra.openCurlyToken - 4];
                        if (!checkToken) {
                            return scanPunctuator();
                        }
                    } else if (extra.tokens[extra.openCurlyToken - 4] &&
                            extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') {
                        // Named function.
                        checkToken = extra.tokens[extra.openCurlyToken - 5];
                        if (!checkToken) {
                            return scanRegExp();
                        }
                    } else {
                        return scanPunctuator();
                    }
                    // checkToken determines whether the function is
                    // a declaration or an expression.
                    if (FnExprTokens.indexOf(checkToken.value) >= 0) {
                        // It is an expression.
                        return scanPunctuator();
                    }
                    // It is a declaration.
                    return scanRegExp();
                }
                return scanRegExp();
            }
            if (prevToken.type === 'Keyword' && prevToken.value !== 'this') {
                return scanRegExp();
            }
            return scanPunctuator();
        }

        function advance() {
            var ch;

            if (!state.inJSXChild) {
                skipComment();
            }

            if (index >= length) {
                return {
                    type: Token.EOF,
                    lineNumber: lineNumber,
                    lineStart: lineStart,
                    range: [index, index]
                };
            }

            if (state.inJSXChild) {
                return advanceJSXChild();
            }

            ch = source.charCodeAt(index);

            // Very common: ( and ) and ;
            if (ch === 40 || ch === 41 || ch === 58) {
                return scanPunctuator();
            }

            // String literal starts with single quote (#39) or double quote (#34).
            if (ch === 39 || ch === 34) {
                if (state.inJSXTag) {
                    return scanJSXStringLiteral();
                }
                return scanStringLiteral();
            }

            if (state.inJSXTag && isJSXIdentifierStart(ch)) {
                return scanJSXIdentifier();
            }

            // Template literals start with backtick (#96) for template head
            // or close curly (#125) for template middle or template tail.
            if (ch === 96 || (ch === 125 && state.curlyStack[state.curlyStack.length - 1] === 'template')) {
                return scanTemplate();
            }
            if (isIdentifierStart(ch)) {
                return scanIdentifier();
            }

            // Dot (.) char #46 can also start a floating-point number, hence the need
            // to check the next character.
            if (ch === 46) {
                if (isDecimalDigit(source.charCodeAt(index + 1))) {
                    return scanNumericLiteral();
                }
                return scanPunctuator();
            }

            if (isDecimalDigit(ch)) {
                return scanNumericLiteral();
            }

            // Slash (/) char #47 can also start a regex.
            if (extra.tokenize && ch === 47) {
                return advanceSlash();
            }

            return scanPunctuator();
        }

        function lex() {
            var token;

            token = lookahead;
            index = token.range[1];
            lineNumber = token.lineNumber;
            lineStart = token.lineStart;

            lookahead = advance();

            index = token.range[1];
            lineNumber = token.lineNumber;
            lineStart = token.lineStart;

            return token;
        }

        function peek() {
            var pos, line, start;

            pos = index;
            line = lineNumber;
            start = lineStart;
            lookahead = advance();
            index = pos;
            lineNumber = line;
            lineStart = start;
        }

        function lookahead2() {
            var adv, pos, line, start, result;

            // If we are collecting the tokens, don't grab the next one yet.
            /* istanbul ignore next */
            adv = (typeof extra.advance === 'function') ? extra.advance : advance;

            pos = index;
            line = lineNumber;
            start = lineStart;

            // Scan for the next immediate token.
            /* istanbul ignore if */
            if (lookahead === null) {
                lookahead = adv();
            }
            index = lookahead.range[1];
            lineNumber = lookahead.lineNumber;
            lineStart = lookahead.lineStart;

            // Grab the token right after.
            result = adv();
            index = pos;
            lineNumber = line;
            lineStart = start;

            return result;
        }

        function rewind(token) {
            index = token.range[0];
            lineNumber = token.lineNumber;
            lineStart = token.lineStart;
            lookahead = token;
        }

        function markerCreate() {
            if (!extra.loc && !extra.range) {
                return undefined;
            }
            skipComment();
            return {offset: index, line: lineNumber, col: index - lineStart};
        }

        function markerCreatePreserveWhitespace() {
            if (!extra.loc && !extra.range) {
                return undefined;
            }
            return {offset: index, line: lineNumber, col: index - lineStart};
        }

        function processComment(node) {
            var lastChild,
                trailingComments,
                bottomRight = extra.bottomRightStack,
                last = bottomRight[bottomRight.length - 1];

            if (node.type === Syntax.Program) {
                /* istanbul ignore else */
                if (node.body.length > 0) {
                    return;
                }
            }

            if (extra.trailingComments.length > 0) {
                if (extra.trailingComments[0].range[0] >= node.range[1]) {
                    trailingComments = extra.trailingComments;
                    extra.trailingComments = [];
                } else {
                    extra.trailingComments.length = 0;
                }
            } else {
                if (last && last.trailingComments && last.trailingComments[0].range[0] >= node.range[1]) {
                    trailingComments = last.trailingComments;
                    delete last.trailingComments;
                }
            }

            // Eating the stack.
            if (last) {
                while (last && last.range[0] >= node.range[0]) {
                    lastChild = last;
                    last = bottomRight.pop();
                }
            }

            if (lastChild) {
                if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= node.range[0]) {
                    node.leadingComments = lastChild.leadingComments;
                    delete lastChild.leadingComments;
                }
            } else if (extra.leadingComments.length > 0 && extra.leadingComments[extra.leadingComments.length - 1].range[1] <= node.range[0]) {
                node.leadingComments = extra.leadingComments;
                extra.leadingComments = [];
            }

            if (trailingComments) {
                node.trailingComments = trailingComments;
            }

            bottomRight.push(node);
        }

        function markerApply(marker, node) {
            if (extra.range) {
                node.range = [marker.offset, index];
            }
            if (extra.loc) {
                node.loc = {
                    start: {
                        line: marker.line,
                        column: marker.col
                    },
                    end: {
                        line: lineNumber,
                        column: index - lineStart
                    }
                };
                node = delegate.postProcess(node);
            }
            if (extra.attachComment) {
                processComment(node);
            }
            return node;
        }

        SyntaxTreeDelegate = {

            name: 'SyntaxTree',

            postProcess: function (node) {
                return node;
            },

            createArrayExpression: function (elements) {
                return {
                    type: Syntax.ArrayExpression,
                    elements: elements
                };
            },

            createAssignmentExpression: function (operator, left, right) {
                return {
                    type: Syntax.AssignmentExpression,
                    operator: operator,
                    left: left,
                    right: right
                };
            },

            createBinaryExpression: function (operator, left, right) {
                var type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression :
                            Syntax.BinaryExpression;
                return {
                    type: type,
                    operator: operator,
                    left: left,
                    right: right
                };
            },

            createBlockStatement: function (body) {
                return {
                    type: Syntax.BlockStatement,
                    body: body
                };
            },

            createBreakStatement: function (label) {
                return {
                    type: Syntax.BreakStatement,
                    label: label
                };
            },

            createCallExpression: function (callee, args) {
                return {
                    type: Syntax.CallExpression,
                    callee: callee,
                    'arguments': args
                };
            },

            createCatchClause: function (param, body) {
                return {
                    type: Syntax.CatchClause,
                    param: param,
                    body: body
                };
            },

            createConditionalExpression: function (test, consequent, alternate) {
                return {
                    type: Syntax.ConditionalExpression,
                    test: test,
                    consequent: consequent,
                    alternate: alternate
                };
            },

            createContinueStatement: function (label) {
                return {
                    type: Syntax.ContinueStatement,
                    label: label
                };
            },

            createDebuggerStatement: function () {
                return {
                    type: Syntax.DebuggerStatement
                };
            },

            createDoWhileStatement: function (body, test) {
                return {
                    type: Syntax.DoWhileStatement,
                    body: body,
                    test: test
                };
            },

            createEmptyStatement: function () {
                return {
                    type: Syntax.EmptyStatement
                };
            },

            createExpressionStatement: function (expression) {
                return {
                    type: Syntax.ExpressionStatement,
                    expression: expression
                };
            },

            createForStatement: function (init, test, update, body) {
                return {
                    type: Syntax.ForStatement,
                    init: init,
                    test: test,
                    update: update,
                    body: body
                };
            },

            createForInStatement: function (left, right, body) {
                return {
                    type: Syntax.ForInStatement,
                    left: left,
                    right: right,
                    body: body,
                    each: false
                };
            },

            createForOfStatement: function (left, right, body) {
                return {
                    type: Syntax.ForOfStatement,
                    left: left,
                    right: right,
                    body: body
                };
            },

            createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression,
                                                 isAsync, returnType, typeParameters) {
                var funDecl = {
                    type: Syntax.FunctionDeclaration,
                    id: id,
                    params: params,
                    defaults: defaults,
                    body: body,
                    rest: rest,
                    generator: generator,
                    expression: expression,
                    returnType: returnType,
                    typeParameters: typeParameters
                };

                if (isAsync) {
                    funDecl.async = true;
                }

                return funDecl;
            },

            createFunctionExpression: function (id, params, defaults, body, rest, generator, expression,
                                                isAsync, returnType, typeParameters) {
                var funExpr = {
                    type: Syntax.FunctionExpression,
                    id: id,
                    params: params,
                    defaults: defaults,
                    body: body,
                    rest: rest,
                    generator: generator,
                    expression: expression,
                    returnType: returnType,
                    typeParameters: typeParameters
                };

                if (isAsync) {
                    funExpr.async = true;
                }

                return funExpr;
            },

            createIdentifier: function (name) {
                return {
                    type: Syntax.Identifier,
                    name: name,
                    // Only here to initialize the shape of the object to ensure
                    // that the 'typeAnnotation' key is ordered before others that
                    // are added later (like 'loc' and 'range'). This just helps
                    // keep the shape of Identifier nodes consistent with everything
                    // else.
                    typeAnnotation: undefined,
                    optional: undefined
                };
            },

            createTypeAnnotation: function (typeAnnotation) {
                return {
                    type: Syntax.TypeAnnotation,
                    typeAnnotation: typeAnnotation
                };
            },

            createTypeCast: function (expression, typeAnnotation) {
                return {
                    type: Syntax.TypeCastExpression,
                    expression: expression,
                    typeAnnotation: typeAnnotation
                };
            },

            createFunctionTypeAnnotation: function (params, returnType, rest, typeParameters) {
                return {
                    type: Syntax.FunctionTypeAnnotation,
                    params: params,
                    returnType: returnType,
                    rest: rest,
                    typeParameters: typeParameters
                };
            },

            createFunctionTypeParam: function (name, typeAnnotation, optional) {
                return {
                    type: Syntax.FunctionTypeParam,
                    name: name,
                    typeAnnotation: typeAnnotation,
                    optional: optional
                };
            },

            createNullableTypeAnnotation: function (typeAnnotation) {
                return {
                    type: Syntax.NullableTypeAnnotation,
                    typeAnnotation: typeAnnotation
                };
            },

            createArrayTypeAnnotation: function (elementType) {
                return {
                    type: Syntax.ArrayTypeAnnotation,
                    elementType: elementType
                };
            },

            createGenericTypeAnnotation: function (id, typeParameters) {
                return {
                    type: Syntax.GenericTypeAnnotation,
                    id: id,
                    typeParameters: typeParameters
                };
            },

            createQualifiedTypeIdentifier: function (qualification, id) {
                return {
                    type: Syntax.QualifiedTypeIdentifier,
                    qualification: qualification,
                    id: id
                };
            },

            createTypeParameterDeclaration: function (params) {
                return {
                    type: Syntax.TypeParameterDeclaration,
                    params: params
                };
            },

            createTypeParameterInstantiation: function (params) {
                return {
                    type: Syntax.TypeParameterInstantiation,
                    params: params
                };
            },

            createAnyTypeAnnotation: function () {
                return {
                    type: Syntax.AnyTypeAnnotation
                };
            },

            createBooleanTypeAnnotation: function () {
                return {
                    type: Syntax.BooleanTypeAnnotation
                };
            },

            createNumberTypeAnnotation: function () {
                return {
                    type: Syntax.NumberTypeAnnotation
                };
            },

            createStringTypeAnnotation: function () {
                return {
                    type: Syntax.StringTypeAnnotation
                };
            },

            createStringLiteralTypeAnnotation: function (token) {
                return {
                    type: Syntax.StringLiteralTypeAnnotation,
                    value: token.value,
                    raw: source.slice(token.range[0], token.range[1])
                };
            },

            createVoidTypeAnnotation: function () {
                return {
                    type: Syntax.VoidTypeAnnotation
                };
            },

            createTypeofTypeAnnotation: function (argument) {
                return {
                    type: Syntax.TypeofTypeAnnotation,
                    argument: argument
                };
            },

            createTupleTypeAnnotation: function (types) {
                return {
                    type: Syntax.TupleTypeAnnotation,
                    types: types
                };
            },

            createObjectTypeAnnotation: function (properties, indexers, callProperties) {
                return {
                    type: Syntax.ObjectTypeAnnotation,
                    properties: properties,
                    indexers: indexers,
                    callProperties: callProperties
                };
            },

            createObjectTypeIndexer: function (id, key, value, isStatic) {
                return {
                    type: Syntax.ObjectTypeIndexer,
                    id: id,
                    key: key,
                    value: value,
                    static: isStatic
                };
            },

            createObjectTypeCallProperty: function (value, isStatic) {
                return {
                    type: Syntax.ObjectTypeCallProperty,
                    value: value,
                    static: isStatic
                };
            },

            createObjectTypeProperty: function (key, value, optional, isStatic) {
                return {
                    type: Syntax.ObjectTypeProperty,
                    key: key,
                    value: value,
                    optional: optional,
                    static: isStatic
                };
            },

            createUnionTypeAnnotation: function (types) {
                return {
                    type: Syntax.UnionTypeAnnotation,
                    types: types
                };
            },

            createIntersectionTypeAnnotation: function (types) {
                return {
                    type: Syntax.IntersectionTypeAnnotation,
                    types: types
                };
            },

            createTypeAlias: function (id, typeParameters, right) {
                return {
                    type: Syntax.TypeAlias,
                    id: id,
                    typeParameters: typeParameters,
                    right: right
                };
            },

            createInterface: function (id, typeParameters, body, extended) {
                return {
                    type: Syntax.InterfaceDeclaration,
                    id: id,
                    typeParameters: typeParameters,
                    body: body,
                    extends: extended
                };
            },

            createInterfaceExtends: function (id, typeParameters) {
                return {
                    type: Syntax.InterfaceExtends,
                    id: id,
                    typeParameters: typeParameters
                };
            },

            createDeclareFunction: function (id) {
                return {
                    type: Syntax.DeclareFunction,
                    id: id
                };
            },

            createDeclareVariable: function (id) {
                return {
                    type: Syntax.DeclareVariable,
                    id: id
                };
            },

            createDeclareModule: function (id, body) {
                return {
                    type: Syntax.DeclareModule,
                    id: id,
                    body: body
                };
            },

            createJSXAttribute: function (name, value) {
                return {
                    type: Syntax.JSXAttribute,
                    name: name,
                    value: value || null
                };
            },

            createJSXSpreadAttribute: function (argument) {
                return {
                    type: Syntax.JSXSpreadAttribute,
                    argument: argument
                };
            },

            createJSXIdentifier: function (name) {
                return {
                    type: Syntax.JSXIdentifier,
                    name: name
                };
            },

            createJSXNamespacedName: function (namespace, name) {
                return {
                    type: Syntax.JSXNamespacedName,
                    namespace: namespace,
                    name: name
                };
            },

            createJSXMemberExpression: function (object, property) {
                return {
                    type: Syntax.JSXMemberExpression,
                    object: object,
                    property: property
                };
            },

            createJSXElement: function (openingElement, closingElement, children) {
                return {
                    type: Syntax.JSXElement,
                    openingElement: openingElement,
                    closingElement: closingElement,
                    children: children
                };
            },

            createJSXEmptyExpression: function () {
                return {
                    type: Syntax.JSXEmptyExpression
                };
            },

            createJSXExpressionContainer: function (expression) {
                return {
                    type: Syntax.JSXExpressionContainer,
                    expression: expression
                };
            },

            createJSXOpeningElement: function (name, attributes, selfClosing) {
                return {
                    type: Syntax.JSXOpeningElement,
                    name: name,
                    selfClosing: selfClosing,
                    attributes: attributes
                };
            },

            createJSXClosingElement: function (name) {
                return {
                    type: Syntax.JSXClosingElement,
                    name: name
                };
            },

            createIfStatement: function (test, consequent, alternate) {
                return {
                    type: Syntax.IfStatement,
                    test: test,
                    consequent: consequent,
                    alternate: alternate
                };
            },

            createLabeledStatement: function (label, body) {
                return {
                    type: Syntax.LabeledStatement,
                    label: label,
                    body: body
                };
            },

            createLiteral: function (token) {
                var object = {
                    type: Syntax.Literal,
                    value: token.value,
                    raw: source.slice(token.range[0], token.range[1])
                };
                if (token.regex) {
                    object.regex = token.regex;
                }
                return object;
            },

            createMemberExpression: function (accessor, object, property) {
                return {
                    type: Syntax.MemberExpression,
                    computed: accessor === '[',
                    object: object,
                    property: property
                };
            },

            createNewExpression: function (callee, args) {
                return {
                    type: Syntax.NewExpression,
                    callee: callee,
                    'arguments': args
                };
            },

            createObjectExpression: function (properties) {
                return {
                    type: Syntax.ObjectExpression,
                    properties: properties
                };
            },

            createPostfixExpression: function (operator, argument) {
                return {
                    type: Syntax.UpdateExpression,
                    operator: operator,
                    argument: argument,
                    prefix: false
                };
            },

            createProgram: function (body) {
                return {
                    type: Syntax.Program,
                    body: body
                };
            },

            createProperty: function (kind, key, value, method, shorthand, computed) {
                return {
                    type: Syntax.Property,
                    key: key,
                    value: value,
                    kind: kind,
                    method: method,
                    shorthand: shorthand,
                    computed: computed
                };
            },

            createReturnStatement: function (argument) {
                return {
                    type: Syntax.ReturnStatement,
                    argument: argument
                };
            },

            createSequenceExpression: function (expressions) {
                return {
                    type: Syntax.SequenceExpression,
                    expressions: expressions
                };
            },

            createSwitchCase: function (test, consequent) {
                return {
                    type: Syntax.SwitchCase,
                    test: test,
                    consequent: consequent
                };
            },

            createSwitchStatement: function (discriminant, cases) {
                return {
                    type: Syntax.SwitchStatement,
                    discriminant: discriminant,
                    cases: cases
                };
            },

            createThisExpression: function () {
                return {
                    type: Syntax.ThisExpression
                };
            },

            createThrowStatement: function (argument) {
                return {
                    type: Syntax.ThrowStatement,
                    argument: argument
                };
            },

            createTryStatement: function (block, guardedHandlers, handlers, finalizer) {
                return {
                    type: Syntax.TryStatement,
                    block: block,
                    guardedHandlers: guardedHandlers,
                    handlers: handlers,
                    finalizer: finalizer
                };
            },

            createUnaryExpression: function (operator, argument) {
                if (operator === '++' || operator === '--') {
                    return {
                        type: Syntax.UpdateExpression,
                        operator: operator,
                        argument: argument,
                        prefix: true
                    };
                }
                return {
                    type: Syntax.UnaryExpression,
                    operator: operator,
                    argument: argument,
                    prefix: true
                };
            },

            createVariableDeclaration: function (declarations, kind) {
                return {
                    type: Syntax.VariableDeclaration,
                    declarations: declarations,
                    kind: kind
                };
            },

            createVariableDeclarator: function (id, init) {
                return {
                    type: Syntax.VariableDeclarator,
                    id: id,
                    init: init
                };
            },

            createWhileStatement: function (test, body) {
                return {
                    type: Syntax.WhileStatement,
                    test: test,
                    body: body
                };
            },

            createWithStatement: function (object, body) {
                return {
                    type: Syntax.WithStatement,
                    object: object,
                    body: body
                };
            },

            createTemplateElement: function (value, tail) {
                return {
                    type: Syntax.TemplateElement,
                    value: value,
                    tail: tail
                };
            },

            createTemplateLiteral: function (quasis, expressions) {
                return {
                    type: Syntax.TemplateLiteral,
                    quasis: quasis,
                    expressions: expressions
                };
            },

            createSpreadElement: function (argument) {
                return {
                    type: Syntax.SpreadElement,
                    argument: argument
                };
            },

            createSpreadProperty: function (argument) {
                return {
                    type: Syntax.SpreadProperty,
                    argument: argument
                };
            },

            createTaggedTemplateExpression: function (tag, quasi) {
                return {
                    type: Syntax.TaggedTemplateExpression,
                    tag: tag,
                    quasi: quasi
                };
            },

            createArrowFunctionExpression: function (params, defaults, body, rest, expression, isAsync) {
                var arrowExpr = {
                    type: Syntax.ArrowFunctionExpression,
                    id: null,
                    params: params,
                    defaults: defaults,
                    body: body,
                    rest: rest,
                    generator: false,
                    expression: expression
                };

                if (isAsync) {
                    arrowExpr.async = true;
                }

                return arrowExpr;
            },

            createMethodDefinition: function (propertyType, kind, key, value, computed) {
                return {
                    type: Syntax.MethodDefinition,
                    key: key,
                    value: value,
                    kind: kind,
                    'static': propertyType === ClassPropertyType.static,
                    computed: computed
                };
            },

            createClassProperty: function (key, typeAnnotation, computed, isStatic) {
                return {
                    type: Syntax.ClassProperty,
                    key: key,
                    typeAnnotation: typeAnnotation,
                    computed: computed,
                    static: isStatic
                };
            },

            createClassBody: function (body) {
                return {
                    type: Syntax.ClassBody,
                    body: body
                };
            },

            createClassImplements: function (id, typeParameters) {
                return {
                    type: Syntax.ClassImplements,
                    id: id,
                    typeParameters: typeParameters
                };
            },

            createClassExpression: function (id, superClass, body, typeParameters, superTypeParameters, implemented) {
                return {
                    type: Syntax.ClassExpression,
                    id: id,
                    superClass: superClass,
                    body: body,
                    typeParameters: typeParameters,
                    superTypeParameters: superTypeParameters,
                    implements: implemented
                };
            },

            createClassDeclaration: function (id, superClass, body, typeParameters, superTypeParameters, implemented) {
                return {
                    type: Syntax.ClassDeclaration,
                    id: id,
                    superClass: superClass,
                    body: body,
                    typeParameters: typeParameters,
                    superTypeParameters: superTypeParameters,
                    implements: implemented
                };
            },

            createExportSpecifier: function (id, name) {
                return {
                    type: Syntax.ExportSpecifier,
                    id: id,
                    name: name
                };
            },

            createExportBatchSpecifier: function () {
                return {
                    type: Syntax.ExportBatchSpecifier
                };
            },

            createImportDefaultSpecifier: function (id) {
                return {
                    type: Syntax.ImportDefaultSpecifier,
                    id: id
                };
            },

            createImportNamespaceSpecifier: function (id) {
                return {
                    type: Syntax.ImportNamespaceSpecifier,
                    id: id
                };
            },

            createExportDeclaration: function (isDefault, declaration, specifiers, src, exportKind) {
                return {
                    type: Syntax.ExportDeclaration,
                    'default': !!isDefault,
                    declaration: declaration,
                    specifiers: specifiers,
                    source: src,
                    exportKind: exportKind
                };
            },

            createImportSpecifier: function (id, name) {
                return {
                    type: Syntax.ImportSpecifier,
                    id: id,
                    name: name
                };
            },

            createImportDeclaration: function (specifiers, src, importKind) {
                return {
                    type: Syntax.ImportDeclaration,
                    specifiers: specifiers,
                    source: src,
                    importKind: importKind
                };
            },

            createYieldExpression: function (argument, dlg) {
                return {
                    type: Syntax.YieldExpression,
                    argument: argument,
                    delegate: dlg
                };
            },

            createAwaitExpression: function (argument) {
                return {
                    type: Syntax.AwaitExpression,
                    argument: argument
                };
            },

            createComprehensionExpression: function (filter, blocks, body) {
                return {
                    type: Syntax.ComprehensionExpression,
                    filter: filter,
                    blocks: blocks,
                    body: body
                };
            }

        };

        // Return true if there is a line terminator before the next token.

        function peekLineTerminator() {
            var pos, line, start, found;

            pos = index;
            line = lineNumber;
            start = lineStart;
            skipComment();
            found = lineNumber !== line;
            index = pos;
            lineNumber = line;
            lineStart = start;

            return found;
        }

        // Throw an exception

        function throwError(token, messageFormat) {
            var error,
                args = Array.prototype.slice.call(arguments, 2),
                msg = messageFormat.replace(
                    /%(\d)/g,
                    function (whole, idx) {
                        assert(idx < args.length, 'Message reference must be in range');
                        return args[idx];
                    }
                );

            if (typeof token.lineNumber === 'number') {
                error = new Error('Line ' + token.lineNumber + ': ' + msg);
                error.index = token.range[0];
                error.lineNumber = token.lineNumber;
                error.column = token.range[0] - lineStart + 1;
            } else {
                error = new Error('Line ' + lineNumber + ': ' + msg);
                error.index = index;
                error.lineNumber = lineNumber;
                error.column = index - lineStart + 1;
            }

            error.description = msg;
            throw error;
        }

        function throwErrorTolerant() {
            try {
                throwError.apply(null, arguments);
            } catch (e) {
                if (extra.errors) {
                    extra.errors.push(e);
                } else {
                    throw e;
                }
            }
        }

        // Throw an exception because of the token.

        function throwUnexpected(token) {
            if (token.type === Token.EOF) {
                throwError(token, Messages.UnexpectedEOS);
            }

            if (token.type === Token.NumericLiteral) {
                throwError(token, Messages.UnexpectedNumber);
            }

            if (token.type === Token.StringLiteral || token.type === Token.JSXText) {
                throwError(token, Messages.UnexpectedString);
            }

            if (token.type === Token.Identifier) {
                throwError(token, Messages.UnexpectedIdentifier);
            }

            if (token.type === Token.Keyword) {
                if (isFutureReservedWord(token.value)) {
                    throwError(token, Messages.UnexpectedReserved);
                } else if (strict && isStrictModeReservedWord(token.value)) {
                    throwErrorTolerant(token, Messages.StrictReservedWord);
                    return;
                }
                throwError(token, Messages.UnexpectedToken, token.value);
            }

            if (token.type === Token.Template) {
                throwError(token, Messages.UnexpectedTemplate, token.value.raw);
            }

            // BooleanLiteral, NullLiteral, or Punctuator.
            throwError(token, Messages.UnexpectedToken, token.value);
        }

        // Expect the next token to match the specified punctuator.
        // If not, an exception will be thrown.

        function expect(value) {
            var token = lex();
            if (token.type !== Token.Punctuator || token.value !== value) {
                throwUnexpected(token);
            }
        }

        // Expect the next token to match the specified keyword.
        // If not, an exception will be thrown.

        function expectKeyword(keyword, contextual) {
            var token = lex();
            if (token.type !== (contextual ? Token.Identifier : Token.Keyword) ||
                    token.value !== keyword) {
                throwUnexpected(token);
            }
        }

        // Expect the next token to match the specified contextual keyword.
        // If not, an exception will be thrown.

        function expectContextualKeyword(keyword) {
            return expectKeyword(keyword, true);
        }

        // Return true if the next token matches the specified punctuator.

        function match(value) {
            return lookahead.type === Token.Punctuator && lookahead.value === value;
        }

        // Return true if the next token matches the specified keyword

        function matchKeyword(keyword, contextual) {
            var expectedType = contextual ? Token.Identifier : Token.Keyword;
            return lookahead.type === expectedType && lookahead.value === keyword;
        }

        // Return true if the next token matches the specified contextual keyword

        function matchContextualKeyword(keyword) {
            return matchKeyword(keyword, true);
        }

        // Return true if the next token is an assignment operator

        function matchAssign() {
            var op;

            if (lookahead.type !== Token.Punctuator) {
                return false;
            }
            op = lookahead.value;
            return op === '=' ||
                op === '*=' ||
                op === '/=' ||
                op === '%=' ||
                op === '+=' ||
                op === '-=' ||
                op === '<<=' ||
                op === '>>=' ||
                op === '>>>=' ||
                op === '&=' ||
                op === '^=' ||
                op === '|=';
        }

        // Note that 'yield' is treated as a keyword in strict mode, but a
        // contextual keyword (identifier) in non-strict mode, so we need to
        // use matchKeyword('yield', false) and matchKeyword('yield', true)
        // (i.e. matchContextualKeyword) appropriately.
        function matchYield() {
            return state.yieldAllowed && matchKeyword('yield', !strict);
        }

        function matchAsync() {
            var backtrackToken = lookahead, matches = false;

            if (matchContextualKeyword('async')) {
                lex(); // Make sure peekLineTerminator() starts after 'async'.
                matches = !peekLineTerminator();
                rewind(backtrackToken); // Revert the lex().
            }

            return matches;
        }

        function matchAwait() {
            return state.awaitAllowed && matchContextualKeyword('await');
        }

        function consumeSemicolon() {
            var line, oldIndex = index, oldLineNumber = lineNumber,
                oldLineStart = lineStart, oldLookahead = lookahead;

            // Catch the very common case first: immediately a semicolon (char #59).
            if (source.charCodeAt(index) === 59) {
                lex();
                return;
            }

            line = lineNumber;
            skipComment();
            if (lineNumber !== line) {
                index = oldIndex;
                lineNumber = oldLineNumber;
                lineStart = oldLineStart;
                lookahead = oldLookahead;
                return;
            }

            if (match(';')) {
                lex();
                return;
            }

            if (lookahead.type !== Token.EOF && !match('}')) {
                throwUnexpected(lookahead);
            }
        }

        // Return true if provided expression is LeftHandSideExpression

        function isLeftHandSide(expr) {
            return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
        }

        function isAssignableLeftHandSide(expr) {
            return isLeftHandSide(expr) || expr.type === Syntax.ObjectPattern || expr.type === Syntax.ArrayPattern;
        }

        // 11.1.4 Array Initialiser

        function parseArrayInitialiser() {
            var elements = [], blocks = [], filter = null, tmp, possiblecomprehension = true,
                marker = markerCreate();

            expect('[');
            while (!match(']')) {
                if (lookahead.value === 'for' &&
                        lookahead.type === Token.Keyword) {
                    if (!possiblecomprehension) {
                        throwError({}, Messages.ComprehensionError);
                    }
                    matchKeyword('for');
                    tmp = parseForStatement({ignoreBody: true});
                    tmp.of = tmp.type === Syntax.ForOfStatement;
                    tmp.type = Syntax.ComprehensionBlock;
                    if (tmp.left.kind) { // can't be let or const
                        throwError({}, Messages.ComprehensionError);
                    }
                    blocks.push(tmp);
                } else if (lookahead.value === 'if' &&
                               lookahead.type === Token.Keyword) {
                    if (!possiblecomprehension) {
                        throwError({}, Messages.ComprehensionError);
                    }
                    expectKeyword('if');
                    expect('(');
                    filter = parseExpression();
                    expect(')');
                } else if (lookahead.value === ',' &&
                               lookahead.type === Token.Punctuator) {
                    possiblecomprehension = false; // no longer allowed.
                    lex();
                    elements.push(null);
                } else {
                    tmp = parseSpreadOrAssignmentExpression();
                    elements.push(tmp);
                    if (tmp && tmp.type === Syntax.SpreadElement) {
                        if (!match(']')) {
                            throwError({}, Messages.ElementAfterSpreadElement);
                        }
                    } else if (!(match(']') || matchKeyword('for') || matchKeyword('if'))) {
                        expect(','); // this lexes.
                        possiblecomprehension = false;
                    }
                }
            }

            expect(']');

            if (filter && !blocks.length) {
                throwError({}, Messages.ComprehensionRequiresBlock);
            }

            if (blocks.length) {
                if (elements.length !== 1) {
                    throwError({}, Messages.ComprehensionError);
                }
                return markerApply(marker, delegate.createComprehensionExpression(filter, blocks, elements[0]));
            }
            return markerApply(marker, delegate.createArrayExpression(elements));
        }

        // 11.1.5 Object Initialiser

        function parsePropertyFunction(options) {
            var previousStrict, previousYieldAllowed, previousAwaitAllowed,
                params, defaults, body, marker = markerCreate();

            previousStrict = strict;
            previousYieldAllowed = state.yieldAllowed;
            state.yieldAllowed = options.generator;
            previousAwaitAllowed = state.awaitAllowed;
            state.awaitAllowed = options.async;
            params = options.params || [];
            defaults = options.defaults || [];

            body = parseConciseBody();
            if (options.name && strict && isRestrictedWord(params[0].name)) {
                throwErrorTolerant(options.name, Messages.StrictParamName);
            }
            strict = previousStrict;
            state.yieldAllowed = previousYieldAllowed;
            state.awaitAllowed = previousAwaitAllowed;

            return markerApply(marker, delegate.createFunctionExpression(
                null,
                params,
                defaults,
                body,
                options.rest || null,
                options.generator,
                body.type !== Syntax.BlockStatement,
                options.async,
                options.returnType,
                options.typeParameters
            ));
        }

        function parsePropertyMethodFunction(options) {
            var previousStrict, tmp, method;

            previousStrict = strict;
            strict = true;

            tmp = parseParams();

            if (tmp.stricted) {
                throwErrorTolerant(tmp.stricted, tmp.message);
            }

            method = parsePropertyFunction({
                params: tmp.params,
                defaults: tmp.defaults,
                rest: tmp.rest,
                generator: options.generator,
                async: options.async,
                returnType: tmp.returnType,
                typeParameters: options.typeParameters
            });

            strict = previousStrict;

            return method;
        }

        function parseObjectPropertyKey() {
            var marker = markerCreate(),
                token = lex(),
                propertyKey,
                result;

            // Note: This function is called only from parseObjectProperty(), where
            // EOF and Punctuator tokens are already filtered out.

            if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
                if (strict && token.octal) {
                    throwErrorTolerant(token, Messages.StrictOctalLiteral);
                }
                return markerApply(marker, delegate.createLiteral(token));
            }

            if (token.type === Token.Punctuator && token.value === '[') {
                // For computed properties we should skip the [ and ], and
                // capture in marker only the assignment expression itself.
                marker = markerCreate();
                propertyKey = parseAssignmentExpression();
                result = markerApply(marker, propertyKey);
                expect(']');
                return result;
            }

            return markerApply(marker, delegate.createIdentifier(token.value));
        }

        function parseObjectProperty() {
            var token, key, id, param, computed,
                marker = markerCreate(), returnType, typeParameters;

            token = lookahead;
            computed = (token.value === '[' && token.type === Token.Punctuator);

            if (token.type === Token.Identifier || computed || matchAsync()) {
                id = parseObjectPropertyKey();

                if (match(':')) {
                    lex();

                    return markerApply(
                        marker,
                        delegate.createProperty(
                            'init',
                            id,
                            parseAssignmentExpression(),
                            false,
                            false,
                            computed
                        )
                    );
                }

                if (match('(') || match('<')) {
                    if (match('<')) {
                        typeParameters = parseTypeParameterDeclaration();
                    }
                    return markerApply(
                        marker,
                        delegate.createProperty(
                            'init',
                            id,
                            parsePropertyMethodFunction({
                                generator: false,
                                async: false,
                                typeParameters: typeParameters
                            }),
                            true,
                            false,
                            computed
                        )
                    );
                }

                // Property Assignment: Getter and Setter.

                if (token.value === 'get') {
                    computed = (lookahead.value === '[');
                    key = parseObjectPropertyKey();

                    expect('(');
                    expect(')');
                    if (match(':')) {
                        returnType = parseTypeAnnotation();
                    }

                    return markerApply(
                        marker,
                        delegate.createProperty(
                            'get',
                            key,
                            parsePropertyFunction({
                                generator: false,
                                async: false,
                                returnType: returnType
                            }),
                            false,
                            false,
                            computed
                        )
                    );
                }

                if (token.value === 'set') {
                    computed = (lookahead.value === '[');
                    key = parseObjectPropertyKey();

                    expect('(');
                    token = lookahead;
                    param = [ parseTypeAnnotatableIdentifier() ];
                    expect(')');
                    if (match(':')) {
                        returnType = parseTypeAnnotation();
                    }

                    return markerApply(
                        marker,
                        delegate.createProperty(
                            'set',
                            key,
                            parsePropertyFunction({
                                params: param,
                                generator: false,
                                async: false,
                                name: token,
                                returnType: returnType
                            }),
                            false,
                            false,
                            computed
                        )
                    );
                }

                if (token.value === 'async') {
                    computed = (lookahead.value === '[');
                    key = parseObjectPropertyKey();

                    if (match('<')) {
                        typeParameters = parseTypeParameterDeclaration();
                    }

                    return markerApply(
                        marker,
                        delegate.createProperty(
                            'init',
                            key,
                            parsePropertyMethodFunction({
                                generator: false,
                                async: true,
                                typeParameters: typeParameters
                            }),
                            true,
                            false,
                            computed
                        )
                    );
                }

                if (computed) {
                    // Computed properties can only be used with full notation.
                    throwUnexpected(lookahead);
                }

                return markerApply(
                    marker,
                    delegate.createProperty('init', id, id, false, true, false)
                );
            }

            if (token.type === Token.EOF || token.type === Token.Punctuator) {
                if (!match('*')) {
                    throwUnexpected(token);
                }
                lex();

                computed = (lookahead.type === Token.Punctuator && lookahead.value === '[');

                id = parseObjectPropertyKey();

                if (match('<')) {
                    typeParameters = parseTypeParameterDeclaration();
                }

                if (!match('(')) {
                    throwUnexpected(lex());
                }

                return markerApply(marker, delegate.createProperty(
                    'init',
                    id,
                    parsePropertyMethodFunction({
                        generator: true,
                        typeParameters: typeParameters
                    }),
                    true,
                    false,
                    computed
                ));
            }
            key = parseObjectPropertyKey();
            if (match(':')) {
                lex();
                return markerApply(marker, delegate.createProperty('init', key, parseAssignmentExpression(), false, false, false));
            }
            if (match('(') || match('<')) {
                if (match('<')) {
                    typeParameters = parseTypeParameterDeclaration();
                }
                return markerApply(marker, delegate.createProperty(
                    'init',
                    key,
                    parsePropertyMethodFunction({
                        generator: false,
                        typeParameters: typeParameters
                    }),
                    true,
                    false,
                    false
                ));
            }
            throwUnexpected(lex());
        }

        function parseObjectSpreadProperty() {
            var marker = markerCreate();
            expect('...');
            return markerApply(marker, delegate.createSpreadProperty(parseAssignmentExpression()));
        }

        function getFieldName(key) {
            var toString = String;
            if (key.type === Syntax.Identifier) {
                return key.name;
            }
            return toString(key.value);
        }

        function parseObjectInitialiser() {
            var properties = [], property, name, kind, storedKind, map = new StringMap(),
                marker = markerCreate(), toString = String;

            expect('{');

            while (!match('}')) {
                if (match('...')) {
                    property = parseObjectSpreadProperty();
                } else {
                    property = parseObjectProperty();

                    if (property.key.type === Syntax.Identifier) {
                        name = property.key.name;
                    } else {
                        name = toString(property.key.value);
                    }
                    kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;

                    if (map.has(name)) {
                        storedKind = map.get(name);
                        if (storedKind === PropertyKind.Data) {
                            if (strict && kind === PropertyKind.Data) {
                                throwErrorTolerant({}, Messages.StrictDuplicateProperty);
                            } else if (kind !== PropertyKind.Data) {
                                throwErrorTolerant({}, Messages.AccessorDataProperty);
                            }
                        } else {
                            if (kind === PropertyKind.Data) {
                                throwErrorTolerant({}, Messages.AccessorDataProperty);
                            } else if (storedKind & kind) {
                                throwErrorTolerant({}, Messages.AccessorGetSet);
                            }
                        }
                        map.set(name, storedKind | kind);
                    } else {
                        map.set(name, kind);
                    }
                }

                properties.push(property);

                if (!match('}')) {
                    expect(',');
                }
            }

            expect('}');

            return markerApply(marker, delegate.createObjectExpression(properties));
        }

        function parseTemplateElement(option) {
            var marker, token;

            if (lookahead.type !== Token.Template || (option.head && !lookahead.head)) {
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            marker = markerCreate();
            token = lex();

            if (strict && token.octal) {
                throwError(token, Messages.StrictOctalLiteral);
            }
            return markerApply(marker, delegate.createTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail));
        }

        function parseTemplateLiteral() {
            var quasi, quasis, expressions, marker = markerCreate();

            quasi = parseTemplateElement({ head: true });
            quasis = [ quasi ];
            expressions = [];

            while (!quasi.tail) {
                expressions.push(parseExpression());
                quasi = parseTemplateElement({ head: false });
                quasis.push(quasi);
            }

            return markerApply(marker, delegate.createTemplateLiteral(quasis, expressions));
        }

        // 11.1.6 The Grouping Operator

        function parseGroupExpression() {
            var expr, marker, typeAnnotation;

            expect('(');

            ++state.parenthesizedCount;

            marker = markerCreate();

            expr = parseExpression();

            if (match(':')) {
                typeAnnotation = parseTypeAnnotation();
                expr = markerApply(marker, delegate.createTypeCast(
                    expr,
                    typeAnnotation
                ));
            }

            expect(')');

            return expr;
        }

        function matchAsyncFuncExprOrDecl() {
            var token;

            if (matchAsync()) {
                token = lookahead2();
                if (token.type === Token.Keyword && token.value === 'function') {
                    return true;
                }
            }

            return false;
        }

        // 11.1 Primary Expressions

        function parsePrimaryExpression() {
            var marker, type, token, expr;

            type = lookahead.type;

            if (type === Token.Identifier) {
                marker = markerCreate();
                return markerApply(marker, delegate.createIdentifier(lex().value));
            }

            if (type === Token.StringLiteral || type === Token.NumericLiteral) {
                if (strict && lookahead.octal) {
                    throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
                }
                marker = markerCreate();
                return markerApply(marker, delegate.createLiteral(lex()));
            }

            if (type === Token.Keyword) {
                if (matchKeyword('this')) {
                    marker = markerCreate();
                    lex();
                    return markerApply(marker, delegate.createThisExpression());
                }

                if (matchKeyword('function')) {
                    return parseFunctionExpression();
                }

                if (matchKeyword('class')) {
                    return parseClassExpression();
                }

                if (matchKeyword('super')) {
                    marker = markerCreate();
                    lex();
                    return markerApply(marker, delegate.createIdentifier('super'));
                }
            }

            if (type === Token.BooleanLiteral) {
                marker = markerCreate();
                token = lex();
                token.value = (token.value === 'true');
                return markerApply(marker, delegate.createLiteral(token));
            }

            if (type === Token.NullLiteral) {
                marker = markerCreate();
                token = lex();
                token.value = null;
                return markerApply(marker, delegate.createLiteral(token));
            }

            if (match('[')) {
                return parseArrayInitialiser();
            }

            if (match('{')) {
                return parseObjectInitialiser();
            }

            if (match('(')) {
                return parseGroupExpression();
            }

            if (match('/') || match('/=')) {
                marker = markerCreate();
                expr = delegate.createLiteral(scanRegExp());
                peek();
                return markerApply(marker, expr);
            }

            if (type === Token.Template) {
                return parseTemplateLiteral();
            }

            if (match('<')) {
                return parseJSXElement();
            }

            throwUnexpected(lex());
        }

        // 11.2 Left-Hand-Side Expressions

        function parseArguments() {
            var args = [], arg;

            expect('(');

            if (!match(')')) {
                while (index < length) {
                    arg = parseSpreadOrAssignmentExpression();
                    args.push(arg);

                    if (arg.type === Syntax.SpreadElement) {
                        if (match(')')) {
                            break;
                        } else {
                            throwError({}, Messages.ElementAfterSpreadElement);
                        }
                    }

                    if (match(')')) {
                        break;
                    } else {
                        expect(',');
                        if (match(')')) {
                            break;
                        }
                    }
                }
            }

            expect(')');

            return args;
        }

        function parseSpreadOrAssignmentExpression() {
            if (match('...')) {
                var marker = markerCreate();
                lex();
                return markerApply(marker, delegate.createSpreadElement(parseAssignmentExpression()));
            }
            return parseAssignmentExpression();
        }

        function parseNonComputedProperty() {
            var marker = markerCreate(),
                token = lex();

            if (!isIdentifierName(token)) {
                throwUnexpected(token);
            }

            return markerApply(marker, delegate.createIdentifier(token.value));
        }

        function parseNonComputedMember() {
            expect('.');

            return parseNonComputedProperty();
        }

        function parseComputedMember() {
            var expr;

            expect('[');

            expr = parseExpression();

            expect(']');

            return expr;
        }

        function parseNewExpression() {
            var callee, args, marker = markerCreate();

            expectKeyword('new');
            callee = parseLeftHandSideExpression();
            args = match('(') ? parseArguments() : [];

            return markerApply(marker, delegate.createNewExpression(callee, args));
        }

        function parseLeftHandSideExpressionAllowCall() {
            var expr, args, marker = markerCreate();

            expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();

            while (match('.') || match('[') || match('(') || (lookahead.type === Token.Template && lookahead.head)) {
                if (match('(')) {
                    args = parseArguments();
                    expr = markerApply(marker, delegate.createCallExpression(expr, args));
                } else if (match('[')) {
                    expr = markerApply(marker, delegate.createMemberExpression('[', expr, parseComputedMember()));
                } else if (match('.')) {
                    expr = markerApply(marker, delegate.createMemberExpression('.', expr, parseNonComputedMember()));
                } else {
                    expr = markerApply(marker, delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()));
                }
            }

            return expr;
        }

        function parseLeftHandSideExpression() {
            var expr, marker = markerCreate();

            expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();

            while (match('.') || match('[') || (lookahead.type === Token.Template && lookahead.head)) {
                if (match('[')) {
                    expr = markerApply(marker, delegate.createMemberExpression('[', expr, parseComputedMember()));
                } else if (match('.')) {
                    expr = markerApply(marker, delegate.createMemberExpression('.', expr, parseNonComputedMember()));
                } else {
                    expr = markerApply(marker, delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()));
                }
            }

            return expr;
        }

        // 11.3 Postfix Expressions

        function parsePostfixExpression() {
            var marker = markerCreate(),
                expr = parseLeftHandSideExpressionAllowCall(),
                token;

            if (lookahead.type !== Token.Punctuator) {
                return expr;
            }

            if ((match('++') || match('--')) && !peekLineTerminator()) {
                // 11.3.1, 11.3.2
                if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
                    throwErrorTolerant({}, Messages.StrictLHSPostfix);
                }

                if (!isLeftHandSide(expr)) {
                    throwError({}, Messages.InvalidLHSInAssignment);
                }

                token = lex();
                expr = markerApply(marker, delegate.createPostfixExpression(token.value, expr));
            }

            return expr;
        }

        // 11.4 Unary Operators

        function parseUnaryExpression() {
            var marker, token, expr;

            if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
                return parsePostfixExpression();
            }

            if (match('++') || match('--')) {
                marker = markerCreate();
                token = lex();
                expr = parseUnaryExpression();
                // 11.4.4, 11.4.5
                if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
                    throwErrorTolerant({}, Messages.StrictLHSPrefix);
                }

                if (!isLeftHandSide(expr)) {
                    throwError({}, Messages.InvalidLHSInAssignment);
                }

                return markerApply(marker, delegate.createUnaryExpression(token.value, expr));
            }

            if (match('+') || match('-') || match('~') || match('!')) {
                marker = markerCreate();
                token = lex();
                expr = parseUnaryExpression();
                return markerApply(marker, delegate.createUnaryExpression(token.value, expr));
            }

            if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
                marker = markerCreate();
                token = lex();
                expr = parseUnaryExpression();
                expr = markerApply(marker, delegate.createUnaryExpression(token.value, expr));
                if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
                    throwErrorTolerant({}, Messages.StrictDelete);
                }
                return expr;
            }

            return parsePostfixExpression();
        }

        function binaryPrecedence(token, allowIn) {
            var prec = 0;

            if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
                return 0;
            }

            switch (token.value) {
            case '||':
                prec = 1;
                break;

            case '&&':
                prec = 2;
                break;

            case '|':
                prec = 3;
                break;

            case '^':
                prec = 4;
                break;

            case '&':
                prec = 5;
                break;

            case '==':
            case '!=':
            case '===':
            case '!==':
                prec = 6;
                break;

            case '<':
            case '>':
            case '<=':
            case '>=':
            case 'instanceof':
                prec = 7;
                break;

            case 'in':
                prec = allowIn ? 7 : 0;
                break;

            case '<<':
            case '>>':
            case '>>>':
                prec = 8;
                break;

            case '+':
            case '-':
                prec = 9;
                break;

            case '*':
            case '/':
            case '%':
                prec = 11;
                break;

            default:
                break;
            }

            return prec;
        }

        // 11.5 Multiplicative Operators
        // 11.6 Additive Operators
        // 11.7 Bitwise Shift Operators
        // 11.8 Relational Operators
        // 11.9 Equality Operators
        // 11.10 Binary Bitwise Operators
        // 11.11 Binary Logical Operators

        function parseBinaryExpression() {
            var expr, token, prec, previousAllowIn, stack, right, operator, left, i,
                marker, markers;

            previousAllowIn = state.allowIn;
            state.allowIn = true;

            marker = markerCreate();
            left = parseUnaryExpression();

            token = lookahead;
            prec = binaryPrecedence(token, previousAllowIn);
            if (prec === 0) {
                return left;
            }
            token.prec = prec;
            lex();

            markers = [marker, markerCreate()];
            right = parseUnaryExpression();

            stack = [left, token, right];

            while ((prec = binaryPrecedence(lookahead, previousAllowIn)) > 0) {

                // Reduce: make a binary expression from the three topmost entries.
                while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
                    right = stack.pop();
                    operator = stack.pop().value;
                    left = stack.pop();
                    expr = delegate.createBinaryExpression(operator, left, right);
                    markers.pop();
                    marker = markers.pop();
                    markerApply(marker, expr);
                    stack.push(expr);
                    markers.push(marker);
                }

                // Shift.
                token = lex();
                token.prec = prec;
                stack.push(token);
                markers.push(markerCreate());
                expr = parseUnaryExpression();
                stack.push(expr);
            }

            state.allowIn = previousAllowIn;

            // Final reduce to clean-up the stack.
            i = stack.length - 1;
            expr = stack[i];
            markers.pop();
            while (i > 1) {
                expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
                i -= 2;
                marker = markers.pop();
                markerApply(marker, expr);
            }

            return expr;
        }

        // 11.12 Conditional Operator

        function parseConditionalExpression() {
            var expr, previousAllowIn, consequent, alternate, marker = markerCreate();
            expr = parseBinaryExpression();

            if (match('?')) {
                lex();
                previousAllowIn = state.allowIn;
                state.allowIn = true;
                consequent = parseAssignmentExpression();
                state.allowIn = previousAllowIn;
                expect(':');
                alternate = parseAssignmentExpression();

                expr = markerApply(marker, delegate.createConditionalExpression(expr, consequent, alternate));
            }

            return expr;
        }

        // 11.13 Assignment Operators

        // 12.14.5 AssignmentPattern

        function reinterpretAsAssignmentBindingPattern(expr) {
            var i, len, property, element;

            if (expr.type === Syntax.ObjectExpression) {
                expr.type = Syntax.ObjectPattern;
                for (i = 0, len = expr.properties.length; i < len; i += 1) {
                    property = expr.properties[i];
                    if (property.type === Syntax.SpreadProperty) {
                        if (i < len - 1) {
                            throwError({}, Messages.PropertyAfterSpreadProperty);
                        }
                        reinterpretAsAssignmentBindingPattern(property.argument);
                    } else {
                        if (property.kind !== 'init') {
                            throwError({}, Messages.InvalidLHSInAssignment);
                        }
                        reinterpretAsAssignmentBindingPattern(property.value);
                    }
                }
            } else if (expr.type === Syntax.ArrayExpression) {
                expr.type = Syntax.ArrayPattern;
                for (i = 0, len = expr.elements.length; i < len; i += 1) {
                    element = expr.elements[i];
                    /* istanbul ignore else */
                    if (element) {
                        reinterpretAsAssignmentBindingPattern(element);
                    }
                }
            } else if (expr.type === Syntax.Identifier) {
                if (isRestrictedWord(expr.name)) {
                    throwError({}, Messages.InvalidLHSInAssignment);
                }
            } else if (expr.type === Syntax.SpreadElement) {
                reinterpretAsAssignmentBindingPattern(expr.argument);
                if (expr.argument.type === Syntax.ObjectPattern) {
                    throwError({}, Messages.ObjectPatternAsSpread);
                }
            } else {
                /* istanbul ignore else */
                if (expr.type !== Syntax.MemberExpression && expr.type !== Syntax.CallExpression && expr.type !== Syntax.NewExpression) {
                    throwError({}, Messages.InvalidLHSInAssignment);
                }
            }
        }

        // 13.2.3 BindingPattern

        function reinterpretAsDestructuredParameter(options, expr) {
            var i, len, property, element;

            if (expr.type === Syntax.ObjectExpression) {
                expr.type = Syntax.ObjectPattern;
                for (i = 0, len = expr.properties.length; i < len; i += 1) {
                    property = expr.properties[i];
                    if (property.type === Syntax.SpreadProperty) {
                        if (i < len - 1) {
                            throwError({}, Messages.PropertyAfterSpreadProperty);
                        }
                        reinterpretAsDestructuredParameter(options, property.argument);
                    } else {
                        if (property.kind !== 'init') {
                            throwError({}, Messages.InvalidLHSInFormalsList);
                        }
                        reinterpretAsDestructuredParameter(options, property.value);
                    }
                }
            } else if (expr.type === Syntax.ArrayExpression) {
                expr.type = Syntax.ArrayPattern;
                for (i = 0, len = expr.elements.length; i < len; i += 1) {
                    element = expr.elements[i];
                    if (element) {
                        reinterpretAsDestructuredParameter(options, element);
                    }
                }
            } else if (expr.type === Syntax.Identifier) {
                validateParam(options, expr, expr.name);
            } else if (expr.type === Syntax.SpreadElement) {
                // BindingRestElement only allows BindingIdentifier
                if (expr.argument.type !== Syntax.Identifier) {
                    throwError({}, Messages.InvalidLHSInFormalsList);
                }
                validateParam(options, expr.argument, expr.argument.name);
            } else {
                throwError({}, Messages.InvalidLHSInFormalsList);
            }
        }

        function reinterpretAsCoverFormalsList(expressions) {
            var i, len, param, params, defaults, defaultCount, options, rest;

            params = [];
            defaults = [];
            defaultCount = 0;
            rest = null;
            options = {
                paramSet: new StringMap()
            };

            for (i = 0, len = expressions.length; i < len; i += 1) {
                param = expressions[i];
                if (param.type === Syntax.Identifier) {
                    params.push(param);
                    defaults.push(null);
                    validateParam(options, param, param.name);
                } else if (param.type === Syntax.ObjectExpression || param.type === Syntax.ArrayExpression) {
                    reinterpretAsDestructuredParameter(options, param);
                    params.push(param);
                    defaults.push(null);
                } else if (param.type === Syntax.SpreadElement) {
                    assert(i === len - 1, 'It is guaranteed that SpreadElement is last element by parseExpression');
                    if (param.argument.type !== Syntax.Identifier) {
                        throwError({}, Messages.InvalidLHSInFormalsList);
                    }
                    reinterpretAsDestructuredParameter(options, param.argument);
                    rest = param.argument;
                } else if (param.type === Syntax.AssignmentExpression) {
                    params.push(param.left);
                    defaults.push(param.right);
                    ++defaultCount;
                    validateParam(options, param.left, param.left.name);
                } else {
                    return null;
                }
            }

            if (options.message === Messages.StrictParamDupe) {
                throwError(
                    strict ? options.stricted : options.firstRestricted,
                    options.message
                );
            }

            if (defaultCount === 0) {
                defaults = [];
            }

            return {
                params: params,
                defaults: defaults,
                rest: rest,
                stricted: options.stricted,
                firstRestricted: options.firstRestricted,
                message: options.message
            };
        }

        function parseArrowFunctionExpression(options, marker) {
            var previousStrict, previousYieldAllowed, previousAwaitAllowed, body;

            expect('=>');

            previousStrict = strict;
            previousYieldAllowed = state.yieldAllowed;
            state.yieldAllowed = false;
            previousAwaitAllowed = state.awaitAllowed;
            state.awaitAllowed = !!options.async;
            body = parseConciseBody();

            if (strict && options.firstRestricted) {
                throwError(options.firstRestricted, options.message);
            }
            if (strict && options.stricted) {
                throwErrorTolerant(options.stricted, options.message);
            }

            strict = previousStrict;
            state.yieldAllowed = previousYieldAllowed;
            state.awaitAllowed = previousAwaitAllowed;

            return markerApply(marker, delegate.createArrowFunctionExpression(
                options.params,
                options.defaults,
                body,
                options.rest,
                body.type !== Syntax.BlockStatement,
                !!options.async
            ));
        }

        function parseAssignmentExpression() {
            var marker, expr, token, params, oldParenthesizedCount,
                startsWithParen = false, backtrackToken = lookahead,
                possiblyAsync = false;

            if (matchYield()) {
                return parseYieldExpression();
            }

            if (matchAwait()) {
                return parseAwaitExpression();
            }

            oldParenthesizedCount = state.parenthesizedCount;

            marker = markerCreate();

            if (matchAsyncFuncExprOrDecl()) {
                return parseFunctionExpression();
            }

            if (matchAsync()) {
                // We can't be completely sure that this 'async' token is
                // actually a contextual keyword modifying a function
                // expression, so we might have to un-lex() it later by
                // calling rewind(backtrackToken).
                possiblyAsync = true;
                lex();
            }

            if (match('(')) {
                token = lookahead2();
                if ((token.type === Token.Punctuator && token.value === ')') || token.value === '...') {
                    params = parseParams();
                    if (!match('=>')) {
                        throwUnexpected(lex());
                    }
                    params.async = possiblyAsync;
                    return parseArrowFunctionExpression(params, marker);
                }
                startsWithParen = true;
            }

            token = lookahead;

            // If the 'async' keyword is not followed by a '(' character or an
            // identifier, then it can't be an arrow function modifier, and we
            // should interpret it as a normal identifer.
            if (possiblyAsync && !match('(') && token.type !== Token.Identifier) {
                possiblyAsync = false;
                rewind(backtrackToken);
            }

            expr = parseConditionalExpression();

            if (match('=>') &&
                    (state.parenthesizedCount === oldParenthesizedCount ||
                    state.parenthesizedCount === (oldParenthesizedCount + 1))) {
                if (expr.type === Syntax.Identifier) {
                    params = reinterpretAsCoverFormalsList([ expr ]);
                } else if (expr.type === Syntax.AssignmentExpression ||
                        expr.type === Syntax.ArrayExpression ||
                        expr.type === Syntax.ObjectExpression) {
                    if (!startsWithParen) {
                        throwUnexpected(lex());
                    }
                    params = reinterpretAsCoverFormalsList([ expr ]);
                } else if (expr.type === Syntax.SequenceExpression) {
                    params = reinterpretAsCoverFormalsList(expr.expressions);
                }
                if (params) {
                    params.async = possiblyAsync;
                    return parseArrowFunctionExpression(params, marker);
                }
            }

            // If we haven't returned by now, then the 'async' keyword was not
            // a function modifier, and we should rewind and interpret it as a
            // normal identifier.
            if (possiblyAsync) {
                possiblyAsync = false;
                rewind(backtrackToken);
                expr = parseConditionalExpression();
            }

            if (matchAssign()) {
                // 11.13.1
                if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
                    throwErrorTolerant(token, Messages.StrictLHSAssignment);
                }

                // ES.next draf 11.13 Runtime Semantics step 1
                if (match('=') && (expr.type === Syntax.ObjectExpression || expr.type === Syntax.ArrayExpression)) {
                    reinterpretAsAssignmentBindingPattern(expr);
                } else if (!isLeftHandSide(expr)) {
                    throwError({}, Messages.InvalidLHSInAssignment);
                }

                expr = markerApply(marker, delegate.createAssignmentExpression(lex().value, expr, parseAssignmentExpression()));
            }

            return expr;
        }

        // 11.14 Comma Operator

        function parseExpression() {
            var marker, expr, expressions, sequence, spreadFound, possibleArrow;

            marker = markerCreate();
            expr = parseAssignmentExpression();
            expressions = [ expr ];

            if (match(',')) {
                while (index < length) {
                    if (!match(',')) {
                        break;
                    }

                    lex();

                    if (match(')')) {
                        possibleArrow = lookahead2();
                        if (
                            possibleArrow.type === Token.Punctuator &&
                            possibleArrow.value === '=>'
                        ) {
                            break;
                        }
                    }

                    expr = parseSpreadOrAssignmentExpression();
                    expressions.push(expr);

                    if (expr.type === Syntax.SpreadElement) {
                        spreadFound = true;
                        if (!match(')')) {
                            throwError({}, Messages.ElementAfterSpreadElement);
                        }
                        break;
                    }
                }

                if (expressions.length > 1) {
                    sequence = markerApply(marker, delegate.createSequenceExpression(expressions));
                }
            }

            if (spreadFound && lookahead2().value !== '=>') {
                throwError({}, Messages.IllegalSpread);
            }

            return sequence || expr;
        }

        // 12.1 Block

        function parseStatementList() {
            var list = [],
                statement;

            while (index < length) {
                if (match('}')) {
                    break;
                }
                statement = parseSourceElement();
                if (typeof statement === 'undefined') {
                    break;
                }
                list.push(statement);
            }

            return list;
        }

        function parseBlock() {
            var block, marker = markerCreate();

            expect('{');

            block = parseStatementList();

            expect('}');

            return markerApply(marker, delegate.createBlockStatement(block));
        }

        // 12.2 Variable Statement

        function parseTypeParameterDeclaration() {
            var marker = markerCreate(), paramTypes = [];

            expect('<');
            while (!match('>')) {
                paramTypes.push(parseTypeAnnotatableIdentifier());
                if (!match('>')) {
                    expect(',');
                }
            }
            expect('>');

            return markerApply(marker, delegate.createTypeParameterDeclaration(
                paramTypes
            ));
        }

        function parseTypeParameterInstantiation() {
            var marker = markerCreate(), oldInType = state.inType, paramTypes = [];

            state.inType = true;

            expect('<');
            while (!match('>')) {
                paramTypes.push(parseType());
                if (!match('>')) {
                    expect(',');
                }
            }
            expect('>');

            state.inType = oldInType;

            return markerApply(marker, delegate.createTypeParameterInstantiation(
                paramTypes
            ));
        }

        function parseObjectTypeIndexer(marker, isStatic) {
            var id, key, value;

            expect('[');
            id = parseObjectPropertyKey();
            expect(':');
            key = parseType();
            expect(']');
            expect(':');
            value = parseType();

            return markerApply(marker, delegate.createObjectTypeIndexer(
                id,
                key,
                value,
                isStatic
            ));
        }

        function parseObjectTypeMethodish(marker) {
            var params = [], rest = null, returnType, typeParameters = null;
            if (match('<')) {
                typeParameters = parseTypeParameterDeclaration();
            }

            expect('(');
            while (lookahead.type === Token.Identifier) {
                params.push(parseFunctionTypeParam());
                if (!match(')')) {
                    expect(',');
                }
            }

            if (match('...')) {
                lex();
                rest = parseFunctionTypeParam();
            }
            expect(')');
            expect(':');
            returnType = parseType();

            return markerApply(marker, delegate.createFunctionTypeAnnotation(
                params,
                returnType,
                rest,
                typeParameters
            ));
        }

        function parseObjectTypeMethod(marker, isStatic, key) {
            var optional = false, value;
            value = parseObjectTypeMethodish(marker);

            return markerApply(marker, delegate.createObjectTypeProperty(
                key,
                value,
                optional,
                isStatic
            ));
        }

        function parseObjectTypeCallProperty(marker, isStatic) {
            var valueMarker = markerCreate();
            return markerApply(marker, delegate.createObjectTypeCallProperty(
                parseObjectTypeMethodish(valueMarker),
                isStatic
            ));
        }

        function parseObjectType(allowStatic) {
            var callProperties = [], indexers = [], marker, optional = false,
                properties = [], propertyKey, propertyTypeAnnotation,
                token, isStatic, matchStatic;

            expect('{');

            while (!match('}')) {
                marker = markerCreate();
                matchStatic =
                       strict
                       ? matchKeyword('static')
                       : matchContextualKeyword('static');

                if (allowStatic && matchStatic) {
                    token = lex();
                    isStatic = true;
                }

                if (match('[')) {
                    indexers.push(parseObjectTypeIndexer(marker, isStatic));
                } else if (match('(') || match('<')) {
                    callProperties.push(parseObjectTypeCallProperty(marker, allowStatic));
                } else {
                    if (isStatic && match(':')) {
                        propertyKey = markerApply(marker, delegate.createIdentifier(token));
                        throwErrorTolerant(token, Messages.StrictReservedWord);
                    } else {
                        propertyKey = parseObjectPropertyKey();
                    }
                    if (match('<') || match('(')) {
                        // This is a method property
                        properties.push(parseObjectTypeMethod(marker, isStatic, propertyKey));
                    } else {
                        if (match('?')) {
                            lex();
                            optional = true;
                        }
                        expect(':');
                        propertyTypeAnnotation = parseType();
                        properties.push(markerApply(marker, delegate.createObjectTypeProperty(
                            propertyKey,
                            propertyTypeAnnotation,
                            optional,
                            isStatic
                        )));
                    }
                }

                if (match(';') || match(',')) {
                    lex();
                } else if (!match('}')) {
                    throwUnexpected(lookahead);
                }
            }

            expect('}');

            return delegate.createObjectTypeAnnotation(
                properties,
                indexers,
                callProperties
            );
        }

        function parseGenericType() {
            var marker = markerCreate(),
                typeParameters = null, typeIdentifier;

            typeIdentifier = parseVariableIdentifier();

            while (match('.')) {
                expect('.');
                typeIdentifier = markerApply(marker, delegate.createQualifiedTypeIdentifier(
                    typeIdentifier,
                    parseVariableIdentifier()
                ));
            }

            if (match('<')) {
                typeParameters = parseTypeParameterInstantiation();
            }

            return markerApply(marker, delegate.createGenericTypeAnnotation(
                typeIdentifier,
                typeParameters
            ));
        }

        function parseVoidType() {
            var marker = markerCreate();
            expectKeyword('void');
            return markerApply(marker, delegate.createVoidTypeAnnotation());
        }

        function parseTypeofType() {
            var argument, marker = markerCreate();
            expectKeyword('typeof');
            argument = parsePrimaryType();
            return markerApply(marker, delegate.createTypeofTypeAnnotation(
                argument
            ));
        }

        function parseTupleType() {
            var marker = markerCreate(), types = [];
            expect('[');
            // We allow trailing commas
            while (index < length && !match(']')) {
                types.push(parseType());
                if (match(']')) {
                    break;
                }
                expect(',');
            }
            expect(']');
            return markerApply(marker, delegate.createTupleTypeAnnotation(
                types
            ));
        }

        function parseFunctionTypeParam() {
            var marker = markerCreate(), name, optional = false, typeAnnotation;
            name = parseVariableIdentifier();
            if (match('?')) {
                lex();
                optional = true;
            }
            expect(':');
            typeAnnotation = parseType();
            return markerApply(marker, delegate.createFunctionTypeParam(
                name,
                typeAnnotation,
                optional
            ));
        }

        function parseFunctionTypeParams() {
            var ret = { params: [], rest: null };
            while (lookahead.type === Token.Identifier) {
                ret.params.push(parseFunctionTypeParam());
                if (!match(')')) {
                    expect(',');
                }
            }

            if (match('...')) {
                lex();
                ret.rest = parseFunctionTypeParam();
            }
            return ret;
        }

        // The parsing of types roughly parallels the parsing of expressions, and
        // primary types are kind of like primary expressions...they're the
        // primitives with which other types are constructed.
        function parsePrimaryType() {
            var params = null, returnType = null,
                marker = markerCreate(), rest = null, tmp,
                typeParameters, token, type, isGroupedType = false;

            switch (lookahead.type) {
            case Token.Identifier:
                switch (lookahead.value) {
                case 'any':
                    lex();
                    return markerApply(marker, delegate.createAnyTypeAnnotation());
                case 'bool':  // fallthrough
                case 'boolean':
                    lex();
                    return markerApply(marker, delegate.createBooleanTypeAnnotation());
                case 'number':
                    lex();
                    return markerApply(marker, delegate.createNumberTypeAnnotation());
                case 'string':
                    lex();
                    return markerApply(marker, delegate.createStringTypeAnnotation());
                }
                return markerApply(marker, parseGenericType());
            case Token.Punctuator:
                switch (lookahead.value) {
                case '{':
                    return markerApply(marker, parseObjectType());
                case '[':
                    return parseTupleType();
                case '<':
                    typeParameters = parseTypeParameterDeclaration();
                    expect('(');
                    tmp = parseFunctionTypeParams();
                    params = tmp.params;
                    rest = tmp.rest;
                    expect(')');

                    expect('=>');

                    returnType = parseType();

                    return markerApply(marker, delegate.createFunctionTypeAnnotation(
                        params,
                        returnType,
                        rest,
                        typeParameters
                    ));
                case '(':
                    lex();
                    // Check to see if this is actually a grouped type
                    if (!match(')') && !match('...')) {
                        if (lookahead.type === Token.Identifier) {
                            token = lookahead2();
                            isGroupedType = token.value !== '?' && token.value !== ':';
                        } else {
                            isGroupedType = true;
                        }
                    }

                    if (isGroupedType) {
                        type = parseType();
                        expect(')');

                        // If we see a => next then someone was probably confused about
                        // function types, so we can provide a better error message
                        if (match('=>')) {
                            throwError({}, Messages.ConfusedAboutFunctionType);
                        }

                        return type;
                    }

                    tmp = parseFunctionTypeParams();
                    params = tmp.params;
                    rest = tmp.rest;

                    expect(')');

                    expect('=>');

                    returnType = parseType();

                    return markerApply(marker, delegate.createFunctionTypeAnnotation(
                        params,
                        returnType,
                        rest,
                        null /* typeParameters */
                    ));
                }
                break;
            case Token.Keyword:
                switch (lookahead.value) {
                case 'void':
                    return markerApply(marker, parseVoidType());
                case 'typeof':
                    return markerApply(marker, parseTypeofType());
                }
                break;
            case Token.StringLiteral:
                token = lex();
                if (token.octal) {
                    throwError(token, Messages.StrictOctalLiteral);
                }
                return markerApply(marker, delegate.createStringLiteralTypeAnnotation(
                    token
                ));
            }

            throwUnexpected(lookahead);
        }

        function parsePostfixType() {
            var marker = markerCreate(), t = parsePrimaryType();
            if (match('[')) {
                expect('[');
                expect(']');
                return markerApply(marker, delegate.createArrayTypeAnnotation(t));
            }
            return t;
        }

        function parsePrefixType() {
            var marker = markerCreate();
            if (match('?')) {
                lex();
                return markerApply(marker, delegate.createNullableTypeAnnotation(
                    parsePrefixType()
                ));
            }
            return parsePostfixType();
        }

        function parseIntersectionType() {
            var marker = markerCreate(), type, types;
            type = parsePrefixType();
            types = [type];
            while (match('&')) {
                lex();
                types.push(parsePrefixType());
            }

            return types.length === 1 ?
                    type :
                    markerApply(marker, delegate.createIntersectionTypeAnnotation(
                        types
                    ));
        }

        function parseUnionType() {
            var marker = markerCreate(), type, types;
            type = parseIntersectionType();
            types = [type];
            while (match('|')) {
                lex();
                types.push(parseIntersectionType());
            }
            return types.length === 1 ?
                    type :
                    markerApply(marker, delegate.createUnionTypeAnnotation(
                        types
                    ));
        }

        function parseType() {
            var oldInType = state.inType, type;
            state.inType = true;

            type = parseUnionType();

            state.inType = oldInType;
            return type;
        }

        function parseTypeAnnotation() {
            var marker = markerCreate(), type;

            expect(':');
            type = parseType();

            return markerApply(marker, delegate.createTypeAnnotation(type));
        }

        function parseVariableIdentifier() {
            var marker = markerCreate(),
                token = lex();

            if (token.type !== Token.Identifier) {
                throwUnexpected(token);
            }

            return markerApply(marker, delegate.createIdentifier(token.value));
        }

        function parseTypeAnnotatableIdentifier(requireTypeAnnotation, canBeOptionalParam) {
            var marker = markerCreate(),
                ident = parseVariableIdentifier(),
                isOptionalParam = false;

            if (canBeOptionalParam && match('?')) {
                expect('?');
                isOptionalParam = true;
            }

            if (requireTypeAnnotation || match(':')) {
                ident.typeAnnotation = parseTypeAnnotation();
                ident = markerApply(marker, ident);
            }

            if (isOptionalParam) {
                ident.optional = true;
                ident = markerApply(marker, ident);
            }

            return ident;
        }

        function parseVariableDeclaration(kind) {
            var id,
                marker = markerCreate(),
                init = null,
                typeAnnotationMarker = markerCreate();
            if (match('{')) {
                id = parseObjectInitialiser();
                reinterpretAsAssignmentBindingPattern(id);
                if (match(':')) {
                    id.typeAnnotation = parseTypeAnnotation();
                    markerApply(typeAnnotationMarker, id);
                }
            } else if (match('[')) {
                id = parseArrayInitialiser();
                reinterpretAsAssignmentBindingPattern(id);
                if (match(':')) {
                    id.typeAnnotation = parseTypeAnnotation();
                    markerApply(typeAnnotationMarker, id);
                }
            } else {
                /* istanbul ignore next */
                id = state.allowKeyword ? parseNonComputedProperty() : parseTypeAnnotatableIdentifier();
                // 12.2.1
                if (strict && isRestrictedWord(id.name)) {
                    throwErrorTolerant({}, Messages.StrictVarName);
                }
            }

            if (kind === 'const') {
                if (!match('=')) {
                    throwError({}, Messages.NoUninitializedConst);
                }
                expect('=');
                init = parseAssignmentExpression();
            } else if (match('=')) {
                lex();
                init = parseAssignmentExpression();
            }

            return markerApply(marker, delegate.createVariableDeclarator(id, init));
        }

        function parseVariableDeclarationList(kind) {
            var list = [];

            do {
                list.push(parseVariableDeclaration(kind));
                if (!match(',')) {
                    break;
                }
                lex();
            } while (index < length);

            return list;
        }

        function parseVariableStatement() {
            var declarations, marker = markerCreate();

            expectKeyword('var');

            declarations = parseVariableDeclarationList();

            consumeSemicolon();

            return markerApply(marker, delegate.createVariableDeclaration(declarations, 'var'));
        }

        // kind may be `const` or `let`
        // Both are experimental and not in the specification yet.
        // see http://wiki.ecmascript.org/doku.php?id=harmony:const
        // and http://wiki.ecmascript.org/doku.php?id=harmony:let
        function parseConstLetDeclaration(kind) {
            var declarations, marker = markerCreate();

            expectKeyword(kind);

            declarations = parseVariableDeclarationList(kind);

            consumeSemicolon();

            return markerApply(marker, delegate.createVariableDeclaration(declarations, kind));
        }

        // people.mozilla.org/~jorendorff/es6-draft.html

        function parseModuleSpecifier() {
            var marker = markerCreate(),
                specifier;

            if (lookahead.type !== Token.StringLiteral) {
                throwError({}, Messages.InvalidModuleSpecifier);
            }
            specifier = delegate.createLiteral(lex());
            return markerApply(marker, specifier);
        }

        function parseExportBatchSpecifier() {
            var marker = markerCreate();
            expect('*');
            return markerApply(marker, delegate.createExportBatchSpecifier());
        }

        function parseExportSpecifier() {
            var id, name = null, marker = markerCreate();
            if (matchKeyword('default')) {
                lex();
                id = markerApply(marker, delegate.createIdentifier('default'));
                // export {default} from "something";
            } else {
                id = parseVariableIdentifier();
            }
            if (matchContextualKeyword('as')) {
                lex();
                name = parseNonComputedProperty();
            }

            return markerApply(marker, delegate.createExportSpecifier(id, name));
        }

        function parseExportDeclaration() {
            var declaration = null,
                possibleIdentifierToken, sourceElement,
                isExportFromIdentifier,
                src = null, specifiers = [],
                marker = markerCreate(),
                token2,
                exportKind = 'value';

            expectKeyword('export');

            if (matchKeyword('default')) {
                // covers:
                // export default ...
                lex();
                if (matchKeyword('function') || matchKeyword('class')) {
                    possibleIdentifierToken = lookahead2();
                    if (isIdentifierName(possibleIdentifierToken)) {
                        // covers:
                        // export default function foo () {}
                        // export default class foo {}
                        sourceElement = parseSourceElement();
                        return markerApply(marker, delegate.createExportDeclaration(true, sourceElement, [sourceElement.id], null, exportKind));
                    }
                    // covers:
                    // export default function () {}
                    // export default class {}
                    switch (lookahead.value) {
                    case 'class':
                        return markerApply(marker, delegate.createExportDeclaration(true, parseClassExpression(), [], null, exportKind));
                    case 'function':
                        return markerApply(marker, delegate.createExportDeclaration(true, parseFunctionExpression(), [], null, exportKind));
                    }
                }

                if (matchContextualKeyword('from')) {
                    throwError({}, Messages.UnexpectedToken, lookahead.value);
                }

                // covers:
                // export default {};
                // export default [];
                if (match('{')) {
                    declaration = parseObjectInitialiser();
                } else if (match('[')) {
                    declaration = parseArrayInitialiser();
                } else {
                    declaration = parseAssignmentExpression();
                }
                consumeSemicolon();
                return markerApply(marker, delegate.createExportDeclaration(true, declaration, [], null, exportKind));
            }

            // non-default export
            if (lookahead.type === Token.Keyword || matchContextualKeyword('type')) {
                // covers:
                // export var f = 1;
                switch (lookahead.value) {
                case 'type':
                    exportKind = 'type';

                    token2 = lookahead2();
                    if (token2.type === Token.Punctuator && token2.value === '{') {
                        lex();
                        break;
                    }
                    // falls through
                case 'let':
                case 'const':
                case 'var':
                case 'class':
                case 'function':
                    return markerApply(marker, delegate.createExportDeclaration(false, parseSourceElement(), specifiers, null, exportKind));
                }
            }

            if (match('*')) {
                // covers:
                // export * from "foo";
                specifiers.push(parseExportBatchSpecifier());

                if (!matchContextualKeyword('from')) {
                    throwError({}, lookahead.value ?
                            Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
                }
                lex();
                src = parseModuleSpecifier();
                consumeSemicolon();

                return markerApply(marker, delegate.createExportDeclaration(false, null, specifiers, src, exportKind));
            }

            expect('{');
            if (!match('}')) {
                do {
                    isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default');
                    specifiers.push(parseExportSpecifier());
                } while (match(',') && lex());
            }
            expect('}');

            if (matchContextualKeyword('from')) {
                // covering:
                // export {default} from "foo";
                // export {foo} from "foo";
                lex();
                src = parseModuleSpecifier();
                consumeSemicolon();
            } else if (isExportFromIdentifier) {
                // covering:
                // export {default}; // missing fromClause
                throwError({}, lookahead.value ?
                        Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
            } else {
                // cover
                // export {foo};
                consumeSemicolon();
            }
            return markerApply(marker, delegate.createExportDeclaration(false, declaration, specifiers, src, exportKind));
        }

        function parseImportSpecifier() {
            // import {<foo as bar>} ...;
            var id, name = null, marker = markerCreate();

            id = parseNonComputedProperty();
            if (matchContextualKeyword('as')) {
                lex();
                name = parseVariableIdentifier();
            }

            return markerApply(marker, delegate.createImportSpecifier(id, name));
        }

        function parseNamedImports() {
            var specifiers = [];
            // {foo, bar as bas}
            expect('{');
            if (!match('}')) {
                do {
                    specifiers.push(parseImportSpecifier());
                } while (match(',') && lex());
            }
            expect('}');
            return specifiers;
        }

        function parseImportDefaultSpecifier() {
            // import <foo> ...;
            var id, marker = markerCreate();

            id = parseNonComputedProperty();

            return markerApply(marker, delegate.createImportDefaultSpecifier(id));
        }

        function parseImportNamespaceSpecifier() {
            // import <* as foo> ...;
            var id, marker = markerCreate();

            expect('*');
            if (!matchContextualKeyword('as')) {
                throwError({}, Messages.NoAsAfterImportNamespace);
            }
            lex();
            id = parseNonComputedProperty();

            return markerApply(marker, delegate.createImportNamespaceSpecifier(id));
        }

        function parseImportDeclaration() {
            var specifiers, src, marker = markerCreate(), importKind = 'value',
                token2;

            expectKeyword('import');

            if (matchContextualKeyword('type')) {
                token2 = lookahead2();
                if ((token2.type === Token.Identifier && token2.value !== 'from') ||
                        (token2.type === Token.Punctuator &&
                            (token2.value === '{' || token2.value === '*'))) {
                    importKind = 'type';
                    lex();
                }
            } else if (matchKeyword('typeof')) {
                importKind = 'typeof';
                lex();
            }

            specifiers = [];

            if (lookahead.type === Token.StringLiteral) {
                // covers:
                // import "foo";
                src = parseModuleSpecifier();
                consumeSemicolon();
                return markerApply(marker, delegate.createImportDeclaration(specifiers, src, importKind));
            }

            if (!matchKeyword('default') && isIdentifierName(lookahead)) {
                // covers:
                // import foo
                // import foo, ...
                specifiers.push(parseImportDefaultSpecifier());
                if (match(',')) {
                    lex();
                }
            }
            if (match('*')) {
                // covers:
                // import foo, * as foo
                // import * as foo
                specifiers.push(parseImportNamespaceSpecifier());
            } else if (match('{')) {
                // covers:
                // import foo, {bar}
                // import {bar}
                specifiers = specifiers.concat(parseNamedImports());
            }

            if (!matchContextualKeyword('from')) {
                throwError({}, lookahead.value ?
                        Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
            }
            lex();
            src = parseModuleSpecifier();
            consumeSemicolon();

            return markerApply(marker, delegate.createImportDeclaration(specifiers, src, importKind));
        }

        // 12.3 Empty Statement

        function parseEmptyStatement() {
            var marker = markerCreate();
            expect(';');
            return markerApply(marker, delegate.createEmptyStatement());
        }

        // 12.4 Expression Statement

        function parseExpressionStatement() {
            var marker = markerCreate(), expr = parseExpression();
            consumeSemicolon();
            return markerApply(marker, delegate.createExpressionStatement(expr));
        }

        // 12.5 If statement

        function parseIfStatement() {
            var test, consequent, alternate, marker = markerCreate();

            expectKeyword('if');

            expect('(');

            test = parseExpression();

            expect(')');

            consequent = parseStatement();

            if (matchKeyword('else')) {
                lex();
                alternate = parseStatement();
            } else {
                alternate = null;
            }

            return markerApply(marker, delegate.createIfStatement(test, consequent, alternate));
        }

        // 12.6 Iteration Statements

        function parseDoWhileStatement() {
            var body, test, oldInIteration, marker = markerCreate();

            expectKeyword('do');

            oldInIteration = state.inIteration;
            state.inIteration = true;

            body = parseStatement();

            state.inIteration = oldInIteration;

            expectKeyword('while');

            expect('(');

            test = parseExpression();

            expect(')');

            if (match(';')) {
                lex();
            }

            return markerApply(marker, delegate.createDoWhileStatement(body, test));
        }

        function parseWhileStatement() {
            var test, body, oldInIteration, marker = markerCreate();

            expectKeyword('while');

            expect('(');

            test = parseExpression();

            expect(')');

            oldInIteration = state.inIteration;
            state.inIteration = true;

            body = parseStatement();

            state.inIteration = oldInIteration;

            return markerApply(marker, delegate.createWhileStatement(test, body));
        }

        function parseForVariableDeclaration() {
            var marker = markerCreate(),
                token = lex(),
                declarations = parseVariableDeclarationList();

            return markerApply(marker, delegate.createVariableDeclaration(declarations, token.value));
        }

        function parseForStatement(opts) {
            var init, test, update, left, right, body, operator, oldInIteration,
                marker = markerCreate();
            init = test = update = null;
            expectKeyword('for');

            // http://wiki.ecmascript.org/doku.php?id=proposals:iterators_and_generators&s=each
            if (matchContextualKeyword('each')) {
                throwError({}, Messages.EachNotAllowed);
            }

            expect('(');

            if (match(';')) {
                lex();
            } else {
                if (matchKeyword('var') || matchKeyword('let') || matchKeyword('const')) {
                    state.allowIn = false;
                    init = parseForVariableDeclaration();
                    state.allowIn = true;

                    if (init.declarations.length === 1) {
                        if (matchKeyword('in') || matchContextualKeyword('of')) {
                            operator = lookahead;
                            if (!((operator.value === 'in' || init.kind !== 'var') && init.declarations[0].init)) {
                                lex();
                                left = init;
                                right = parseExpression();
                                init = null;
                            }
                        }
                    }
                } else {
                    state.allowIn = false;
                    init = parseExpression();
                    state.allowIn = true;

                    if (matchContextualKeyword('of')) {
                        operator = lex();
                        left = init;
                        right = parseExpression();
                        init = null;
                    } else if (matchKeyword('in')) {
                        // LeftHandSideExpression
                        if (!isAssignableLeftHandSide(init)) {
                            throwError({}, Messages.InvalidLHSInForIn);
                        }
                        operator = lex();
                        left = init;
                        right = parseExpression();
                        init = null;
                    }
                }

                if (typeof left === 'undefined') {
                    expect(';');
                }
            }

            if (typeof left === 'undefined') {

                if (!match(';')) {
                    test = parseExpression();
                }
                expect(';');

                if (!match(')')) {
                    update = parseExpression();
                }
            }

            expect(')');

            oldInIteration = state.inIteration;
            state.inIteration = true;

            if (!(opts !== undefined && opts.ignoreBody)) {
                body = parseStatement();
            }

            state.inIteration = oldInIteration;

            if (typeof left === 'undefined') {
                return markerApply(marker, delegate.createForStatement(init, test, update, body));
            }

            if (operator.value === 'in') {
                return markerApply(marker, delegate.createForInStatement(left, right, body));
            }
            return markerApply(marker, delegate.createForOfStatement(left, right, body));
        }

        // 12.7 The continue statement

        function parseContinueStatement() {
            var label = null, marker = markerCreate();

            expectKeyword('continue');

            // Optimize the most common form: 'continue;'.
            if (source.charCodeAt(index) === 59) {
                lex();

                if (!state.inIteration) {
                    throwError({}, Messages.IllegalContinue);
                }

                return markerApply(marker, delegate.createContinueStatement(null));
            }

            if (peekLineTerminator()) {
                if (!state.inIteration) {
                    throwError({}, Messages.IllegalContinue);
                }

                return markerApply(marker, delegate.createContinueStatement(null));
            }

            if (lookahead.type === Token.Identifier) {
                label = parseVariableIdentifier();

                if (!state.labelSet.has(label.name)) {
                    throwError({}, Messages.UnknownLabel, label.name);
                }
            }

            consumeSemicolon();

            if (label === null && !state.inIteration) {
                throwError({}, Messages.IllegalContinue);
            }

            return markerApply(marker, delegate.createContinueStatement(label));
        }

        // 12.8 The break statement

        function parseBreakStatement() {
            var label = null, marker = markerCreate();

            expectKeyword('break');

            // Catch the very common case first: immediately a semicolon (char #59).
            if (source.charCodeAt(index) === 59) {
                lex();

                if (!(state.inIteration || state.inSwitch)) {
                    throwError({}, Messages.IllegalBreak);
                }

                return markerApply(marker, delegate.createBreakStatement(null));
            }

            if (peekLineTerminator()) {
                if (!(state.inIteration || state.inSwitch)) {
                    throwError({}, Messages.IllegalBreak);
                }

                return markerApply(marker, delegate.createBreakStatement(null));
            }

            if (lookahead.type === Token.Identifier) {
                label = parseVariableIdentifier();

                if (!state.labelSet.has(label.name)) {
                    throwError({}, Messages.UnknownLabel, label.name);
                }
            }

            consumeSemicolon();

            if (label === null && !(state.inIteration || state.inSwitch)) {
                throwError({}, Messages.IllegalBreak);
            }

            return markerApply(marker, delegate.createBreakStatement(label));
        }

        // 12.9 The return statement

        function parseReturnStatement() {
            var argument = null, marker = markerCreate();

            expectKeyword('return');

            if (!state.inFunctionBody) {
                throwErrorTolerant({}, Messages.IllegalReturn);
            }

            // 'return' followed by a space and an identifier is very common.
            if (source.charCodeAt(index) === 32) {
                if (isIdentifierStart(source.charCodeAt(index + 1))) {
                    argument = parseExpression();
                    consumeSemicolon();
                    return markerApply(marker, delegate.createReturnStatement(argument));
                }
            }

            if (peekLineTerminator()) {
                return markerApply(marker, delegate.createReturnStatement(null));
            }

            if (!match(';')) {
                if (!match('}') && lookahead.type !== Token.EOF) {
                    argument = parseExpression();
                }
            }

            consumeSemicolon();

            return markerApply(marker, delegate.createReturnStatement(argument));
        }

        // 12.10 The with statement

        function parseWithStatement() {
            var object, body, marker = markerCreate();

            if (strict) {
                throwErrorTolerant({}, Messages.StrictModeWith);
            }

            expectKeyword('with');

            expect('(');

            object = parseExpression();

            expect(')');

            body = parseStatement();

            return markerApply(marker, delegate.createWithStatement(object, body));
        }

        // 12.10 The swith statement

        function parseSwitchCase() {
            var test,
                consequent = [],
                sourceElement,
                marker = markerCreate();

            if (matchKeyword('default')) {
                lex();
                test = null;
            } else {
                expectKeyword('case');
                test = parseExpression();
            }
            expect(':');

            while (index < length) {
                if (match('}') || matchKeyword('default') || matchKeyword('case')) {
                    break;
                }
                sourceElement = parseSourceElement();
                if (typeof sourceElement === 'undefined') {
                    break;
                }
                consequent.push(sourceElement);
            }

            return markerApply(marker, delegate.createSwitchCase(test, consequent));
        }

        function parseSwitchStatement() {
            var discriminant, cases, clause, oldInSwitch, defaultFound, marker = markerCreate();

            expectKeyword('switch');

            expect('(');

            discriminant = parseExpression();

            expect(')');

            expect('{');

            cases = [];

            if (match('}')) {
                lex();
                return markerApply(marker, delegate.createSwitchStatement(discriminant, cases));
            }

            oldInSwitch = state.inSwitch;
            state.inSwitch = true;
            defaultFound = false;

            while (index < length) {
                if (match('}')) {
                    break;
                }
                clause = parseSwitchCase();
                if (clause.test === null) {
                    if (defaultFound) {
                        throwError({}, Messages.MultipleDefaultsInSwitch);
                    }
                    defaultFound = true;
                }
                cases.push(clause);
            }

            state.inSwitch = oldInSwitch;

            expect('}');

            return markerApply(marker, delegate.createSwitchStatement(discriminant, cases));
        }

        // 12.13 The throw statement

        function parseThrowStatement() {
            var argument, marker = markerCreate();

            expectKeyword('throw');

            if (peekLineTerminator()) {
                throwError({}, Messages.NewlineAfterThrow);
            }

            argument = parseExpression();

            consumeSemicolon();

            return markerApply(marker, delegate.createThrowStatement(argument));
        }

        // 12.14 The try statement

        function parseCatchClause() {
            var param, body, marker = markerCreate();

            expectKeyword('catch');

            expect('(');
            if (match(')')) {
                throwUnexpected(lookahead);
            }

            param = parseExpression();
            // 12.14.1
            if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) {
                throwErrorTolerant({}, Messages.StrictCatchVariable);
            }

            expect(')');
            body = parseBlock();
            return markerApply(marker, delegate.createCatchClause(param, body));
        }

        function parseTryStatement() {
            var block, handlers = [], finalizer = null, marker = markerCreate();

            expectKeyword('try');

            block = parseBlock();

            if (matchKeyword('catch')) {
                handlers.push(parseCatchClause());
            }

            if (matchKeyword('finally')) {
                lex();
                finalizer = parseBlock();
            }

            if (handlers.length === 0 && !finalizer) {
                throwError({}, Messages.NoCatchOrFinally);
            }

            return markerApply(marker, delegate.createTryStatement(block, [], handlers, finalizer));
        }

        // 12.15 The debugger statement

        function parseDebuggerStatement() {
            var marker = markerCreate();
            expectKeyword('debugger');

            consumeSemicolon();

            return markerApply(marker, delegate.createDebuggerStatement());
        }

        // 12 Statements

        function parseStatement() {
            var type = lookahead.type,
                marker,
                expr,
                labeledBody;

            if (type === Token.EOF) {
                throwUnexpected(lookahead);
            }

            if (type === Token.Punctuator) {
                switch (lookahead.value) {
                case ';':
                    return parseEmptyStatement();
                case '{':
                    return parseBlock();
                case '(':
                    return parseExpressionStatement();
                default:
                    break;
                }
            }

            if (type === Token.Keyword) {
                switch (lookahead.value) {
                case 'break':
                    return parseBreakStatement();
                case 'continue':
                    return parseContinueStatement();
                case 'debugger':
                    return parseDebuggerStatement();
                case 'do':
                    return parseDoWhileStatement();
                case 'for':
                    return parseForStatement();
                case 'function':
                    return parseFunctionDeclaration();
                case 'class':
                    return parseClassDeclaration();
                case 'if':
                    return parseIfStatement();
                case 'return':
                    return parseReturnStatement();
                case 'switch':
                    return parseSwitchStatement();
                case 'throw':
                    return parseThrowStatement();
                case 'try':
                    return parseTryStatement();
                case 'var':
                    return parseVariableStatement();
                case 'while':
                    return parseWhileStatement();
                case 'with':
                    return parseWithStatement();
                default:
                    break;
                }
            }

            if (matchAsyncFuncExprOrDecl()) {
                return parseFunctionDeclaration();
            }

            marker = markerCreate();
            expr = parseExpression();

            // 12.12 Labelled Statements
            if ((expr.type === Syntax.Identifier) && match(':')) {
                lex();

                if (state.labelSet.has(expr.name)) {
                    throwError({}, Messages.Redeclaration, 'Label', expr.name);
                }

                state.labelSet.set(expr.name, true);
                labeledBody = parseStatement();
                state.labelSet.delete(expr.name);
                return markerApply(marker, delegate.createLabeledStatement(expr, labeledBody));
            }

            consumeSemicolon();

            return markerApply(marker, delegate.createExpressionStatement(expr));
        }

        // 13 Function Definition

        function parseConciseBody() {
            if (match('{')) {
                return parseFunctionSourceElements();
            }
            return parseAssignmentExpression();
        }

        function parseFunctionSourceElements() {
            var sourceElement, sourceElements = [], token, directive, firstRestricted,
                oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesizedCount,
                marker = markerCreate();

            expect('{');

            while (index < length) {
                if (lookahead.type !== Token.StringLiteral) {
                    break;
                }
                token = lookahead;

                sourceElement = parseSourceElement();
                sourceElements.push(sourceElement);
                if (sourceElement.expression.type !== Syntax.Literal) {
                    // this is not directive
                    break;
                }
                directive = source.slice(token.range[0] + 1, token.range[1] - 1);
                if (directive === 'use strict') {
                    strict = true;
                    if (firstRestricted) {
                        throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
                    }
                } else {
                    if (!firstRestricted && token.octal) {
                        firstRestricted = token;
                    }
                }
            }

            oldLabelSet = state.labelSet;
            oldInIteration = state.inIteration;
            oldInSwitch = state.inSwitch;
            oldInFunctionBody = state.inFunctionBody;
            oldParenthesizedCount = state.parenthesizedCount;

            state.labelSet = new StringMap();
            state.inIteration = false;
            state.inSwitch = false;
            state.inFunctionBody = true;
            state.parenthesizedCount = 0;

            while (index < length) {
                if (match('}')) {
                    break;
                }
                sourceElement = parseSourceElement();
                if (typeof sourceElement === 'undefined') {
                    break;
                }
                sourceElements.push(sourceElement);
            }

            expect('}');

            state.labelSet = oldLabelSet;
            state.inIteration = oldInIteration;
            state.inSwitch = oldInSwitch;
            state.inFunctionBody = oldInFunctionBody;
            state.parenthesizedCount = oldParenthesizedCount;

            return markerApply(marker, delegate.createBlockStatement(sourceElements));
        }

        function validateParam(options, param, name) {
            if (strict) {
                if (isRestrictedWord(name)) {
                    options.stricted = param;
                    options.message = Messages.StrictParamName;
                }
                if (options.paramSet.has(name)) {
                    options.stricted = param;
                    options.message = Messages.StrictParamDupe;
                }
            } else if (!options.firstRestricted) {
                if (isRestrictedWord(name)) {
                    options.firstRestricted = param;
                    options.message = Messages.StrictParamName;
                } else if (isStrictModeReservedWord(name)) {
                    options.firstRestricted = param;
                    options.message = Messages.StrictReservedWord;
                } else if (options.paramSet.has(name)) {
                    options.firstRestricted = param;
                    options.message = Messages.StrictParamDupe;
                }
            }
            options.paramSet.set(name, true);
        }

        function parseParam(options) {
            var marker, token, rest, param, def;

            token = lookahead;
            if (token.value === '...') {
                token = lex();
                rest = true;
            }

            if (match('[')) {
                marker = markerCreate();
                param = parseArrayInitialiser();
                reinterpretAsDestructuredParameter(options, param);
                if (match(':')) {
                    param.typeAnnotation = parseTypeAnnotation();
                    markerApply(marker, param);
                }
            } else if (match('{')) {
                marker = markerCreate();
                if (rest) {
                    throwError({}, Messages.ObjectPatternAsRestParameter);
                }
                param = parseObjectInitialiser();
                reinterpretAsDestructuredParameter(options, param);
                if (match(':')) {
                    param.typeAnnotation = parseTypeAnnotation();
                    markerApply(marker, param);
                }
            } else {
                param =
                    rest
                    ? parseTypeAnnotatableIdentifier(
                        false, /* requireTypeAnnotation */
                        false /* canBeOptionalParam */
                    )
                    : parseTypeAnnotatableIdentifier(
                        false, /* requireTypeAnnotation */
                        true /* canBeOptionalParam */
                    );

                validateParam(options, token, token.value);
            }

            if (match('=')) {
                if (rest) {
                    throwErrorTolerant(lookahead, Messages.DefaultRestParameter);
                }
                lex();
                def = parseAssignmentExpression();
                ++options.defaultCount;
            }

            if (rest) {
                if (!match(')')) {
                    throwError({}, Messages.ParameterAfterRestParameter);
                }
                options.rest = param;
                return false;
            }

            options.params.push(param);
            options.defaults.push(def);
            return !match(')');
        }

        function parseParams(firstRestricted) {
            var options, marker = markerCreate();

            options = {
                params: [],
                defaultCount: 0,
                defaults: [],
                rest: null,
                firstRestricted: firstRestricted
            };

            expect('(');

            if (!match(')')) {
                options.paramSet = new StringMap();
                while (index < length) {
                    if (!parseParam(options)) {
                        break;
                    }
                    expect(',');
                    if (!options.rest && match(')')) {
                        break;
                    }
                }
            }

            expect(')');

            if (options.defaultCount === 0) {
                options.defaults = [];
            }

            if (match(':')) {
                options.returnType = parseTypeAnnotation();
            }

            return markerApply(marker, options);
        }

        function parseFunctionDeclaration() {
            var id, body, token, tmp, firstRestricted, message, generator, isAsync,
                previousStrict, previousYieldAllowed, previousAwaitAllowed,
                marker = markerCreate(), typeParameters;

            isAsync = false;
            if (matchAsync()) {
                lex();
                isAsync = true;
            }

            expectKeyword('function');

            generator = false;
            if (match('*')) {
                lex();
                generator = true;
            }

            token = lookahead;

            id = parseVariableIdentifier();

            if (match('<')) {
                typeParameters = parseTypeParameterDeclaration();
            }

            if (strict) {
                if (isRestrictedWord(token.value)) {
                    throwErrorTolerant(token, Messages.StrictFunctionName);
                }
            } else {
                if (isRestrictedWord(token.value)) {
                    firstRestricted = token;
                    message = Messages.StrictFunctionName;
                } else if (isStrictModeReservedWord(token.value)) {
                    firstRestricted = token;
                    message = Messages.StrictReservedWord;
                }
            }

            tmp = parseParams(firstRestricted);
            firstRestricted = tmp.firstRestricted;
            if (tmp.message) {
                message = tmp.message;
            }

            previousStrict = strict;
            previousYieldAllowed = state.yieldAllowed;
            state.yieldAllowed = generator;
            previousAwaitAllowed = state.awaitAllowed;
            state.awaitAllowed = isAsync;

            body = parseFunctionSourceElements();

            if (strict && firstRestricted) {
                throwError(firstRestricted, message);
            }
            if (strict && tmp.stricted) {
                throwErrorTolerant(tmp.stricted, message);
            }
            strict = previousStrict;
            state.yieldAllowed = previousYieldAllowed;
            state.awaitAllowed = previousAwaitAllowed;

            return markerApply(
                marker,
                delegate.createFunctionDeclaration(
                    id,
                    tmp.params,
                    tmp.defaults,
                    body,
                    tmp.rest,
                    generator,
                    false,
                    isAsync,
                    tmp.returnType,
                    typeParameters
                )
            );
        }

        function parseFunctionExpression() {
            var token, id = null, firstRestricted, message, tmp, body, generator, isAsync,
                previousStrict, previousYieldAllowed, previousAwaitAllowed,
                marker = markerCreate(), typeParameters;

            isAsync = false;
            if (matchAsync()) {
                lex();
                isAsync = true;
            }

            expectKeyword('function');

            generator = false;

            if (match('*')) {
                lex();
                generator = true;
            }

            if (!match('(')) {
                if (!match('<')) {
                    token = lookahead;
                    id = parseVariableIdentifier();

                    if (strict) {
                        if (isRestrictedWord(token.value)) {
                            throwErrorTolerant(token, Messages.StrictFunctionName);
                        }
                    } else {
                        if (isRestrictedWord(token.value)) {
                            firstRestricted = token;
                            message = Messages.StrictFunctionName;
                        } else if (isStrictModeReservedWord(token.value)) {
                            firstRestricted = token;
                            message = Messages.StrictReservedWord;
                        }
                    }
                }

                if (match('<')) {
                    typeParameters = parseTypeParameterDeclaration();
                }
            }

            tmp = parseParams(firstRestricted);
            firstRestricted = tmp.firstRestricted;
            if (tmp.message) {
                message = tmp.message;
            }

            previousStrict = strict;
            previousYieldAllowed = state.yieldAllowed;
            state.yieldAllowed = generator;
            previousAwaitAllowed = state.awaitAllowed;
            state.awaitAllowed = isAsync;

            body = parseFunctionSourceElements();

            if (strict && firstRestricted) {
                throwError(firstRestricted, message);
            }
            if (strict && tmp.stricted) {
                throwErrorTolerant(tmp.stricted, message);
            }
            strict = previousStrict;
            state.yieldAllowed = previousYieldAllowed;
            state.awaitAllowed = previousAwaitAllowed;

            return markerApply(
                marker,
                delegate.createFunctionExpression(
                    id,
                    tmp.params,
                    tmp.defaults,
                    body,
                    tmp.rest,
                    generator,
                    false,
                    isAsync,
                    tmp.returnType,
                    typeParameters
                )
            );
        }

        function parseYieldExpression() {
            var delegateFlag, expr, marker = markerCreate();

            expectKeyword('yield', !strict);

            delegateFlag = false;
            if (match('*')) {
                lex();
                delegateFlag = true;
            }

            expr = parseAssignmentExpression();

            return markerApply(marker, delegate.createYieldExpression(expr, delegateFlag));
        }

        function parseAwaitExpression() {
            var expr, marker = markerCreate();
            expectContextualKeyword('await');
            expr = parseAssignmentExpression();
            return markerApply(marker, delegate.createAwaitExpression(expr));
        }

        // 14 Functions and classes

        // 14.1 Functions is defined above (13 in ES5)
        // 14.2 Arrow Functions Definitions is defined in (7.3 assignments)

        // 14.3 Method Definitions
        // 14.3.7
        function specialMethod(methodDefinition) {
            return methodDefinition.kind === 'get' ||
                   methodDefinition.kind === 'set' ||
                   methodDefinition.value.generator;
        }

        function parseMethodDefinition(key, isStatic, generator, computed) {
            var token, param, propType,
                isAsync, typeParameters, tokenValue, returnType;

            propType = isStatic ? ClassPropertyType.static : ClassPropertyType.prototype;

            if (generator) {
                return delegate.createMethodDefinition(
                    propType,
                    '',
                    key,
                    parsePropertyMethodFunction({ generator: true }),
                    computed
                );
            }

            tokenValue = key.type === 'Identifier' && key.name;

            if (tokenValue === 'get' && !match('(')) {
                key = parseObjectPropertyKey();

                expect('(');
                expect(')');
                if (match(':')) {
                    returnType = parseTypeAnnotation();
                }
                return delegate.createMethodDefinition(
                    propType,
                    'get',
                    key,
                    parsePropertyFunction({ generator: false, returnType: returnType }),
                    computed
                );
            }
            if (tokenValue === 'set' && !match('(')) {
                key = parseObjectPropertyKey();

                expect('(');
                token = lookahead;
                param = [ parseTypeAnnotatableIdentifier() ];
                expect(')');
                if (match(':')) {
                    returnType = parseTypeAnnotation();
                }
                return delegate.createMethodDefinition(
                    propType,
                    'set',
                    key,
                    parsePropertyFunction({
                        params: param,
                        generator: false,
                        name: token,
                        returnType: returnType
                    }),
                    computed
                );
            }

            if (match('<')) {
                typeParameters = parseTypeParameterDeclaration();
            }

            isAsync = tokenValue === 'async' && !match('(');
            if (isAsync) {
                key = parseObjectPropertyKey();
            }

            return delegate.createMethodDefinition(
                propType,
                '',
                key,
                parsePropertyMethodFunction({
                    generator: false,
                    async: isAsync,
                    typeParameters: typeParameters
                }),
                computed
            );
        }

        function parseClassProperty(key, computed, isStatic) {
            var typeAnnotation;

            typeAnnotation = parseTypeAnnotation();
            expect(';');

            return delegate.createClassProperty(
                key,
                typeAnnotation,
                computed,
                isStatic
            );
        }

        function parseClassElement() {
            var computed = false, generator = false, key, marker = markerCreate(),
                isStatic = false, possiblyOpenBracketToken;
            if (match(';')) {
                lex();
                return undefined;
            }

            if (lookahead.value === 'static') {
                lex();
                isStatic = true;
            }

            if (match('*')) {
                lex();
                generator = true;
            }

            possiblyOpenBracketToken = lookahead;
            if (matchContextualKeyword('get') || matchContextualKeyword('set')) {
                possiblyOpenBracketToken = lookahead2();
            }

            if (possiblyOpenBracketToken.type === Token.Punctuator
                    && possiblyOpenBracketToken.value === '[') {
                computed = true;
            }

            key = parseObjectPropertyKey();

            if (!generator && lookahead.value === ':') {
                return markerApply(marker, parseClassProperty(key, computed, isStatic));
            }

            return markerApply(marker, parseMethodDefinition(
                key,
                isStatic,
                generator,
                computed
            ));
        }

        function parseClassBody() {
            var classElement, classElements = [], existingProps = {},
                marker = markerCreate(), propName, propType;

            existingProps[ClassPropertyType.static] = new StringMap();
            existingProps[ClassPropertyType.prototype] = new StringMap();

            expect('{');

            while (index < length) {
                if (match('}')) {
                    break;
                }
                classElement = parseClassElement(existingProps);

                if (typeof classElement !== 'undefined') {
                    classElements.push(classElement);

                    propName = !classElement.computed && getFieldName(classElement.key);
                    if (propName !== false) {
                        propType = classElement.static ?
                                    ClassPropertyType.static :
                                    ClassPropertyType.prototype;

                        if (classElement.type === Syntax.MethodDefinition) {
                            if (propName === 'constructor' && !classElement.static) {
                                if (specialMethod(classElement)) {
                                    throwError(classElement, Messages.IllegalClassConstructorProperty);
                                }
                                if (existingProps[ClassPropertyType.prototype].has('constructor')) {
                                    throwError(classElement.key, Messages.IllegalDuplicateClassProperty);
                                }
                            }
                            existingProps[propType].set(propName, true);
                        }
                    }
                }
            }

            expect('}');

            return markerApply(marker, delegate.createClassBody(classElements));
        }

        function parseClassImplements() {
            var id, implemented = [], marker, typeParameters;
            if (strict) {
                expectKeyword('implements');
            } else {
                expectContextualKeyword('implements');
            }
            while (index < length) {
                marker = markerCreate();
                id = parseVariableIdentifier();
                if (match('<')) {
                    typeParameters = parseTypeParameterInstantiation();
                } else {
                    typeParameters = null;
                }
                implemented.push(markerApply(marker, delegate.createClassImplements(
                    id,
                    typeParameters
                )));
                if (!match(',')) {
                    break;
                }
                expect(',');
            }
            return implemented;
        }

        function parseClassExpression() {
            var id, implemented, previousYieldAllowed, superClass = null,
                superTypeParameters, marker = markerCreate(), typeParameters,
                matchImplements;

            expectKeyword('class');

            matchImplements =
                    strict
                    ? matchKeyword('implements')
                    : matchContextualKeyword('implements');

            if (!matchKeyword('extends') && !matchImplements && !match('{')) {
                id = parseVariableIdentifier();
            }

            if (match('<')) {
                typeParameters = parseTypeParameterDeclaration();
            }

            if (matchKeyword('extends')) {
                expectKeyword('extends');
                previousYieldAllowed = state.yieldAllowed;
                state.yieldAllowed = false;
                superClass = parseLeftHandSideExpressionAllowCall();
                if (match('<')) {
                    superTypeParameters = parseTypeParameterInstantiation();
                }
                state.yieldAllowed = previousYieldAllowed;
            }

            if (strict ? matchKeyword('implements') : matchContextualKeyword('implements')) {
                implemented = parseClassImplements();
            }

            return markerApply(marker, delegate.createClassExpression(
                id,
                superClass,
                parseClassBody(),
                typeParameters,
                superTypeParameters,
                implemented
            ));
        }

        function parseClassDeclaration() {
            var id, implemented, previousYieldAllowed, superClass = null,
                superTypeParameters, marker = markerCreate(), typeParameters;

            expectKeyword('class');

            id = parseVariableIdentifier();

            if (match('<')) {
                typeParameters = parseTypeParameterDeclaration();
            }

            if (matchKeyword('extends')) {
                expectKeyword('extends');
                previousYieldAllowed = state.yieldAllowed;
                state.yieldAllowed = false;
                superClass = parseLeftHandSideExpressionAllowCall();
                if (match('<')) {
                    superTypeParameters = parseTypeParameterInstantiation();
                }
                state.yieldAllowed = previousYieldAllowed;
            }

            if (strict ? matchKeyword('implements') : matchContextualKeyword('implements')) {
                implemented = parseClassImplements();
            }

            return markerApply(marker, delegate.createClassDeclaration(
                id,
                superClass,
                parseClassBody(),
                typeParameters,
                superTypeParameters,
                implemented
            ));
        }

        // 15 Program

        function parseSourceElement() {
            var token;
            if (lookahead.type === Token.Keyword) {
                switch (lookahead.value) {
                case 'const':
                case 'let':
                    return parseConstLetDeclaration(lookahead.value);
                case 'function':
                    return parseFunctionDeclaration();
                case 'export':
                    throwErrorTolerant({}, Messages.IllegalExportDeclaration);
                    return parseExportDeclaration();
                case 'import':
                    throwErrorTolerant({}, Messages.IllegalImportDeclaration);
                    return parseImportDeclaration();
                case 'interface':
                    if (lookahead2().type === Token.Identifier) {
                        return parseInterface();
                    }
                    return parseStatement();
                default:
                    return parseStatement();
                }
            }

            if (matchContextualKeyword('type')
                    && lookahead2().type === Token.Identifier) {
                return parseTypeAlias();
            }

            if (matchContextualKeyword('interface')
                    && lookahead2().type === Token.Identifier) {
                return parseInterface();
            }

            if (matchContextualKeyword('declare')) {
                token = lookahead2();
                if (token.type === Token.Keyword) {
                    switch (token.value) {
                    case 'class':
                        return parseDeclareClass();
                    case 'function':
                        return parseDeclareFunction();
                    case 'var':
                        return parseDeclareVariable();
                    }
                } else if (token.type === Token.Identifier
                        && token.value === 'module') {
                    return parseDeclareModule();
                }
            }

            if (lookahead.type !== Token.EOF) {
                return parseStatement();
            }
        }

        function parseProgramElement() {
            var isModule = extra.sourceType === 'module' || extra.sourceType === 'nonStrictModule';

            if (isModule && lookahead.type === Token.Keyword) {
                switch (lookahead.value) {
                case 'export':
                    return parseExportDeclaration();
                case 'import':
                    return parseImportDeclaration();
                }
            }

            return parseSourceElement();
        }

        function parseProgramElements() {
            var sourceElement, sourceElements = [], token, directive, firstRestricted;

            while (index < length) {
                token = lookahead;
                if (token.type !== Token.StringLiteral) {
                    break;
                }

                sourceElement = parseProgramElement();
                sourceElements.push(sourceElement);
                if (sourceElement.expression.type !== Syntax.Literal) {
                    // this is not directive
                    break;
                }
                directive = source.slice(token.range[0] + 1, token.range[1] - 1);
                if (directive === 'use strict') {
                    strict = true;
                    if (firstRestricted) {
                        throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
                    }
                } else {
                    if (!firstRestricted && token.octal) {
                        firstRestricted = token;
                    }
                }
            }

            while (index < length) {
                sourceElement = parseProgramElement();
                if (typeof sourceElement === 'undefined') {
                    break;
                }
                sourceElements.push(sourceElement);
            }
            return sourceElements;
        }

        function parseProgram() {
            var body, marker = markerCreate();
            strict = extra.sourceType === 'module';
            peek();
            body = parseProgramElements();
            return markerApply(marker, delegate.createProgram(body));
        }

        // 16 JSX

        XHTMLEntities = {
            quot: '\u0022',
            amp: '&',
            apos: '\u0027',
            lt: '<',
            gt: '>',
            nbsp: '\u00A0',
            iexcl: '\u00A1',
            cent: '\u00A2',
            pound: '\u00A3',
            curren: '\u00A4',
            yen: '\u00A5',
            brvbar: '\u00A6',
            sect: '\u00A7',
            uml: '\u00A8',
            copy: '\u00A9',
            ordf: '\u00AA',
            laquo: '\u00AB',
            not: '\u00AC',
            shy: '\u00AD',
            reg: '\u00AE',
            macr: '\u00AF',
            deg: '\u00B0',
            plusmn: '\u00B1',
            sup2: '\u00B2',
            sup3: '\u00B3',
            acute: '\u00B4',
            micro: '\u00B5',
            para: '\u00B6',
            middot: '\u00B7',
            cedil: '\u00B8',
            sup1: '\u00B9',
            ordm: '\u00BA',
            raquo: '\u00BB',
            frac14: '\u00BC',
            frac12: '\u00BD',
            frac34: '\u00BE',
            iquest: '\u00BF',
            Agrave: '\u00C0',
            Aacute: '\u00C1',
            Acirc: '\u00C2',
            Atilde: '\u00C3',
            Auml: '\u00C4',
            Aring: '\u00C5',
            AElig: '\u00C6',
            Ccedil: '\u00C7',
            Egrave: '\u00C8',
            Eacute: '\u00C9',
            Ecirc: '\u00CA',
            Euml: '\u00CB',
            Igrave: '\u00CC',
            Iacute: '\u00CD',
            Icirc: '\u00CE',
            Iuml: '\u00CF',
            ETH: '\u00D0',
            Ntilde: '\u00D1',
            Ograve: '\u00D2',
            Oacute: '\u00D3',
            Ocirc: '\u00D4',
            Otilde: '\u00D5',
            Ouml: '\u00D6',
            times: '\u00D7',
            Oslash: '\u00D8',
            Ugrave: '\u00D9',
            Uacute: '\u00DA',
            Ucirc: '\u00DB',
            Uuml: '\u00DC',
            Yacute: '\u00DD',
            THORN: '\u00DE',
            szlig: '\u00DF',
            agrave: '\u00E0',
            aacute: '\u00E1',
            acirc: '\u00E2',
            atilde: '\u00E3',
            auml: '\u00E4',
            aring: '\u00E5',
            aelig: '\u00E6',
            ccedil: '\u00E7',
            egrave: '\u00E8',
            eacute: '\u00E9',
            ecirc: '\u00EA',
            euml: '\u00EB',
            igrave: '\u00EC',
            iacute: '\u00ED',
            icirc: '\u00EE',
            iuml: '\u00EF',
            eth: '\u00F0',
            ntilde: '\u00F1',
            ograve: '\u00F2',
            oacute: '\u00F3',
            ocirc: '\u00F4',
            otilde: '\u00F5',
            ouml: '\u00F6',
            divide: '\u00F7',
            oslash: '\u00F8',
            ugrave: '\u00F9',
            uacute: '\u00FA',
            ucirc: '\u00FB',
            uuml: '\u00FC',
            yacute: '\u00FD',
            thorn: '\u00FE',
            yuml: '\u00FF',
            OElig: '\u0152',
            oelig: '\u0153',
            Scaron: '\u0160',
            scaron: '\u0161',
            Yuml: '\u0178',
            fnof: '\u0192',
            circ: '\u02C6',
            tilde: '\u02DC',
            Alpha: '\u0391',
            Beta: '\u0392',
            Gamma: '\u0393',
            Delta: '\u0394',
            Epsilon: '\u0395',
            Zeta: '\u0396',
            Eta: '\u0397',
            Theta: '\u0398',
            Iota: '\u0399',
            Kappa: '\u039A',
            Lambda: '\u039B',
            Mu: '\u039C',
            Nu: '\u039D',
            Xi: '\u039E',
            Omicron: '\u039F',
            Pi: '\u03A0',
            Rho: '\u03A1',
            Sigma: '\u03A3',
            Tau: '\u03A4',
            Upsilon: '\u03A5',
            Phi: '\u03A6',
            Chi: '\u03A7',
            Psi: '\u03A8',
            Omega: '\u03A9',
            alpha: '\u03B1',
            beta: '\u03B2',
            gamma: '\u03B3',
            delta: '\u03B4',
            epsilon: '\u03B5',
            zeta: '\u03B6',
            eta: '\u03B7',
            theta: '\u03B8',
            iota: '\u03B9',
            kappa: '\u03BA',
            lambda: '\u03BB',
            mu: '\u03BC',
            nu: '\u03BD',
            xi: '\u03BE',
            omicron: '\u03BF',
            pi: '\u03C0',
            rho: '\u03C1',
            sigmaf: '\u03C2',
            sigma: '\u03C3',
            tau: '\u03C4',
            upsilon: '\u03C5',
            phi: '\u03C6',
            chi: '\u03C7',
            psi: '\u03C8',
            omega: '\u03C9',
            thetasym: '\u03D1',
            upsih: '\u03D2',
            piv: '\u03D6',
            ensp: '\u2002',
            emsp: '\u2003',
            thinsp: '\u2009',
            zwnj: '\u200C',
            zwj: '\u200D',
            lrm: '\u200E',
            rlm: '\u200F',
            ndash: '\u2013',
            mdash: '\u2014',
            lsquo: '\u2018',
            rsquo: '\u2019',
            sbquo: '\u201A',
            ldquo: '\u201C',
            rdquo: '\u201D',
            bdquo: '\u201E',
            dagger: '\u2020',
            Dagger: '\u2021',
            bull: '\u2022',
            hellip: '\u2026',
            permil: '\u2030',
            prime: '\u2032',
            Prime: '\u2033',
            lsaquo: '\u2039',
            rsaquo: '\u203A',
            oline: '\u203E',
            frasl: '\u2044',
            euro: '\u20AC',
            image: '\u2111',
            weierp: '\u2118',
            real: '\u211C',
            trade: '\u2122',
            alefsym: '\u2135',
            larr: '\u2190',
            uarr: '\u2191',
            rarr: '\u2192',
            darr: '\u2193',
            harr: '\u2194',
            crarr: '\u21B5',
            lArr: '\u21D0',
            uArr: '\u21D1',
            rArr: '\u21D2',
            dArr: '\u21D3',
            hArr: '\u21D4',
            forall: '\u2200',
            part: '\u2202',
            exist: '\u2203',
            empty: '\u2205',
            nabla: '\u2207',
            isin: '\u2208',
            notin: '\u2209',
            ni: '\u220B',
            prod: '\u220F',
            sum: '\u2211',
            minus: '\u2212',
            lowast: '\u2217',
            radic: '\u221A',
            prop: '\u221D',
            infin: '\u221E',
            ang: '\u2220',
            and: '\u2227',
            or: '\u2228',
            cap: '\u2229',
            cup: '\u222A',
            'int': '\u222B',
            there4: '\u2234',
            sim: '\u223C',
            cong: '\u2245',
            asymp: '\u2248',
            ne: '\u2260',
            equiv: '\u2261',
            le: '\u2264',
            ge: '\u2265',
            sub: '\u2282',
            sup: '\u2283',
            nsub: '\u2284',
            sube: '\u2286',
            supe: '\u2287',
            oplus: '\u2295',
            otimes: '\u2297',
            perp: '\u22A5',
            sdot: '\u22C5',
            lceil: '\u2308',
            rceil: '\u2309',
            lfloor: '\u230A',
            rfloor: '\u230B',
            lang: '\u2329',
            rang: '\u232A',
            loz: '\u25CA',
            spades: '\u2660',
            clubs: '\u2663',
            hearts: '\u2665',
            diams: '\u2666'
        };

        function getQualifiedJSXName(object) {
            if (object.type === Syntax.JSXIdentifier) {
                return object.name;
            }
            if (object.type === Syntax.JSXNamespacedName) {
                return object.namespace.name + ':' + object.name.name;
            }
            /* istanbul ignore else */
            if (object.type === Syntax.JSXMemberExpression) {
                return (
                    getQualifiedJSXName(object.object) + '.' +
                    getQualifiedJSXName(object.property)
                );
            }
            /* istanbul ignore next */
            throwUnexpected(object);
        }

        function isJSXIdentifierStart(ch) {
            // exclude backslash (\)
            return (ch !== 92) && isIdentifierStart(ch);
        }

        function isJSXIdentifierPart(ch) {
            // exclude backslash (\) and add hyphen (-)
            return (ch !== 92) && (ch === 45 || isIdentifierPart(ch));
        }

        function scanJSXIdentifier() {
            var ch, start, value = '';

            start = index;
            while (index < length) {
                ch = source.charCodeAt(index);
                if (!isJSXIdentifierPart(ch)) {
                    break;
                }
                value += source[index++];
            }

            return {
                type: Token.JSXIdentifier,
                value: value,
                lineNumber: lineNumber,
                lineStart: lineStart,
                range: [start, index]
            };
        }

        function scanJSXEntity() {
            var ch, str = '', start = index, count = 0, code;
            ch = source[index];
            assert(ch === '&', 'Entity must start with an ampersand');
            index++;
            while (index < length && count++ < 10) {
                ch = source[index++];
                if (ch === ';') {
                    break;
                }
                str += ch;
            }

            // Well-formed entity (ending was found).
            if (ch === ';') {
                // Numeric entity.
                if (str[0] === '#') {
                    if (str[1] === 'x') {
                        code = +('0' + str.substr(1));
                    } else {
                        // Removing leading zeros in order to avoid treating as octal in old browsers.
                        code = +str.substr(1).replace(Regex.LeadingZeros, '');
                    }

                    if (!isNaN(code)) {
                        return String.fromCharCode(code);
                    }
                /* istanbul ignore else */
                } else if (XHTMLEntities[str]) {
                    return XHTMLEntities[str];
                }
            }

            // Treat non-entity sequences as regular text.
            index = start + 1;
            return '&';
        }

        function scanJSXText(stopChars) {
            var ch, str = '', start;
            start = index;
            while (index < length) {
                ch = source[index];
                if (stopChars.indexOf(ch) !== -1) {
                    break;
                }
                if (ch === '&') {
                    str += scanJSXEntity();
                } else {
                    index++;
                    if (ch === '\r' && source[index] === '\n') {
                        str += ch;
                        ch = source[index];
                        index++;
                    }
                    if (isLineTerminator(ch.charCodeAt(0))) {
                        ++lineNumber;
                        lineStart = index;
                    }
                    str += ch;
                }
            }
            return {
                type: Token.JSXText,
                value: str,
                lineNumber: lineNumber,
                lineStart: lineStart,
                range: [start, index]
            };
        }

        function scanJSXStringLiteral() {
            var innerToken, quote, start;

            quote = source[index];
            assert((quote === '\'' || quote === '"'),
                'String literal must starts with a quote');

            start = index;
            ++index;

            innerToken = scanJSXText([quote]);

            if (quote !== source[index]) {
                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
            }

            ++index;

            innerToken.range = [start, index];

            return innerToken;
        }

        /**
         * Between JSX opening and closing tags (e.g. <foo>HERE</foo>), anything that
         * is not another JSX tag and is not an expression wrapped by {} is text.
         */
        function advanceJSXChild() {
            var ch = source.charCodeAt(index);

            // '<' 60, '>' 62, '{' 123, '}' 125
            if (ch !== 60 && ch !== 62 && ch !== 123 && ch !== 125) {
                return scanJSXText(['<', '>', '{', '}']);
            }

            return scanPunctuator();
        }

        function parseJSXIdentifier() {
            var token, marker = markerCreate();

            if (lookahead.type !== Token.JSXIdentifier) {
                throwUnexpected(lookahead);
            }

            token = lex();
            return markerApply(marker, delegate.createJSXIdentifier(token.value));
        }

        function parseJSXNamespacedName() {
            var namespace, name, marker = markerCreate();

            namespace = parseJSXIdentifier();
            expect(':');
            name = parseJSXIdentifier();

            return markerApply(marker, delegate.createJSXNamespacedName(namespace, name));
        }

        function parseJSXMemberExpression() {
            var marker = markerCreate(),
                expr = parseJSXIdentifier();

            while (match('.')) {
                lex();
                expr = markerApply(marker, delegate.createJSXMemberExpression(expr, parseJSXIdentifier()));
            }

            return expr;
        }

        function parseJSXElementName() {
            if (lookahead2().value === ':') {
                return parseJSXNamespacedName();
            }
            if (lookahead2().value === '.') {
                return parseJSXMemberExpression();
            }

            return parseJSXIdentifier();
        }

        function parseJSXAttributeName() {
            if (lookahead2().value === ':') {
                return parseJSXNamespacedName();
            }

            return parseJSXIdentifier();
        }

        function parseJSXAttributeValue() {
            var value, marker;
            if (match('{')) {
                value = parseJSXExpressionContainer();
                if (value.expression.type === Syntax.JSXEmptyExpression) {
                    throwError(
                        value,
                        'JSX attributes must only be assigned a non-empty ' +
                            'expression'
                    );
                }
            } else if (match('<')) {
                value = parseJSXElement();
            } else if (lookahead.type === Token.JSXText) {
                marker = markerCreate();
                value = markerApply(marker, delegate.createLiteral(lex()));
            } else {
                throwError({}, Messages.InvalidJSXAttributeValue);
            }
            return value;
        }

        function parseJSXEmptyExpression() {
            var ch, marker = markerCreatePreserveWhitespace();
            while (index < length) {
                ch = source.charCodeAt(index);
                if (ch === 125) {
                    break;
                } else if (isLineTerminator(ch)) {
                    if (ch === 13 && source.charCodeAt(index + 1) === 10) {
                        ++index;
                    }
                    ++lineNumber;
                    lineStart = index;
                }
                ++index;
            }
            return markerApply(marker, delegate.createJSXEmptyExpression());
        }

        function parseJSXExpressionContainer() {
            var expression, origInJSXChild, origInJSXTag, marker = markerCreate();

            origInJSXChild = state.inJSXChild;
            origInJSXTag = state.inJSXTag;
            state.inJSXChild = false;
            state.inJSXTag = false;

            expect('{');

            if (match('}')) {
                expression = parseJSXEmptyExpression();
            } else {
                expression = parseExpression();
            }

            state.inJSXChild = origInJSXChild;
            state.inJSXTag = origInJSXTag;

            expect('}');

            return markerApply(marker, delegate.createJSXExpressionContainer(expression));
        }

        function parseJSXSpreadAttribute() {
            var expression, origInJSXChild, origInJSXTag, marker = markerCreate();

            origInJSXChild = state.inJSXChild;
            origInJSXTag = state.inJSXTag;
            state.inJSXChild = false;
            state.inJSXTag = false;

            expect('{');
            expect('...');

            expression = parseAssignmentExpression();

            state.inJSXChild = origInJSXChild;
            state.inJSXTag = origInJSXTag;

            expect('}');

            return markerApply(marker, delegate.createJSXSpreadAttribute(expression));
        }

        function parseJSXAttribute() {
            var name, marker;

            if (match('{')) {
                return parseJSXSpreadAttribute();
            }

            marker = markerCreate();

            name = parseJSXAttributeName();

            // HTML empty attribute
            if (match('=')) {
                lex();
                return markerApply(marker, delegate.createJSXAttribute(name, parseJSXAttributeValue()));
            }

            return markerApply(marker, delegate.createJSXAttribute(name));
        }

        function parseJSXChild() {
            var token, marker;
            if (match('{')) {
                token = parseJSXExpressionContainer();
            } else if (lookahead.type === Token.JSXText) {
                marker = markerCreatePreserveWhitespace();
                token = markerApply(marker, delegate.createLiteral(lex()));
            } else if (match('<')) {
                token = parseJSXElement();
            } else {
                throwUnexpected(lookahead);
            }
            return token;
        }

        function parseJSXClosingElement() {
            var name, origInJSXChild, origInJSXTag, marker = markerCreate();
            origInJSXChild = state.inJSXChild;
            origInJSXTag = state.inJSXTag;
            state.inJSXChild = false;
            state.inJSXTag = true;
            expect('<');
            expect('/');
            name = parseJSXElementName();
            // Because advance() (called by lex() called by expect()) expects there
            // to be a valid token after >, it needs to know whether to look for a
            // standard JS token or an JSX text node
            state.inJSXChild = origInJSXChild;
            state.inJSXTag = origInJSXTag;
            expect('>');
            return markerApply(marker, delegate.createJSXClosingElement(name));
        }

        function parseJSXOpeningElement() {
            var name, attributes = [], selfClosing = false, origInJSXChild, origInJSXTag, marker = markerCreate();

            origInJSXChild = state.inJSXChild;
            origInJSXTag = state.inJSXTag;
            state.inJSXChild = false;
            state.inJSXTag = true;

            expect('<');

            name = parseJSXElementName();

            while (index < length &&
                    lookahead.value !== '/' &&
                    lookahead.value !== '>') {
                attributes.push(parseJSXAttribute());
            }

            state.inJSXTag = origInJSXTag;

            if (lookahead.value === '/') {
                expect('/');
                // Because advance() (called by lex() called by expect()) expects
                // there to be a valid token after >, it needs to know whether to
                // look for a standard JS token or an JSX text node
                state.inJSXChild = origInJSXChild;
                expect('>');
                selfClosing = true;
            } else {
                state.inJSXChild = true;
                expect('>');
            }
            return markerApply(marker, delegate.createJSXOpeningElement(name, attributes, selfClosing));
        }

        function parseJSXElement() {
            var openingElement, closingElement = null, children = [], origInJSXChild, origInJSXTag, marker = markerCreate();

            origInJSXChild = state.inJSXChild;
            origInJSXTag = state.inJSXTag;
            openingElement = parseJSXOpeningElement();

            if (!openingElement.selfClosing) {
                while (index < length) {
                    state.inJSXChild = false; // Call lookahead2() with inJSXChild = false because </ should not be considered in the child
                    if (lookahead.value === '<' && lookahead2().value === '/') {
                        break;
                    }
                    state.inJSXChild = true;
                    children.push(parseJSXChild());
                }
                state.inJSXChild = origInJSXChild;
                state.inJSXTag = origInJSXTag;
                closingElement = parseJSXClosingElement();
                if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
                    throwError({}, Messages.ExpectedJSXClosingTag, getQualifiedJSXName(openingElement.name));
                }
            }

            // When (erroneously) writing two adjacent tags like
            //
            //     var x = <div>one</div><div>two</div>;
            //
            // the default error message is a bit incomprehensible. Since it's
            // rarely (never?) useful to write a less-than sign after an JSX
            // element, we disallow it here in the parser in order to provide a
            // better error message. (In the rare case that the less-than operator
            // was intended, the left tag can be wrapped in parentheses.)
            if (!origInJSXChild && match('<')) {
                throwError(lookahead, Messages.AdjacentJSXElements);
            }

            return markerApply(marker, delegate.createJSXElement(openingElement, closingElement, children));
        }

        function parseTypeAlias() {
            var id, marker = markerCreate(), typeParameters = null, right;
            expectContextualKeyword('type');
            id = parseVariableIdentifier();
            if (match('<')) {
                typeParameters = parseTypeParameterDeclaration();
            }
            expect('=');
            right = parseType();
            consumeSemicolon();
            return markerApply(marker, delegate.createTypeAlias(id, typeParameters, right));
        }

        function parseInterfaceExtends() {
            var marker = markerCreate(), id, typeParameters = null;

            id = parseVariableIdentifier();
            if (match('<')) {
                typeParameters = parseTypeParameterInstantiation();
            }

            return markerApply(marker, delegate.createInterfaceExtends(
                id,
                typeParameters
            ));
        }

        function parseInterfaceish(marker, allowStatic) {
            var body, bodyMarker, extended = [], id,
                typeParameters = null;

            id = parseVariableIdentifier();
            if (match('<')) {
                typeParameters = parseTypeParameterDeclaration();
            }

            if (matchKeyword('extends')) {
                expectKeyword('extends');

                while (index < length) {
                    extended.push(parseInterfaceExtends());
                    if (!match(',')) {
                        break;
                    }
                    expect(',');
                }
            }

            bodyMarker = markerCreate();
            body = markerApply(bodyMarker, parseObjectType(allowStatic));

            return markerApply(marker, delegate.createInterface(
                id,
                typeParameters,
                body,
                extended
            ));
        }

        function parseInterface() {
            var marker = markerCreate();

            if (strict) {
                expectKeyword('interface');
            } else {
                expectContextualKeyword('interface');
            }

            return parseInterfaceish(marker, /* allowStatic */false);
        }

        function parseDeclareClass() {
            var marker = markerCreate(), ret;
            expectContextualKeyword('declare');
            expectKeyword('class');

            ret = parseInterfaceish(marker, /* allowStatic */true);
            ret.type = Syntax.DeclareClass;
            return ret;
        }

        function parseDeclareFunction() {
            var id, idMarker,
                marker = markerCreate(), params, returnType, rest, tmp,
                typeParameters = null, value, valueMarker;

            expectContextualKeyword('declare');
            expectKeyword('function');
            idMarker = markerCreate();
            id = parseVariableIdentifier();

            valueMarker = markerCreate();
            if (match('<')) {
                typeParameters = parseTypeParameterDeclaration();
            }
            expect('(');
            tmp = parseFunctionTypeParams();
            params = tmp.params;
            rest = tmp.rest;
            expect(')');

            expect(':');
            returnType = parseType();

            value = markerApply(valueMarker, delegate.createFunctionTypeAnnotation(
                params,
                returnType,
                rest,
                typeParameters
            ));

            id.typeAnnotation = markerApply(valueMarker, delegate.createTypeAnnotation(
                value
            ));
            markerApply(idMarker, id);

            consumeSemicolon();

            return markerApply(marker, delegate.createDeclareFunction(
                id
            ));
        }

        function parseDeclareVariable() {
            var id, marker = markerCreate();
            expectContextualKeyword('declare');
            expectKeyword('var');
            id = parseTypeAnnotatableIdentifier();

            consumeSemicolon();

            return markerApply(marker, delegate.createDeclareVariable(
                id
            ));
        }

        function parseDeclareModule() {
            var body = [], bodyMarker, id, idMarker, marker = markerCreate(), token;
            expectContextualKeyword('declare');
            expectContextualKeyword('module');

            if (lookahead.type === Token.StringLiteral) {
                if (strict && lookahead.octal) {
                    throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
                }
                idMarker = markerCreate();
                id = markerApply(idMarker, delegate.createLiteral(lex()));
            } else {
                id = parseVariableIdentifier();
            }

            bodyMarker = markerCreate();
            expect('{');
            while (index < length && !match('}')) {
                token = lookahead2();
                switch (token.value) {
                case 'class':
                    body.push(parseDeclareClass());
                    break;
                case 'function':
                    body.push(parseDeclareFunction());
                    break;
                case 'var':
                    body.push(parseDeclareVariable());
                    break;
                default:
                    throwUnexpected(lookahead);
                }
            }
            expect('}');

            return markerApply(marker, delegate.createDeclareModule(
                id,
                markerApply(bodyMarker, delegate.createBlockStatement(body))
            ));
        }

        function collectToken() {
            var loc, token, range, value, entry;

            /* istanbul ignore else */
            if (!state.inJSXChild) {
                skipComment();
            }

            loc = {
                start: {
                    line: lineNumber,
                    column: index - lineStart
                }
            };

            token = extra.advance();
            loc.end = {
                line: lineNumber,
                column: index - lineStart
            };

            if (token.type !== Token.EOF) {
                range = [token.range[0], token.range[1]];
                value = source.slice(token.range[0], token.range[1]);
                entry = {
                    type: TokenName[token.type],
                    value: value,
                    range: range,
                    loc: loc
                };
                if (token.regex) {
                    entry.regex = {
                        pattern: token.regex.pattern,
                        flags: token.regex.flags
                    };
                }
                extra.tokens.push(entry);
            }

            return token;
        }

        function collectRegex() {
            var pos, loc, regex, token;

            skipComment();

            pos = index;
            loc = {
                start: {
                    line: lineNumber,
                    column: index - lineStart
                }
            };

            regex = extra.scanRegExp();
            loc.end = {
                line: lineNumber,
                column: index - lineStart
            };

            if (!extra.tokenize) {
                /* istanbul ignore next */
                // Pop the previous token, which is likely '/' or '/='
                if (extra.tokens.length > 0) {
                    token = extra.tokens[extra.tokens.length - 1];
                    if (token.range[0] === pos && token.type === 'Punctuator') {
                        if (token.value === '/' || token.value === '/=') {
                            extra.tokens.pop();
                        }
                    }
                }

                extra.tokens.push({
                    type: 'RegularExpression',
                    value: regex.literal,
                    regex: regex.regex,
                    range: [pos, index],
                    loc: loc
                });
            }

            return regex;
        }

        function filterTokenLocation() {
            var i, entry, token, tokens = [];

            for (i = 0; i < extra.tokens.length; ++i) {
                entry = extra.tokens[i];
                token = {
                    type: entry.type,
                    value: entry.value
                };
                if (entry.regex) {
                    token.regex = {
                        pattern: entry.regex.pattern,
                        flags: entry.regex.flags
                    };
                }
                if (extra.range) {
                    token.range = entry.range;
                }
                if (extra.loc) {
                    token.loc = entry.loc;
                }
                tokens.push(token);
            }

            extra.tokens = tokens;
        }

        function patch() {
            if (typeof extra.tokens !== 'undefined') {
                extra.advance = advance;
                extra.scanRegExp = scanRegExp;

                advance = collectToken;
                scanRegExp = collectRegex;
            }
        }

        function unpatch() {
            if (typeof extra.scanRegExp === 'function') {
                advance = extra.advance;
                scanRegExp = extra.scanRegExp;
            }
        }

        // This is used to modify the delegate.

        function extend(object, properties) {
            var entry, result = {};

            for (entry in object) {
                /* istanbul ignore else */
                if (object.hasOwnProperty(entry)) {
                    result[entry] = object[entry];
                }
            }

            for (entry in properties) {
                /* istanbul ignore else */
                if (properties.hasOwnProperty(entry)) {
                    result[entry] = properties[entry];
                }
            }

            return result;
        }

        function tokenize(code, options) {
            var toString,
                token,
                tokens;

            toString = String;
            if (typeof code !== 'string' && !(code instanceof String)) {
                code = toString(code);
            }

            delegate = SyntaxTreeDelegate;
            source = code;
            index = 0;
            lineNumber = (source.length > 0) ? 1 : 0;
            lineStart = 0;
            length = source.length;
            lookahead = null;
            state = {
                allowKeyword: true,
                allowIn: true,
                labelSet: new StringMap(),
                inFunctionBody: false,
                inIteration: false,
                inSwitch: false,
                lastCommentStart: -1,
                curlyStack: [],
                curlyLastIndex: 0
            };

            extra = {};

            // Options matching.
            options = options || {};

            // Of course we collect tokens here.
            options.tokens = true;
            extra.tokens = [];
            extra.tokenize = true;
            // The following two fields are necessary to compute the Regex tokens.
            extra.openParenToken = -1;
            extra.openCurlyToken = -1;

            extra.range = (typeof options.range === 'boolean') && options.range;
            extra.loc = (typeof options.loc === 'boolean') && options.loc;

            if (typeof options.comment === 'boolean' && options.comment) {
                extra.comments = [];
            }
            if (typeof options.tolerant === 'boolean' && options.tolerant) {
                extra.errors = [];
            }

            patch();

            try {
                peek();
                if (lookahead.type === Token.EOF) {
                    return extra.tokens;
                }

                token = lex();
                while (lookahead.type !== Token.EOF) {
                    try {
                        token = lex();
                    } catch (lexError) {
                        token = lookahead;
                        if (extra.errors) {
                            extra.errors.push(lexError);
                            // We have to break on the first error
                            // to avoid infinite loops.
                            break;
                        } else {
                            throw lexError;
                        }
                    }
                }

                filterTokenLocation();
                tokens = extra.tokens;
                if (typeof extra.comments !== 'undefined') {
                    tokens.comments = extra.comments;
                }
                if (typeof extra.errors !== 'undefined') {
                    tokens.errors = extra.errors;
                }
            } catch (e) {
                throw e;
            } finally {
                unpatch();
                extra = {};
            }
            return tokens;
        }

        function parse(code, options) {
            var program, toString;

            toString = String;
            if (typeof code !== 'string' && !(code instanceof String)) {
                code = toString(code);
            }

            delegate = SyntaxTreeDelegate;
            source = code;
            index = 0;
            lineNumber = (source.length > 0) ? 1 : 0;
            lineStart = 0;
            length = source.length;
            lookahead = null;
            state = {
                allowKeyword: false,
                allowIn: true,
                labelSet: new StringMap(),
                parenthesizedCount: 0,
                inFunctionBody: false,
                inIteration: false,
                inSwitch: false,
                inJSXChild: false,
                inJSXTag: false,
                inType: false,
                lastCommentStart: -1,
                yieldAllowed: false,
                awaitAllowed: false,
                curlyPosition: 0,
                curlyStack: [],
                curlyLastIndex: 0
            };

            extra = {};
            if (typeof options !== 'undefined') {
                extra.range = (typeof options.range === 'boolean') && options.range;
                extra.loc = (typeof options.loc === 'boolean') && options.loc;
                extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment;

                if (extra.loc && options.source !== null && options.source !== undefined) {
                    delegate = extend(delegate, {
                        'postProcess': function (node) {
                            node.loc.source = toString(options.source);
                            return node;
                        }
                    });
                }

                extra.sourceType = options.sourceType;
                if (typeof options.tokens === 'boolean' && options.tokens) {
                    extra.tokens = [];
                }
                if (typeof options.comment === 'boolean' && options.comment) {
                    extra.comments = [];
                }
                if (typeof options.tolerant === 'boolean' && options.tolerant) {
                    extra.errors = [];
                }
                if (extra.attachComment) {
                    extra.range = true;
                    extra.comments = [];
                    extra.bottomRightStack = [];
                    extra.trailingComments = [];
                    extra.leadingComments = [];
                }
            }

            patch();
            try {
                program = parseProgram();
                if (typeof extra.comments !== 'undefined') {
                    program.comments = extra.comments;
                }
                if (typeof extra.tokens !== 'undefined') {
                    filterTokenLocation();
                    program.tokens = extra.tokens;
                }
                if (typeof extra.errors !== 'undefined') {
                    program.errors = extra.errors;
                }
            } catch (e) {
                throw e;
            } finally {
                unpatch();
                extra = {};
            }

            return program;
        }

        // Sync with *.json manifests.
        exports.version = '15001.1001.0-dev-harmony-fb';

        exports.tokenize = tokenize;

        exports.parse = parse;

        // Deep copy.
       /* istanbul ignore next */
        exports.Syntax = (function () {
            var name, types = {};

            if (typeof Object.create === 'function') {
                types = Object.create(null);
            }

            for (name in Syntax) {
                if (Syntax.hasOwnProperty(name)) {
                    types[name] = Syntax[name];
                }
            }

            if (typeof Object.freeze === 'function') {
                Object.freeze(types);
            }

            return types;
        }());

    }));
    /* vim: set sw=4 ts=4 et tw=80 : */

  provide("esprima-fb", module.exports);
}(global));

// pakmanager:ansi-regex
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    module.exports = function () {
    	return /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
    };

  provide("ansi-regex", module.exports);
}(global));

// pakmanager:has-flag
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  'use strict';
    module.exports = function (flag, argv) {
    	argv = argv || process.argv;

    	var terminatorPos = argv.indexOf('--');
    	var prefix = /^--/.test(flag) ? '' : '--';
    	var pos = argv.indexOf(prefix + flag);

    	return pos !== -1 && (terminatorPos !== -1 ? pos < terminatorPos : true);
    };

  provide("has-flag", module.exports);
}(global));

// pakmanager:lodash._basecopy
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  /**
     * lodash 3.0.1 (Custom Build) <https://lodash.com/>
     * Build: `lodash modern modularize exports="npm" -o ./`
     * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
     * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
     * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
     * Available under MIT license <https://lodash.com/license>
     */

    /**
     * Copies properties of `source` to `object`.
     *
     * @private
     * @param {Object} source The object to copy properties from.
     * @param {Array} props The property names to copy.
     * @param {Object} [object={}] The object to copy properties to.
     * @returns {Object} Returns `object`.
     */
    function baseCopy(source, props, object) {
      object || (object = {});

      var index = -1,
          length = props.length;

      while (++index < length) {
        var key = props[index];
        object[key] = source[key];
      }
      return object;
    }

    module.exports = baseCopy;

  provide("lodash._basecopy", module.exports);
}(global));

// pakmanager:lodash.keys
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  /**
     * lodash 3.1.2 (Custom Build) <https://lodash.com/>
     * Build: `lodash modern modularize exports="npm" -o ./`
     * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
     * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
     * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
     * Available under MIT license <https://lodash.com/license>
     */
    var getNative = require('lodash._getnative'),
        isArguments = require('lodash.isarguments'),
        isArray = require('lodash.isarray');

    /** Used to detect unsigned integer values. */
    var reIsUint = /^\d+$/;

    /** Used for native method references. */
    var objectProto = Object.prototype;

    /** Used to check objects for own properties. */
    var hasOwnProperty = objectProto.hasOwnProperty;

    /* Native method references for those with the same name as other `lodash` methods. */
    var nativeKeys = getNative(Object, 'keys');

    /**
     * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
     * of an array-like value.
     */
    var MAX_SAFE_INTEGER = 9007199254740991;

    /**
     * The base implementation of `_.property` without support for deep paths.
     *
     * @private
     * @param {string} key The key of the property to get.
     * @returns {Function} Returns the new function.
     */
    function baseProperty(key) {
      return function(object) {
        return object == null ? undefined : object[key];
      };
    }

    /**
     * Gets the "length" property value of `object`.
     *
     * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
     * that affects Safari on at least iOS 8.1-8.3 ARM64.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {*} Returns the "length" value.
     */
    var getLength = baseProperty('length');

    /**
     * Checks if `value` is array-like.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
     */
    function isArrayLike(value) {
      return value != null && isLength(getLength(value));
    }

    /**
     * Checks if `value` is a valid array-like index.
     *
     * @private
     * @param {*} value The value to check.
     * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
     * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
     */
    function isIndex(value, length) {
      value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
      length = length == null ? MAX_SAFE_INTEGER : length;
      return value > -1 && value % 1 == 0 && value < length;
    }

    /**
     * Checks if `value` is a valid array-like length.
     *
     * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
     */
    function isLength(value) {
      return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
    }

    /**
     * A fallback implementation of `Object.keys` which creates an array of the
     * own enumerable property names of `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property names.
     */
    function shimKeys(object) {
      var props = keysIn(object),
          propsLength = props.length,
          length = propsLength && object.length;

      var allowIndexes = !!length && isLength(length) &&
        (isArray(object) || isArguments(object));

      var index = -1,
          result = [];

      while (++index < propsLength) {
        var key = props[index];
        if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
          result.push(key);
        }
      }
      return result;
    }

    /**
     * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
     *
     * @static
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an object, else `false`.
     * @example
     *
     * _.isObject({});
     * // => true
     *
     * _.isObject([1, 2, 3]);
     * // => true
     *
     * _.isObject(1);
     * // => false
     */
    function isObject(value) {
      // Avoid a V8 JIT bug in Chrome 19-20.
      // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
      var type = typeof value;
      return !!value && (type == 'object' || type == 'function');
    }

    /**
     * Creates an array of the own enumerable property names of `object`.
     *
     * **Note:** Non-object values are coerced to objects. See the
     * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
     * for more details.
     *
     * @static
     * @memberOf _
     * @category Object
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property names.
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.keys(new Foo);
     * // => ['a', 'b'] (iteration order is not guaranteed)
     *
     * _.keys('hi');
     * // => ['0', '1']
     */
    var keys = !nativeKeys ? shimKeys : function(object) {
      var Ctor = object == null ? undefined : object.constructor;
      if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
          (typeof object != 'function' && isArrayLike(object))) {
        return shimKeys(object);
      }
      return isObject(object) ? nativeKeys(object) : [];
    };

    /**
     * Creates an array of the own and inherited enumerable property names of `object`.
     *
     * **Note:** Non-object values are coerced to objects.
     *
     * @static
     * @memberOf _
     * @category Object
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property names.
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.keysIn(new Foo);
     * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
     */
    function keysIn(object) {
      if (object == null) {
        return [];
      }
      if (!isObject(object)) {
        object = Object(object);
      }
      var length = object.length;
      length = (length && isLength(length) &&
        (isArray(object) || isArguments(object)) && length) || 0;

      var Ctor = object.constructor,
          index = -1,
          isProto = typeof Ctor == 'function' && Ctor.prototype === object,
          result = Array(length),
          skipIndexes = length > 0;

      while (++index < length) {
        result[index] = (index + '');
      }
      for (var key in object) {
        if (!(skipIndexes && isIndex(key, length)) &&
            !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
          result.push(key);
        }
      }
      return result;
    }

    module.exports = keys;

  provide("lodash.keys", module.exports);
}(global));

// pakmanager:lodash._bindcallback
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  /**
     * lodash 3.0.1 (Custom Build) <https://lodash.com/>
     * Build: `lodash modern modularize exports="npm" -o ./`
     * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
     * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
     * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
     * Available under MIT license <https://lodash.com/license>
     */

    /**
     * A specialized version of `baseCallback` which only supports `this` binding
     * and specifying the number of arguments to provide to `func`.
     *
     * @private
     * @param {Function} func The function to bind.
     * @param {*} thisArg The `this` binding of `func`.
     * @param {number} [argCount] The number of arguments to provide to `func`.
     * @returns {Function} Returns the callback.
     */
    function bindCallback(func, thisArg, argCount) {
      if (typeof func != 'function') {
        return identity;
      }
      if (thisArg === undefined) {
        return func;
      }
      switch (argCount) {
        case 1: return function(value) {
          return func.call(thisArg, value);
        };
        case 3: return function(value, index, collection) {
          return func.call(thisArg, value, index, collection);
        };
        case 4: return function(accumulator, value, index, collection) {
          return func.call(thisArg, accumulator, value, index, collection);
        };
        case 5: return function(value, other, key, object, source) {
          return func.call(thisArg, value, other, key, object, source);
        };
      }
      return function() {
        return func.apply(thisArg, arguments);
      };
    }

    /**
     * This method returns the first argument provided to it.
     *
     * @static
     * @memberOf _
     * @category Utility
     * @param {*} value Any value.
     * @returns {*} Returns `value`.
     * @example
     *
     * var object = { 'user': 'fred' };
     *
     * _.identity(object) === object;
     * // => true
     */
    function identity(value) {
      return value;
    }

    module.exports = bindCallback;

  provide("lodash._bindcallback", module.exports);
}(global));

// pakmanager:lodash._isiterateecall
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  /**
     * lodash 3.0.9 (Custom Build) <https://lodash.com/>
     * Build: `lodash modern modularize exports="npm" -o ./`
     * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
     * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
     * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
     * Available under MIT license <https://lodash.com/license>
     */

    /** Used to detect unsigned integer values. */
    var reIsUint = /^\d+$/;

    /**
     * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
     * of an array-like value.
     */
    var MAX_SAFE_INTEGER = 9007199254740991;

    /**
     * The base implementation of `_.property` without support for deep paths.
     *
     * @private
     * @param {string} key The key of the property to get.
     * @returns {Function} Returns the new function.
     */
    function baseProperty(key) {
      return function(object) {
        return object == null ? undefined : object[key];
      };
    }

    /**
     * Gets the "length" property value of `object`.
     *
     * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
     * that affects Safari on at least iOS 8.1-8.3 ARM64.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {*} Returns the "length" value.
     */
    var getLength = baseProperty('length');

    /**
     * Checks if `value` is array-like.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
     */
    function isArrayLike(value) {
      return value != null && isLength(getLength(value));
    }

    /**
     * Checks if `value` is a valid array-like index.
     *
     * @private
     * @param {*} value The value to check.
     * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
     * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
     */
    function isIndex(value, length) {
      value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
      length = length == null ? MAX_SAFE_INTEGER : length;
      return value > -1 && value % 1 == 0 && value < length;
    }

    /**
     * Checks if the provided arguments are from an iteratee call.
     *
     * @private
     * @param {*} value The potential iteratee value argument.
     * @param {*} index The potential iteratee index or key argument.
     * @param {*} object The potential iteratee object argument.
     * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
     */
    function isIterateeCall(value, index, object) {
      if (!isObject(object)) {
        return false;
      }
      var type = typeof index;
      if (type == 'number'
          ? (isArrayLike(object) && isIndex(index, object.length))
          : (type == 'string' && index in object)) {
        var other = object[index];
        return value === value ? (value === other) : (other !== other);
      }
      return false;
    }

    /**
     * Checks if `value` is a valid array-like length.
     *
     * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
     */
    function isLength(value) {
      return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
    }

    /**
     * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
     *
     * @static
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an object, else `false`.
     * @example
     *
     * _.isObject({});
     * // => true
     *
     * _.isObject([1, 2, 3]);
     * // => true
     *
     * _.isObject(1);
     * // => false
     */
    function isObject(value) {
      // Avoid a V8 JIT bug in Chrome 19-20.
      // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
      var type = typeof value;
      return !!value && (type == 'object' || type == 'function');
    }

    module.exports = isIterateeCall;

  provide("lodash._isiterateecall", module.exports);
}(global));

// pakmanager:lodash.restparam
(function (context) {

  var module = { exports: {} }, exports = module.exports
    , $ = require("ender")
    ;

  /**
     * lodash 3.6.1 (Custom Build) <https://lodash.com/>
     * Build: `lodash modern modularize exports="npm" -o ./`
     * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
     * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
     * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
     * Available under MIT license <https://lodash.com/license>
     */

    /** Used as the `TypeError` message for "Functions" methods. */
    var FUNC_ERROR_TEXT = 'Expected a function';

    /* Native method references for those with the same name as other `lodash` methods. */
    var nativeMax = Math.max;

    /**
     * Creates a function that invokes `func` with the `this` binding of the
     * created function and arguments from `start` and beyond provided as an array.
     *
     * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters).
     *
     * @static
     * @memberOf _
     * @category Function
     * @param {Function} func The function to apply a rest parameter to.
     * @param {number} [start=func.length-1] The start position of the rest parameter.
     * @returns {Function} Returns the new function.
     * @example
     *
     * var say = _.restParam(function(what, names) {
     *   return what + ' ' + _.initial(names).join(', ') +
     *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
     * });
     *
     * say('hello', 'fred', 'barney', 'pebbles');
     * // => 'hello fred, barney, & pebbles'
     */
    function restParam(func, start) {
      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
      return function() {
        var args = arguments,
            index = -1,
            length = nativeMax(args.length - start, 0),
            rest = Array(length);

        while (++index < length) {
          rest[index] = args[start + index];
        }
        switch (start) {
          case 0: return func.call(this, rest);
          case 1: return func.call(this, args[0], rest);
          c