You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cmda.apache.org by xi...@apache.org on 2015/10/17 01:11:53 UTC

[19/51] [partial] incubator-cmda git commit: Update ApacheCMDA_1.0

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/a9a83675/ApacheCMDA_Backend_1.0/project/target/node-modules/webjars/jshint/src/jshint.js
----------------------------------------------------------------------
diff --git a/ApacheCMDA_Backend_1.0/project/target/node-modules/webjars/jshint/src/jshint.js b/ApacheCMDA_Backend_1.0/project/target/node-modules/webjars/jshint/src/jshint.js
new file mode 100644
index 0000000..6783f5d
--- /dev/null
+++ b/ApacheCMDA_Backend_1.0/project/target/node-modules/webjars/jshint/src/jshint.js
@@ -0,0 +1,5136 @@
+/*!
+ * JSHint, by JSHint Community.
+ *
+ * This file (and this file only) is licensed under the same slightly modified
+ * MIT license that JSLint is. It stops evil-doers everywhere:
+ *
+ *	 Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)
+ *
+ *	 Permission is hereby granted, free of charge, to any person obtaining
+ *	 a copy of this software and associated documentation files (the "Software"),
+ *	 to deal in the Software without restriction, including without limitation
+ *	 the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *	 and/or sell copies of the Software, and to permit persons to whom
+ *	 the Software is furnished to do so, subject to the following conditions:
+ *
+ *	 The above copyright notice and this permission notice shall be included
+ *	 in all copies or substantial portions of the Software.
+ *
+ *	 The Software shall be used for Good, not Evil.
+ *
+ *	 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *	 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *	 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *	 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *	 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *	 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *	 DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*jshint quotmark:double */
+/*global console:true */
+/*exported console */
+
+var _        = require("underscore");
+var events   = require("events");
+var vars     = require("./vars.js");
+var messages = require("./messages.js");
+var Lexer    = require("./lex.js").Lexer;
+var reg      = require("./reg.js");
+var state    = require("./state.js").state;
+var style    = require("./style.js");
+
+// We need this module here because environments such as IE and Rhino
+// don't necessarilly expose the 'console' API and browserify uses
+// it to log things. It's a sad state of affair, really.
+var console = require("console-browserify");
+
+// We build the application inside a function so that we produce only a singleton
+// variable. That function will be invoked immediately, and its return value is
+// the JSHINT function itself.
+
+var JSHINT = (function () {
+	"use strict";
+
+	var anonname, // The guessed name for anonymous functions.
+		api, // Extension API
+
+		// These are operators that should not be used with the ! operator.
+		bang = {
+			"<"  : true,
+			"<=" : true,
+			"==" : true,
+			"===": true,
+			"!==": true,
+			"!=" : true,
+			">"  : true,
+			">=" : true,
+			"+"  : true,
+			"-"  : true,
+			"*"  : true,
+			"/"  : true,
+			"%"  : true
+		},
+
+		// These are the JSHint boolean options.
+		boolOptions = {
+			asi         : true, // if automatic semicolon insertion should be tolerated
+			bitwise     : true, // if bitwise operators should not be allowed
+			boss        : true, // if advanced usage of assignments should be allowed
+			browser     : true, // if the standard browser globals should be predefined
+			camelcase   : true, // if identifiers should be required in camel case
+			couch       : true, // if CouchDB globals should be predefined
+			curly       : true, // if curly braces around all blocks should be required
+			debug       : true, // if debugger statements should be allowed
+			devel       : true, // if logging globals should be predefined (console, alert, etc.)
+			dojo        : true, // if Dojo Toolkit globals should be predefined
+			eqeqeq      : true, // if === should be required
+			eqnull      : true, // if == null comparisons should be tolerated
+			notypeof    : true, // if should report typos in typeof comparisons
+			es3         : true, // if ES3 syntax should be allowed
+			es5         : true, // if ES5 syntax should be allowed (is now set per default)
+			esnext      : true, // if es.next specific syntax should be allowed
+			moz         : true, // if mozilla specific syntax should be allowed
+			evil        : true, // if eval should be allowed
+			expr        : true, // if ExpressionStatement should be allowed as Programs
+			forin       : true, // if for in statements must filter
+			funcscope   : true, // if only function scope should be used for scope tests
+			gcl         : true, // if JSHint should be compatible with Google Closure Linter
+			globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict')
+			immed       : true, // if immediate invocations must be wrapped in parens
+			iterator    : true, // if the `__iterator__` property should be allowed
+			jquery      : true, // if jQuery globals should be predefined
+			lastsemic   : true, // if semicolons may be ommitted for the trailing
+			                    // statements inside of a one-line blocks.
+			laxbreak    : true, // if line breaks should not be checked
+			laxcomma    : true, // if line breaks should not be checked around commas
+			loopfunc    : true, // if functions should be allowed to be defined within
+			                    // loops
+			mootools    : true, // if MooTools globals should be predefined
+			multistr    : true, // allow multiline strings
+			freeze      : true, // if modifying native object prototypes should be disallowed
+			newcap      : true, // if constructor names must be capitalized
+			noarg       : true, // if arguments.caller and arguments.callee should be
+			                    // disallowed
+			node        : true, // if the Node.js environment globals should be
+			                    // predefined
+			noempty     : true, // if empty blocks should be disallowed
+			nonew       : true, // if using `new` for side-effects should be disallowed
+			nonstandard : true, // if non-standard (but widely adopted) globals should
+			                    // be predefined
+			nomen       : true, // if names should be checked
+			onevar      : true, // if only one var statement per function should be
+			                    // allowed
+			passfail    : true, // if the scan should stop on first error
+			phantom     : true, // if PhantomJS symbols should be allowed
+			plusplus    : true, // if increment/decrement should not be allowed
+			proto       : true, // if the `__proto__` property should be allowed
+			prototypejs : true, // if Prototype and Scriptaculous globals should be
+			                    // predefined
+			rhino       : true, // if the Rhino environment globals should be predefined
+			shelljs     : true, // if ShellJS globals should be predefined
+			typed       : true, // if typed array globals should be predefined
+			undef       : true, // if variables should be declared before used
+			scripturl   : true, // if script-targeted URLs should be tolerated
+			smarttabs   : true, // if smarttabs should be tolerated
+			                    // (http://www.emacswiki.org/emacs/SmartTabs)
+			strict      : true, // require the "use strict"; pragma
+			sub         : true, // if all forms of subscript notation are tolerated
+			supernew    : true, // if `new function () { ... };` and `new Object;`
+			                    // should be tolerated
+			trailing    : true, // if trailing whitespace rules apply
+			validthis   : true, // if 'this' inside a non-constructor function is valid.
+			                    // This is a function scoped option only.
+			withstmt    : true, // if with statements should be allowed
+			white       : true, // if strict whitespace rules apply
+			worker      : true, // if Web Worker script symbols should be allowed
+			wsh         : true, // if the Windows Scripting Host environment globals
+			                    // should be predefined
+			yui         : true, // YUI variables should be predefined
+			noyield     : true, // allow generators without a yield
+
+			// Obsolete options
+			onecase     : true, // if one case switch statements should be allowed
+			regexp      : true, // if the . should not be allowed in regexp literals
+			regexdash   : true  // if unescaped first/last dash (-) inside brackets
+			                    // should be tolerated
+		},
+
+		// These are the JSHint options that can take any value
+		// (we use this object to detect invalid options)
+		valOptions = {
+			maxlen       : false,
+			indent       : false,
+			maxerr       : false,
+			predef       : false, //predef is deprecated and being replaced by globals
+			globals      : false,
+			quotmark     : false, //'single'|'double'|true
+			scope        : false,
+			maxstatements: false, // {int} max statements per function
+			maxdepth     : false, // {int} max nested block depth per function
+			maxparams    : false, // {int} max params per function
+			maxcomplexity: false, // {int} max cyclomatic complexity per function
+			shadow       : false, // if variable shadowing should be tolerated
+			                      //   "inner"  - check for variables defined in the same scope only
+			                      //   "outer"  - check for variables defined in outer scopes as well
+			                      //   false    - same as inner
+			                      //   true     - allow variable shadowing
+			unused       : true,  // warn if variables are unused. Available options:
+			                      //   false    - don't check for unused variables
+			                      //   true     - "vars" + check last function param
+			                      //   "vars"   - skip checking unused function params
+			                      //   "strict" - "vars" + check all function params
+			latedef      : false, // warn if the variable is used before its definition
+			                      //   false    - don't emit any warnings
+			                      //   true     - warn if any variable is used before its definition
+			                      //   "nofunc" - warn for any variable but function declarations
+			ignore       : false  // start/end ignoring lines of code, bypassing the lexer
+			                      //   start    - start ignoring lines, including the current line
+			                      //   end      - stop ignoring lines, starting on the next line
+			                      //   line     - ignore warnings / errors for just a single line
+			                      //              (this option does not bypass the lexer)
+		},
+
+		// These are JSHint boolean options which are shared with JSLint
+		// where the definition in JSHint is opposite JSLint
+		invertedOptions = {
+			bitwise : true,
+			forin   : true,
+			newcap  : true,
+			nomen   : true,
+			plusplus: true,
+			regexp  : true,
+			undef   : true,
+			white   : true,
+
+			// Inverted and renamed, use JSHint name here
+			eqeqeq  : true,
+			onevar  : true,
+			strict  : true
+		},
+
+		// These are JSHint boolean options which are shared with JSLint
+		// where the name has been changed but the effect is unchanged
+		renamedOptions = {
+			eqeq   : "eqeqeq",
+			vars   : "onevar",
+			windows: "wsh",
+			sloppy : "strict"
+		},
+
+		declared, // Globals that were declared using /*global ... */ syntax.
+		exported, // Variables that are used outside of the current file.
+
+		functionicity = [
+			"closure", "exception", "global", "label",
+			"outer", "unused", "var"
+		],
+
+		funct, // The current function
+		functions, // All of the functions
+
+		global, // The global scope
+		implied, // Implied globals
+		inblock,
+		indent,
+		lookahead,
+		lex,
+		member,
+		membersOnly,
+		noreach,
+		predefined,		// Global variables defined by option
+
+		scope,  // The current scope
+		stack,
+		unuseds,
+		urls,
+		warnings,
+
+		extraModules = [],
+		emitter = new events.EventEmitter();
+
+	function checkOption(name, t) {
+		name = name.trim();
+
+		if (/^[+-]W\d{3}$/g.test(name)) {
+			return true;
+		}
+
+		if (valOptions[name] === undefined && boolOptions[name] === undefined) {
+			if (t.type !== "jslint") {
+				error("E001", t, name);
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	function isString(obj) {
+		return Object.prototype.toString.call(obj) === "[object String]";
+	}
+
+	function isIdentifier(tkn, value) {
+		if (!tkn)
+			return false;
+
+		if (!tkn.identifier || tkn.value !== value)
+			return false;
+
+		return true;
+	}
+
+	function isReserved(token) {
+		if (!token.reserved) {
+			return false;
+		}
+		var meta = token.meta;
+
+		if (meta && meta.isFutureReservedWord && state.option.inES5()) {
+			// ES3 FutureReservedWord in an ES5 environment.
+			if (!meta.es5) {
+				return false;
+			}
+
+			// Some ES5 FutureReservedWord identifiers are active only
+			// within a strict mode environment.
+			if (meta.strictOnly) {
+				if (!state.option.strict && !state.directive["use strict"]) {
+					return false;
+				}
+			}
+
+			if (token.isProperty) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	function supplant(str, data) {
+		return str.replace(/\{([^{}]*)\}/g, function (a, b) {
+			var r = data[b];
+			return typeof r === "string" || typeof r === "number" ? r : a;
+		});
+	}
+
+	function combine(dest, src) {
+		Object.keys(src).forEach(function (name) {
+			if (JSHINT.blacklist.hasOwnProperty(name)) return;
+			dest[name] = src[name];
+		});
+	}
+
+	function assume() {
+		if (state.option.es5) {
+			warning("I003");
+		}
+		if (state.option.couch) {
+			combine(predefined, vars.couch);
+		}
+
+		if (state.option.rhino) {
+			combine(predefined, vars.rhino);
+		}
+
+		if (state.option.shelljs) {
+			combine(predefined, vars.shelljs);
+			combine(predefined, vars.node);
+		}
+		if (state.option.typed) {
+			combine(predefined, vars.typed);
+		}
+
+		if (state.option.phantom) {
+			combine(predefined, vars.phantom);
+		}
+
+		if (state.option.prototypejs) {
+			combine(predefined, vars.prototypejs);
+		}
+
+		if (state.option.node) {
+			combine(predefined, vars.node);
+			combine(predefined, vars.typed);
+		}
+
+		if (state.option.devel) {
+			combine(predefined, vars.devel);
+		}
+
+		if (state.option.dojo) {
+			combine(predefined, vars.dojo);
+		}
+
+		if (state.option.browser) {
+			combine(predefined, vars.browser);
+			combine(predefined, vars.typed);
+		}
+
+		if (state.option.nonstandard) {
+			combine(predefined, vars.nonstandard);
+		}
+
+		if (state.option.jquery) {
+			combine(predefined, vars.jquery);
+		}
+
+		if (state.option.mootools) {
+			combine(predefined, vars.mootools);
+		}
+
+		if (state.option.worker) {
+			combine(predefined, vars.worker);
+		}
+
+		if (state.option.wsh) {
+			combine(predefined, vars.wsh);
+		}
+
+		if (state.option.globalstrict && state.option.strict !== false) {
+			state.option.strict = true;
+		}
+
+		if (state.option.yui) {
+			combine(predefined, vars.yui);
+		}
+
+		// Let's assume that chronologically ES3 < ES5 < ES6/ESNext < Moz
+
+		state.option.inMoz = function (strict) {
+			if (strict) {
+				return state.option.moz && !state.option.esnext;
+			}
+			return state.option.moz;
+		};
+
+		state.option.inESNext = function (strict) {
+			if (strict) {
+				return !state.option.moz && state.option.esnext;
+			}
+			return state.option.moz || state.option.esnext;
+		};
+
+		state.option.inES5 = function (/* strict */) {
+			return !state.option.es3;
+		};
+
+		state.option.inES3 = function (strict) {
+			if (strict) {
+				return !state.option.moz && !state.option.esnext && state.option.es3;
+			}
+			return state.option.es3;
+		};
+	}
+
+	// Produce an error warning.
+	function quit(code, line, chr) {
+		var percentage = Math.floor((line / state.lines.length) * 100);
+		var message = messages.errors[code].desc;
+
+		throw {
+			name: "JSHintError",
+			line: line,
+			character: chr,
+			message: message + " (" + percentage + "% scanned).",
+			raw: message,
+			code: code
+		};
+	}
+
+	function isundef(scope, code, token, a) {
+		return JSHINT.undefs.push([scope, code, token, a]);
+	}
+
+	function warning(code, t, a, b, c, d) {
+		var ch, l, w, msg;
+
+		if (/^W\d{3}$/.test(code)) {
+			if (state.ignored[code])
+				return;
+
+			msg = messages.warnings[code];
+		} else if (/E\d{3}/.test(code)) {
+			msg = messages.errors[code];
+		} else if (/I\d{3}/.test(code)) {
+			msg = messages.info[code];
+		}
+
+		t = t || state.tokens.next;
+		if (t.id === "(end)") {  // `~
+			t = state.tokens.curr;
+		}
+
+		l = t.line || 0;
+		ch = t.from || 0;
+
+		w = {
+			id: "(error)",
+			raw: msg.desc,
+			code: msg.code,
+			evidence: state.lines[l - 1] || "",
+			line: l,
+			character: ch,
+			scope: JSHINT.scope,
+			a: a,
+			b: b,
+			c: c,
+			d: d
+		};
+
+		w.reason = supplant(msg.desc, w);
+		JSHINT.errors.push(w);
+
+		if (state.option.passfail) {
+			quit("E042", l, ch);
+		}
+
+		warnings += 1;
+		if (warnings >= state.option.maxerr) {
+			quit("E043", l, ch);
+		}
+
+		return w;
+	}
+
+	function warningAt(m, l, ch, a, b, c, d) {
+		return warning(m, {
+			line: l,
+			from: ch
+		}, a, b, c, d);
+	}
+
+	function error(m, t, a, b, c, d) {
+		warning(m, t, a, b, c, d);
+	}
+
+	function errorAt(m, l, ch, a, b, c, d) {
+		return error(m, {
+			line: l,
+			from: ch
+		}, a, b, c, d);
+	}
+
+	// Tracking of "internal" scripts, like eval containing a static string
+	function addInternalSrc(elem, src) {
+		var i;
+		i = {
+			id: "(internal)",
+			elem: elem,
+			value: src
+		};
+		JSHINT.internals.push(i);
+		return i;
+	}
+
+	// name: string
+	// opts: { type: string, token: token, islet: bool }
+	function addlabel(name, opts) {
+		opts = opts || {};
+
+		var type  = opts.type;
+		var token = opts.token;
+		var islet = opts.islet;
+
+		// Define label in the current function in the current scope.
+		if (type === "exception") {
+			if (_.has(funct["(context)"], name)) {
+				if (funct[name] !== true && !state.option.node) {
+					warning("W002", state.tokens.next, name);
+				}
+			}
+		}
+
+		if (_.has(funct, name) && !funct["(global)"]) {
+			if (funct[name] === true) {
+				if (state.option.latedef) {
+					if ((state.option.latedef === true && _.contains([funct[name], type], "unction")) ||
+							!_.contains([funct[name], type], "unction")) {
+						warning("W003", state.tokens.next, name);
+					}
+				}
+			} else {
+				if ((!state.option.shadow || _.contains([ "inner", "outer" ], state.option.shadow)) &&
+						type !== "exception" || funct["(blockscope)"].getlabel(name)) {
+					warning("W004", state.tokens.next, name);
+				}
+			}
+		}
+
+		if (funct["(context)"] && _.has(funct["(context)"], name) && type !== "function") {
+			if (state.option.shadow === "outer") {
+				warning("W123", state.tokens.next, name);
+			}
+		}
+
+		// if the identifier is from a let, adds it only to the current blockscope
+		if (islet) {
+			funct["(blockscope)"].current.add(name, type, state.tokens.curr);
+		} else {
+			funct["(blockscope)"].shadow(name);
+			funct[name] = type;
+
+			if (token) {
+				funct["(tokens)"][name] = token;
+			}
+
+			setprop(funct, name, { unused: opts.unused || false });
+
+			if (funct["(global)"]) {
+				global[name] = funct;
+				if (_.has(implied, name)) {
+					if (state.option.latedef) {
+						if ((state.option.latedef === true && _.contains([funct[name], type], "unction")) ||
+								!_.contains([funct[name], type], "unction")) {
+							warning("W003", state.tokens.next, name);
+						}
+					}
+
+					delete implied[name];
+				}
+			} else {
+				scope[name] = funct;
+			}
+		}
+	}
+
+	function doOption() {
+		var nt = state.tokens.next;
+		var body = nt.body.split(",").map(function (s) { return s.trim(); });
+		var predef = {};
+
+		if (nt.type === "globals") {
+			body.forEach(function (g) {
+				g = g.split(":");
+				var key = (g[0] || "").trim();
+				var val = (g[1] || "").trim();
+
+				if (key.charAt(0) === "-") {
+					key = key.slice(1);
+					val = false;
+
+					JSHINT.blacklist[key] = key;
+					delete predefined[key];
+				} else {
+					predef[key] = (val === "true");
+				}
+			});
+
+			combine(predefined, predef);
+
+			for (var key in predef) {
+				if (_.has(predef, key)) {
+					declared[key] = nt;
+				}
+			}
+		}
+
+		if (nt.type === "exported") {
+			body.forEach(function (e) {
+				exported[e] = true;
+			});
+		}
+
+		if (nt.type === "members") {
+			membersOnly = membersOnly || {};
+
+			body.forEach(function (m) {
+				var ch1 = m.charAt(0);
+				var ch2 = m.charAt(m.length - 1);
+
+				if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) {
+					m = m
+						.substr(1, m.length - 2)
+						.replace("\\\"", "\"");
+				}
+
+				membersOnly[m] = false;
+			});
+		}
+
+		var numvals = [
+			"maxstatements",
+			"maxparams",
+			"maxdepth",
+			"maxcomplexity",
+			"maxerr",
+			"maxlen",
+			"indent"
+		];
+
+		if (nt.type === "jshint" || nt.type === "jslint") {
+			body.forEach(function (g) {
+				g = g.split(":");
+				var key = (g[0] || "").trim();
+				var val = (g[1] || "").trim();
+
+				if (!checkOption(key, nt)) {
+					return;
+				}
+
+				if (numvals.indexOf(key) >= 0) {
+
+					// GH988 - numeric options can be disabled by setting them to `false`
+					if (val !== "false") {
+						val = +val;
+
+						if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
+							error("E032", nt, g[1].trim());
+							return;
+						}
+
+						if (key === "indent") {
+							state.option["(explicitIndent)"] = true;
+						}
+						state.option[key] = val;
+					} else {
+						if (key === "indent") {
+							state.option["(explicitIndent)"] = false;
+						} else {
+							state.option[key] = false;
+						}
+					}
+
+					return;
+				}
+
+				if (key === "validthis") {
+					// `validthis` is valid only within a function scope.
+
+					if (funct["(global)"])
+						return void error("E009");
+
+					if (val !== "true" && val !== "false")
+						return void error("E002", nt);
+
+					state.option.validthis = (val === "true");
+					return;
+				}
+
+				if (key === "quotmark") {
+					switch (val) {
+					case "true":
+					case "false":
+						state.option.quotmark = (val === "true");
+						break;
+					case "double":
+					case "single":
+						state.option.quotmark = val;
+						break;
+					default:
+						error("E002", nt);
+					}
+					return;
+				}
+
+				if (key === "shadow") {
+					switch (val) {
+					case "true":
+						state.option.shadow = true;
+						break;
+					case "outer":
+						state.option.shadow = "outer";
+						break;
+					case "false":
+					case "inner":
+						state.option.shadow = "inner";
+						break;
+					default:
+						error("E002", nt);
+					}
+					return;
+				}
+
+				if (key === "unused") {
+					switch (val) {
+					case "true":
+						state.option.unused = true;
+						break;
+					case "false":
+						state.option.unused = false;
+						break;
+					case "vars":
+					case "strict":
+						state.option.unused = val;
+						break;
+					default:
+						error("E002", nt);
+					}
+					return;
+				}
+
+				if (key === "latedef") {
+					switch (val) {
+					case "true":
+						state.option.latedef = true;
+						break;
+					case "false":
+						state.option.latedef = false;
+						break;
+					case "nofunc":
+						state.option.latedef = "nofunc";
+						break;
+					default:
+						error("E002", nt);
+					}
+					return;
+				}
+
+				if (key === "ignore") {
+					switch (val) {
+					case "start":
+						state.ignoreLinterErrors = true;
+						break;
+					case "end":
+						state.ignoreLinterErrors = false;
+						break;
+					case "line":
+						// Any errors or warnings that happened on the current line, make them go away.
+						JSHINT.errors = _.reject(JSHINT.errors, function (error) {
+							// nt.line returns to the current line
+							return error.line === nt.line;
+						});
+						break;
+					default:
+						error("E002", nt);
+					}
+					return;
+				}
+
+				var match = /^([+-])(W\d{3})$/g.exec(key);
+				if (match) {
+					// ignore for -W..., unignore for +W...
+					state.ignored[match[2]] = (match[1] === "-");
+					return;
+				}
+
+				var tn;
+				if (val === "true" || val === "false") {
+					if (nt.type === "jslint") {
+						tn = renamedOptions[key] || key;
+						state.option[tn] = (val === "true");
+
+						if (invertedOptions[tn] !== undefined) {
+							state.option[tn] = !state.option[tn];
+						}
+					} else {
+						state.option[key] = (val === "true");
+					}
+
+					if (key === "newcap") {
+						state.option["(explicitNewcap)"] = true;
+					}
+					return;
+				}
+
+				error("E002", nt);
+			});
+
+			assume();
+		}
+	}
+
+	// We need a peek function. If it has an argument, it peeks that much farther
+	// ahead. It is used to distinguish
+	//	   for ( var i in ...
+	// from
+	//	   for ( var i = ...
+
+	function peek(p) {
+		var i = p || 0, j = 0, t;
+
+		while (j <= i) {
+			t = lookahead[j];
+			if (!t) {
+				t = lookahead[j] = lex.token();
+			}
+			j += 1;
+		}
+		return t;
+	}
+
+	// Produce the next token. It looks for programming errors.
+
+	function advance(id, t) {
+		switch (state.tokens.curr.id) {
+		case "(number)":
+			if (state.tokens.next.id === ".") {
+				warning("W005", state.tokens.curr);
+			}
+			break;
+		case "-":
+			if (state.tokens.next.id === "-" || state.tokens.next.id === "--") {
+				warning("W006");
+			}
+			break;
+		case "+":
+			if (state.tokens.next.id === "+" || state.tokens.next.id === "++") {
+				warning("W007");
+			}
+			break;
+		}
+
+		if (state.tokens.curr.type === "(string)" || state.tokens.curr.identifier) {
+			anonname = state.tokens.curr.value;
+		}
+
+		if (id && state.tokens.next.id !== id) {
+			if (t) {
+				if (state.tokens.next.id === "(end)") {
+					error("E019", t, t.id);
+				} else {
+					error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value);
+				}
+			} else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) {
+				warning("W116", state.tokens.next, id, state.tokens.next.value);
+			}
+		}
+
+		state.tokens.prev = state.tokens.curr;
+		state.tokens.curr = state.tokens.next;
+		for (;;) {
+			state.tokens.next = lookahead.shift() || lex.token();
+
+			if (!state.tokens.next) { // No more tokens left, give up
+				quit("E041", state.tokens.curr.line);
+			}
+
+			if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
+				return;
+			}
+
+			if (state.tokens.next.check) {
+				state.tokens.next.check();
+			}
+
+			if (state.tokens.next.isSpecial) {
+				doOption();
+			} else {
+				if (state.tokens.next.id !== "(endline)") {
+					break;
+				}
+			}
+		}
+	}
+
+	function isInfix(token) {
+		return token.infix || (!token.identifier && !!token.led);
+	}
+
+	function isEndOfExpr() {
+		var curr = state.tokens.curr;
+		var next = state.tokens.next;
+		if (next.id === ";" || next.id === "}" || next.id === ":") {
+			return true;
+		}
+		if (isInfix(next) === isInfix(curr) || (curr.id === "yield" && state.option.inMoz(true))) {
+			return curr.line !== next.line;
+		}
+		return false;
+	}
+
+	// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it
+	// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
+	// like .nud except that it is only used on the first token of a statement.
+	// Having .fud makes it much easier to define statement-oriented languages like
+	// JavaScript. I retained Pratt's nomenclature.
+
+	// .nud  Null denotation
+	// .fud  First null denotation
+	// .led  Left denotation
+	//  lbp  Left binding power
+	//  rbp  Right binding power
+
+	// They are elements of the parsing method called Top Down Operator Precedence.
+
+	function expression(rbp, initial) {
+		var left, isArray = false, isObject = false, isLetExpr = false;
+
+		// if current expression is a let expression
+		if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") {
+			if (!state.option.inMoz(true)) {
+				warning("W118", state.tokens.next, "let expressions");
+			}
+			isLetExpr = true;
+			// create a new block scope we use only for the current expression
+			funct["(blockscope)"].stack();
+			advance("let");
+			advance("(");
+			state.syntax["let"].fud.call(state.syntax["let"].fud, false);
+			advance(")");
+		}
+
+		if (state.tokens.next.id === "(end)")
+			error("E006", state.tokens.curr);
+
+		advance();
+
+		if (initial) {
+			anonname = "anonymous";
+			funct["(verb)"] = state.tokens.curr.value;
+		}
+
+		if (initial === true && state.tokens.curr.fud) {
+			left = state.tokens.curr.fud();
+		} else {
+			if (state.tokens.curr.nud) {
+				left = state.tokens.curr.nud();
+			} else {
+				error("E030", state.tokens.curr, state.tokens.curr.id);
+			}
+
+			while (rbp < state.tokens.next.lbp && !isEndOfExpr()) {
+				isArray = state.tokens.curr.value === "Array";
+				isObject = state.tokens.curr.value === "Object";
+
+				// #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
+				// Line breaks in IfStatement heads exist to satisfy the checkJSHint
+				// "Line too long." error.
+				if (left && (left.value || (left.first && left.first.value))) {
+					// If the left.value is not "new", or the left.first.value is a "."
+					// then safely assume that this is not "new Array()" and possibly
+					// not "new Object()"...
+					if (left.value !== "new" ||
+					  (left.first && left.first.value && left.first.value === ".")) {
+						isArray = false;
+						// ...In the case of Object, if the left.value and state.tokens.curr.value
+						// are not equal, then safely assume that this not "new Object()"
+						if (left.value !== state.tokens.curr.value) {
+							isObject = false;
+						}
+					}
+				}
+
+				advance();
+
+				if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
+					warning("W009", state.tokens.curr);
+				}
+
+				if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
+					warning("W010", state.tokens.curr);
+				}
+
+				if (left && state.tokens.curr.led) {
+					left = state.tokens.curr.led(left);
+				} else {
+					error("E033", state.tokens.curr, state.tokens.curr.id);
+				}
+			}
+		}
+		if (isLetExpr) {
+			funct["(blockscope)"].unstack();
+		}
+		return left;
+	}
+
+
+// Functions for conformance of style.
+
+	function adjacent(left, right) {
+		left = left || state.tokens.curr;
+		right = right || state.tokens.next;
+		if (state.option.white) {
+			if (left.character !== right.from && left.line === right.line) {
+				left.from += (left.character - left.from);
+				warning("W011", left, left.value);
+			}
+		}
+	}
+
+	function nobreak(left, right) {
+		left = left || state.tokens.curr;
+		right = right || state.tokens.next;
+		if (state.option.white && (left.character !== right.from || left.line !== right.line)) {
+			warning("W012", right, right.value);
+		}
+	}
+
+	function nospace(left, right) {
+		left = left || state.tokens.curr;
+		right = right || state.tokens.next;
+		if (state.option.white && !left.comment) {
+			if (left.line === right.line) {
+				adjacent(left, right);
+			}
+		}
+	}
+
+	function nonadjacent(left, right) {
+		if (state.option.white) {
+			left = left || state.tokens.curr;
+			right = right || state.tokens.next;
+
+			if (left.value === ";" && right.value === ";") {
+				return;
+			}
+
+			if (left.line === right.line && left.character === right.from) {
+				left.from += (left.character - left.from);
+				warning("W013", left, left.value);
+			}
+		}
+	}
+
+	function nobreaknonadjacent(left, right) {
+		left = left || state.tokens.curr;
+		right = right || state.tokens.next;
+		if (!state.option.laxbreak && left.line !== right.line) {
+			warning("W014", right, right.value);
+		} else if (state.option.white) {
+			left = left || state.tokens.curr;
+			right = right || state.tokens.next;
+			if (left.character === right.from) {
+				left.from += (left.character - left.from);
+				warning("W013", left, left.value);
+			}
+		}
+	}
+
+	function indentation(bias) {
+		if (!state.option.white && !state.option["(explicitIndent)"]) {
+			return;
+		}
+
+		if (state.tokens.next.id === "(end)") {
+			return;
+		}
+
+		var i = indent + (bias || 0);
+		if (state.tokens.next.from !== i) {
+			warning("W015", state.tokens.next, state.tokens.next.value, i, state.tokens.next.from);
+		}
+	}
+
+	function nolinebreak(t) {
+		t = t || state.tokens.curr;
+		if (t.line !== state.tokens.next.line) {
+			warning("E022", t, t.value);
+		}
+	}
+
+	function nobreakcomma(left, right) {
+		if (left.line !== right.line) {
+			if (!state.option.laxcomma) {
+				if (comma.first) {
+					warning("I001");
+					comma.first = false;
+				}
+				warning("W014", left, right.value);
+			}
+		} else if (!left.comment && left.character !== right.from && state.option.white) {
+			left.from += (left.character - left.from);
+			warning("W011", left, left.value);
+		}
+	}
+
+	function comma(opts) {
+		opts = opts || {};
+
+		if (!opts.peek) {
+			nobreakcomma(state.tokens.curr, state.tokens.next);
+			advance(",");
+		} else {
+			nobreakcomma(state.tokens.prev, state.tokens.curr);
+		}
+
+		// TODO: This is a temporary solution to fight against false-positives in
+		// arrays and objects with trailing commas (see GH-363). The best solution
+		// would be to extract all whitespace rules out of parser.
+
+		if (state.tokens.next.value !== "]" && state.tokens.next.value !== "}") {
+			nonadjacent(state.tokens.curr, state.tokens.next);
+		}
+
+		if (state.tokens.next.identifier && !(opts.property && state.option.inES5())) {
+			// Keywords that cannot follow a comma operator.
+			switch (state.tokens.next.value) {
+			case "break":
+			case "case":
+			case "catch":
+			case "continue":
+			case "default":
+			case "do":
+			case "else":
+			case "finally":
+			case "for":
+			case "if":
+			case "in":
+			case "instanceof":
+			case "return":
+			case "switch":
+			case "throw":
+			case "try":
+			case "var":
+			case "let":
+			case "while":
+			case "with":
+				error("E024", state.tokens.next, state.tokens.next.value);
+				return false;
+			}
+		}
+
+		if (state.tokens.next.type === "(punctuator)") {
+			switch (state.tokens.next.value) {
+			case "}":
+			case "]":
+			case ",":
+				if (opts.allowTrailing) {
+					return true;
+				}
+
+				/* falls through */
+			case ")":
+				error("E024", state.tokens.next, state.tokens.next.value);
+				return false;
+			}
+		}
+		return true;
+	}
+
+	// Functional constructors for making the symbols that will be inherited by
+	// tokens.
+
+	function symbol(s, p) {
+		var x = state.syntax[s];
+		if (!x || typeof x !== "object") {
+			state.syntax[s] = x = {
+				id: s,
+				lbp: p,
+				value: s
+			};
+		}
+		return x;
+	}
+
+	function delim(s) {
+		return symbol(s, 0);
+	}
+
+	function stmt(s, f) {
+		var x = delim(s);
+		x.identifier = x.reserved = true;
+		x.fud = f;
+		return x;
+	}
+
+	function blockstmt(s, f) {
+		var x = stmt(s, f);
+		x.block = true;
+		return x;
+	}
+
+	function reserveName(x) {
+		var c = x.id.charAt(0);
+		if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
+			x.identifier = x.reserved = true;
+		}
+		return x;
+	}
+
+	function prefix(s, f) {
+		var x = symbol(s, 150);
+		reserveName(x);
+
+		x.nud = (typeof f === "function") ? f : function () {
+			this.right = expression(150);
+			this.arity = "unary";
+
+			if (this.id === "++" || this.id === "--") {
+				if (state.option.plusplus) {
+					warning("W016", this, this.id);
+				} else if (this.right && (!this.right.identifier || isReserved(this.right)) &&
+						this.right.id !== "." && this.right.id !== "[") {
+					warning("W017", this);
+				}
+			}
+
+			return this;
+		};
+
+		return x;
+	}
+
+	function type(s, f) {
+		var x = delim(s);
+		x.type = s;
+		x.nud = f;
+		return x;
+	}
+
+	function reserve(name, func) {
+		var x = type(name, func);
+		x.identifier = true;
+		x.reserved = true;
+		return x;
+	}
+
+	function FutureReservedWord(name, meta) {
+		var x = type(name, (meta && meta.nud) || function () {
+			return this;
+		});
+
+		meta = meta || {};
+		meta.isFutureReservedWord = true;
+
+		x.value = name;
+		x.identifier = true;
+		x.reserved = true;
+		x.meta = meta;
+
+		return x;
+	}
+
+	function reservevar(s, v) {
+		return reserve(s, function () {
+			if (typeof v === "function") {
+				v(this);
+			}
+			return this;
+		});
+	}
+
+	function infix(s, f, p, w) {
+		var x = symbol(s, p);
+		reserveName(x);
+		x.infix = true;
+		x.led = function (left) {
+			if (!w) {
+				nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+				nonadjacent(state.tokens.curr, state.tokens.next);
+			}
+			if (s === "in" && left.id === "!") {
+				warning("W018", left, "!");
+			}
+			if (typeof f === "function") {
+				return f(left, this);
+			} else {
+				this.left = left;
+				this.right = expression(p);
+				return this;
+			}
+		};
+		return x;
+	}
+
+
+	function application(s) {
+		var x = symbol(s, 42);
+
+		x.led = function (left) {
+			if (!state.option.inESNext()) {
+				warning("W104", state.tokens.curr, "arrow function syntax (=>)");
+			}
+
+			nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+			nonadjacent(state.tokens.curr, state.tokens.next);
+
+			this.left = left;
+			this.right = doFunction(undefined, undefined, false, left);
+			return this;
+		};
+		return x;
+	}
+
+	function relation(s, f) {
+		var x = symbol(s, 100);
+
+		x.led = function (left) {
+			nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+			nonadjacent(state.tokens.curr, state.tokens.next);
+			var right = expression(100);
+
+			if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
+				warning("W019", this);
+			} else if (f) {
+				f.apply(this, [left, right]);
+			}
+
+			if (!left || !right) {
+				quit("E041", state.tokens.curr.line);
+			}
+
+			if (left.id === "!") {
+				warning("W018", left, "!");
+			}
+
+			if (right.id === "!") {
+				warning("W018", right, "!");
+			}
+
+			this.left = left;
+			this.right = right;
+			return this;
+		};
+		return x;
+	}
+
+	function isPoorRelation(node) {
+		return node &&
+			  ((node.type === "(number)" && +node.value === 0) ||
+			   (node.type === "(string)" && node.value === "") ||
+			   (node.type === "null" && !state.option.eqnull) ||
+				node.type === "true" ||
+				node.type === "false" ||
+				node.type === "undefined");
+	}
+
+	// Checks whether the 'typeof' operator is used with the correct
+	// value. For docs on 'typeof' see:
+	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
+
+	function isTypoTypeof(left, right) {
+		if (state.option.notypeof)
+			return false;
+
+		if (!left || !right)
+			return false;
+
+		var values = [
+			"undefined", "object", "boolean", "number",
+			"string", "function", "xml", "object"
+		];
+
+		if (right.type === "(identifier)" && right.value === "typeof" && left.type === "(string)")
+			return !_.contains(values, left.value);
+
+		return false;
+	}
+
+	function findNativePrototype(left) {
+		var natives = [
+			"Array", "ArrayBuffer", "Boolean", "Collator", "DataView", "Date",
+			"DateTimeFormat", "Error", "EvalError", "Float32Array", "Float64Array",
+			"Function", "Infinity", "Intl", "Int16Array", "Int32Array", "Int8Array",
+			"Iterator", "Number", "NumberFormat", "Object", "RangeError",
+			"ReferenceError", "RegExp", "StopIteration", "String", "SyntaxError",
+			"TypeError", "Uint16Array", "Uint32Array", "Uint8Array", "Uint8ClampedArray",
+			"URIError"
+		];
+
+		function walkPrototype(obj) {
+			if (typeof obj !== "object") return;
+			return obj.right === "prototype" ? obj : walkPrototype(obj.left);
+		}
+
+		function walkNative(obj) {
+			while (!obj.identifier && typeof obj.left === "object")
+			  obj = obj.left;
+
+			if (obj.identifier && natives.indexOf(obj.value) >= 0)
+			  return obj.value;
+		}
+
+		var prototype = walkPrototype(left);
+		if (prototype) return walkNative(prototype);
+	}
+
+	function assignop(s, f, p) {
+		var x = infix(s, typeof f === "function" ? f : function (left, that) {
+			that.left = left;
+
+			if (left) {
+				if (state.option.freeze) {
+					var nativeObject = findNativePrototype(left);
+					if (nativeObject)
+						warning("W121", left, nativeObject);
+				}
+
+				if (predefined[left.value] === false &&
+						scope[left.value]["(global)"] === true) {
+					warning("W020", left);
+				} else if (left["function"]) {
+					warning("W021", left, left.value);
+				}
+
+				if (funct[left.value] === "const") {
+					error("E013", left, left.value);
+				}
+
+				if (left.id === ".") {
+					if (!left.left) {
+						warning("E031", that);
+					} else if (left.left.value === "arguments" && !state.directive["use strict"]) {
+						warning("E031", that);
+					}
+
+					that.right = expression(10);
+					return that;
+				} else if (left.id === "[") {
+					if (state.tokens.curr.left.first) {
+						state.tokens.curr.left.first.forEach(function (t) {
+							if (funct[t.value] === "const") {
+								error("E013", t, t.value);
+							}
+						});
+					} else if (!left.left) {
+						warning("E031", that);
+					} else if (left.left.value === "arguments" && !state.directive["use strict"]) {
+						warning("E031", that);
+					}
+					that.right = expression(10);
+					return that;
+				} else if (left.identifier && !isReserved(left)) {
+					if (funct[left.value] === "exception") {
+						warning("W022", left);
+					}
+					that.right = expression(10);
+					return that;
+				}
+
+				if (left === state.syntax["function"]) {
+					warning("W023", state.tokens.curr);
+				}
+			}
+
+			error("E031", that);
+		}, p);
+
+		x.exps = true;
+		x.assign = true;
+		return x;
+	}
+
+
+	function bitwise(s, f, p) {
+		var x = symbol(s, p);
+		reserveName(x);
+		x.led = (typeof f === "function") ? f : function (left) {
+			if (state.option.bitwise) {
+				warning("W016", this, this.id);
+			}
+			this.left = left;
+			this.right = expression(p);
+			return this;
+		};
+		return x;
+	}
+
+
+	function bitwiseassignop(s) {
+		return assignop(s, function (left, that) {
+			if (state.option.bitwise) {
+				warning("W016", that, that.id);
+			}
+			nonadjacent(state.tokens.prev, state.tokens.curr);
+			nonadjacent(state.tokens.curr, state.tokens.next);
+			if (left) {
+				if (left.id === "." || left.id === "[" ||
+						(left.identifier && !isReserved(left))) {
+					expression(10);
+					return that;
+				}
+				if (left === state.syntax["function"]) {
+					warning("W023", state.tokens.curr);
+				}
+				return that;
+			}
+			error("E031", that);
+		}, 20);
+	}
+
+
+	function suffix(s) {
+		var x = symbol(s, 150);
+
+		x.led = function (left) {
+			if (state.option.plusplus) {
+				warning("W016", this, this.id);
+			} else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") {
+				warning("W017", this);
+			}
+
+			this.left = left;
+			return this;
+		};
+		return x;
+	}
+
+	// fnparam means that this identifier is being defined as a function
+	// argument (see identifier())
+	// prop means that this identifier is that of an object property
+
+	function optionalidentifier(fnparam, prop) {
+		if (!state.tokens.next.identifier) {
+			return;
+		}
+
+		advance();
+
+		var curr = state.tokens.curr;
+		var val  = state.tokens.curr.value;
+
+		if (!isReserved(curr)) {
+			return val;
+		}
+
+		if (prop) {
+			if (state.option.inES5()) {
+				return val;
+			}
+		}
+
+		if (fnparam && val === "undefined") {
+			return val;
+		}
+
+		// Display an info message about reserved words as properties
+		// and ES5 but do it only once.
+		if (prop && !api.getCache("displayed:I002")) {
+			api.setCache("displayed:I002", true);
+			warning("I002");
+		}
+
+		warning("W024", state.tokens.curr, state.tokens.curr.id);
+		return val;
+	}
+
+	// fnparam means that this identifier is being defined as a function
+	// argument
+	// prop means that this identifier is that of an object property
+	function identifier(fnparam, prop) {
+		var i = optionalidentifier(fnparam, prop);
+		if (i) {
+			return i;
+		}
+		if (state.tokens.curr.id === "function" && state.tokens.next.id === "(") {
+			warning("W025");
+		} else {
+			error("E030", state.tokens.next, state.tokens.next.value);
+		}
+	}
+
+
+	function reachable(s) {
+		var i = 0, t;
+		if (state.tokens.next.id !== ";" || noreach) {
+			return;
+		}
+		for (;;) {
+			do {
+				t = peek(i);
+				i += 1;
+			} while (t.id != "(end)" && t.id === "(comment)");
+
+			if (t.reach) {
+				return;
+			}
+			if (t.id !== "(endline)") {
+				if (t.id === "function") {
+					if (state.option.latedef === true) {
+						warning("W026", t);
+					}
+					break;
+				}
+
+				warning("W027", t, t.value, s);
+				break;
+			}
+		}
+	}
+
+
+	function statement(noindent) {
+		var values;
+		var i = indent, r, s = scope, t = state.tokens.next;
+
+		if (t.id === ";") {
+			advance(";");
+			return;
+		}
+
+		// Is this a labelled statement?
+		var res = isReserved(t);
+
+		// We're being more tolerant here: if someone uses
+		// a FutureReservedWord as a label, we warn but proceed
+		// anyway.
+
+		if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") {
+			warning("W024", t, t.id);
+			res = false;
+		}
+
+		// detect a destructuring assignment
+		if (_.has(["[", "{"], t.value)) {
+			if (lookupBlockType().isDestAssign) {
+				if (!state.option.inESNext()) {
+					warning("W104", state.tokens.curr, "destructuring expression");
+				}
+				values = destructuringExpression();
+				values.forEach(function (tok) {
+					isundef(funct, "W117", tok.token, tok.id);
+				});
+				advance("=");
+				destructuringExpressionMatch(values, expression(10, true));
+				advance(";");
+				return;
+			}
+		}
+		if (t.identifier && !res && peek().id === ":") {
+			advance();
+			advance(":");
+			scope = Object.create(s);
+			addlabel(t.value, { type: "label" });
+
+			if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
+				warning("W028", state.tokens.next, t.value, state.tokens.next.value);
+			}
+
+			state.tokens.next.label = t.value;
+			t = state.tokens.next;
+		}
+
+		// Is it a lonely block?
+
+		if (t.id === "{") {
+			// Is it a switch case block?
+			//
+			//	switch (foo) {
+			//		case bar: { <= here.
+			//			...
+			//		}
+			//	}
+			var iscase = (funct["(verb)"] === "case" && state.tokens.curr.value === ":");
+			block(true, true, false, false, iscase);
+			return;
+		}
+
+		// Parse the statement.
+
+		if (!noindent) {
+			indentation();
+		}
+		r = expression(0, true);
+
+		if (r && (!r.identifier || r.value !== "function") && (r.type !== "(punctuator)")) {
+			if (!state.directive["use strict"] &&
+					state.option.globalstrict &&
+					state.option.strict) {
+				warning("E007");
+			}
+		}
+
+		// Look for the final semicolon.
+
+		if (!t.block) {
+			if (!state.option.expr && (!r || !r.exps)) {
+				warning("W030", state.tokens.curr);
+			} else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") {
+				warning("W031", t);
+			}
+
+			if (state.tokens.next.id !== ";") {
+				if (!state.option.asi) {
+					// If this is the last statement in a block that ends on
+					// the same line *and* option lastsemic is on, ignore the warning.
+					// Otherwise, complain about missing semicolon.
+					if (!state.option.lastsemic || state.tokens.next.id !== "}" ||
+						state.tokens.next.line !== state.tokens.curr.line) {
+						warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
+					}
+				}
+			} else {
+				adjacent(state.tokens.curr, state.tokens.next);
+				advance(";");
+				nonadjacent(state.tokens.curr, state.tokens.next);
+			}
+		}
+
+		// Restore the indentation.
+
+		indent = i;
+		scope = s;
+		return r;
+	}
+
+
+	function statements(startLine) {
+		var a = [], p;
+
+		while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
+			if (state.tokens.next.id === ";") {
+				p = peek();
+
+				if (!p || (p.id !== "(" && p.id !== "[")) {
+					warning("W032");
+				}
+
+				advance(";");
+			} else {
+				a.push(statement(startLine === state.tokens.next.line));
+			}
+		}
+		return a;
+	}
+
+
+	/*
+	 * read all directives
+	 * recognizes a simple form of asi, but always
+	 * warns, if it is used
+	 */
+	function directives() {
+		var i, p, pn;
+
+		for (;;) {
+			if (state.tokens.next.id === "(string)") {
+				p = peek(0);
+				if (p.id === "(endline)") {
+					i = 1;
+					do {
+						pn = peek(i);
+						i = i + 1;
+					} while (pn.id === "(endline)");
+
+					if (pn.id !== ";") {
+						if (pn.id !== "(string)" && pn.id !== "(number)" &&
+							pn.id !== "(regexp)" && pn.identifier !== true &&
+							pn.id !== "}") {
+							break;
+						}
+						warning("W033", state.tokens.next);
+					} else {
+						p = pn;
+					}
+				} else if (p.id === "}") {
+					// Directive with no other statements, warn about missing semicolon
+					warning("W033", p);
+				} else if (p.id !== ";") {
+					break;
+				}
+
+				indentation();
+				advance();
+				if (state.directive[state.tokens.curr.value]) {
+					warning("W034", state.tokens.curr, state.tokens.curr.value);
+				}
+
+				if (state.tokens.curr.value === "use strict") {
+					if (!state.option["(explicitNewcap)"])
+						state.option.newcap = true;
+					state.option.undef = true;
+				}
+
+				// there's no directive negation, so always set to true
+				state.directive[state.tokens.curr.value] = true;
+
+				if (p.id === ";") {
+					advance(";");
+				}
+				continue;
+			}
+			break;
+		}
+	}
+
+
+	/*
+	 * Parses a single block. A block is a sequence of statements wrapped in
+	 * braces.
+	 *
+	 * ordinary   - true for everything but function bodies and try blocks.
+	 * stmt       - true if block can be a single statement (e.g. in if/for/while).
+	 * isfunc     - true if block is a function body
+	 * isfatarrow - true if its a body of a fat arrow function
+	 * iscase	    - true if block is a switch case block
+	 */
+	function block(ordinary, stmt, isfunc, isfatarrow, iscase) {
+		var a,
+			b = inblock,
+			old_indent = indent,
+			m,
+			s = scope,
+			t,
+			line,
+			d;
+
+		inblock = ordinary;
+
+		if (!ordinary || !state.option.funcscope)
+			scope = Object.create(scope);
+
+		nonadjacent(state.tokens.curr, state.tokens.next);
+		t = state.tokens.next;
+
+		var metrics = funct["(metrics)"];
+		metrics.nestedBlockDepth += 1;
+		metrics.verifyMaxNestedBlockDepthPerFunction();
+
+		if (state.tokens.next.id === "{") {
+			advance("{");
+
+			// create a new block scope
+			funct["(blockscope)"].stack();
+
+			line = state.tokens.curr.line;
+			if (state.tokens.next.id !== "}") {
+				indent += state.option.indent;
+				while (!ordinary && state.tokens.next.from > indent) {
+					indent += state.option.indent;
+				}
+
+				if (isfunc) {
+					m = {};
+					for (d in state.directive) {
+						if (_.has(state.directive, d)) {
+							m[d] = state.directive[d];
+						}
+					}
+					directives();
+
+					if (state.option.strict && funct["(context)"]["(global)"]) {
+						if (!m["use strict"] && !state.directive["use strict"]) {
+							warning("E007");
+						}
+					}
+				}
+
+				a = statements(line);
+
+				metrics.statementCount += a.length;
+
+				if (isfunc) {
+					state.directive = m;
+				}
+
+				indent -= state.option.indent;
+				if (line !== state.tokens.next.line) {
+					indentation();
+				}
+			} else if (line !== state.tokens.next.line) {
+				indentation();
+			}
+			advance("}", t);
+
+			funct["(blockscope)"].unstack();
+
+			indent = old_indent;
+		} else if (!ordinary) {
+			if (isfunc) {
+				m = {};
+				if (stmt && !isfatarrow && !state.option.inMoz(true)) {
+					error("W118", state.tokens.curr, "function closure expressions");
+				}
+
+				if (!stmt) {
+					for (d in state.directive) {
+						if (_.has(state.directive, d)) {
+							m[d] = state.directive[d];
+						}
+					}
+				}
+				expression(10);
+
+				if (state.option.strict && funct["(context)"]["(global)"]) {
+					if (!m["use strict"] && !state.directive["use strict"]) {
+						warning("E007");
+					}
+				}
+			} else {
+				error("E021", state.tokens.next, "{", state.tokens.next.value);
+			}
+		} else {
+
+			// check to avoid let declaration not within a block
+			funct["(nolet)"] = true;
+
+			if (!stmt || state.option.curly) {
+				warning("W116", state.tokens.next, "{", state.tokens.next.value);
+			}
+
+			noreach = true;
+			indent += state.option.indent;
+			// test indentation only if statement is in new line
+			a = [statement(state.tokens.next.line === state.tokens.curr.line)];
+			indent -= state.option.indent;
+			noreach = false;
+
+			delete funct["(nolet)"];
+		}
+		// Don't clear and let it propagate out if it is "break", "return", or "throw" in switch case
+		if (!(iscase && ["break", "return", "throw"].indexOf(funct["(verb)"]) != -1)) {
+			funct["(verb)"] = null;
+		}
+
+		if (!ordinary || !state.option.funcscope) scope = s;
+		inblock = b;
+		if (ordinary && state.option.noempty && (!a || a.length === 0)) {
+			warning("W035");
+		}
+		metrics.nestedBlockDepth -= 1;
+		return a;
+	}
+
+
+	function countMember(m) {
+		if (membersOnly && typeof membersOnly[m] !== "boolean") {
+			warning("W036", state.tokens.curr, m);
+		}
+		if (typeof member[m] === "number") {
+			member[m] += 1;
+		} else {
+			member[m] = 1;
+		}
+	}
+
+
+	function note_implied(tkn) {
+		var name = tkn.value;
+		var desc = Object.getOwnPropertyDescriptor(implied, name);
+
+		if (!desc)
+			implied[name] = [tkn.line];
+		else
+			desc.value.push(tkn.line);
+	}
+
+
+	// Build the syntax table by declaring the syntactic elements of the language.
+
+	type("(number)", function () {
+		return this;
+	});
+
+	type("(string)", function () {
+		return this;
+	});
+
+	state.syntax["(identifier)"] = {
+		type: "(identifier)",
+		lbp: 0,
+		identifier: true,
+
+		nud: function () {
+			var v = this.value;
+			var s = scope[v];
+			var f;
+			var block;
+
+			if (typeof s === "function") {
+				// Protection against accidental inheritance.
+				s = undefined;
+			} else if (!funct["(blockscope)"].current.has(v) && typeof s === "boolean") {
+				f = funct;
+				funct = functions[0];
+				addlabel(v, { type: "var" });
+				s = funct;
+				funct = f;
+			}
+
+			block = funct["(blockscope)"].getlabel(v);
+
+			// The name is in scope and defined in the current function.
+			if (funct === s || block) {
+				// Change 'unused' to 'var', and reject labels.
+				// the name is in a block scope.
+				switch (block ? block[v]["(type)"] : funct[v]) {
+				case "unused":
+					if (block) block[v]["(type)"] = "var";
+					else funct[v] = "var";
+					break;
+				case "unction":
+					if (block) block[v]["(type)"] = "function";
+					else funct[v] = "function";
+					this["function"] = true;
+					break;
+				case "const":
+					setprop(funct, v, { unused: false });
+					break;
+				case "function":
+					this["function"] = true;
+					break;
+				case "label":
+					warning("W037", state.tokens.curr, v);
+					break;
+				}
+			} else if (funct["(global)"]) {
+				// The name is not defined in the function.  If we are in the global
+				// scope, then we have an undefined variable.
+				//
+				// Operators typeof and delete do not raise runtime errors even if
+				// the base object of a reference is null so no need to display warning
+				// if we're inside of typeof or delete.
+
+				if (typeof predefined[v] !== "boolean") {
+					// Attempting to subscript a null reference will throw an
+					// error, even within the typeof and delete operators
+					if (!(anonname === "typeof" || anonname === "delete") ||
+						(state.tokens.next && (state.tokens.next.value === "." ||
+							state.tokens.next.value === "["))) {
+
+						// if we're in a list comprehension, variables are declared
+						// locally and used before being defined. So we check
+						// the presence of the given variable in the comp array
+						// before declaring it undefined.
+
+						if (!funct["(comparray)"].check(v)) {
+							isundef(funct, "W117", state.tokens.curr, v);
+						}
+					}
+				}
+
+				note_implied(state.tokens.curr);
+			} else {
+				// If the name is already defined in the current
+				// function, but not as outer, then there is a scope error.
+
+				switch (funct[v]) {
+				case "closure":
+				case "function":
+				case "var":
+				case "unused":
+					warning("W038", state.tokens.curr, v);
+					break;
+				case "label":
+					warning("W037", state.tokens.curr, v);
+					break;
+				case "outer":
+				case "global":
+					break;
+				default:
+					// If the name is defined in an outer function, make an outer entry,
+					// and if it was unused, make it var.
+					if (s === true) {
+						funct[v] = true;
+					} else if (s === null) {
+						warning("W039", state.tokens.curr, v);
+						note_implied(state.tokens.curr);
+					} else if (typeof s !== "object") {
+						// Operators typeof and delete do not raise runtime errors even
+						// if the base object of a reference is null so no need to
+						//
+						// display warning if we're inside of typeof or delete.
+						// Attempting to subscript a null reference will throw an
+						// error, even within the typeof and delete operators
+						if (!(anonname === "typeof" || anonname === "delete") ||
+							(state.tokens.next &&
+								(state.tokens.next.value === "." || state.tokens.next.value === "["))) {
+
+							isundef(funct, "W117", state.tokens.curr, v);
+						}
+						funct[v] = true;
+						note_implied(state.tokens.curr);
+					} else {
+						switch (s[v]) {
+						case "function":
+						case "unction":
+							this["function"] = true;
+							s[v] = "closure";
+							funct[v] = s["(global)"] ? "global" : "outer";
+							break;
+						case "var":
+						case "unused":
+							s[v] = "closure";
+							funct[v] = s["(global)"] ? "global" : "outer";
+							break;
+						case "const":
+							setprop(s, v, { unused: false });
+							break;
+						case "closure":
+							funct[v] = s["(global)"] ? "global" : "outer";
+							break;
+						case "label":
+							warning("W037", state.tokens.curr, v);
+						}
+					}
+				}
+			}
+			return this;
+		},
+
+		led: function () {
+			error("E033", state.tokens.next, state.tokens.next.value);
+		}
+	};
+
+	type("(regexp)", function () {
+		return this;
+	});
+
+	// ECMAScript parser
+
+	delim("(endline)");
+	delim("(begin)");
+	delim("(end)").reach = true;
+	delim("(error)").reach = true;
+	delim("}").reach = true;
+	delim(")");
+	delim("]");
+	delim("\"").reach = true;
+	delim("'").reach = true;
+	delim(";");
+	delim(":").reach = true;
+	delim("#");
+
+	reserve("else");
+	reserve("case").reach = true;
+	reserve("catch");
+	reserve("default").reach = true;
+	reserve("finally");
+	reservevar("arguments", function (x) {
+		if (state.directive["use strict"] && funct["(global)"]) {
+			warning("E008", x);
+		}
+	});
+	reservevar("eval");
+	reservevar("false");
+	reservevar("Infinity");
+	reservevar("null");
+	reservevar("this", function (x) {
+		if (state.directive["use strict"] && !state.option.validthis && ((funct["(statement)"] &&
+				funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
+			warning("W040", x);
+		}
+	});
+	reservevar("true");
+	reservevar("undefined");
+
+	assignop("=", "assign", 20);
+	assignop("+=", "assignadd", 20);
+	assignop("-=", "assignsub", 20);
+	assignop("*=", "assignmult", 20);
+	assignop("/=", "assigndiv", 20).nud = function () {
+		error("E014");
+	};
+	assignop("%=", "assignmod", 20);
+
+	bitwiseassignop("&=", "assignbitand", 20);
+	bitwiseassignop("|=", "assignbitor", 20);
+	bitwiseassignop("^=", "assignbitxor", 20);
+	bitwiseassignop("<<=", "assignshiftleft", 20);
+	bitwiseassignop(">>=", "assignshiftright", 20);
+	bitwiseassignop(">>>=", "assignshiftrightunsigned", 20);
+	infix(",", function (left, that) {
+		var expr;
+		that.exprs = [left];
+		if (!comma({peek: true})) {
+			return that;
+		}
+		while (true) {
+			if (!(expr = expression(10)))  {
+				break;
+			}
+			that.exprs.push(expr);
+			if (state.tokens.next.value !== "," || !comma()) {
+				break;
+			}
+		}
+		return that;
+	}, 10, true);
+
+	infix("?", function (left, that) {
+		increaseComplexityCount();
+		that.left = left;
+		that.right = expression(10);
+		advance(":");
+		that["else"] = expression(10);
+		return that;
+	}, 30);
+
+	var orPrecendence = 40;
+	infix("||", function (left, that) {
+		increaseComplexityCount();
+		that.left = left;
+		that.right = expression(orPrecendence);
+		return that;
+	}, orPrecendence);
+	infix("&&", "and", 50);
+	bitwise("|", "bitor", 70);
+	bitwise("^", "bitxor", 80);
+	bitwise("&", "bitand", 90);
+	relation("==", function (left, right) {
+		var eqnull = state.option.eqnull && (left.value === "null" || right.value === "null");
+
+		switch (true) {
+			case !eqnull && state.option.eqeqeq:
+				this.from = this.character;
+				warning("W116", this, "===", "==");
+				break;
+			case isPoorRelation(left):
+				warning("W041", this, "===", left.value);
+				break;
+			case isPoorRelation(right):
+				warning("W041", this, "===", right.value);
+				break;
+			case isTypoTypeof(right, left):
+				warning("W122", this, right.value);
+				break;
+			case isTypoTypeof(left, right):
+				warning("W122", this, left.value);
+				break;
+		}
+
+		return this;
+	});
+	relation("===", function (left, right) {
+		if (isTypoTypeof(right, left)) {
+			warning("W122", this, right.value);
+		} else if (isTypoTypeof(left, right)) {
+			warning("W122", this, left.value);
+		}
+		return this;
+	});
+	relation("!=", function (left, right) {
+		var eqnull = state.option.eqnull &&
+				(left.value === "null" || right.value === "null");
+
+		if (!eqnull && state.option.eqeqeq) {
+			this.from = this.character;
+			warning("W116", this, "!==", "!=");
+		} else if (isPoorRelation(left)) {
+			warning("W041", this, "!==", left.value);
+		} else if (isPoorRelation(right)) {
+			warning("W041", this, "!==", right.value);
+		} else if (isTypoTypeof(right, left)) {
+			warning("W122", this, right.value);
+		} else if (isTypoTypeof(left, right)) {
+			warning("W122", this, left.value);
+		}
+		return this;
+	});
+	relation("!==", function (left, right) {
+		if (isTypoTypeof(right, left)) {
+			warning("W122", this, right.value);
+		} else if (isTypoTypeof(left, right)) {
+			warning("W122", this, left.value);
+		}
+		return this;
+	});
+	relation("<");
+	relation(">");
+	relation("<=");
+	relation(">=");
+	bitwise("<<", "shiftleft", 120);
+	bitwise(">>", "shiftright", 120);
+	bitwise(">>>", "shiftrightunsigned", 120);
+	infix("in", "in", 120);
+	infix("instanceof", "instanceof", 120);
+	infix("+", function (left, that) {
+		var right = expression(130);
+		if (left && right && left.id === "(string)" && right.id === "(string)") {
+			left.value += right.value;
+			left.character = right.character;
+			if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
+				warning("W050", left);
+			}
+			return left;
+		}
+		that.left = left;
+		that.right = right;
+		return that;
+	}, 130);
+	prefix("+", "num");
+	prefix("+++", function () {
+		warning("W007");
+		this.right = expression(150);
+		this.arity = "unary";
+		return this;
+	});
+	infix("+++", function (left) {
+		warning("W007");
+		this.left = left;
+		this.right = expression(130);
+		return this;
+	}, 130);
+	infix("-", "sub", 130);
+	prefix("-", "neg");
+	prefix("---", function () {
+		warning("W006");
+		this.right = expression(150);
+		this.arity = "unary";
+		return this;
+	});
+	infix("---", function (left) {
+		warning("W006");
+		this.left = left;
+		this.right = expression(130);
+		return this;
+	}, 130);
+	infix("*", "mult", 140);
+	infix("/", "div", 140);
+	infix("%", "mod", 140);
+
+	suffix("++", "postinc");
+	prefix("++", "preinc");
+	state.syntax["++"].exps = true;
+
+	suffix("--", "postdec");
+	prefix("--", "predec");
+	state.syntax["--"].exps = true;
+	prefix("delete", function () {
+		var p = expression(10);
+		if (!p || (p.id !== "." && p.id !== "[")) {
+			warning("W051");
+		}
+		this.first = p;
+		return this;
+	}).exps = true;
+
+	prefix("~", function () {
+		if (state.option.bitwise) {
+			warning("W052", this, "~");
+		}
+		expression(150);
+		return this;
+	});
+
+	prefix("...", function () {
+		if (!state.option.inESNext()) {
+			warning("W104", this, "spread/rest operator");
+		}
+		if (!state.tokens.next.identifier) {
+			error("E030", state.tokens.next, state.tokens.next.value);
+		}
+		expression(150);
+		return this;
+	});
+
+	prefix("!", function () {
+		this.right = expression(150);
+		this.arity = "unary";
+
+		if (!this.right) { // '!' followed by nothing? Give up.
+			quit("E041", this.line || 0);
+		}
+
+		if (bang[this.right.id] === true) {
+			warning("W018", this, "!");
+		}
+		return this;
+	});
+
+	prefix("typeof", "typeof");
+	prefix("new", function () {
+		var c = expression(155), i;
+		if (c && c.id !== "function") {
+			if (c.identifier) {
+				c["new"] = true;
+				switch (c.value) {
+				case "Number":
+				case "String":
+				case "Boolean":
+				case "Math":
+				case "JSON":
+					warning("W053", state.tokens.prev, c.value);
+					break;
+				case "Function":
+					if (!state.option.evil) {
+						warning("W054");
+					}
+					break;
+				case "Date":
+				case "RegExp":
+				case "this":
+					break;
+				default:
+					if (c.id !== "function") {
+						i = c.value.substr(0, 1);
+						if (state.option.newcap && (i < "A" || i > "Z") && !_.has(global, c.value)) {
+							warning("W055", state.tokens.curr);
+						}
+					}
+				}
+			} else {
+				if (c.id !== "." && c.id !== "[" && c.id !== "(") {
+					warning("W056", state.tokens.curr);
+				}
+			}
+		} else {
+			if (!state.option.supernew)
+				warning("W057", this);
+		}
+		adjacent(state.tokens.curr, state.tokens.next);
+		if (state.tokens.next.id !== "(" && !state.option.supernew) {
+			warning("W058", state.tokens.curr, state.tokens.curr.value);
+		}
+		this.first = c;
+		return this;
+	});
+	state.syntax["new"].exps = true;
+
+	prefix("void").exps = true;
+
+	infix(".", function (left, that) {
+		adjacent(state.tokens.prev, state.tokens.curr);
+		nobreak();
+		var m = identifier(false, true);
+
+		if (typeof m === "string") {
+			countMember(m);
+		}
+
+		that.left = left;
+		that.right = m;
+
+		if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
+			warning("W001");
+		}
+
+		if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
+			if (state.option.noarg)
+				warning("W059", left, m);
+			else if (state.directive["use strict"])
+				error("E008");
+		} else if (!state.option.evil && left && left.value === "document" &&
+				(m === "write" || m === "writeln")) {
+			warning("W060", left);
+		}
+
+		if (!state.option.evil && (m === "eval" || m === "execScript")) {
+			warning("W061");
+		}
+
+		return that;
+	}, 160, true);
+
+	infix("(", function (left, that) {
+		if (state.tokens.prev.id !== "}" && state.tokens.prev.id !== ")") {
+			nobreak(state.tokens.prev, state.tokens.curr);
+		}
+
+		nospace();
+		if (state.option.immed && left && !left.immed && left.id === "function") {
+			warning("W062");
+		}
+
+		var n = 0;
+		var p = [];
+
+		if (left) {
+			if (left.type === "(identifier)") {
+				if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
+					if ("Number String Boolean Date Object".indexOf(left.value) === -1) {
+						if (left.value === "Math") {
+							warning("W063", left);
+						} else if (state.option.newcap) {
+							warning("W064", left);
+						}
+					}
+				}
+			}
+		}
+
+		if (state.tokens.next.id !== ")") {
+			for (;;) {
+				p[p.length] = expression(10);
+				n += 1;
+				if (state.tokens.next.id !== ",") {
+					break;
+				}
+				comma();
+			}
+		}
+
+		advance(")");
+		nospace(state.tokens.prev, state.tokens.curr);
+
+		if (typeof left === "object") {
+			if (state.option.inES3() && left.value === "parseInt" && n === 1) {
+				warning("W065", state.tokens.curr);
+			}
+			if (!state.option.evil) {
+				if (left.value === "eval" || left.value === "Function" ||
+						left.value === "execScript") {
+					warning("W061", left);
+
+					if (p[0] && [0].id === "(string)") {
+						addInternalSrc(left, p[0].value);
+					}
+				} else if (p[0] && p[0].id === "(string)" &&
+					   (left.value === "setTimeout" ||
+						left.value === "setInterval")) {
+					warning("W066", left);
+					addInternalSrc(left, p[0].value);
+
+				// window.setTimeout/setInterval
+				} else if (p[0] && p[0].id === "(string)" &&
+					   left.value === "." &&
+					   left.left.value === "window" &&
+					   (left.right === "setTimeout" ||
+						left.right === "setInterval")) {
+					warning("W066", left);
+					addInternalSrc(left, p[0].value);
+				}
+			}
+			if (!left.identifier && left.id !== "." && left.id !== "[" &&
+					left.id !== "(" && left.id !== "&&" && left.id !== "||" &&
+					left.id !== "?") {
+				warning("W067", left);
+			}
+		}
+
+		that.left = left;
+		return that;
+	}, 155, true).exps = true;
+
+	prefix("(", function () {
+		nospace();
+		var bracket, brackets = [];
+		var pn, pn1, i = 0;
+		var ret;
+
+		do {
+			pn = peek(i);
+			i += 1;
+			pn1 = peek(i);
+			i += 1;
+		} while (pn.value !== ")" && pn1.value !== "=>" && pn1.value !== ";" && pn1.type !== "(end)");
+
+		if (state.tokens.next.id === "function") {
+			state.tokens.next.immed = true;
+		}
+
+		var exprs = [];
+
+		if (state.tokens.next.id !== ")") {
+			for (;;) {
+				if (pn1.value === "=>" && state.tokens.next.value === "{") {
+					bracket = state.tokens.next;
+					bracket.left = destructuringExpression();
+					brackets.push(bracket);
+					for (var t in bracket.left) {
+						exprs.push(bracket.left[t].token);
+					}
+				} else {
+					exprs.push(expression(10));
+				}
+				if (state.tokens.next.id !== ",") {
+					break;
+				}
+				comma();
+			}
+		}
+
+		advance(")", this);
+		nospace(state.tokens.prev, state.tokens.curr);
+		if (state.option.immed && exprs[0] && exprs[0].id === "function") {
+			if (state.tokens.next.id !== "(" &&
+			  (state.tokens.next.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
+				warning("W068", this);
+			}
+		}
+
+		if (state.tokens.next.value === "=>") {
+			return exprs;
+		}
+		if (!exprs.length) {
+			return;
+		}
+		if (exprs.length > 1) {
+			ret = Object.create(state.syntax[","]);
+			ret.exprs = exprs;
+		} else {
+			ret = exprs[0];
+		}
+		if (ret) {
+			ret.paren = true;
+		}
+		return ret;
+	});
+
+	application("=>");
+
+	infix("[", function (left, that) {
+		nobreak(state.tokens.prev, state.tokens.curr);
+		nospace();
+		var e = expression(10), s;
+		if (e && e.type === "(string)") {
+			if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
+				warning("W061", that);
+			}
+
+			countMember(e.value);
+			if (!state.option.sub && reg.identifier.test(e.value)) {
+				s = state.syntax[e.value];
+				if (!s || !isReserved(s)) {
+					warning("W069", state.tokens.prev, e.value);
+				}
+			}
+		}
+		advance("]", that);
+
+		if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
+			warning("W001");
+		}
+
+		nospace(state.tokens.prev, state.tokens.curr);
+		that.left = left;
+		that.right = e;
+		return that;
+	}, 160, true);
+
+	function comprehensiveArrayExpression() {
+		var res = {};
+		res.exps = true;
+		funct["(comparray)"].stack();
+
+		// Handle reversed for expressions, used in spidermonkey
+		var reversed = false;
+		if (state.tokens.next.value !== "for") {
+			reversed = true;
+			if (!state.option.inMoz(true)) {
+				warning("W116", state.tokens.next, "for", state.tokens.next.value);
+			}
+			funct["(comparray)"].setState("use");
+			res.right = expression(10);
+		}
+
+		advance("for");
+		if (state.tokens.next.value === "each") {
+			advance("each");
+			if (!state.option.inMoz(true)) {
+				warning("W118", state.tokens.curr, "for each");
+			}
+		}
+		advance("(");
+		funct["(comparray)"].setState("define");
+		res.left = expression(130);
+		if (_.contains(["in", "of"], state.tokens.next.value)) {
+			advance();
+		} else {
+			error("E045", state.tokens.curr);
+		}
+		funct["(comparray)"].setState("generate");
+		expression(10);
+
+		advance(")");
+		if (state.tokens.next.value === "if") {
+			advance("if");
+			advance("(");
+			funct["(comparray)"].setState("filter");
+			res.filter = expression(10);
+			advance(")");
+		}
+
+		if (!reversed) {
+			funct["(comparray)"].setState("use");
+			res.right = expression(10);
+		}
+
+		advance("]");
+		funct["(comparray)"].unstack();
+		return res;
+	}
+
+	prefix("[", function () {
+		var blocktype = lookupBlockType(true);
+		if (blocktype.isCompArray) {
+			if (!state.option.inESNext()) {
+				warning("W119", state.tokens.curr, "array comprehension");
+			}
+			return comprehensiveArrayExpression();
+		} else if (blocktype.isDestAssign && !state.option.inESNext()) {
+			warning("W104", state.tokens.curr, "destructuring assignment");
+		}
+		var b = state.tokens.curr.line !== state.tokens.next.line;
+		this.first = [];
+		if (b) {
+			indent += state.option.indent;
+			if (state.tokens.next.from === indent + state.option.indent) {
+				indent += state.option.indent;
+			}
+		}
+		while (state.tokens.next.id !== "(end)") {
+			while (state.tokens.next.id === ",") {
+				if (!state.option.inES5())
+					warning("W070");
+				advance(",");
+			}
+			if (state.tokens.next.id === "]") {
+				break;
+			}
+			if (b && state.tokens.curr.line !== state.tokens.next.line) {
+				indentation();
+			}
+			this.first.push(expression(10));
+			if (state.tokens.next.id === ",") {
+				comma({ allowTrailing: true });
+				if (state.tokens.next.id === "]" && !state.option.inES5(true)) {
+					warning("W070", state.tokens.curr);
+					break;
+				}
+			} else {
+				break;
+			}
+		}
+		if (b) {
+			indent -= state.option.indent;
+			indentation();
+		}
+		advance("]", this);
+		return this;
+	}, 160);
+
+
+	function property_name() {
+		var id = optionalidentifier(false, true);
+
+		if (!id) {
+			if (state.tokens.next.id === "(string)") {
+				id = state.tokens.next.value;
+				advance();
+			} else if (state.tokens.next.id === "(number)") {
+				id = state.tokens.next.value.toString();
+				advance();
+			}
+		}
+
+		if (id === "hasOwnProperty") {
+			warning("W001");
+		}
+
+		return id;
+	}
+
+	function functionparams(parsed) {
+		var curr, next;
+		var params = [];
+		var ident;
+		var tokens = [];
+		var t;
+		var pastDefault = false;
+
+		if (parsed) {
+			if (Array.isArray(parsed)) {
+				for (var i in parsed) {
+					curr = parsed[i];
+					if (_.contains(["{", "["], curr.id)) {
+						for (t in curr.left) {
+							t = tokens[t];
+							if (t.id) {
+								params.push(t.id);
+								addlabel(t.id, { type: "unused", token: t.token });
+							}
+						}
+					} else if (curr.value === "...") {
+						if (!state.option.inESNext()) {
+							warning("W104", curr, "spread/rest operator");
+						}
+						continue;
+					} else {
+						params.push(curr.value);
+						addlabel(curr.value, { type: "unused", token: curr });
+					}
+				}
+				return params;
+			} else {
+				if (parsed.identifier === true) {
+					addlabel(parsed.value, { type: "unused", token: parsed });
+					return [parsed];
+				}
+			}
+		}
+
+		next = state.tokens.next;
+
+		advance("(");
+		nospace();
+
+		if (state.tokens.next.id === ")") {
+			advance(")");
+			return;
+		}
+
+		for (;;) {
+			if (_.contains(["{", "["], state.tokens.next.id)) {
+				tokens = destructuringExpression();
+				for (t in tokens) {
+					t = tokens[t];
+					if (t.id) {
+						params.push(t.id);
+						addlabel(t.id, { type: "unused", token: t.token });
+					}
+				}
+			} else if (state.tokens.next.value === "...") {
+				if (!state.option.inESNext()) {
+					warning("W104", state.tokens.next, "spread/rest operator");
+				}
+				advance("...");
+				nospace();
+				ident = identifier(true);
+				params.push(ident);
+				addlabel(ident, { type: "unused", token: state.tokens.curr });
+			} else {
+				ident = identifier(true);
+				params.push(ident);
+				addlabel(ident, { type: "unused", token: state.tokens.curr });
+			}
+
+			// it is a syntax error to have a regular argument after a default argument
+			if (pastDefault) {
+				if (state.tokens.next.id !== "=") {
+					error("E051", state.tokens.current);
+				}
+			}
+			if (state.tokens.next.id === "=") {
+				if (!state.option.inESNext()) {
+					warning("W119", state.tokens.next, "default parameters");
+				}
+				advance("=");
+				pastDefault = true;
+				expression(10);
+			}
+			if (state.tokens.next.id === ",") {
+				comma();
+			} else {
+				advance(")", next);
+				nospace(state.tokens.prev, state.tokens.curr);
+				return params;
+			}
+		}
+	}
+
+	function setprop(funct, name, values) {
+		if (!funct["(properties)"][name]) {
+			funct["(properties)"][name] = { unused: false };
+		}
+
+		_.extend(funct["(properties)"][name], values);
+	}
+
+	function getprop(funct, name, prop) {
+		if (!funct["(properties)"][name])
+			return null;
+
+		return funct["(properties)"][name][prop] || null;
+	}
+
+	function functor(name, token, scope, overwrites) {
+		var funct = {
+			"(name)"      : name,
+			"(breakage)"  : 0,
+			"(loopage)"   : 0,
+			"(scope)"     : scope,
+			"(tokens)"    : {},
+			"(properties)": {},
+
+			"(catch)"     : false,
+			"(global)"    : false,
+
+			"(line)"      : null,
+			"(character)" : null,
+			"(metrics)"   : null,
+			"(statement)" : null,
+			"(context)"   : null,
+			"(blockscope)": null,
+			"(comparray)" : null,
+			"(generator)" : null,
+			"(params)"    : null
+		};
+
+		if (token) {
+			_.extend(funct, {
+				"(line)"     : token.line,
+				"(character)": token.character,
+				"(metrics)"  : createMetrics(token)
+			});
+		}
+
+		_.extend(funct, overwrites);
+
+		if (funct["(context)"]) {
+			funct["(blockscope)"] = funct["(context)"]["(blockscope)"];
+			funct["(comparray)"]  = funct["(context)"]["(comparray)"];
+		}
+
+		return funct;
+	}
+
+	function doFunction(name, statement, generator, fatarrowparams) {
+		var f;
+		var oldOption = state.option;
+		var oldIgnored = state.ignored;
+		var oldScope  = scope;
+
+		state.option = Object.create(state.option);
+		state.ignored = Object.create(state.ignored);
+		scope = Object.create(scope);
+
+		funct = functor(name || "\"" + anonname + "\"", state.tokens.next, scope, {
+			"(statement)": statement,
+			"(context)":   funct,
+			"(generator)": generator ? true : null
+		});
+
+		f = funct;
+		state.tokens.curr.funct = funct;
+
+		functions.push(funct);
+
+		if (name) {
+			addlabel(name, { type: "function" });
+		}
+
+		funct["(params)"] = functionparams(fatarrowparams);
+		funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
+
+		// So we parse fat-arrow functions after we encounter =>. So basically
+		// doFunction is called with the left side of => as its last argument.
+		// This means that the parser, at that point, had already added its
+		// arguments to the undefs array and here we undo that.
+
+		JSHINT.undefs = _.filter(JSHINT.undefs, function (item) {
+			return !_.contains(_.union(fatarrowparams), item[2]);
+		});
+
+		block(false, true, true, fatarrowparams ? true : false);
+
+		if (!state.option.noyield && generator && funct["(generator)"] !== "yielded") {
+			warning("W124", state.tokens.curr);
+		}
+
+		funct["(metrics)"].verifyMaxStatementsPerFunction();
+		funct["(metrics)"].verifyMaxComplexityPerFunction();
+		funct["(unusedOption)"] = state.option.unused;
+
+		scope = oldScope;
+		state.option = oldOption;
+		state.ignored = oldIgnored;
+		funct["(last)"] = state.tokens.curr.line;
+		funct["(lastcharacter)"] = state.tokens.curr.character;
+
+		_.map(Object.keys(funct), function (key) {
+			if (key[0] === "(") return;
+			funct["(blockscope)"].unshadow(key);
+		});
+
+		funct = funct["(context)"];
+
+		return f;
+	}
+
+	function createMetrics(functionStartToken) {
+		return {
+			statementCount: 0,
+			nestedBlockDepth: -1,
+			ComplexityCount: 1,
+
+			verifyMaxStatementsPerFunction: function () {
+				if (state.option.maxstatements &&
+					this.statementCount > state.option.maxstatements) {
+					warning("W071", functionStartToken, this.statementCount);
+				}
+			},
+
+			verifyMaxParametersPerFunction: function (params) {
+				params = params || [];
+
+				if (state.option.maxparams && params.length > state.option.maxparams) {
+					warning("W072", functionStartToken, params.length);
+				}
+			},
+
+			verifyMaxNestedBlockDepthPerFunction: function () {
+				if (state.option.maxdepth &&
+					this.nestedBlockDepth > 0 &&
+					this.nestedBlockDepth === state.option.maxdepth + 1) {
+					warning("W073", null, this.nestedBlockDepth);
+				}
+			},
+
+			verifyMaxComplexityPerFunction: function () {
+				var max = state.option.maxcomplexity;
+				var cc = this.ComplexityCount;
+				if (max && cc > max) {
+					warning("W074", functionStartToken, cc);
+				}
+			}
+		};
+	}
+
+	function increaseComplexityCount() {
+		funct["(metrics)"].ComplexityCount += 1;
+	}
+
+	// Parse assignments that were found instead of conditionals.
+	// For example: if (a = 1) { ... }
+
+	function checkCondAssignment(expr) {
+		var id, paren;
+		if (expr) {
+			id = expr.id;
+			paren = expr.paren;
+			if (id === "," && (expr = expr.exprs[expr.exprs.length - 1])) {
+				id = expr.id;
+				paren = paren || expr.paren;
+			}
+		}
+		switch (id) {
+		case "=":
+		case "+=":
+		case "-=":
+		case "*=":
+		case "%=":
+		case "&=":
+		case "|=":
+		case "^=":
+		case "/=":
+			if (!paren && !state.option.boss) {
+				warning("W084");
+			}
+		}
+	}
+
+
+	(function (x) {
+		x.nud = function (isclassdef) {
+			var b, f, i, p, t, g;
+			var props = {}; // All properties, including accessors
+			var tag = "";
+
+			function saveProperty(name, tkn) {
+				if (props[name] && _.has(props, name))
+					warning("W075", state.tokens.next, i);
+				else
+					props[name] = {};
+
+				props[name].basic = true;
+				props[name].basictkn = tkn;
+			}
+
+			function saveSetter(name, tkn) {
+				if (props[name] && _.has(props, name)) {
+					if (props[name].basic || props[name].setter)
+						warning("W075", state.tokens.next, i);
+				} else {
+					props[name] = {};
+				}
+
+				props[name].setter = true;
+				props[name].setterToken = tkn;
+			}
+
+			function saveGetter(name) {
+				if (props[name] && _.has(props, name)) {
+					if (props[name].basic || props[name].getter)
+						warning("W075", state.tokens.next, i);
+				} else {
+					props[name] = {};
+				}
+
+				props[name].getter = true;
+				props[name].getterToken = state.tokens.curr;
+			}
+
+			b = state.tokens.curr.line !== state.tokens.next.line;
+			if (b) {
+				indent += state.option.indent;
+				if (state.tokens.next.from === indent + state.option.indent) {
+					indent += state.option.indent;
+				}
+			}
+
+			for (;;) {
+				if (state.tokens.next.id === "}") {
+					break;
+				}
+
+				if (b) {
+					indentation();
+				}
+
+				if (isclassdef && state.tokens.next.value === "static") {
+					advance("static");
+					tag = "static ";
+				}
+
+				if (state.tokens.next.value === "get" && peek().id !== ":") {
+					advance("get");
+
+					if (!state.option.inES5(!isclassdef)) {
+						error("E034");
+					}
+
+					i = property_name();
+
+					// ES6 allows for get() {...} and set() {...} method
+					// definition shorthand syntax, so we don't produce an error
+					// if the esnext option is enabled.
+					if (!i && !state.option.inESNext()) {
+						error("E035");
+					}
+
+					// It is a Syntax Error if PropName of MethodDefinition is
+					// "constructor" and SpecialMethod of MethodDefinition is true.
+					if (isclassdef && i === "constructor") {
+						error("E049", state.tokens.next, "class getter method", i);
+					}
+
+					// We don't want to save this getter unless it's an actual getter
+					// and not an ES6 concise method
+					if (i) {
+						saveGetter(tag + i);
+					}
+
+					t = state.tokens.next;
+					adjacent(state.tokens.curr, state.tokens.next);
+					f = doFunction();
+					p = f["(params)"];
+
+					// Don't warn about getter/setter pairs if this is an ES6 concise method
+					if (i && p) {
+						warning("W076", t, p[0], i);
+					}
+
+					adjacent(state.tokens.curr, state.tokens.next);
+				} else if (state.tokens.next.value === "set" && peek().id !== ":") {
+					advance("set");
+
+					if (!state.option.inES5(!isclassdef)) {
+						error("E034");
+					}
+
+					i = property_name();
+
+					// ES6 allows for get() {...} and set() {...} method
+					// definition shorthand syntax, so we don't produce an error
+					// if the esnext option is enabled.
+					if (!i && !state.option.inESNext()) {
+						error("E035");
+					}
+
+					// It is a Syntax Error if PropName of MethodDefinition is
+					// "constructor" and SpecialMethod of MethodDefinition is true.
+					if (isclassdef && i === "constructor") {
+						error("E049", state.tokens.next, "class setter method", i);
+					}
+
+					// We don't want to save this getter unless it's an actual getter
+					// and not an ES6 concise method
+					if (i) {
+						saveSetter(tag + i, state.tokens.next);
+					}
+
+					t = state.tokens.next;
+					adjacent(state.tokens.curr, state.tokens.next);
+					f = doFunction();
+					p = f["(params)"];
+
+					// Don't warn about getter/setter pairs if this is an ES6 concise method
+					if (i && (!p || p.length !== 1)) {
+						warning("W077", t, i);
+					}
+				} else {
+					g = false;
+					if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") {
+						if (!state.option.inESNext()) {
+							warning("W104", state.tokens.next, "generator functions");
+						}
+						advance("*");
+						g = true;
+					}
+					i = property_name();
+					saveProperty(tag + i, state.tokens.next);
+
+					if (typeof i !== "string") {
+						break;
+					}
+
+					if (state.tokens.next.value === "(") {
+						if (!state.option.inESNext()) {
+							warning("W104", state.tokens.curr, "concise methods");
+						}
+						doFunction(i, undefined, g);
+					} else if (!isclassdef) {
+						advance(":");
+						nonadjacent(state.tokens.curr, state.tokens.next);
+						expression(10);
+					}
+				}
+				// It is a Syntax Error if PropName of MethodDefinition is "prototype".
+				if (isclassdef && i === "prototype") {
+					error("E049", state.tokens.next, "class method", i);
+				}
+
+				countMember(i);
+				if (isclassdef) {
+					tag = "";
+					continue;
+				}
+				if (state.tokens.next.id === ",") {
+					comma({ allowTrailing: true, property: true });
+					if (state.tokens.next.id === ",") {
+						warning("W070", state.tokens.curr);
+					} else if (state.tokens.next.id === "}" && !state.option.inES5(true)) {
+						warning("W070", state.tokens.curr);
+					}
+				} else {
+					break;
+				}
+			}
+			if (b) {
+				indent -= state.option.indent;
+				indentation();
+			}
+			advance("}", this);
+
+			// Check for lonely setters if in the ES5 mode.
+			if (state.option.inES5()) {
+				for (var name in props) {
+					if (_.has(props, name) && props[name].setter && !props[name].getter) {
+						warning("W078", props[name].setterToken);
+					}
+				}
+			}
+			return this;
+		};
+		x.fud = function () {
+			error("E036", state.tokens.curr);
+		};
+	}(delim("{")));
+
+	function destructuringExpression() {
+		var id, ids;
+		var identifiers = [];
+		if (!state.option.inESNext()) {
+			warning("W104", state.tokens.curr, "destructuring expression");
+		}
+		var nextInnerDE = function () {
+			var ident;
+			if (_.contains(["[", "{"], state.tokens.next.value)) {
+				ids = destructuringExpression();
+				for (var id in ids) {
+					id = ids[id];
+					identifiers.push({ id: id.id, token: id.token });
+				}
+			} else if (state.tokens.next.value === ",") {
+				identifiers.push({ id: null, token: state.tokens.curr });
+			} else {
+				ident = identifier();
+				if (ident)
+					identifiers.push({ id: ident, token: state.tokens.curr });
+			}
+		};
+		if (state.tokens.next.value === "[") {
+			advance("[");
+			nextInnerDE();
+			while (state.tokens.next.value !== "]") {
+				advance(",");
+				nextInnerDE();
+			}
+			advance("]");
+		} else if (state.tokens.next.value === "{") {
+			advance("{");
+			id = identifier();
+			if (state.tokens.next.value === ":") {
+				advance(":");
+				nextInnerDE();
+			} else {
+				identifiers.push({ id: id, token: state.tokens.curr });
+			}
+			while (state.tokens.next.value !== "}") {
+				advance(",");
+				id = identifier();
+				if (state.tokens.next.value === ":") {
+					advance(":");
+					nextInnerDE();
+				} else {
+					identifiers.push({ id: id, token: state.tokens.curr });
+				}
+			}
+			advance("}");
+		}
+		return identifiers;
+	}
+
+	function destructuringExpressionMatch(tokens, value) {
+		var first = value.first;
+
+		if (!first)
+			return;
+
+		_.zip(tokens, Array.isArray(first) ? first : [ first ]).forEach(function (val) {
+			var token = val[0];
+			var value = val[1];
+
+			if (token

<TRUNCATED>