]> dev.renevier.net Git - syj.git/blob - scripts/fulljslint.js
allow opening terms of use box with space keyboard
[syj.git] / scripts / fulljslint.js
1 // jslint.js
2 // 2011-03-07
3
4 /*
5 Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy of
8 this software and associated documentation files (the "Software"), to deal in
9 the Software without restriction, including without limitation the rights to
10 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11 of the Software, and to permit persons to whom the Software is furnished to do
12 so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16
17 The Software shall be used for Good, not Evil.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 SOFTWARE.
26 */
27
28 /*
29     JSLINT is a global function. It takes two parameters.
30
31         var myResult = JSLINT(source, option);
32
33     The first parameter is either a string or an array of strings. If it is a
34     string, it will be split on '\n' or '\r'. If it is an array of strings, it
35     is assumed that each string represents one line. The source can be a
36     JavaScript text, or HTML text, or a JSON text, or a CSS text.
37
38     The second parameter is an optional object of options which control the
39     operation of JSLINT. Most of the options are booleans: They are all
40     optional and have a default value of false. One of the options, predef,
41     can be an array of names, which will be used to declare global variables,
42     or an object whose keys are used as global names, with a boolean value
43     that determines if they are assignable.
44
45     If it checks out, JSLINT returns true. Otherwise, it returns false.
46
47     If false, you can inspect JSLINT.errors to find out the problems.
48     JSLINT.errors is an array of objects containing these properties:
49
50     {
51         line      : The line (relative to 0) at which the lint was found
52         character : The character (relative to 0) at which the lint was found
53         reason    : The problem
54         evidence  : The text line in which the problem occurred
55         raw       : The raw message before the details were inserted
56         a         : The first detail
57         b         : The second detail
58         c         : The third detail
59         d         : The fourth detail
60     }
61
62     If a fatal error was found, a null will be the last element of the
63     JSLINT.errors array.
64
65     You can request a Function Report, which shows all of the functions
66     and the parameters and vars that they use. This can be used to find
67     implied global variables and other problems. The report is in HTML and
68     can be inserted in an HTML <body>.
69
70         var myReport = JSLINT.report(errors_only);
71
72     If errors_only is true, then the report will be limited to only errors.
73
74     You can request a data structure which contains JSLint's results.
75
76         var myData = JSLINT.data();
77
78     It returns a structure with this form:
79
80     {
81         errors: [
82             {
83                 line: NUMBER,
84                 character: NUMBER,
85                 reason: STRING,
86                 evidence: STRING
87             }
88         ],
89         functions: [
90             name: STRING,
91             line: NUMBER,
92             last: NUMBER,
93             param: [
94                 TOKEN
95             ],
96             closure: [
97                 STRING
98             ],
99             var: [
100                 STRING
101             ],
102             exception: [
103                 STRING
104             ],
105             outer: [
106                 STRING
107             ],
108             unused: [
109                 STRING
110             ],
111             global: [
112                 STRING
113             ],
114             label: [
115                 STRING
116             ]
117         ],
118         globals: [
119             STRING
120         ],
121         member: {
122             STRING: NUMBER
123         },
124         unuseds: [
125             {
126                 name: STRING,
127                 line: NUMBER
128             }
129         ],
130         implieds: [
131             {
132                 name: STRING,
133                 line: NUMBER
134             }
135         ],
136         urls: [
137             STRING
138         ],
139         json: BOOLEAN
140     }
141
142     Empty arrays will not be included.
143
144     You can obtain the parse tree that JSLint constructed while parsing. The
145     latest tree is kept in JSLINT.tree. A nice stringication can be produced
146     with
147
148         JSON.stringify(JSLINT.tree, [
149             'value',  'arity', 'name',  'first',
150             'second', 'third', 'block', 'else'
151         ], 4));
152
153 */
154
155 /*
156     JSLint provides three directives. They look like slashstar comments, and
157     allow for setting options, declaring global variables, and establishing a
158     set of allowed property names.
159
160     These directives respect function scope.
161 */
162
163 /*
164     The jslint directive is a special comment that can set one or more options.
165     The current option set is
166
167     adsafe     true, if ADsafe rules should be enforced
168     bitwise    true, if bitwise operators should not be allowed
169     browser    true, if the standard browser globals should be predefined
170     cap        true, if upper case HTML should be allowed
171     'continue' true, if the continuation statement should be tolerated
172     css        true, if CSS workarounds should be tolerated
173     debug      true, if debugger statements should be allowed
174     devel      true, if logging should be allowed (console, alert, etc.)
175     es5        true, if ES5 syntax should be allowed
176     evil       true, if eval should be allowed
177     forin      true, if for in statements need not filter
178     fragment   true, if HTML fragments should be allowed
179     indent     the indentation factor
180     maxerr     the maximum number of errors to allow
181     maxlen     the maximum length of a source line
182     newcap     true, if constructor names must be capitalized
183     nomen      true, if names should be checked
184     on         true, if HTML event handlers should be allowed
185     onevar     true, if only one var statement per function should be allowed
186     passfail   true, if the scan should stop on first error
187     plusplus   true, if increment/decrement should not be allowed
188     regexp     true, if the . should not be allowed in regexp literals
189     rhino      true, if the Rhino environment globals should be predefined
190     undef      true, if variables should be declared before used
191     safe       true, if use of some browser features should be restricted
192     windows    true, if MS Windows-specigic globals should be predefined
193     strict     true, require the "use strict"; pragma
194     sub        true, if all forms of subscript notation are tolerated
195     white      true, if strict whitespace rules apply
196     widget     true  if the Yahoo Widgets globals should be predefined
197
198     For example:
199 */
200
201
202 /*jslint
203     evil: true, nomen: false, onevar: false, regexp: false, strict: true
204 */
205
206 /*
207     The properties directive declares an exclusive list of property names.
208     Any properties named in the program that are not in the list will
209     produce a warning.
210
211     For example:
212 */
213
214 /*properties "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "'",
215     "(begin)", "(breakage)", "(context)", "(error)", "(global)",
216     "(identifier)", "(line)", "(loopage)", "(name)", "(onevar)", "(params)",
217     "(scope)", "(statement)", "(token)", "(verb)", ")", "*", "+", "-", "\/",
218     ";", "<", "<=", "==", "===", ">", ">=", ADSAFE, ActiveXObject,
219     Array, Boolean, COM, CScript, Canvas, CustomAnimation, Date, Debug, E,
220     Enumerator, Error, EvalError, FadeAnimation, Flash, FormField, Frame,
221     Function, HotKey, Image, JSON, LN10, LN2, LOG10E, LOG2E, MAX_VALUE,
222     MIN_VALUE, Math, MenuItem, MoveAnimation, NEGATIVE_INFINITY, Number,
223     Object, Option, PI, POSITIVE_INFINITY, Point, RangeError, Rectangle,
224     ReferenceError, RegExp, ResizeAnimation, RotateAnimation, SQRT1_2,
225     SQRT2, ScrollBar, String, Style, SyntaxError, System, Text, TextArea,
226     Timer, TypeError, URIError, URL, VBArray, WScript, Web, Window, XMLDOM,
227     XMLHttpRequest, "\\", a, a_function, a_label, a_not_allowed,
228     a_not_defined, a_scope, abbr, acronym, activeborder, activecaption,
229     address, adsafe, adsafe_a, adsafe_autocomplete, adsafe_bad_id,
230     adsafe_div, adsafe_fragment, adsafe_go, adsafe_html, adsafe_id,
231     adsafe_id_go, adsafe_lib, adsafe_lib_second, adsafe_missing_id,
232     adsafe_name_a, adsafe_placement, adsafe_prefix_a, adsafe_script,
233     adsafe_source, adsafe_subscript_a, adsafe_tag, alert, aliceblue, all,
234     already_defined, and, animator, antiquewhite, appleScript, applet,
235     apply, approved, appworkspace, aqua, aquamarine, area, arguments, arity,
236     article, aside, assign, assign_exception,
237     assignment_function_expression, at, attribute_case_a, audio,
238     autocomplete, avoid_a, azure, b, background, "background-attachment",
239     "background-color", "background-image", "background-position",
240     "background-repeat", bad_assignment, bad_color_a, bad_constructor,
241     bad_entity, bad_html, bad_id_a, bad_in_a, bad_invocation, bad_name_a,
242     bad_new, bad_number, bad_operand, bad_type, bad_url, bad_wrap, base,
243     bdo, beep, beige, big, bisque, bitwise, black, blanchedalmond, block,
244     blockquote, blue, blueviolet, body, border, "border-bottom",
245     "border-bottom-color", "border-bottom-style", "border-bottom-width",
246     "border-collapse", "border-color", "border-left", "border-left-color",
247     "border-left-style", "border-left-width", "border-right",
248     "border-right-color", "border-right-style", "border-right-width",
249     "border-spacing", "border-style", "border-top", "border-top-color",
250     "border-top-style", "border-top-width", "border-width", bottom, br,
251     braille, brown, browser, burlywood, button, buttonface, buttonhighlight,
252     buttonshadow, buttontext, bytesToUIString, c, cadetblue, call, callee,
253     caller, canvas, cap, caption, "caption-side", captiontext, center,
254     charAt, charCodeAt, character, chartreuse, chocolate, chooseColor,
255     chooseFile, chooseFolder, cite, clear, clearInterval, clearTimeout,
256     clip, closeWidget, closure, cm, code, col, colgroup, color, combine_var,
257     command, comments, concat, conditional_assignment, confirm, confusing_a,
258     confusing_regexp, console, constructor, constructor_name_a, content,
259     continue, control_a, convertPathToHFS, convertPathToPlatform, coral,
260     cornflowerblue, cornsilk, "counter-increment", "counter-reset", create,
261     crimson, css, cursor, cyan, d, dangerous_comment, dangling_a, darkblue,
262     darkcyan, darkgoldenrod, darkgray, darkgreen, darkkhaki, darkmagenta,
263     darkolivegreen, darkorange, darkorchid, darkred, darksalmon,
264     darkseagreen, darkslateblue, darkslategray, darkturquoise, darkviolet,
265     data, datalist, dd, debug, decodeURI, decodeURIComponent, deeppink,
266     deepskyblue, defineClass, del, deleted, deserialize, details, devel,
267     dfn, dialog, dimgray, dir, direction, display, disrupt, div, dl,
268     document, dodgerblue, dt, duplicate_a, edge, edition, else, em, embed,
269     embossed, empty, "empty-cells", empty_block, empty_case, empty_class,
270     encodeURI, encodeURIComponent, entityify, errors, es5, escape, eval,
271     event, evidence, evil, ex, exception, exec, expected_a,
272     expected_a_at_b_c, expected_a_b, expected_a_b_from_c_d, expected_at_a,
273     expected_attribute_a, expected_attribute_value_a, expected_class_a,
274     expected_fraction_a, expected_id_a, expected_identifier_a,
275     expected_identifier_a_reserved, expected_lang_a, expected_linear_a,
276     expected_media_a, expected_name_a, expected_nonstandard_style_attribute,
277     expected_number_a, expected_operator_a, expected_percent_a,
278     expected_positive_a, expected_pseudo_a, expected_selector_a,
279     expected_small_a, expected_space_a_b, expected_string_a,
280     expected_style_attribute, expected_style_pattern, expected_tagname_a,
281     fieldset, figure, filesystem, filter, firebrick, first, float, floor,
282     floralwhite, focusWidget, font, "font-family", "font-size",
283     "font-size-adjust", "font-stretch", "font-style", "font-variant",
284     "font-weight", footer, for_if, forestgreen, forin, form, fragment,
285     frame, frames, frameset, from, fromCharCode, fuchsia, fud, funct,
286     function, function_block, function_eval, function_loop,
287     function_statement, function_strict, functions, g, gainsboro, gc,
288     get_set, ghostwhite, global, globals, gold, goldenrod, gray, graytext,
289     green, greenyellow, h1, h2, h3, h4, h5, h6, handheld, hasOwnProperty,
290     head, header, height, help, hgroup, highlight, highlighttext, history,
291     honeydew, hotpink, hr, "hta:application", html, html_confusion_a,
292     html_handlers, i, iTunes, id, identifier, identifier_function, iframe,
293     img, immed, implied_evil, implieds, in, inactiveborder, inactivecaption,
294     inactivecaptiontext, include, indent, indexOf, indianred, indigo,
295     infix_in, infobackground, infotext, init, input, ins, insecure_a,
296     isAlpha, isApplicationRunning, isArray, isDigit, isFinite, isNaN, ivory,
297     join, jslint, json, kbd, keygen, keys, khaki, konfabulatorVersion,
298     label, label_a_b, labeled, lang, lavender, lavenderblush, lawngreen,
299     lbp, leading_decimal_a, led, left, legend, lemonchiffon, length,
300     "letter-spacing", li, lib, lightblue, lightcoral, lightcyan,
301     lightgoldenrodyellow, lightgreen, lightpink, lightsalmon, lightseagreen,
302     lightskyblue, lightslategray, lightsteelblue, lightyellow, lime,
303     limegreen, line, "line-height", linen, link, "list-style",
304     "list-style-image", "list-style-position", "list-style-type", load,
305     loadClass, location, log, m, magenta, map, margin, "margin-bottom",
306     "margin-left", "margin-right", "margin-top", mark, "marker-offset",
307     maroon, match, "max-height", "max-width", maxerr, maxlen, md5,
308     mediumaquamarine, mediumblue, mediumorchid, mediumpurple,
309     mediumseagreen, mediumslateblue, mediumspringgreen, mediumturquoise,
310     mediumvioletred, member, menu, menutext, message, meta, meter,
311     midnightblue, "min-height", "min-width", mintcream, missing_a,
312     missing_a_after_b, missing_option, missing_property, missing_space_a_b,
313     missing_url, missing_use_strict, mistyrose, mixed, mm, moccasin, mode,
314     move_invocation, move_var, name, name_function, nav, navajowhite,
315     navigator, navy, nested_comment, newcap, next, noframes, nomen,
316     noscript, not, not_a_constructor, not_a_defined, not_a_function, not_a_label,
317     not_a_scope, not_greater, nud, object, ol, oldlace, olive, olivedrab,
318     on, onevar, opacity, open, openURL, opera, optgroup, option, orange,
319     orangered, orchid, outer, outline, "outline-color", "outline-style",
320     "outline-width", output, overflow, "overflow-x", "overflow-y", p,
321     padding, "padding-bottom", "padding-left", "padding-right",
322     "padding-top", "page-break-after", "page-break-before", palegoldenrod,
323     palegreen, paleturquoise, palevioletred, papayawhip, param,
324     parameter_a_get_b, parameter_set_a, paren, parent, parseFloat, parseInt,
325     passfail, pc, peachpuff, peru, pink, play, plum, plusplus, pop,
326     popupMenu, position, postcomments, postscript, powderblue, pre, predef,
327     preferenceGroups, preferences, prev, print, progress, projection,
328     prompt, prototype, pt, purple, push, px, q, quit, quote, quotes, radix,
329     random, range, raw, readFile, readUrl, read_only, reason, red,
330     redefinition_a, regexp, reloadWidget, replace, report, reserved,
331     reserved_a, resolvePath, resumeUpdates, rhino, right, rosybrown,
332     royalblue, rp, rt, ruby, runCommand, runCommandInBg, saddlebrown, safe,
333     salmon, samp, sandybrown, saveAs, savePreferences, scanned_a_b, screen,
334     script, scrollbar, seagreen, seal, search, seashell, second, section,
335     select, serialize, setInterval, setTimeout, shift,
336     showWidgetPreferences, sienna, silver, skyblue, slash_equal, slateblue,
337     slategray, sleep, slice, small, snow, sort, source, span, spawn, speak,
338     speech, split, springgreen, src, stack, statement_block, steelblue,
339     stopping, strange_loop, strict, strong, style, styleproperty, sub,
340     subscript, substr, sup, supplant, suppressUpdates, sync, system, table,
341     "table-layout", tag_a_in_b, tan, tbody, td, teal, tellWidget, test,
342     "text-align", "text-decoration", "text-indent", "text-shadow",
343     "text-transform", textarea, tfoot, th, thead, third, thistle,
344     threeddarkshadow, threedface, threedhighlight, threedlightshadow,
345     threedshadow, thru, time, title, toLowerCase, toString, toUpperCase,
346     toint32, token, tomato, too_long, too_many, top, tr, trailing_decimal_a,
347     tree, tt, tty, turquoise, tv, type, u, ul, unclosed, unclosed_comment,
348     unclosed_regexp, undef, unescape, unescaped_a, unexpected_a,
349     unexpected_char_a_b, unexpected_comment, unexpected_member_a,
350     unexpected_space_a_b, "unicode-bidi", unnecessary_initialize,
351     unnecessary_use, unreachable_a_b, unrecognized_style_attribute_a,
352     unrecognized_tag_a, unsafe, unused, unwatch, updateNow, url, urls,
353     use_array, use_braces, use_object, used_before_a, value, valueOf, var,
354     var_a_not, version, "vertical-align", video, violet, visibility, was,
355     watch, weird_assignment, weird_condition, weird_new, weird_program,
356     weird_relation, weird_ternary, wheat, white, "white-space", whitesmoke,
357     widget, width, window, windowframe, windows, windowtext, "word-spacing",
358     "word-wrap", wrap, wrap_immediate, wrap_regexp, write_is_wrong,
359     yahooCheckLogin, yahooLogin, yahooLogout, yellow, yellowgreen,
360     "z-index"
361 */
362
363 /*
364     The global directive is used to declare global variables that can
365     be accessed by the program. If a declaration is true, then the variable
366     is writeable. Otherwise, it is read-only.
367 */
368
369 // We build the application inside a function so that we produce only a single
370 // global variable. That function will be invoked immediately, and its return
371 // value is the JSLINT function itself. That function is also an object that
372 // can contain data and other functions.
373
374 var JSLINT = (function () {
375     "use strict";
376
377     var adsafe_id,      // The widget's ADsafe id.
378         adsafe_may,     // The widget may load approved scripts.
379         adsafe_top,     // At the top of the widget script.
380         adsafe_went,    // ADSAFE.go has been called.
381         anonname,       // The guessed name for anonymous functions.
382         approved,       // ADsafe approved urls.
383
384 // These are operators that should not be used with the ! operator.
385
386         bang = {
387             '<': true,
388             '<=': true,
389             '==': true,
390             '===': true,
391             '!==': true,
392             '!=': true,
393             '>': true,
394             '>=': true,
395             '+': true,
396             '-': true,
397             '*': true,
398             '/': true,
399             '%': true
400         },
401
402 // These are property names that should not be permitted in the safe subset.
403
404         banned = {
405             'arguments'     : true,
406             callee          : true,
407             caller          : true,
408             constructor     : true,
409             'eval'          : true,
410             prototype       : true,
411             stack           : true,
412             unwatch         : true,
413             valueOf         : true,
414             watch           : true
415         },
416
417 // browser contains a set of global names that are commonly provided by a
418 // web browser environment. self and window are intentially excluded because
419 // of the high likelihood for misue.
420
421         browser = {
422             clearInterval   : false,
423             clearTimeout    : false,
424             document        : false,
425             event           : false,
426             frames          : false,
427             history         : false,
428             Image           : false,
429             location        : false,
430             name            : false,
431             navigator       : false,
432             Option          : false,
433             parent          : false,
434             screen          : false,
435             setInterval     : false,
436             setTimeout      : false,
437             XMLHttpRequest  : false
438         },
439
440 // bundle contains the text messages.
441
442         bundle = {
443             a_function: "'{a}' is a function.",
444             a_label: "'{a}' is a statement label.",
445             a_not_allowed: "'{a}' is not allowed.",
446             a_not_defined: "'{a}' is not defined.",
447             a_scope: "'{a}' used out of scope.",
448             adsafe: "ADsafe violation.",
449             adsafe_a: "ADsafe violation: '{a}'.",
450             adsafe_autocomplete: "ADsafe autocomplete violation.",
451             adsafe_bad_id: "ADSAFE violation: bad id.",
452             adsafe_div: "ADsafe violation: Wrap the widget in a div.",
453             adsafe_fragment: "ADSAFE: Use the fragment option.",
454             adsafe_go: "ADsafe violation: Missing ADSAFE.go.",
455             adsafe_html: "Currently, ADsafe does not operate on whole HTML documents. It operates on <div> fragments and .js files.",
456             adsafe_id: "ADsafe violation: id does not match.",
457             adsafe_id_go: "ADsafe violation: Missing ADSAFE.id or ADSAFE.go.",
458             adsafe_lib: "ADsafe lib violation.",
459             adsafe_lib_second: "ADsafe: The second argument to lib must be a function.",
460             adsafe_missing_id: "ADSAFE violation: missing ID_.",
461             adsafe_name_a: "ADsafe name violation: '{a}'.",
462             adsafe_placement: "ADsafe script placement violation.",
463             adsafe_prefix_a: "ADsafe violation: An id must have a '{a}' prefix",
464             adsafe_script: "ADsafe script violation.",
465             adsafe_source: "ADsafe unapproved script source.",
466             adsafe_subscript_a: "ADsafe subscript '{a}'.",
467             adsafe_tag: "ADsafe violation: Disallowed tag '{a}'.",
468             already_defined: "'{a}' is already defined.",
469             and: "The '&&' subexpression should be wrapped in parens.",
470             assign_exception: "Do not assign to the exception parameter.",
471             assignment_function_expression: "Expected an assignment or function call and instead saw an expression.",
472             attribute_case_a: "Attribute '{a}' not all lower case.",
473             avoid_a: "Avoid '{a}'.",
474             bad_assignment: "Bad assignment.",
475             bad_color_a: "Bad hex color '{a}'.",
476             bad_constructor: "Bad constructor.",
477             bad_entity: "Bad entity.",
478             bad_html: "Bad HTML string",
479             bad_id_a: "Bad id: '{a}'.",
480             bad_in_a: "Bad for in variable '{a}'.",
481             bad_invocation: "Bad invocation.",
482             bad_name_a: "Bad name: '{a}'.",
483             bad_new: "Do not use 'new' for side effects.",
484             bad_number: "Bad number '{a}'.",
485             bad_operand: "Bad operand.",
486             bad_type: "Bad type.",
487             bad_url: "Bad url string.",
488             bad_wrap: "Do not wrap function literals in parens unless they are to be immediately invoked.",
489             combine_var: "Combine this with the previous 'var' statement.",
490             conditional_assignment: "Expected a conditional expression and instead saw an assignment.",
491             confusing_a: "Confusing use of '{a}'.",
492             confusing_regexp: "Confusing regular expression.",
493             constructor_name_a: "A constructor name '{a}' should start with an uppercase letter.",
494             control_a: "Unexpected control character '{a}'.",
495             css: "A css file should begin with @charset 'UTF-8';",
496             dangling_a: "Unexpected dangling '_' in '{a}'.",
497             dangerous_comment: "Dangerous comment.",
498             deleted: "Only properties should be deleted.",
499             duplicate_a: "Duplicate '{a}'.",
500             empty_block: "Empty block.",
501             empty_case: "Empty case.",
502             empty_class: "Empty class.",
503             evil: "eval is evil.",
504             expected_a: "Expected '{a}'.",
505             expected_a_b: "Expected '{a}' and instead saw '{b}'.",
506             expected_a_b_from_c_d: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
507             expected_at_a: "Expected an at-rule, and instead saw @{a}.",
508             expected_a_at_b_c: "Expected '{a}' at column {b}, not column {c}.",
509             expected_attribute_a: "Expected an attribute, and instead saw [{a}].",
510             expected_attribute_value_a: "Expected an attribute value and instead saw '{a}'.",
511             expected_class_a: "Expected a class, and instead saw .{a}.",
512             expected_fraction_a: "Expected a number between 0 and 1 and instead saw '{a}'",
513             expected_id_a: "Expected an id, and instead saw #{a}.",
514             expected_identifier_a: "Expected an identifier and instead saw '{a}'.",
515             expected_identifier_a_reserved: "Expected an identifier and instead saw '{a}' (a reserved word).",
516             expected_linear_a: "Expected a linear unit and instead saw '{a}'.",
517             expected_lang_a: "Expected a lang code, and instead saw :{a}.",
518             expected_media_a: "Expected a CSS media type, and instead saw '{a}'.",
519             expected_name_a: "Expected a name and instead saw '{a}'.",
520             expected_nonstandard_style_attribute: "Expected a non-standard style attribute and instead saw '{a}'.",
521             expected_number_a: "Expected a number and instead saw '{a}'.",
522             expected_operator_a: "Expected an operator and instead saw '{a}'.",
523             expected_percent_a: "Expected a percentage and instead saw '{a}'",
524             expected_positive_a: "Expected a positive number and instead saw '{a}'",
525             expected_pseudo_a: "Expected a pseudo, and instead saw :{a}.",
526             expected_selector_a: "Expected a CSS selector, and instead saw {a}.",
527             expected_small_a: "Expected a small number and instead saw '{a}'",
528             expected_space_a_b: "Expected exactly one space between '{a}' and '{b}'.",
529             expected_string_a: "Expected a string and instead saw {a}.",
530             expected_style_attribute: "Excepted a style attribute, and instead saw '{a}'.",
531             expected_style_pattern: "Expected a style pattern, and instead saw '{a}'.",
532             expected_tagname_a: "Expected a tagName, and instead saw {a}.",
533             for_if: "The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.",
534             function_block: "Function statements should not be placed in blocks. " +
535                 "Use a function expression or move the statement to the top of " +
536                 "the outer function.",
537             function_eval: "The Function constructor is eval.",
538             function_loop: "Don't make functions within a loop.",
539             function_statement: "Function statements are not invocable. " +
540                 "Wrap the whole function invocation in parens.",
541             function_strict: "Use the function form of \"use strict\".",
542             get_set: "get/set are ES5 features.",
543             html_confusion_a: "HTML confusion in regular expression '<{a}'.",
544             html_handlers: "Avoid HTML event handlers.",
545             identifier_function: "Expected an identifier in an assignment and instead saw a function invocation.",
546             implied_evil: "Implied eval is evil. Pass a function instead of a string.",
547             infix_in: "Unexpected 'in'. Compare with undefined, or use the hasOwnProperty method instead.",
548             insecure_a: "Insecure '{a}'.",
549             isNaN: "Use the isNaN function to compare with NaN.",
550             label_a_b: "Label '{a}' on '{b}' statement.",
551             lang: "lang is deprecated.",
552             leading_decimal_a: "A leading decimal point can be confused with a dot: '.{a}'.",
553             missing_a: "Missing '{a}'.",
554             missing_a_after_b: "Missing '{a}' after '{b}'.",
555             missing_option: "Missing option value.",
556             missing_property: "Missing property name.",
557             missing_space_a_b: "Missing space between '{a}' and '{b}'.",
558             missing_url: "Missing url.",
559             missing_use_strict: "Missing \"use strict\" statement.",
560             mixed: "Mixed spaces and tabs.",
561             move_invocation: "Move the invocation into the parens that contain the function.",
562             move_var: "Move 'var' declarations to the top of the function.",
563             name_function: "Missing name in function statement.",
564             nested_comment: "Nested comment.",
565             not: "Nested not.",
566             not_a_constructor: "Do not use {a} as a constructor.",
567             not_a_defined: "'{a}' has not been fully defined yet.",
568             not_a_function: "'{a}' is not a function.",
569             not_a_label: "'{a}' is not a label.",
570             not_a_scope: "'{a}' is out of scope.",
571             not_greater: "'{a}' should not be greater than '{b}'.",
572             parameter_a_get_b: "Unexpected parameter '{a}' in get {b} function.",
573             parameter_set_a: "Expected parameter (value) in set {a} function.",
574             radix: "Missing radix parameter.",
575             read_only: "Read only.",
576             redefinition_a: "Redefinition of '{a}'.",
577             reserved_a: "Reserved name '{a}'.",
578             scanned_a_b: "{a} ({b}% scanned).",
579             slash_equal: "A regular expression literal can be confused with '/='.",
580             statement_block: "Expected to see a statement and instead saw a block.",
581             stopping: "Stopping. ",
582             strange_loop: "Strange loop.",
583             strict: "Strict violation.",
584             subscript: "['{a}'] is better written in dot notation.",
585             tag_a_in_b: "A '<{a}>' must be within '<{b}>'.",
586             too_long: "Line too long.",
587             too_many: "Too many errors.",
588             trailing_decimal_a: "A trailing decimal point can be confused with a dot: '.{a}'.",
589             type: "type is unnecessary.",
590             unclosed: "Unclosed string.",
591             unclosed_comment: "Unclosed comment.",
592             unclosed_regexp: "Unclosed regular expression.",
593             unescaped_a: "Unescaped '{a}'.",
594             unexpected_a: "Unexpected '{a}'.",
595             unexpected_char_a_b: "Unexpected character '{a}' in {b}.",
596             unexpected_comment: "Unexpected comment.",
597             unexpected_member_a: "Unexpected property '{a}'.",
598             unexpected_space_a_b: "Unexpected space between '{a}' and '{b}'.",
599             unnecessary_initialize: "It is not necessary to initialize '{a}' to 'undefined'.",
600             unnecessary_use: "Unnecessary \"use strict\".",
601             unreachable_a_b: "Unreachable '{a}' after '{b}'.",
602             unrecognized_style_attribute_a: "Unrecognized style attribute '{a}'.",
603             unrecognized_tag_a: "Unrecognized tag '<{a}>'.",
604             unsafe: "Unsafe character.",
605             url: "JavaScript URL.",
606             use_array: "Use the array literal notation [].",
607             use_braces: "Spaces are hard to count. Use {{a}}.",
608             use_object: "Use the object literal notation {}.",
609             used_before_a: "'{a}' was used before it was defined.",
610             var_a_not: "Variable {a} was not declared correctly.",
611             weird_assignment: "Weird assignment.",
612             weird_condition: "Weird condition.",
613             weird_new: "Weird construction. Delete 'new'.",
614             weird_program: "Weird program.",
615             weird_relation: "Weird relation.",
616             weird_ternary: "Weird ternary.",
617             wrap_immediate: "Wrap an immediate function invocation in parentheses " +
618                 "to assist the reader in understanding that the expression " +
619                 "is the result of a function, and not the function itself.",
620             wrap_regexp: "Wrap the /regexp/ literal in parens to disambiguate the slash operator.",
621             write_is_wrong: "document.write can be a form of eval."
622         },
623         comments_off,
624         css_attribute_data,
625         css_any,
626
627         css_colorData = {
628             "aliceblue"             : true,
629             "antiquewhite"          : true,
630             "aqua"                  : true,
631             "aquamarine"            : true,
632             "azure"                 : true,
633             "beige"                 : true,
634             "bisque"                : true,
635             "black"                 : true,
636             "blanchedalmond"        : true,
637             "blue"                  : true,
638             "blueviolet"            : true,
639             "brown"                 : true,
640             "burlywood"             : true,
641             "cadetblue"             : true,
642             "chartreuse"            : true,
643             "chocolate"             : true,
644             "coral"                 : true,
645             "cornflowerblue"        : true,
646             "cornsilk"              : true,
647             "crimson"               : true,
648             "cyan"                  : true,
649             "darkblue"              : true,
650             "darkcyan"              : true,
651             "darkgoldenrod"         : true,
652             "darkgray"              : true,
653             "darkgreen"             : true,
654             "darkkhaki"             : true,
655             "darkmagenta"           : true,
656             "darkolivegreen"        : true,
657             "darkorange"            : true,
658             "darkorchid"            : true,
659             "darkred"               : true,
660             "darksalmon"            : true,
661             "darkseagreen"          : true,
662             "darkslateblue"         : true,
663             "darkslategray"         : true,
664             "darkturquoise"         : true,
665             "darkviolet"            : true,
666             "deeppink"              : true,
667             "deepskyblue"           : true,
668             "dimgray"               : true,
669             "dodgerblue"            : true,
670             "firebrick"             : true,
671             "floralwhite"           : true,
672             "forestgreen"           : true,
673             "fuchsia"               : true,
674             "gainsboro"             : true,
675             "ghostwhite"            : true,
676             "gold"                  : true,
677             "goldenrod"             : true,
678             "gray"                  : true,
679             "green"                 : true,
680             "greenyellow"           : true,
681             "honeydew"              : true,
682             "hotpink"               : true,
683             "indianred"             : true,
684             "indigo"                : true,
685             "ivory"                 : true,
686             "khaki"                 : true,
687             "lavender"              : true,
688             "lavenderblush"         : true,
689             "lawngreen"             : true,
690             "lemonchiffon"          : true,
691             "lightblue"             : true,
692             "lightcoral"            : true,
693             "lightcyan"             : true,
694             "lightgoldenrodyellow"  : true,
695             "lightgreen"            : true,
696             "lightpink"             : true,
697             "lightsalmon"           : true,
698             "lightseagreen"         : true,
699             "lightskyblue"          : true,
700             "lightslategray"        : true,
701             "lightsteelblue"        : true,
702             "lightyellow"           : true,
703             "lime"                  : true,
704             "limegreen"             : true,
705             "linen"                 : true,
706             "magenta"               : true,
707             "maroon"                : true,
708             "mediumaquamarine"      : true,
709             "mediumblue"            : true,
710             "mediumorchid"          : true,
711             "mediumpurple"          : true,
712             "mediumseagreen"        : true,
713             "mediumslateblue"       : true,
714             "mediumspringgreen"     : true,
715             "mediumturquoise"       : true,
716             "mediumvioletred"       : true,
717             "midnightblue"          : true,
718             "mintcream"             : true,
719             "mistyrose"             : true,
720             "moccasin"              : true,
721             "navajowhite"           : true,
722             "navy"                  : true,
723             "oldlace"               : true,
724             "olive"                 : true,
725             "olivedrab"             : true,
726             "orange"                : true,
727             "orangered"             : true,
728             "orchid"                : true,
729             "palegoldenrod"         : true,
730             "palegreen"             : true,
731             "paleturquoise"         : true,
732             "palevioletred"         : true,
733             "papayawhip"            : true,
734             "peachpuff"             : true,
735             "peru"                  : true,
736             "pink"                  : true,
737             "plum"                  : true,
738             "powderblue"            : true,
739             "purple"                : true,
740             "red"                   : true,
741             "rosybrown"             : true,
742             "royalblue"             : true,
743             "saddlebrown"           : true,
744             "salmon"                : true,
745             "sandybrown"            : true,
746             "seagreen"              : true,
747             "seashell"              : true,
748             "sienna"                : true,
749             "silver"                : true,
750             "skyblue"               : true,
751             "slateblue"             : true,
752             "slategray"             : true,
753             "snow"                  : true,
754             "springgreen"           : true,
755             "steelblue"             : true,
756             "tan"                   : true,
757             "teal"                  : true,
758             "thistle"               : true,
759             "tomato"                : true,
760             "turquoise"             : true,
761             "violet"                : true,
762             "wheat"                 : true,
763             "white"                 : true,
764             "whitesmoke"            : true,
765             "yellow"                : true,
766             "yellowgreen"           : true,
767
768             "activeborder"          : true,
769             "activecaption"         : true,
770             "appworkspace"          : true,
771             "background"            : true,
772             "buttonface"            : true,
773             "buttonhighlight"       : true,
774             "buttonshadow"          : true,
775             "buttontext"            : true,
776             "captiontext"           : true,
777             "graytext"              : true,
778             "highlight"             : true,
779             "highlighttext"         : true,
780             "inactiveborder"        : true,
781             "inactivecaption"       : true,
782             "inactivecaptiontext"   : true,
783             "infobackground"        : true,
784             "infotext"              : true,
785             "menu"                  : true,
786             "menutext"              : true,
787             "scrollbar"             : true,
788             "threeddarkshadow"      : true,
789             "threedface"            : true,
790             "threedhighlight"       : true,
791             "threedlightshadow"     : true,
792             "threedshadow"          : true,
793             "window"                : true,
794             "windowframe"           : true,
795             "windowtext"            : true
796         },
797
798         css_border_style,
799         css_break,
800
801         css_lengthData = {
802             '%': true,
803             'cm': true,
804             'em': true,
805             'ex': true,
806             'in': true,
807             'mm': true,
808             'pc': true,
809             'pt': true,
810             'px': true
811         },
812
813         css_media,
814         css_overflow,
815
816         devel = {
817             alert           : false,
818             confirm         : false,
819             console         : false,
820             Debug           : false,
821             opera           : false,
822             prompt          : false
823         },
824
825         escapes = {
826             '\b': '\\b',
827             '\t': '\\t',
828             '\n': '\\n',
829             '\f': '\\f',
830             '\r': '\\r',
831             '"' : '\\"',
832             '/' : '\\/',
833             '\\': '\\\\'
834         },
835
836         funct,          // The current function
837
838         functionicity = [
839             'closure', 'exception', 'global', 'label', 'outer', 'unused', 'var'
840         ],
841
842         functions,      // All of the functions
843         global,         // The global scope
844         html_tag = {
845             a:        {},
846             abbr:     {},
847             acronym:  {},
848             address:  {},
849             applet:   {},
850             area:     {empty: true, parent: ' map '},
851             article:  {},
852             aside:    {},
853             audio:    {},
854             b:        {},
855             base:     {empty: true, parent: ' head '},
856             bdo:      {},
857             big:      {},
858             blockquote: {},
859             body:     {parent: ' html noframes '},
860             br:       {empty: true},
861             button:   {},
862             canvas:   {parent: ' body p div th td '},
863             caption:  {parent: ' table '},
864             center:   {},
865             cite:     {},
866             code:     {},
867             col:      {empty: true, parent: ' table colgroup '},
868             colgroup: {parent: ' table '},
869             command:  {parent: ' menu '},
870             datalist: {},
871             dd:       {parent: ' dl '},
872             del:      {},
873             details:  {},
874             dialog:   {},
875             dfn:      {},
876             dir:      {},
877             div:      {},
878             dl:       {},
879             dt:       {parent: ' dl '},
880             em:       {},
881             embed:    {},
882             fieldset: {},
883             figure:   {},
884             font:     {},
885             footer:   {},
886             form:     {},
887             frame:    {empty: true, parent: ' frameset '},
888             frameset: {parent: ' html frameset '},
889             h1:       {},
890             h2:       {},
891             h3:       {},
892             h4:       {},
893             h5:       {},
894             h6:       {},
895             head:     {parent: ' html '},
896             header:   {},
897             hgroup:   {},
898             hr:       {empty: true},
899             'hta:application':
900                       {empty: true, parent: ' head '},
901             html:     {parent: '*'},
902             i:        {},
903             iframe:   {},
904             img:      {empty: true},
905             input:    {empty: true},
906             ins:      {},
907             kbd:      {},
908             keygen:   {},
909             label:    {},
910             legend:   {parent: ' details fieldset figure '},
911             li:       {parent: ' dir menu ol ul '},
912             link:     {empty: true, parent: ' head '},
913             map:      {},
914             mark:     {},
915             menu:     {},
916             meta:     {empty: true, parent: ' head noframes noscript '},
917             meter:    {},
918             nav:      {},
919             noframes: {parent: ' html body '},
920             noscript: {parent: ' body head noframes '},
921             object:   {},
922             ol:       {},
923             optgroup: {parent: ' select '},
924             option:   {parent: ' optgroup select '},
925             output:   {},
926             p:        {},
927             param:    {empty: true, parent: ' applet object '},
928             pre:      {},
929             progress: {},
930             q:        {},
931             rp:       {},
932             rt:       {},
933             ruby:     {},
934             samp:     {},
935             script:   {empty: true, parent: ' body div frame head iframe p pre span '},
936             section:  {},
937             select:   {},
938             small:    {},
939             span:     {},
940             source:   {},
941             strong:   {},
942             style:    {parent: ' head ', empty: true},
943             sub:      {},
944             sup:      {},
945             table:    {},
946             tbody:    {parent: ' table '},
947             td:       {parent: ' tr '},
948             textarea: {},
949             tfoot:    {parent: ' table '},
950             th:       {parent: ' tr '},
951             thead:    {parent: ' table '},
952             time:     {},
953             title:    {parent: ' head '},
954             tr:       {parent: ' table tbody thead tfoot '},
955             tt:       {},
956             u:        {},
957             ul:       {},
958             'var':    {},
959             video:    {}
960         },
961
962         ids,            // HTML ids
963         implied,        // Implied globals
964         in_block,
965         indent,
966         json_mode,
967         lines,
968         lookahead,
969         member,
970         properties,
971         nexttoken,
972         option,
973         predefined,     // Global variables defined by option
974         prereg,
975         prevtoken,
976         regexp_flag = {
977             g: true,
978             i: true,
979             m: true
980         },
981         rhino = {
982             defineClass : false,
983             deserialize : false,
984             gc          : false,
985             help        : false,
986             load        : false,
987             loadClass   : false,
988             print       : false,
989             quit        : false,
990             readFile    : false,
991             readUrl     : false,
992             runCommand  : false,
993             seal        : false,
994             serialize   : false,
995             spawn       : false,
996             sync        : false,
997             toint32     : false,
998             version     : false
999         },
1000
1001         scope,      // The current scope
1002         semicolon_coda = {
1003             ';' : true,
1004             '"' : true,
1005             '\'': true,
1006             ')' : true
1007         },
1008         src,
1009         stack,
1010
1011 // standard contains the global names that are provided by the
1012 // ECMAScript standard.
1013
1014         standard = {
1015             Array               : false,
1016             Boolean             : false,
1017             Date                : false,
1018             decodeURI           : false,
1019             decodeURIComponent  : false,
1020             encodeURI           : false,
1021             encodeURIComponent  : false,
1022             Error               : false,
1023             'eval'              : false,
1024             EvalError           : false,
1025             Function            : false,
1026             hasOwnProperty      : false,
1027             isFinite            : false,
1028             isNaN               : false,
1029             JSON                : false,
1030             Math                : false,
1031             Number              : false,
1032             Object              : false,
1033             parseInt            : false,
1034             parseFloat          : false,
1035             RangeError          : false,
1036             ReferenceError      : false,
1037             RegExp              : false,
1038             String              : false,
1039             SyntaxError         : false,
1040             TypeError           : false,
1041             URIError            : false
1042         },
1043
1044         standard_member = {
1045             E                   : true,
1046             LN2                 : true,
1047             LN10                : true,
1048             LOG2E               : true,
1049             LOG10E              : true,
1050             MAX_VALUE           : true,
1051             MIN_VALUE           : true,
1052             NEGATIVE_INFINITY   : true,
1053             PI                  : true,
1054             POSITIVE_INFINITY   : true,
1055             SQRT1_2             : true,
1056             SQRT2               : true
1057         },
1058
1059         strict_mode,
1060         syntax = {},
1061         tab,
1062         token,
1063         urls,
1064         var_mode,
1065         warnings,
1066
1067 // widget contains the global names which are provided to a Yahoo
1068 // (fna Konfabulator) widget.
1069
1070         widget = {
1071             alert                   : true,
1072             animator                : true,
1073             appleScript             : true,
1074             beep                    : true,
1075             bytesToUIString         : true,
1076             Canvas                  : true,
1077             chooseColor             : true,
1078             chooseFile              : true,
1079             chooseFolder            : true,
1080             closeWidget             : true,
1081             COM                     : true,
1082             convertPathToHFS        : true,
1083             convertPathToPlatform   : true,
1084             CustomAnimation         : true,
1085             escape                  : true,
1086             FadeAnimation           : true,
1087             filesystem              : true,
1088             Flash                   : true,
1089             focusWidget             : true,
1090             form                    : true,
1091             FormField               : true,
1092             Frame                   : true,
1093             HotKey                  : true,
1094             Image                   : true,
1095             include                 : true,
1096             isApplicationRunning    : true,
1097             iTunes                  : true,
1098             konfabulatorVersion     : true,
1099             log                     : true,
1100             md5                     : true,
1101             MenuItem                : true,
1102             MoveAnimation           : true,
1103             openURL                 : true,
1104             play                    : true,
1105             Point                   : true,
1106             popupMenu               : true,
1107             preferenceGroups        : true,
1108             preferences             : true,
1109             print                   : true,
1110             prompt                  : true,
1111             random                  : true,
1112             Rectangle               : true,
1113             reloadWidget            : true,
1114             ResizeAnimation         : true,
1115             resolvePath             : true,
1116             resumeUpdates           : true,
1117             RotateAnimation         : true,
1118             runCommand              : true,
1119             runCommandInBg          : true,
1120             saveAs                  : true,
1121             savePreferences         : true,
1122             screen                  : true,
1123             ScrollBar               : true,
1124             showWidgetPreferences   : true,
1125             sleep                   : true,
1126             speak                   : true,
1127             Style                   : true,
1128             suppressUpdates         : true,
1129             system                  : true,
1130             tellWidget              : true,
1131             Text                    : true,
1132             TextArea                : true,
1133             Timer                   : true,
1134             unescape                : true,
1135             updateNow               : true,
1136             URL                     : true,
1137             Web                     : true,
1138             widget                  : true,
1139             Window                  : true,
1140             XMLDOM                  : true,
1141             XMLHttpRequest          : true,
1142             yahooCheckLogin         : true,
1143             yahooLogin              : true,
1144             yahooLogout             : true
1145         },
1146
1147         windows = {
1148             ActiveXObject: false,
1149             CScript      : false,
1150             Debug        : false,
1151             Enumerator   : false,
1152             System       : false,
1153             VBArray      : false,
1154             WScript      : false
1155         },
1156
1157 //  xmode is used to adapt to the exceptions in html parsing.
1158 //  It can have these states:
1159 //      false   .js script file
1160 //      html
1161 //      outer
1162 //      script
1163 //      style
1164 //      scriptstring
1165 //      styleproperty
1166
1167         xmode,
1168         xquote,
1169
1170 // Regular expressions. Some of these are stupidly long.
1171
1172 // unsafe comment or string
1173         ax = /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i,
1174 // unsafe characters that are silently deleted by one or more browsers
1175         cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,
1176 // token
1177         tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jslint|properties|members|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/,
1178 // html token
1179         hx = /^\s*(['"=>\/&#]|<(?:\/|\!(?:--)?)?|[a-zA-Z][a-zA-Z0-9_\-:]*|[0-9]+|--)/,
1180 // characters in strings that need escapement
1181         nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,
1182         nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
1183 // outer html token
1184         ox = /[>&]|<[\/!]?|--/,
1185 // star slash
1186         lx = /\*\/|\/\*/,
1187 // identifier
1188         ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,
1189 // javascript url
1190         jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i,
1191 // url badness
1192         ux = /&|\+|\u00AD|\.\.|\/\*|%[^;]|base64|url|expression|data|mailto/i,
1193 // style
1194         sx = /^\s*([{:#%.=,>+\[\]@()"';]|\*=?|\$=|\|=|\^=|~=|[a-zA-Z_][a-zA-Z0-9_\-]*|[0-9]+|<\/|\/\*)/,
1195         ssx = /^\s*([@#!"'};:\-%.=,+\[\]()*_]|[a-zA-Z][a-zA-Z0-9._\-]*|\/\*?|\d+(?:\.\d+)?|<\/)/,
1196 // attributes characters
1197         qx = /[^a-zA-Z0-9+\-_\/ ]/,
1198 // query characters for ids
1199         dx = /[\[\]\/\\"'*<>.&:(){}+=#]/,
1200
1201         rx = {
1202             outer: hx,
1203             html: hx,
1204             style: sx,
1205             styleproperty: ssx
1206         };
1207
1208
1209     function return_this() {
1210         return this;
1211     }
1212
1213     function F() {}     // Used by Object.create
1214
1215 // Provide critical ES5 functions to ES3.
1216
1217     if (typeof Array.prototype.filter !== 'function') {
1218         Array.prototype.filter = function (f) {
1219             var i, length = this.length, result = [];
1220             for (i = 0; i < length; i += 1) {
1221                 try {
1222                     result.push(f(this[i]));
1223                 } catch (ignore) {
1224                 }
1225             }
1226             return result;
1227         };
1228     }
1229
1230     if (typeof Array.isArray !== 'function') {
1231         Array.isArray = function (o) {
1232             return Object.prototype.toString.apply(o) === '[object Array]';
1233         };
1234     }
1235
1236     if (typeof Object.create !== 'function') {
1237         Object.create = function (o) {
1238             F.prototype = o;
1239             return new F();
1240         };
1241     }
1242
1243     if (typeof Object.keys !== 'function') {
1244         Object.keys = function (o) {
1245             var a = [], k;
1246             for (k in o) {
1247                 if (Object.prototype.hasOwnProperty.call(o, k)) {
1248                     a.push(k);
1249                 }
1250             }
1251             return a;
1252         };
1253     }
1254
1255 // Substandard methods
1256
1257     if (typeof String.prototype.entityify !== 'function') {
1258         String.prototype.entityify = function () {
1259             return this
1260                 .replace(/&/g, '&amp;')
1261                 .replace(/</g, '&lt;')
1262                 .replace(/>/g, '&gt;');
1263         };
1264     }
1265
1266     if (typeof String.prototype.isAlpha !== 'function') {
1267         String.prototype.isAlpha = function () {
1268             return (this >= 'a' && this <= 'z\uffff') ||
1269                 (this >= 'A' && this <= 'Z\uffff');
1270         };
1271     }
1272
1273     if (typeof String.prototype.isDigit !== 'function') {
1274         String.prototype.isDigit = function () {
1275             return (this >= '0' && this <= '9');
1276         };
1277     }
1278
1279     if (typeof String.prototype.supplant !== 'function') {
1280         String.prototype.supplant = function (o) {
1281             return this.replace(/\{([^{}]*)\}/g, function (a, b) {
1282                 var r = o[b];
1283                 return typeof r === 'string' || typeof r === 'number' ? r : a;
1284             });
1285         };
1286     }
1287
1288     if (typeof String.prototype.name !== 'function') {
1289         String.prototype.name = function () {
1290
1291 // If the string looks like an identifier, then we can return it as is.
1292 // If the string contains no control characters, no quote characters, and no
1293 // backslash characters, then we can simply slap some quotes around it.
1294 // Otherwise we must also replace the offending characters with safe
1295 // sequences.
1296
1297             if (ix.test(this)) {
1298                 return this;
1299             }
1300             if (nx.test(this)) {
1301                 return '"' + this.replace(nxg, function (a) {
1302                     var c = escapes[a];
1303                     if (c) {
1304                         return c;
1305                     }
1306                     return '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);
1307                 }) + '"';
1308             }
1309             return '"' + this + '"';
1310         };
1311     }
1312
1313
1314     function combine(t, o) {
1315         var n;
1316         for (n in o) {
1317             if (Object.prototype.hasOwnProperty.call(o, n)) {
1318                 t[n] = o[n];
1319             }
1320         }
1321     }
1322
1323     function assume() {
1324         if (!option.safe) {
1325             if (option.rhino) {
1326                 combine(predefined, rhino);
1327             }
1328             if (option.devel) {
1329                 combine(predefined, devel);
1330             }
1331             if (option.browser) {
1332                 combine(predefined, browser);
1333             }
1334             if (option.windows) {
1335                 combine(predefined, windows);
1336             }
1337             if (option.widget) {
1338                 combine(predefined, widget);
1339             }
1340         }
1341     }
1342
1343
1344 // Produce an error warning.
1345
1346     function quit(message, line, character) {
1347         throw {
1348             name: 'JSLintError',
1349             line: line,
1350             character: character,
1351             message: bundle.scanned_a_b.supplant({
1352                 a: message,
1353                 b: Math.floor((line / lines.length) * 100)
1354             })
1355         };
1356     }
1357
1358     function warn(message, offender, a, b, c, d) {
1359         var character, line, warning;
1360         offender = offender || nexttoken;  // `~
1361         line = offender.line || 0;
1362         character = offender.from || 0;
1363         warning = {
1364             id: '(error)',
1365             raw: message,
1366             evidence: lines[line - 1] || '',
1367             line: line,
1368             character: character,
1369             a: a || offender.value,
1370             b: b,
1371             c: c,
1372             d: d
1373         };
1374         warning.reason = message.supplant(warning);
1375         JSLINT.errors.push(warning);
1376         if (option.passfail) {
1377             quit(bundle.stopping, line, character);
1378         }
1379         warnings += 1;
1380         if (warnings >= option.maxerr) {
1381             quit(bundle.too_many, line, character);
1382         }
1383         return warning;
1384     }
1385
1386     function warn_at(message, line, character, a, b, c, d) {
1387         return warn(message, {
1388             line: line,
1389             from: character
1390         }, a, b, c, d);
1391     }
1392
1393     function fail(message, offender, a, b, c, d) {
1394         var warning = warn(message, offender, a, b, c, d);
1395         quit(bundle.stopping, warning.line, warning.character);
1396     }
1397
1398     function fail_at(message, line, character, a, b, c, d) {
1399         return fail(message, {
1400             line: line,
1401             from: character
1402         }, a, b, c, d);
1403     }
1404
1405     function expected_at(at) {
1406         if (option.white && nexttoken.from !== at) {
1407             warn(bundle.expected_a_at_b_c, nexttoken, nexttoken.value, at,
1408                 nexttoken.from);
1409         }
1410     }
1411
1412     function aint(it, name, expected) {
1413
1414         if (it[name] !== expected) {
1415             warn(bundle.expected_a_b, it, expected, it[name]);
1416             return true;
1417         } else {
1418             return false;
1419         }
1420     }
1421
1422
1423
1424 // lexical analysis and token construction
1425
1426     var lex = (function lex() {
1427         var character, comments, from, line, source_row, older_token = {};
1428
1429 // Private lex methods
1430
1431         function collect_comment(comment, quote,  at) {
1432             if (older_token.line !== line) {
1433                 if (comments) {
1434                     comments.push(comment);
1435                 } else {
1436                     comments = [comment];
1437                 }
1438             } else {
1439                 if (older_token.postcomments) {
1440                     older_token.postcomments.push(comment);
1441                 } else {
1442                     older_token.postcomments = [comment];
1443                 }
1444             }
1445         }
1446
1447         function next_line() {
1448             var at;
1449             if (line >= lines.length) {
1450                 return false;
1451             }
1452             character = 1;
1453             source_row = lines[line];
1454             line += 1;
1455             at = source_row.search(/ \t/);
1456             if (at >= 0) {
1457                 warn_at(bundle.mixed, line, at + 1);
1458             }
1459             source_row = source_row.replace(/\t/g, tab);
1460             at = source_row.search(cx);
1461             if (at >= 0) {
1462                 warn_at(bundle.unsafe, line, at);
1463             }
1464             if (option.maxlen && option.maxlen < source_row.length) {
1465                 warn_at(bundle.too_long, line, source_row.length);
1466             }
1467             return true;
1468         }
1469
1470 // Produce a token object.  The token inherits from a syntax symbol.
1471
1472         function it(type, value, quote) {
1473             var id, the_token;
1474             if (type === '(string)' || type === '(range)') {
1475                 if (jx.test(value)) {
1476                     warn_at(bundle.url, line, from);
1477                 }
1478             }
1479             the_token = Object.create(syntax[(
1480                 type === '(punctuator)' ||
1481                     (type === '(identifier)' && Object.prototype.hasOwnProperty.call(syntax, value)) ?
1482                 value :
1483                 type
1484             )] || syntax['(error)']);
1485             if (type === '(identifier)') {
1486                 the_token.identifier = true;
1487                 if (value === '__iterator__' || value === '__proto__') {
1488                     fail_at(bundle.reserved_a, line, from, value);
1489                 } else if (option.nomen &&
1490                         (value.charAt(0) === '_' ||
1491                         value.charAt(value.length - 1) === '_')) {
1492                     warn_at(bundle.dangling_a, line, from, value);
1493                 }
1494             }
1495             if (value !== undefined) {
1496                 the_token.value = value;
1497             }
1498             if (quote) {
1499                 the_token.quote = quote;
1500             }
1501             if (comments) {
1502                 the_token.comments = comments;
1503                 comments = null;
1504             }
1505             the_token.line = line;
1506             the_token.from = from;
1507             the_token.thru = character;
1508             the_token.prev = older_token;
1509             id = the_token.id;
1510             prereg = id && (
1511                 ('(,=:[!&|?{};'.indexOf(id.charAt(id.length - 1)) >= 0) ||
1512                 id === 'return'
1513             );
1514             older_token.next = the_token;
1515             older_token = the_token;
1516             return the_token;
1517         }
1518
1519 // Public lex methods
1520
1521         return {
1522             init: function (source) {
1523                 if (typeof source === 'string') {
1524                     lines = source
1525                         .replace(/\r\n/g, '\n')
1526                         .replace(/\r/g, '\n')
1527                         .split('\n');
1528                 } else {
1529                     lines = source;
1530                 }
1531                 line = 0;
1532                 next_line();
1533                 from = 1;
1534             },
1535
1536             range: function (begin, end) {
1537                 var c, value = '';
1538                 from = character;
1539                 if (source_row.charAt(0) !== begin) {
1540                     fail_at(bundle.expected_a_b, line, character, begin, source_row.charAt(0));
1541                 }
1542                 for (;;) {
1543                     source_row = source_row.slice(1);
1544                     character += 1;
1545                     c = source_row.charAt(0);
1546                     switch (c) {
1547                     case '':
1548                         fail_at(bundle.missing_a, line, character, c);
1549                         break;
1550                     case end:
1551                         source_row = source_row.slice(1);
1552                         character += 1;
1553                         return it('(range)', value);
1554                     case xquote:
1555                     case '\\':
1556                         warn_at(bundle.unexpected_a, line, character, c);
1557                         break;
1558                     }
1559                     value += c;
1560                 }
1561             },
1562
1563 // token -- this is called by advance to get the next token.
1564
1565             token: function () {
1566                 var b, c, captures, digit, depth, flag, high, i, j, length, low, quote, t;
1567
1568                 function match(x) {
1569                     var exec = x.exec(source_row), first;
1570                     if (exec) {
1571                         length = exec[0].length;
1572                         first = exec[1];
1573                         c = first.charAt(0);
1574                         source_row = source_row.substr(length);
1575                         from = character + length - first.length;
1576                         character += length;
1577                         return first;
1578                     }
1579                 }
1580
1581                 function string(x) {
1582                     var c, j, r = '';
1583
1584                     function hex(n) {
1585                         var i = parseInt(source_row.substr(j + 1, n), 16);
1586                         j += n;
1587                         if (i >= 32 && i <= 126 &&
1588                                 i !== 34 && i !== 92 && i !== 39) {
1589                             warn_at(bundle.unexpected_a, line, character, '\\');
1590                         }
1591                         character += n;
1592                         c = String.fromCharCode(i);
1593                     }
1594
1595                     if (json_mode && x !== '"') {
1596                         warn_at(bundle.expected_a, line, character, '"');
1597                     }
1598
1599                     if (xquote === x || (xmode === 'scriptstring' && !xquote)) {
1600                         return it('(punctuator)', x);
1601                     }
1602
1603                     j = 0;
1604                     for (;;) {
1605                         while (j >= source_row.length) {
1606                             j = 0;
1607                             if (xmode !== 'html' || !next_line()) {
1608                                 fail_at(bundle.unclosed, line, from);
1609                             }
1610                         }
1611                         c = source_row.charAt(j);
1612                         if (c === x) {
1613                             character += 1;
1614                             source_row = source_row.substr(j + 1);
1615                             return it('(string)', r, x);
1616                         }
1617                         if (c < ' ') {
1618                             if (c === '\n' || c === '\r') {
1619                                 break;
1620                             }
1621                             warn_at(bundle.control_a,
1622                                 line, character + j, source_row.slice(0, j));
1623                         } else if (c === xquote) {
1624                             warn_at(bundle.bad_html, line, character + j);
1625                         } else if (c === '<') {
1626                             if (option.safe && xmode === 'html') {
1627                                 warn_at(bundle.adsafe_a, line, character + j, c);
1628                             } else if (source_row.charAt(j + 1) === '/' && (xmode || option.safe)) {
1629                                 warn_at(bundle.expected_a_b, line, character,
1630                                     '<\\/', '</');
1631                             } else if (source_row.charAt(j + 1) === '!' && (xmode || option.safe)) {
1632                                 warn_at(bundle.unexpected_a, line, character, '<!');
1633                             }
1634                         } else if (c === '\\') {
1635                             if (xmode === 'html') {
1636                                 if (option.safe) {
1637                                     warn_at(bundle.adsafe_a, line, character + j, c);
1638                                 }
1639                             } else if (xmode === 'styleproperty') {
1640                                 j += 1;
1641                                 character += 1;
1642                                 c = source_row.charAt(j);
1643                                 if (c !== x) {
1644                                     warn_at(bundle.unexpected_a, line, character, '\\');
1645                                 }
1646                             } else {
1647                                 j += 1;
1648                                 character += 1;
1649                                 c = source_row.charAt(j);
1650                                 switch (c) {
1651                                 case xquote:
1652                                     warn_at(bundle.bad_html, line, character + j);
1653                                     break;
1654                                 case '\\':
1655                                 case '"':
1656                                 case '/':
1657                                     break;
1658                                 case '\'':
1659                                     if (json_mode) {
1660                                         warn_at(bundle.unexpected_a, line, character, '\\\'');
1661                                     }
1662                                     break;
1663                                 case 'b':
1664                                     c = '\b';
1665                                     break;
1666                                 case 'f':
1667                                     c = '\f';
1668                                     break;
1669                                 case 'n':
1670                                     c = '\n';
1671                                     break;
1672                                 case 'r':
1673                                     c = '\r';
1674                                     break;
1675                                 case 't':
1676                                     c = '\t';
1677                                     break;
1678                                 case 'u':
1679                                     hex(4);
1680                                     break;
1681                                 case 'v':
1682                                     if (json_mode) {
1683                                         warn_at(bundle.unexpected_a, line, character, '\\v');
1684                                     }
1685                                     c = '\v';
1686                                     break;
1687                                 case 'x':
1688                                     if (json_mode) {
1689                                         warn_at(bundle.unexpected_a, line, character, '\\x');
1690                                     }
1691                                     hex(2);
1692                                     break;
1693                                 default:
1694                                     warn_at(bundle.unexpected_a, line, character, '\\');
1695                                 }
1696                             }
1697                         }
1698                         r += c;
1699                         character += 1;
1700                         j += 1;
1701                     }
1702                 }
1703
1704                 for (;;) {
1705                     while (!source_row) {
1706                         if (!next_line()) {
1707                             return it('(end)');
1708                         }
1709                     }
1710                     while (xmode === 'outer') {
1711                         i = source_row.search(ox);
1712                         if (i === 0) {
1713                             break;
1714                         } else if (i > 0) {
1715                             character += 1;
1716                             source_row = source_row.slice(i);
1717                             break;
1718                         } else {
1719                             if (!next_line()) {
1720                                 return it('(end)', '');
1721                             }
1722                         }
1723                     }
1724                     t = match(rx[xmode] || tx);
1725                     if (!t) {
1726                         t = '';
1727                         c = '';
1728                         while (source_row && source_row < '!') {
1729                             source_row = source_row.substr(1);
1730                         }
1731                         if (source_row) {
1732                             if (xmode === 'html') {
1733                                 return it('(error)', source_row.charAt(0));
1734                             } else {
1735                                 fail_at(bundle.unexpected_a,
1736                                     line, character, source_row.substr(0, 1));
1737                             }
1738                         }
1739                     } else {
1740
1741     //      identifier
1742
1743                         if (c.isAlpha() || c === '_' || c === '$') {
1744                             return it('(identifier)', t);
1745                         }
1746
1747     //      number
1748
1749                         if (c.isDigit()) {
1750                             if (xmode !== 'style' &&
1751                                     xmode !== 'styleproperty' &&
1752                                     source_row.substr(0, 1).isAlpha()) {
1753                                 warn_at(bundle.expected_space_a_b,
1754                                     line, character, c, source_row.charAt(0));
1755                             }
1756                             if (c === '0') {
1757                                 digit = t.substr(1, 1);
1758                                 if (digit.isDigit()) {
1759                                     if (token.id !== '.' && xmode !== 'styleproperty') {
1760                                         warn_at(bundle.unexpected_a,
1761                                             line, character, t);
1762                                     }
1763                                 } else if (json_mode && (digit === 'x' || digit === 'X')) {
1764                                     warn_at(bundle.unexpected_a, line, character, '0x');
1765                                 }
1766                             }
1767                             if (t.substr(t.length - 1) === '.') {
1768                                 warn_at(bundle.trailing_decimal_a, line,
1769                                     character, t);
1770                             }
1771                             if (xmode !== 'style') {
1772                                 digit = +t;
1773                                 if (!isFinite(digit)) {
1774                                     warn_at(bundle.bad_number, line, character, t);
1775                                 }
1776                                 t = digit;
1777                             }
1778                             return it('(number)', t);
1779                         }
1780                         switch (t) {
1781
1782     //      string
1783
1784                         case '"':
1785                         case "'":
1786                             return string(t);
1787
1788     //      // comment
1789
1790                         case '//':
1791                             if (comments_off || src || (xmode && xmode !== 'script')) {
1792                                 warn_at(bundle.unexpected_comment, line, character);
1793                             } else if (xmode === 'script' && /<\source_row*\//i.test(source_row)) {
1794                                 warn_at(bundle.unexpected_a, line, character, '<\/');
1795                             } else if ((option.safe || xmode === 'script') && ax.test(source_row)) {
1796                                 warn_at(bundle.dangerous_comment, line, character);
1797                             }
1798                             collect_comment(source_row);
1799                             source_row = '';
1800                             break;
1801
1802     //      /* comment
1803
1804                         case '/*':
1805                             if (comments_off || src || (xmode && xmode !== 'script' && xmode !== 'style' && xmode !== 'styleproperty')) {
1806                                 warn_at(bundle.unexpected_comment, line, character);
1807                             }
1808                             if (option.safe && ax.test(source_row)) {
1809                                 warn_at(bundle.dangerous_comment, line, character);
1810                             }
1811                             for (;;) {
1812                                 i = source_row.search(lx);
1813                                 if (i >= 0) {
1814                                     break;
1815                                 }
1816                                 collect_comment(source_row);
1817                                 if (!next_line()) {
1818                                     fail_at(bundle.unclosed_comment, line, character);
1819                                 } else {
1820                                     if (option.safe && ax.test(source_row)) {
1821                                         warn_at(bundle.dangerous_comment, line, character);
1822                                     }
1823                                 }
1824                             }
1825                             character += i + 2;
1826                             if (source_row.substr(i, 1) === '/') {
1827                                 fail_at(bundle.nested_comment, line, character);
1828                             }
1829                             collect_comment(source_row.substr(0, i));
1830                             source_row = source_row.substr(i + 2);
1831                             break;
1832
1833                         case '':
1834                             break;
1835     //      /
1836                         case '/':
1837                             if (token.id === '/=') {
1838                                 fail_at(
1839                                     bundle.slash_equal,
1840                                     line,
1841                                     from
1842                                 );
1843                             }
1844                             if (prereg) {
1845                                 depth = 0;
1846                                 captures = 0;
1847                                 length = 0;
1848                                 for (;;) {
1849                                     b = true;
1850                                     c = source_row.charAt(length);
1851                                     length += 1;
1852                                     switch (c) {
1853                                     case '':
1854                                         fail_at(bundle.unclosed_regexp, line, from);
1855                                         return;
1856                                     case '/':
1857                                         if (depth > 0) {
1858                                             warn_at(bundle.unescaped_a,
1859                                                 line, from + length, '/');
1860                                         }
1861                                         c = source_row.substr(0, length - 1);
1862                                         flag = Object.create(regexp_flag);
1863                                         while (flag[source_row.charAt(length)] === true) {
1864                                             flag[source_row.charAt(length)] = false;
1865                                             length += 1;
1866                                         }
1867                                         if (source_row.charAt(length).isAlpha()) {
1868                                             fail_at(bundle.unexpected_a,
1869                                                 line, from, source_row.charAt(length));
1870                                         }
1871                                         character += length;
1872                                         source_row = source_row.substr(length);
1873                                         quote = source_row.charAt(0);
1874                                         if (quote === '/' || quote === '*') {
1875                                             fail_at(bundle.confusing_regexp,
1876                                                 line, from);
1877                                         }
1878                                         return it('(regexp)', c);
1879                                     case '\\':
1880                                         c = source_row.charAt(length);
1881                                         if (c < ' ') {
1882                                             warn_at(bundle.control_a,
1883                                                 line, from + length, String(c));
1884                                         } else if (c === '<') {
1885                                             warn_at(
1886                                                 bundle.unexpected_a,
1887                                                 line,
1888                                                 from + length,
1889                                                 '\\'
1890                                             );
1891                                         }
1892                                         length += 1;
1893                                         break;
1894                                     case '(':
1895                                         depth += 1;
1896                                         b = false;
1897                                         if (source_row.charAt(length) === '?') {
1898                                             length += 1;
1899                                             switch (source_row.charAt(length)) {
1900                                             case ':':
1901                                             case '=':
1902                                             case '!':
1903                                                 length += 1;
1904                                                 break;
1905                                             default:
1906                                                 warn_at(
1907                                                     bundle.expected_a_b,
1908                                                     line,
1909                                                     from + length,
1910                                                     ':',
1911                                                     source_row.charAt(length)
1912                                                 );
1913                                             }
1914                                         } else {
1915                                             captures += 1;
1916                                         }
1917                                         break;
1918                                     case '|':
1919                                         b = false;
1920                                         break;
1921                                     case ')':
1922                                         if (depth === 0) {
1923                                             warn_at(bundle.unescaped_a,
1924                                                 line, from + length, ')');
1925                                         } else {
1926                                             depth -= 1;
1927                                         }
1928                                         break;
1929                                     case ' ':
1930                                         j = 1;
1931                                         while (source_row.charAt(length) === ' ') {
1932                                             length += 1;
1933                                             j += 1;
1934                                         }
1935                                         if (j > 1) {
1936                                             warn_at(bundle.use_braces,
1937                                                 line, from + length, j);
1938                                         }
1939                                         break;
1940                                     case '[':
1941                                         c = source_row.charAt(length);
1942                                         if (c === '^') {
1943                                             length += 1;
1944                                             if (option.regexp) {
1945                                                 warn_at(bundle.insecure_a,
1946                                                     line, from + length, c);
1947                                             } else if (source_row.charAt(length) === ']') {
1948                                                 fail_at(bundle.unescaped_a,
1949                                                     line, from + length, '^');
1950                                             }
1951                                         }
1952                                         quote = false;
1953                                         if (c === ']') {
1954                                             warn_at(bundle.empty_class, line,
1955                                                 from + length - 1);
1956                                             quote = true;
1957                                         }
1958 klass:                                  do {
1959                                             c = source_row.charAt(length);
1960                                             length += 1;
1961                                             switch (c) {
1962                                             case '[':
1963                                             case '^':
1964                                                 warn_at(bundle.unescaped_a,
1965                                                     line, from + length, c);
1966                                                 quote = true;
1967                                                 break;
1968                                             case '-':
1969                                                 if (quote) {
1970                                                     quote = false;
1971                                                 } else {
1972                                                     warn_at(bundle.unescaped_a,
1973                                                         line, from + length, '-');
1974                                                     quote = true;
1975                                                 }
1976                                                 break;
1977                                             case ']':
1978                                                 if (!quote) {
1979                                                     warn_at(bundle.unescaped_a,
1980                                                         line, from + length - 1, '-');
1981                                                 }
1982                                                 break klass;
1983                                             case '\\':
1984                                                 c = source_row.charAt(length);
1985                                                 if (c < ' ') {
1986                                                     warn_at(
1987                                                         bundle.control_a,
1988                                                         line,
1989                                                         from + length,
1990                                                         String(c)
1991                                                     );
1992                                                 } else if (c === '<') {
1993                                                     warn_at(
1994                                                         bundle.unexpected_a,
1995                                                         line,
1996                                                         from + length,
1997                                                         '\\'
1998                                                     );
1999                                                 }
2000                                                 length += 1;
2001                                                 quote = true;
2002                                                 break;
2003                                             case '/':
2004                                                 warn_at(bundle.unescaped_a,
2005                                                     line, from + length - 1, '/');
2006                                                 quote = true;
2007                                                 break;
2008                                             case '<':
2009                                                 if (xmode === 'script') {
2010                                                     c = source_row.charAt(length);
2011                                                     if (c === '!' || c === '/') {
2012                                                         warn_at(
2013                                                             bundle.html_confusion_a,
2014                                                             line,
2015                                                             from + length,
2016                                                             c
2017                                                         );
2018                                                     }
2019                                                 }
2020                                                 quote = true;
2021                                                 break;
2022                                             default:
2023                                                 quote = true;
2024                                             }
2025                                         } while (c);
2026                                         break;
2027                                     case '.':
2028                                         if (option.regexp) {
2029                                             warn_at(bundle.insecure_a, line,
2030                                                 from + length, c);
2031                                         }
2032                                         break;
2033                                     case ']':
2034                                     case '?':
2035                                     case '{':
2036                                     case '}':
2037                                     case '+':
2038                                     case '*':
2039                                         warn_at(bundle.unescaped_a, line,
2040                                             from + length, c);
2041                                         break;
2042                                     case '<':
2043                                         if (xmode === 'script') {
2044                                             c = source_row.charAt(length);
2045                                             if (c === '!' || c === '/') {
2046                                                 warn_at(
2047                                                     bundle.html_confusion_a,
2048                                                     line,
2049                                                     from + length,
2050                                                     c
2051                                                 );
2052                                             }
2053                                         }
2054                                         break;
2055                                     }
2056                                     if (b) {
2057                                         switch (source_row.charAt(length)) {
2058                                         case '?':
2059                                         case '+':
2060                                         case '*':
2061                                             length += 1;
2062                                             if (source_row.charAt(length) === '?') {
2063                                                 length += 1;
2064                                             }
2065                                             break;
2066                                         case '{':
2067                                             length += 1;
2068                                             c = source_row.charAt(length);
2069                                             if (c < '0' || c > '9') {
2070                                                 warn_at(
2071                                                     bundle.expected_number_a,
2072                                                     line,
2073                                                     from + length,
2074                                                     c
2075                                                 );
2076                                             }
2077                                             length += 1;
2078                                             low = +c;
2079                                             for (;;) {
2080                                                 c = source_row.charAt(length);
2081                                                 if (c < '0' || c > '9') {
2082                                                     break;
2083                                                 }
2084                                                 length += 1;
2085                                                 low = +c + (low * 10);
2086                                             }
2087                                             high = low;
2088                                             if (c === ',') {
2089                                                 length += 1;
2090                                                 high = Infinity;
2091                                                 c = source_row.charAt(length);
2092                                                 if (c >= '0' && c <= '9') {
2093                                                     length += 1;
2094                                                     high = +c;
2095                                                     for (;;) {
2096                                                         c = source_row.charAt(length);
2097                                                         if (c < '0' || c > '9') {
2098                                                             break;
2099                                                         }
2100                                                         length += 1;
2101                                                         high = +c + (high * 10);
2102                                                     }
2103                                                 }
2104                                             }
2105                                             if (source_row.charAt(length) !== '}') {
2106                                                 warn_at(
2107                                                     bundle.expected_a_b,
2108                                                     line,
2109                                                     from + length,
2110                                                     '}',
2111                                                     c
2112                                                 );
2113                                             } else {
2114                                                 length += 1;
2115                                             }
2116                                             if (source_row.charAt(length) === '?') {
2117                                                 length += 1;
2118                                             }
2119                                             if (low > high) {
2120                                                 warn_at(
2121                                                     bundle.not_greater,
2122                                                     line,
2123                                                     from + length,
2124                                                     low,
2125                                                     high
2126                                                 );
2127                                             }
2128                                             break;
2129                                         }
2130                                     }
2131                                 }
2132                                 c = source_row.substr(0, length - 1);
2133                                 character += length;
2134                                 source_row = source_row.substr(length);
2135                                 return it('(regexp)', c);
2136                             }
2137                             return it('(punctuator)', t);
2138
2139     //      punctuator
2140
2141                         case '<!--':
2142                             length = line;
2143                             c = character;
2144                             for (;;) {
2145                                 i = source_row.indexOf('--');
2146                                 if (i >= 0) {
2147                                     break;
2148                                 }
2149                                 i = source_row.indexOf('<!');
2150                                 if (i >= 0) {
2151                                     fail_at(bundle.nested_comment,
2152                                         line, character + i);
2153                                 }
2154                                 if (!next_line()) {
2155                                     fail_at(bundle.unclosed_comment, length, c);
2156                                 }
2157                             }
2158                             length = source_row.indexOf('<!');
2159                             if (length >= 0 && length < i) {
2160                                 fail_at(bundle.nested_comment,
2161                                     line, character + length);
2162                             }
2163                             character += i;
2164                             if (source_row.charAt(i + 2) !== '>') {
2165                                 fail_at(bundle.expected_a, line, character, '-->');
2166                             }
2167                             character += 3;
2168                             source_row = source_row.slice(i + 3);
2169                             break;
2170                         case '#':
2171                             if (xmode === 'html' || xmode === 'styleproperty') {
2172                                 for (;;) {
2173                                     c = source_row.charAt(0);
2174                                     if ((c < '0' || c > '9') &&
2175                                             (c < 'a' || c > 'f') &&
2176                                             (c < 'A' || c > 'F')) {
2177                                         break;
2178                                     }
2179                                     character += 1;
2180                                     source_row = source_row.substr(1);
2181                                     t += c;
2182                                 }
2183                                 if (t.length !== 4 && t.length !== 7) {
2184                                     warn_at(bundle.bad_color_a, line,
2185                                         from + length, t);
2186                                 }
2187                                 return it('(color)', t);
2188                             }
2189                             return it('(punctuator)', t);
2190
2191                         default:
2192                             if (xmode === 'outer' && c === '&') {
2193                                 character += 1;
2194                                 source_row = source_row.substr(1);
2195                                 for (;;) {
2196                                     c = source_row.charAt(0);
2197                                     character += 1;
2198                                     source_row = source_row.substr(1);
2199                                     if (c === ';') {
2200                                         break;
2201                                     }
2202                                     if (!((c >= '0' && c <= '9') ||
2203                                             (c >= 'a' && c <= 'z') ||
2204                                             c === '#')) {
2205                                         fail_at(bundle.bad_entity, line, from + length,
2206                                             character);
2207                                     }
2208                                 }
2209                                 break;
2210                             }
2211                             return it('(punctuator)', t);
2212                         }
2213                     }
2214                 }
2215             }
2216         };
2217     }());
2218
2219
2220     function add_label(t, type) {
2221
2222         if (option.safe && funct['(global)'] &&
2223                 typeof predefined[t] !== 'boolean') {
2224             warn(bundle.adsafe_a, token, t);
2225         } else if (t === 'hasOwnProperty') {
2226             warn(bundle.bad_name_a, token, t);
2227         }
2228
2229 // Define t in the current function in the current scope.
2230
2231         if (Object.prototype.hasOwnProperty.call(funct, t) && !funct['(global)']) {
2232             warn(funct[t] === true ?
2233                 bundle.used_before_a :
2234                 bundle.already_defined,
2235                 nexttoken, t);
2236         }
2237         funct[t] = type;
2238         if (funct['(global)']) {
2239             if (global[t] === false) {
2240                 warn(bundle.read_only);
2241             }
2242             global[t] = true;
2243             if (Object.prototype.hasOwnProperty.call(implied, t)) {
2244                 warn(bundle.used_before_a, nexttoken, t);
2245                 delete implied[t];
2246             }
2247         } else {
2248             scope[t] = funct;
2249         }
2250     }
2251
2252
2253     function peek(distance) {
2254
2255 // Peek ahead to a future token. The distance is how far ahead to look. The
2256 // default is the next token.
2257
2258         var found, slot = 0;
2259
2260         distance = distance || 0;
2261         while (slot <= distance) {
2262             found = lookahead[slot];
2263             if (!found) {
2264                 found = lookahead[slot] = lex.token();
2265             }
2266             slot += 1;
2267         }
2268         return found;
2269     }
2270
2271
2272     function discard(it) {
2273
2274 // The token will not be included in the parse tree, so move the comments
2275 // that are attached to the token to tokens that are in the tree.
2276
2277         var next, prev;
2278         it = it || token;
2279         if (it.postcomments) {
2280             next = it.next || peek();
2281             next.comments = next.comments ?
2282                 next.comments.concat(it.postcomments) :
2283                 it.postcomments;
2284         }
2285         if (it.comments) {
2286             prev = it.prev;
2287             while (prev.postcomments === null) {
2288                 prev = prev.prev;
2289             }
2290             if (prev.postcomments) {
2291                 prev.postcomments = prev.postcomments.concat(it.comments);
2292             } else {
2293                 prev.postcomments = it.comments;
2294             }
2295         }
2296         it.comments = null;
2297         it.postcomments = null;
2298     }
2299
2300
2301     function advance(id, match) {
2302
2303 // Produce the next token, also looking for programming errors.
2304
2305         if (indent) {
2306
2307 // In indentation checking was requested, then inspect all of the line breakings.
2308 // The var statement is tricky because the names might be aligned or not. We
2309 // look at the first line break after the var to determine the programmer's
2310 // intention.
2311
2312             if (var_mode && nexttoken.line !== token.line) {
2313                 if ((var_mode !== indent || !nexttoken.edge) &&
2314                         nexttoken.from === indent.at -
2315                         (nexttoken.edge ? option.indent : 0)) {
2316                     var dent = indent;
2317                     for (;;) {
2318                         dent.at -= option.indent;
2319                         if (dent === var_mode) {
2320                             break;
2321                         }
2322                         dent = dent.was;
2323                     }
2324                     dent.open = false;
2325                 }
2326                 var_mode = false;
2327             }
2328             if (indent.open) {
2329
2330 // If the token is an edge.
2331
2332                 if (nexttoken.edge) {
2333                     if (nexttoken.edge === 'label') {
2334                         expected_at(1);
2335                     } else if (nexttoken.edge === 'case') {
2336                         expected_at(indent.at - option.indent);
2337                     } else if (indent.mode !== 'array' || nexttoken.line !== token.line) {
2338                         expected_at(indent.at);
2339                     }
2340
2341 // If the token is not an edge, but is the first token on the line.
2342
2343                 } else if (nexttoken.line !== token.line &&
2344                         nexttoken.from < indent.at + (indent.mode ===
2345                         'expression' ? 0 : option.indent)) {
2346                     expected_at(indent.at + option.indent);
2347                 }
2348             } else if (nexttoken.line !== token.line) {
2349                 if (nexttoken.edge) {
2350                     expected_at(indent.at);
2351                 } else {
2352                     indent.wrap = true;
2353                     if (indent.mode === 'statement' || indent.mode === 'var') {
2354                         expected_at(indent.at + option.indent);
2355                     } else if (nexttoken.from < indent.at + (indent.mode ===
2356                             'expression' ? 0 : option.indent)) {
2357                         expected_at(indent.at + option.indent);
2358                     }
2359                 }
2360             }
2361         }
2362
2363         switch (token.id) {
2364         case '(number)':
2365             if (nexttoken.id === '.') {
2366                 warn(bundle.trailing_decimal_a);
2367             }
2368             break;
2369         case '-':
2370             if (nexttoken.id === '-' || nexttoken.id === '--') {
2371                 warn(bundle.confusing_a);
2372             }
2373             break;
2374         case '+':
2375             if (nexttoken.id === '+' || nexttoken.id === '++') {
2376                 warn(bundle.confusing_a);
2377             }
2378             break;
2379         }
2380         if (token.arity === 'string' || token.identifier) {
2381             anonname = token.value;
2382         }
2383
2384         if (id && nexttoken.id !== id) {
2385             if (match) {
2386                 warn(bundle.expected_a_b_from_c_d, nexttoken, id,
2387                     match.id, match.line, nexttoken.value);
2388             } else if (!nexttoken.identifier || nexttoken.value !== id) {
2389                 warn(bundle.expected_a_b, nexttoken, id, nexttoken.value);
2390             }
2391         }
2392         prevtoken = token;
2393         token = nexttoken;
2394         nexttoken = lookahead.shift() || lex.token();
2395         if (token.id === '(end)') {
2396             discard();
2397         }
2398     }
2399
2400
2401     function directive() {
2402         var command = this.id,
2403             name,
2404             old_comments_off = comments_off,
2405             old_option_white = option.white,
2406             value;
2407         comments_off = true;
2408         option.white = false;
2409         if (lookahead.length > 0 || this.postcomments || nexttoken.comments) {
2410             warn(bundle.unexpected_a, this);
2411         }
2412         switch (command) {
2413         case '/*properties':
2414         case '/*members':
2415             command = '/*properties';
2416             if (!properties) {
2417                 properties = {};
2418             }
2419             break;
2420         case '/*jslint':
2421             if (option.safe) {
2422                 warn(bundle.adsafe_a, this);
2423             }
2424             break;
2425         case '/*global':
2426             if (option.safe) {
2427                 warn(bundle.adsafe_a, this);
2428             }
2429             break;
2430         default:
2431             fail("What?");
2432         }
2433 loop:   for (;;) {
2434             for (;;) {
2435                 if (nexttoken.id === '*/') {
2436                     break loop;
2437                 }
2438                 if (nexttoken.id !== ',') {
2439                     break;
2440                 }
2441                 advance();
2442             }
2443             if (nexttoken.arity !== 'string' && !nexttoken.identifier) {
2444                 fail(bundle.unexpected_a, nexttoken);
2445             }
2446             name = nexttoken.value;
2447             advance();
2448             switch (command) {
2449             case '/*global':
2450                 if (nexttoken.id === ':') {
2451                     advance(':');
2452                     switch (nexttoken.id) {
2453                     case 'true':
2454                         if (typeof scope[name] === 'object' ||
2455                                 global[name] === false) {
2456                             fail(bundle.unexpected_a);
2457                         }
2458                         global[name] = true;
2459                         advance('true');
2460                         break;
2461                     case 'false':
2462                         if (typeof scope[name] === 'object') {
2463                             fail(bundle.unexpected_a);
2464                         }
2465                         global[name] = false;
2466                         advance('false');
2467                         break;
2468                     default:
2469                         fail(bundle.unexpected_a);
2470                     }
2471                 } else {
2472                     if (typeof scope[name] === 'object') {
2473                         fail(bundle.unexpected_a);
2474                     }
2475                     global[name] = false;
2476                 }
2477                 break;
2478             case '/*jslint':
2479                 if (nexttoken.id !== ':') {
2480                     fail(bundle.expected_a_b, nexttoken, ':', nexttoken.value);
2481                 }
2482                 advance(':');
2483                 switch (name) {
2484                 case 'indent':
2485                     value = +nexttoken.value;
2486                     if (typeof value !== 'number' ||
2487                             !isFinite(value) || value < 0 ||
2488                             Math.floor(value) !== value) {
2489                         fail(bundle.expected_small_a);
2490                     }
2491                     if (value > 0) {
2492                         old_option_white = true;
2493                     }
2494                     option.indent = value;
2495                     break;
2496                 case 'maxerr':
2497                     value = +nexttoken.value;
2498                     if (typeof value !== 'number' ||
2499                             !isFinite(value) ||
2500                             value <= 0 ||
2501                             Math.floor(value) !== value) {
2502                         fail(bundle.expected_small_a, nexttoken);
2503                     }
2504                     option.maxerr = value;
2505                     break;
2506                 case 'maxlen':
2507                     value = +nexttoken.value;
2508                     if (typeof value !== 'number' || !isFinite(value) || value < 0 ||
2509                             Math.floor(value) !== value) {
2510                         fail(bundle.expected_small_a);
2511                     }
2512                     option.maxlen = value;
2513                     break;
2514                 case 'white':
2515                     if (nexttoken.id === 'true') {
2516                         old_option_white = true;
2517                     } else if (nexttoken.id === 'false') {
2518                         old_option_white = false;
2519                     } else {
2520                         fail(bundle.unexpected_a);
2521                     }
2522                     break;
2523                 default:
2524                     if (nexttoken.id === 'true') {
2525                         option[name] = true;
2526                     } else if (nexttoken.id === 'false') {
2527                         option[name] = false;
2528                     } else {
2529                         fail(bundle.unexpected_a);
2530                     }
2531                 }
2532                 advance();
2533                 break;
2534             case '/*properties':
2535                 properties[name] = true;
2536                 break;
2537             default:
2538                 fail(bundle.unexpected_a);
2539             }
2540         }
2541         if (command === '/*jslint') {
2542             assume();
2543         }
2544         comments_off = old_comments_off;
2545         advance('*/');
2546         option.white = old_option_white;
2547     }
2548
2549
2550 // Indentation intention
2551
2552     function edge(mode) {
2553         nexttoken.edge = !indent || (indent.open && (mode || true));
2554     }
2555
2556
2557     function step_in(mode) {
2558         var open, was;
2559         if (typeof mode === 'number') {
2560             indent = {
2561                 at: mode,
2562                 open: true,
2563                 was: was
2564             };
2565         } else if (!indent) {
2566             indent = {
2567                 at: 1,
2568                 mode: 'statement',
2569                 open: true
2570             };
2571         } else {
2572             was = indent;
2573             open = mode === 'var' ||
2574                 (nexttoken.line !== token.line && mode !== 'statement');
2575             indent = {
2576                 at: (open || mode === 'control' ?
2577                     was.at + option.indent : was.at) +
2578                     (was.wrap ? option.indent : 0),
2579                 mode: mode,
2580                 open: open,
2581                 was: was
2582             };
2583             if (mode === 'var' && open) {
2584                 var_mode = indent;
2585             }
2586         }
2587     }
2588
2589     function step_out(id, t) {
2590         if (id) {
2591             if (indent && indent.open) {
2592                 indent.at -= option.indent;
2593                 edge();
2594             }
2595             advance(id, t);
2596         }
2597         if (indent) {
2598             indent = indent.was;
2599         }
2600     }
2601
2602 // Functions for conformance of whitespace.
2603
2604     function one_space(left, right) {
2605         left = left || token;
2606         right = right || nexttoken;
2607         if (right.id !== '(end)' && option.white &&
2608                 (token.line !== right.line ||
2609                 token.thru + 1 !== right.from)) {
2610             warn(bundle.expected_space_a_b, right, token.value, right.value);
2611         }
2612     }
2613
2614     function one_space_only(left, right) {
2615         left = left || token;
2616         right = right || nexttoken;
2617         if (right.id !== '(end)' && (left.line !== right.line ||
2618                 (option.white && left.thru + 1 !== right.from))) {
2619             warn(bundle.expected_space_a_b, right, left.value, right.value);
2620         }
2621     }
2622
2623     function no_space(left, right) {
2624         left = left || token;
2625         right = right || nexttoken;
2626         if ((option.white || xmode === 'styleproperty' || xmode === 'style') &&
2627                 left.thru !== right.from && left.line === right.line) {
2628             warn(bundle.unexpected_space_a_b, right, left.value, right.value);
2629         }
2630     }
2631
2632     function no_space_only(left, right) {
2633         left = left || token;
2634         right = right || nexttoken;
2635         if (right.id !== '(end)' && (left.line !== right.line ||
2636                 (option.white && left.thru !== right.from))) {
2637             warn(bundle.unexpected_space_a_b, right, left.value, right.value);
2638         }
2639     }
2640
2641     function spaces(left, right) {
2642         if (option.white) {
2643             left = left || token;
2644             right = right || nexttoken;
2645             if (left.thru === right.from && left.line === right.line) {
2646                 warn(bundle.missing_space_a_b, right, left.value, right.value);
2647             }
2648         }
2649     }
2650
2651     function comma() {
2652         if (nexttoken.id !== ',') {
2653             warn_at(bundle.expected_a_b, token.line, token.thru, ',', nexttoken.value);
2654         } else {
2655             if (option.white) {
2656                 no_space_only();
2657             }
2658             advance(',');
2659             discard();
2660             spaces();
2661         }
2662     }
2663
2664
2665     function semicolon() {
2666         if (nexttoken.id !== ';') {
2667             warn_at(bundle.expected_a_b, token.line, token.thru, ';', nexttoken.value);
2668         } else {
2669             if (option.white) {
2670                 no_space_only();
2671             }
2672             advance(';');
2673             discard();
2674             if (semicolon_coda[nexttoken.id] !== true) {
2675                 spaces();
2676             }
2677         }
2678     }
2679
2680     function use_strict() {
2681         if (nexttoken.value === 'use strict') {
2682             if (strict_mode) {
2683                 warn(bundle.unnecessary_use);
2684             }
2685             edge();
2686             advance();
2687             semicolon();
2688             strict_mode = true;
2689             option.newcap = true;
2690             option.undef = true;
2691             return true;
2692         } else {
2693             return false;
2694         }
2695     }
2696
2697
2698     function are_similar(a, b) {
2699         if (a === b) {
2700             return true;
2701         }
2702         if (Array.isArray(a)) {
2703             if (Array.isArray(b) && a.length === b.length) {
2704                 var i;
2705                 for (i = 0; i < a.length; i += 1) {
2706                     if (!are_similar(a[i], b[i])) {
2707                         return false;
2708                     }
2709                 }
2710                 return true;
2711             }
2712             return false;
2713         }
2714         if (Array.isArray(b)) {
2715             return false;
2716         }
2717         if (a.arity === b.arity && a.value === b.value) {
2718             switch (a.arity) {
2719             case 'prefix':
2720             case 'suffix':
2721             case undefined:
2722                 return are_similar(a.first, b.first);
2723             case 'infix':
2724                 return are_similar(a.first, b.first) &&
2725                     are_similar(a.second, b.second);
2726             case 'ternary':
2727                 return are_similar(a.first, b.first) &&
2728                     are_similar(a.second, b.second) &&
2729                     are_similar(a.third, b.third);
2730             case 'function':
2731             case 'regexp':
2732                 return false;
2733             default:
2734                 return true;
2735             }
2736         } else {
2737             if (a.id === '.' && b.id === '[' && b.arity === 'infix') {
2738                 return a.second.value === b.second.value && b.second.arity === 'string';
2739             } else if (a.id === '[' && a.arity === 'infix' && b.id === '.') {
2740                 return a.second.value === b.second.value && a.second.arity === 'string';
2741             }
2742         }
2743         return false;
2744     }
2745
2746
2747 // This is the heart of JSLINT, the Pratt parser. In addition to parsing, it
2748 // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
2749 // like .nud except that it is only used on the first token of a statement.
2750 // Having .fud makes it much easier to define statement-oriented languages like
2751 // JavaScript. I retained Pratt's nomenclature.
2752
2753 // .nud     Null denotation
2754 // .fud     First null denotation
2755 // .led     Left denotation
2756 //  lbp     Left binding power
2757 //  rbp     Right binding power
2758
2759 // They are elements of the parsing method called Top Down Operator Precedence.
2760
2761     function expression(rbp, initial) {
2762
2763 // rbp is the right binding power.
2764 // initial indicates that this is the first expression of a statement.
2765
2766         var left;
2767         if (nexttoken.id === '(end)') {
2768             fail(bundle.unexpected_a, token, nexttoken.id);
2769         }
2770         advance();
2771         if (option.safe && typeof predefined[token.value] === 'boolean' &&
2772                 (nexttoken.id !== '(' && nexttoken.id !== '.')) {
2773             warn(bundle.adsafe, token);
2774         }
2775         if (initial) {
2776             anonname = 'anonymous';
2777             funct['(verb)'] = token.value;
2778         }
2779         if (initial === true && token.fud) {
2780             left = token.fud();
2781         } else {
2782             if (token.nud) {
2783                 left = token.nud();
2784             } else {
2785                 if (nexttoken.arity === 'number' && token.id === '.') {
2786                     warn(bundle.leading_decimal_a, token,
2787                         nexttoken.value);
2788                     advance();
2789                     return token;
2790                 } else {
2791                     fail(bundle.expected_identifier_a, token, token.id);
2792                 }
2793             }
2794             while (rbp < nexttoken.lbp) {
2795                 advance();
2796                 if (token.led) {
2797                     left = token.led(left);
2798                 } else {
2799                     fail(bundle.expected_operator_a, token, token.id);
2800                 }
2801             }
2802         }
2803         return left;
2804     }
2805
2806
2807 // Functional constructors for making the symbols that will be inherited by
2808 // tokens.
2809
2810     function symbol(s, p) {
2811         var x = syntax[s];
2812         if (!x || typeof x !== 'object') {
2813             syntax[s] = x = {
2814                 id: s,
2815                 lbp: p,
2816                 value: s
2817             };
2818         }
2819         return x;
2820     }
2821
2822
2823     function delim(s) {
2824         return symbol(s, 0);
2825     }
2826
2827
2828     function postscript(x) {
2829         x.postscript = true;
2830         return x;
2831     }
2832
2833     function ultimate(s) {
2834         var x = symbol(s, 0);
2835         x.from = 1;
2836         x.thru = 1;
2837         x.line = 0;
2838         x.edge = true;
2839         s.value = s;
2840         return postscript(x);
2841     }
2842
2843
2844     function stmt(s, f) {
2845         var x = delim(s);
2846         x.identifier = x.reserved = true;
2847         x.fud = f;
2848         return x;
2849     }
2850
2851     function labeled_stmt(s, f) {
2852         var x = stmt(s, f);
2853         x.labeled = true;
2854     }
2855
2856     function disrupt_stmt(s, f) {
2857         var x = stmt(s, f);
2858         x.disrupt = true;
2859     }
2860
2861
2862     function reserve_name(x) {
2863         var c = x.id.charAt(0);
2864         if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
2865             x.identifier = x.reserved = true;
2866         }
2867         return x;
2868     }
2869
2870
2871     function prefix(s, f) {
2872         var x = symbol(s, 150);
2873         reserve_name(x);
2874         x.nud = (typeof f === 'function') ? f : function () {
2875             if (s === 'typeof') {
2876                 one_space();
2877             } else {
2878                 no_space_only();
2879             }
2880             this.first = expression(150);
2881             this.arity = 'prefix';
2882             if (this.id === '++' || this.id === '--') {
2883                 if (option.plusplus) {
2884                     warn(bundle.unexpected_a, this);
2885                 } else if ((!this.first.identifier || this.first.reserved) &&
2886                         this.first.id !== '.' && this.first.id !== '[') {
2887                     warn(bundle.bad_operand, this);
2888                 }
2889             }
2890             return this;
2891         };
2892         return x;
2893     }
2894
2895
2896     function type(s, arity, nud) {
2897         var x = delim(s);
2898         x.arity = arity;
2899         if (nud) {
2900             x.nud = nud;
2901         }
2902         return x;
2903     }
2904
2905
2906     function reserve(s, f) {
2907         var x = delim(s);
2908         x.identifier = x.reserved = true;
2909         if (typeof f === 'function') {
2910             x.nud = f;
2911         }
2912         return x;
2913     }
2914
2915
2916     function reservevar(s, v) {
2917         return reserve(s, function () {
2918             if (typeof v === 'function') {
2919                 v(this);
2920             }
2921             return this;
2922         });
2923     }
2924
2925
2926     function infix(s, p, f, w) {
2927         var x = symbol(s, p);
2928         reserve_name(x);
2929         x.led = function (left) {
2930             this.arity = 'infix';
2931             if (!w) {
2932                 spaces(prevtoken, token);
2933                 spaces();
2934             }
2935             if (typeof f === 'function') {
2936                 return f(left, this);
2937             } else {
2938                 this.first = left;
2939                 this.second = expression(p);
2940                 return this;
2941             }
2942         };
2943         return x;
2944     }
2945
2946     function expected_relation(node, message) {
2947         if (node.assign) {
2948             warn(message || bundle.conditional_assignment, node);
2949         }
2950         return node;
2951     }
2952
2953     function expected_condition(node, message) {
2954         switch (node.id) {
2955         case '[':
2956         case '-':
2957             if (node.arity !== 'infix') {
2958                 warn(message || bundle.weird_condition, node);
2959             }
2960             break;
2961         case 'false':
2962         case 'function':
2963         case 'Infinity':
2964         case 'NaN':
2965         case 'null':
2966         case 'true':
2967         case 'undefined':
2968         case 'void':
2969         case '(number)':
2970         case '(regexp)':
2971         case '(string)':
2972         case '{':
2973             warn(message || bundle.weird_condition, node);
2974             break;
2975         }
2976         return node;
2977     }
2978
2979     function check_relation(node) {
2980         switch (node.arity) {
2981         case 'prefix':
2982             switch (node.id) {
2983             case '{':
2984             case '[':
2985                 warn(bundle.unexpected_a, node);
2986                 break;
2987             case '!':
2988                 warn(bundle.confusing_a, node);
2989                 break;
2990             }
2991             break;
2992         case 'function':
2993         case 'regexp':
2994             warn(bundle.unexpected_a, node);
2995             break;
2996         default:
2997             if (node.id  === 'NaN') {
2998                 warn(bundle.isNaN, node);
2999             }
3000         }
3001         return node;
3002     }
3003
3004
3005     function relation(s, eqeq) {
3006         var x = infix(s, 100, function (left, that) {
3007             check_relation(left);
3008             if (eqeq) {
3009                 warn(bundle.expected_a_b, that, eqeq, that.id);
3010             }
3011             var right = expression(100);
3012             if (are_similar(left, right) ||
3013                     ((left.arity === 'string' || left.arity === 'number') &&
3014                     (right.arity === 'string' || right.arity === 'number'))) {
3015                 warn(bundle.weird_relation, that);
3016             }
3017             that.first = left;
3018             that.second = check_relation(right);
3019             return that;
3020         });
3021         return x;
3022     }
3023
3024
3025     function assignop(s, bit) {
3026         var x = infix(s, 20, function (left, that) {
3027             var l;
3028             if (option.bitwise && bit) {
3029                 warn(bundle.unexpected_a, that);
3030             }
3031             that.first = left;
3032             if (funct[left.value] === false) {
3033                 warn(bundle.read_only, left);
3034             } else if (left['function']) {
3035                 warn(bundle.a_function, left);
3036             }
3037             if (option.safe) {
3038                 l = left;
3039                 do {
3040                     if (typeof predefined[l.value] === 'boolean') {
3041                         warn(bundle.adsafe, l);
3042                     }
3043                     l = l.first;
3044                 } while (l);
3045             }
3046             if (left) {
3047                 if (left === syntax['function']) {
3048                     warn(bundle.identifier_function, token);
3049                 }
3050                 if (left.id === '.' || left.id === '[') {
3051                     if (!left.first || left.first.value === 'arguments') {
3052                         warn(bundle.bad_assignment, that);
3053                     }
3054                     that.second = expression(19);
3055                     if (that.id === '=' && are_similar(that.first, that.second)) {
3056                         warn(bundle.weird_assignment, that);
3057                     }
3058                     return that;
3059                 } else if (left.identifier && !left.reserved) {
3060                     if (funct[left.value] === 'exception') {
3061                         warn(bundle.assign_exception, left);
3062                     }
3063                     that.second = expression(19);
3064                     if (that.id === '=' && are_similar(that.first, that.second)) {
3065                         warn(bundle.weird_assignment, that);
3066                     }
3067                     return that;
3068                 }
3069             }
3070             fail(bundle.bad_assignment, that);
3071         });
3072         x.assign = true;
3073         return x;
3074     }
3075
3076
3077     function bitwise(s, p) {
3078         return infix(s, p, function (left, that) {
3079             if (option.bitwise) {
3080                 warn(bundle.unexpected_a, that);
3081             }
3082             that.first = left;
3083             that.second = expression(p);
3084             return that;
3085         });
3086     }
3087
3088
3089     function suffix(s, f) {
3090         var x = symbol(s, 150);
3091         x.led = function (left) {
3092             no_space_only(prevtoken, token);
3093             if (option.plusplus) {
3094                 warn(bundle.unexpected_a, this);
3095             } else if ((!left.identifier || left.reserved) &&
3096                     left.id !== '.' && left.id !== '[') {
3097                 warn(bundle.bad_operand, this);
3098             }
3099             this.first = left;
3100             this.arity = 'suffix';
3101             return this;
3102         };
3103         return x;
3104     }
3105
3106
3107     function optional_identifier() {
3108         if (nexttoken.identifier) {
3109             advance();
3110             if (option.safe && banned[token.value]) {
3111                 warn(bundle.adsafe_a, token);
3112             } else if (token.reserved && !option.es5) {
3113                 warn(bundle.expected_identifier_a_reserved, token);
3114             }
3115             return token.value;
3116         }
3117     }
3118
3119
3120     function identifier() {
3121         var i = optional_identifier();
3122         if (i) {
3123             return i;
3124         }
3125         if (token.id === 'function' && nexttoken.id === '(') {
3126             warn(bundle.name_function);
3127         } else {
3128             fail(bundle.expected_identifier_a);
3129         }
3130     }
3131
3132
3133     function statement(no_indent) {
3134
3135 // Usually a statement starts a line. Exceptions include the var statement in the
3136 // initialization part of a for statement, and an if after an else.
3137
3138         var label, old_scope = scope, the_statement;
3139
3140 // We don't like the empty statement.
3141
3142         if (nexttoken.id === ';') {
3143             warn(bundle.unexpected_a);
3144             semicolon();
3145             return;
3146         }
3147
3148 // Is this a labeled statement?
3149
3150         if (nexttoken.identifier && !nexttoken.reserved && peek().id === ':') {
3151             edge('label');
3152             label = nexttoken;
3153             advance();
3154             discard();
3155             advance(':');
3156             discard();
3157             scope = Object.create(old_scope);
3158             add_label(label.value, 'label');
3159             if (nexttoken.labeled !== true) {
3160                 warn(bundle.label_a_b, nexttoken, label.value, nexttoken.value);
3161             }
3162             if (jx.test(label.value + ':')) {
3163                 warn(bundle.url, label);
3164             }
3165             nexttoken.label = label;
3166         }
3167
3168 // Parse the statement.
3169
3170         edge();
3171         step_in('statement');
3172         the_statement = expression(0, true);
3173         if (the_statement) {
3174
3175 // Look for the final semicolon.
3176
3177             if (the_statement.arity === 'statement') {
3178                 if (the_statement.id === 'switch' ||
3179                         (the_statement.block && the_statement.id !== 'do')) {
3180                     spaces();
3181                 } else {
3182                     semicolon();
3183                 }
3184             } else {
3185
3186 // If this is an expression statement, determine if it is acceptble.
3187 // We do not like
3188 //      new Blah();
3189 // statments. If it is to be used at all, new should only be used to make
3190 // objects, not side effects. The expression statements we do like do
3191 // assignment or invocation or delete.
3192
3193                 if (the_statement.id === '(') {
3194                     if (the_statement.first.id === 'new') {
3195                         warn(bundle.bad_new);
3196                     }
3197                 } else if (!the_statement.assign &&
3198                         the_statement.id !== 'delete' &&
3199                         the_statement.id !== '++' &&
3200                         the_statement.id !== '--') {
3201                     warn(bundle.assignment_function_expression, token);
3202                 }
3203                 semicolon();
3204             }
3205         }
3206         step_out();
3207         scope = old_scope;
3208         return the_statement;
3209     }
3210
3211
3212     function statements() {
3213         var array = [], disruptor, the_statement;
3214
3215 // A disrupt statement may not be followed by any other statement.
3216 // If the last statement is disrupt, then the sequence is disrupt.
3217
3218         while (nexttoken.postscript !== true) {
3219             if (nexttoken.id === ';') {
3220                 warn(bundle.unexpected_a, nexttoken);
3221                 semicolon();
3222             } else {
3223                 if (disruptor) {
3224                     warn(bundle.unreachable_a_b, nexttoken, nexttoken.value,
3225                         disruptor.value);
3226                     disruptor = null;
3227                 }
3228                 the_statement = statement();
3229                 if (the_statement) {
3230                     array.push(the_statement);
3231                     if (the_statement.disrupt) {
3232                         disruptor = the_statement;
3233                         array.disrupt = true;
3234                     }
3235                 }
3236             }
3237         }
3238         return array;
3239     }
3240
3241
3242     function block(ordinary) {
3243
3244 // array block is array sequence of statements wrapped in braces.
3245 // ordinary is false for function bodies and try blocks.
3246 // ordinary is true for if statements, while, etc.
3247
3248         var array,
3249             curly = nexttoken,
3250             old_inblock = in_block,
3251             old_scope = scope,
3252             old_strict_mode = strict_mode;
3253
3254         in_block = ordinary;
3255         scope = Object.create(scope);
3256         spaces();
3257         if (nexttoken.id === '{') {
3258             advance('{');
3259             step_in();
3260             if (!ordinary && !use_strict() && !old_strict_mode &&
3261                     option.strict && funct['(context)']['(global)']) {
3262                 warn(bundle.missing_use_strict);
3263             }
3264             array = statements();
3265             strict_mode = old_strict_mode;
3266             step_out('}', curly);
3267             discard();
3268         } else if (!ordinary) {
3269             fail(bundle.expected_a_b, nexttoken, '{', nexttoken.value);
3270         } else {
3271             warn(bundle.expected_a_b, nexttoken, '{', nexttoken.value);
3272             array = [statement()];
3273             array.disrupt = array[0].disrupt;
3274         }
3275         funct['(verb)'] = null;
3276         scope = old_scope;
3277         in_block = old_inblock;
3278         if (ordinary && array.length === 0) {
3279             warn(bundle.empty_block);
3280         }
3281         return array;
3282     }
3283
3284
3285     function tally_member(name) {
3286         if (properties && typeof properties[name] !== 'boolean') {
3287             warn(bundle.unexpected_member_a, token, name);
3288         }
3289         if (typeof member[name] === 'number') {
3290             member[name] += 1;
3291         } else {
3292             member[name] = 1;
3293         }
3294     }
3295
3296
3297     function note_implied(token) {
3298         var name = token.value, line = token.line, a = implied[name];
3299         if (typeof a === 'function') {
3300             a = false;
3301         }
3302         if (!a) {
3303             a = [line];
3304             implied[name] = a;
3305         } else if (a[a.length - 1] !== line) {
3306             a.push(line);
3307         }
3308     }
3309
3310
3311 // ECMAScript parser
3312
3313     syntax['(identifier)'] = {
3314         type: '(identifier)',
3315         lbp: 0,
3316         identifier: true,
3317         nud: function () {
3318             var variable = this.value,
3319                 site = scope[variable];
3320             if (typeof site === 'function') {
3321                 site = undefined;
3322             }
3323
3324 // The name is in scope and defined in the current function.
3325
3326             if (funct === site) {
3327
3328 //      Change 'unused' to 'var', and reject labels.
3329
3330                 switch (funct[variable]) {
3331                 case 'error':
3332                     warn(bundle.unexpected_a, token);
3333                     funct[variable] = 'var';
3334                     break;
3335                 case 'unused':
3336                     funct[variable] = 'var';
3337                     break;
3338                 case 'unction':
3339                     funct[variable] = 'function';
3340                     this['function'] = true;
3341                     break;
3342                 case 'function':
3343                     this['function'] = true;
3344                     break;
3345                 case 'label':
3346                     warn(bundle.a_label, token, variable);
3347                     break;
3348                 }
3349
3350 // The name is not defined in the function.  If we are in the global scope,
3351 // then we have an undefined variable.
3352
3353             } else if (funct['(global)']) {
3354                 if (typeof global[variable] === 'boolean') {
3355                     funct[variable] = global[variable];
3356                 } else {
3357                     if (option.undef) {
3358                         warn(bundle.not_a_defined, token, variable);
3359                     } else {
3360                         note_implied(token);
3361                     }
3362                 }
3363
3364 // If the name is already defined in the current
3365 // function, but not as outer, then there is a scope error.
3366
3367             } else {
3368                 switch (funct[variable]) {
3369                 case 'closure':
3370                 case 'function':
3371                 case 'var':
3372                 case 'unused':
3373                     warn(bundle.a_scope, token, variable);
3374                     break;
3375                 case 'label':
3376                     warn(bundle.a_label, token, variable);
3377                     break;
3378                 case 'outer':
3379                 case true:
3380                 case false:
3381                     break;
3382                 default:
3383
3384 // If the name is defined in an outer function, make an outer entry, and if
3385 // it was unused, make it var.
3386
3387                     if (typeof site === 'boolean') {
3388                         funct[variable] = site;
3389                         functions[0][variable] = true;
3390                     } else if (site === null) {
3391                         warn(bundle.a_not_allowed, token, variable);
3392                         note_implied(token);
3393                     } else if (typeof site !== 'object') {
3394                         if (option.undef) {
3395                             warn(bundle.a_not_defined, token, variable);
3396                         } else {
3397                             funct[variable] = true;
3398                         }
3399                         note_implied(token);
3400                     } else {
3401                         switch (site[variable]) {
3402                         case 'function':
3403                         case 'unction':
3404                             this['function'] = true;
3405                             site[variable] = 'closure';
3406                             funct[variable] = site['(global)'] ? false : 'outer';
3407                             break;
3408                         case 'var':
3409                         case 'unused':
3410                             site[variable] = 'closure';
3411                             funct[variable] = site['(global)'] ? true : 'outer';
3412                             break;
3413                         case 'closure':
3414                         case 'parameter':
3415                             funct[variable] = site['(global)'] ? true : 'outer';
3416                             break;
3417                         case 'error':
3418                             warn(bundle.not_a_defined, token);
3419                             break;
3420                         case 'label':
3421                             warn(bundle.a_label, token, variable);
3422                             break;
3423                         }
3424                     }
3425                 }
3426             }
3427             return this;
3428         },
3429         led: function () {
3430             fail(bundle.expected_operator_a);
3431         }
3432     };
3433
3434 // Build the syntax table by declaring the syntactic elements of the language.
3435
3436     type('(number)', 'number', return_this);
3437     type('(string)', 'string', return_this);
3438     type('(regexp)', 'regexp', return_this);
3439     type('(color)', 'color');
3440     type('(range)', 'range');
3441
3442     ultimate('(begin)');
3443     ultimate('(end)');
3444     ultimate('(error)');
3445     postscript(delim('</'));
3446     delim('<!');
3447     delim('<!--');
3448     delim('-->');
3449     postscript(delim('}'));
3450     delim(')');
3451     delim(']');
3452     postscript(delim('"'));
3453     postscript(delim('\''));
3454     delim(';');
3455     delim(':');
3456     delim(',');
3457     delim('#');
3458     delim('@');
3459     delim('*/');
3460     reserve('else');
3461     postscript(reserve('case'));
3462     reserve('catch');
3463     postscript(reserve('default'));
3464     reserve('finally');
3465     reservevar('arguments', function (x) {
3466         if (strict_mode && funct['(global)']) {
3467             warn(bundle.strict, x);
3468         } else if (option.safe) {
3469             warn(bundle.adsafe, x);
3470         }
3471     });
3472     reservevar('eval', function (x) {
3473         if (option.safe) {
3474             warn(bundle.adsafe, x);
3475         }
3476     });
3477     reservevar('false');
3478     reservevar('Infinity');
3479     reservevar('NaN');
3480     reservevar('null');
3481     reservevar('this', function (x) {
3482         if (strict_mode && ((funct['(statement)'] &&
3483                 funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) {
3484             warn(bundle.strict, x);
3485         } else if (option.safe) {
3486             warn(bundle.adsafe, x);
3487         }
3488     });
3489     reservevar('true');
3490     reservevar('undefined');
3491     assignop('=');
3492     assignop('+=');
3493     assignop('-=');
3494     assignop('*=');
3495     assignop('/=').nud = function () {
3496         fail(bundle.slash_equal);
3497     };
3498     assignop('%=');
3499     assignop('&=', true);
3500     assignop('|=', true);
3501     assignop('^=', true);
3502     assignop('<<=', true);
3503     assignop('>>=', true);
3504     assignop('>>>=', true);
3505     infix('?', 30, function (left, that) {
3506         that.first = expected_condition(expected_relation(left));
3507         that.second = expression(0);
3508         spaces();
3509         advance(':');
3510         discard();
3511         spaces();
3512         that.third = expression(10);
3513         that.arity = 'ternary';
3514         if (are_similar(that.second, that.third)) {
3515             warn(bundle.weird_ternary, that);
3516         }
3517         return that;
3518     });
3519
3520     infix('||', 40, function (left, that) {
3521         function paren_check(that) {
3522             if (that.id === '&&' && !that.paren) {
3523                 warn(bundle.and, that);
3524             }
3525             return that;
3526         }
3527
3528         that.first = paren_check(expected_condition(expected_relation(left)));
3529         that.second = paren_check(expected_relation(expression(40)));
3530         if (are_similar(that.first, that.second)) {
3531             warn(bundle.weird_condition, that);
3532         }
3533         return that;
3534     });
3535     infix('&&', 50, function (left, that) {
3536         that.first = expected_condition(expected_relation(left));
3537         that.second = expected_relation(expression(50));
3538         if (are_similar(that.first, that.second)) {
3539             warn(bundle.weird_condition, that);
3540         }
3541         return that;
3542     });
3543     prefix('void', function () {
3544         this.first = expression(0);
3545         if (this.first.arity !== 'number' || this.first.value) {
3546             warn(bundle.unexpected_a, this);
3547             return this;
3548         }
3549         return this;
3550     });
3551     bitwise('|', 70);
3552     bitwise('^', 80);
3553     bitwise('&', 90);
3554     relation('==', '===');
3555     relation('===');
3556     relation('!=', '!==');
3557     relation('!==');
3558     relation('<');
3559     relation('>');
3560     relation('<=');
3561     relation('>=');
3562     bitwise('<<', 120);
3563     bitwise('>>', 120);
3564     bitwise('>>>', 120);
3565     infix('in', 120, function (left, that) {
3566         warn(bundle.infix_in, that);
3567         that.left = left;
3568         that.right = expression(130);
3569         return that;
3570     });
3571     infix('instanceof', 120);
3572     infix('+', 130, function (left, that) {
3573         if (!left.value) {
3574             if (left.arity === 'number') {
3575                 warn(bundle.unexpected_a, left);
3576             } else if (left.arity === 'string') {
3577                 warn(bundle.expected_a_b, left, 'String', '\'\'');
3578             }
3579         }
3580         var right = expression(130);
3581         if (!right.value) {
3582             if (right.arity === 'number') {
3583                 warn(bundle.unexpected_a, right);
3584             } else if (right.arity === 'string') {
3585                 warn(bundle.expected_a_b, right, 'String', '\'\'');
3586             }
3587         }
3588         if (left.arity === right.arity &&
3589                 (left.arity === 'string' || left.arity === 'number')) {
3590             left.value += right.value;
3591             left.thru = right.thru;
3592             if (left.arity === 'string' && jx.test(left.value)) {
3593                 warn(bundle.url, left);
3594             }
3595             discard(right);
3596             discard(that);
3597             return left;
3598         }
3599         that.first = left;
3600         that.second = right;
3601         return that;
3602     });
3603     prefix('+', 'num');
3604     prefix('+++', function () {
3605         warn(bundle.confusing_a, token);
3606         this.first = expression(150);
3607         this.arity = 'prefix';
3608         return this;
3609     });
3610     infix('+++', 130, function (left) {
3611         warn(bundle.confusing_a, token);
3612         this.first = left;
3613         this.second = expression(130);
3614         return this;
3615     });
3616     infix('-', 130, function (left, that) {
3617         if ((left.arity === 'number' && left.value === 0) || left.arity === 'string') {
3618             warn(bundle.unexpected_a, left);
3619         }
3620         var right = expression(130);
3621         if ((right.arity === 'number' && right.value === 0) || right.arity === 'string') {
3622             warn(bundle.unexpected_a, left);
3623         }
3624         if (left.arity === right.arity && left.arity === 'number') {
3625             left.value -= right.value;
3626             left.thru = right.thru;
3627             discard(right);
3628             discard(that);
3629             return left;
3630         }
3631         that.first = left;
3632         that.second = right;
3633         return that;
3634     });
3635     prefix('-');
3636     prefix('---', function () {
3637         warn(bundle.confusing_a, token);
3638         this.first = expression(150);
3639         this.arity = 'prefix';
3640         return this;
3641     });
3642     infix('---', 130, function (left) {
3643         warn(bundle.confusing_a, token);
3644         this.first = left;
3645         this.second = expression(130);
3646         return this;
3647     });
3648     infix('*', 140, function (left, that) {
3649         if ((left.arity === 'number' && (left.value === 0 || left.value === 1)) || left.arity === 'string') {
3650             warn(bundle.unexpected_a, left);
3651         }
3652         var right = expression(140);
3653         if ((right.arity === 'number' && (right.value === 0 || right.value === 1)) || right.arity === 'string') {
3654             warn(bundle.unexpected_a, right);
3655         }
3656         if (left.arity === right.arity && left.arity === 'number') {
3657             left.value *= right.value;
3658             left.thru = right.thru;
3659             discard(right);
3660             discard(that);
3661             return left;
3662         }
3663         that.first = left;
3664         that.second = right;
3665         return that;
3666     });
3667     infix('/', 140, function (left, that) {
3668         if ((left.arity === 'number' && left.value === 0) || left.arity === 'string') {
3669             warn(bundle.unexpected_a, left);
3670         }
3671         var right = expression(140);
3672         if ((right.arity === 'number' && (right.value === 0 || right.value === 1)) || right.arity === 'string') {
3673             warn(bundle.unexpected_a, right);
3674         }
3675         if (left.arity === right.arity && left.arity === 'number') {
3676             left.value /= right.value;
3677             left.thru = right.thru;
3678             discard(right);
3679             discard(that);
3680             return left;
3681         }
3682         that.first = left;
3683         that.second = right;
3684         return that;
3685     });
3686     infix('%', 140, function (left, that) {
3687         if ((left.arity === 'number' && (left.value === 0 || left.value === 1)) || left.arity === 'string') {
3688             warn(bundle.unexpected_a, left);
3689         }
3690         var right = expression(140);
3691         if ((right.arity === 'number' && (right.value === 0 || right.value === 1)) || right.arity === 'string') {
3692             warn(bundle.unexpected_a, right);
3693         }
3694         if (left.arity === right.arity && left.arity === 'number') {
3695             left.value %= right.value;
3696             left.thru = right.thru;
3697             discard(right);
3698             discard(that);
3699             return left;
3700         }
3701         that.first = left;
3702         that.second = right;
3703         return that;
3704     });
3705
3706     suffix('++');
3707     prefix('++');
3708
3709     suffix('--');
3710     prefix('--');
3711     prefix('delete', function () {
3712         one_space();
3713         var p = expression(0);
3714         if (!p || (p.id !== '.' && p.id !== '[')) {
3715             warn(bundle.deleted);
3716         }
3717         this.first = p;
3718         return this;
3719     });
3720
3721
3722     prefix('~', function () {
3723         no_space_only();
3724         if (option.bitwise) {
3725             warn(bundle.unexpected_a, this);
3726         }
3727         expression(150);
3728         return this;
3729     });
3730     prefix('!', function () {
3731         no_space_only();
3732         this.first = expression(150);
3733         this.arity = 'prefix';
3734         if (bang[this.first.id] === true) {
3735             warn(bundle.confusing_a, this);
3736         }
3737         return this;
3738     });
3739     prefix('typeof');
3740     prefix('new', function () {
3741         one_space();
3742         var c = expression(160), i, p;
3743         this.first = c;
3744         if (c.id !== 'function') {
3745             if (c.identifier) {
3746                 switch (c.value) {
3747                 case 'Object':
3748                     warn(bundle.use_object, token);
3749                     break;
3750                 case 'Array':
3751                     if (nexttoken.id === '(') {
3752                         p = nexttoken;
3753                         p.first = this;
3754                         advance('(');
3755                         if (nexttoken.id !== ')') {
3756                             p.second = expression(0);
3757                             if (p.second.arity !== 'number' || !p.second.value) {
3758                                 expected_condition(p.second,  bundle.use_array);
3759                                 i = false;
3760                             } else {
3761                                 i = true;
3762                             }
3763                             while (nexttoken.id !== ')' && nexttoken.id !== '(end)') {
3764                                 if (i) {
3765                                     warn(bundle.use_array, p);
3766                                     i = false;
3767                                 }
3768                                 advance();
3769                             }
3770                         } else {
3771                             warn(bundle.use_array, token);
3772                         }
3773                         advance(')', p);
3774                         discard();
3775                         return p;
3776                     }
3777                     warn(bundle.use_array, token);
3778                     break;
3779                 case 'Number':
3780                 case 'String':
3781                 case 'Boolean':
3782                 case 'Math':
3783                 case 'JSON':
3784                     warn(bundle.not_a_constructor, c);
3785                     break;
3786                 case 'Function':
3787                     if (!option.evil) {
3788                         warn(bundle.function_eval);
3789                     }
3790                     break;
3791                 case 'Date':
3792                 case 'RegExp':
3793                     break;
3794                 default:
3795                     if (c.id !== 'function') {
3796                         i = c.value.substr(0, 1);
3797                         if (option.newcap && (i < 'A' || i > 'Z')) {
3798                             warn(bundle.constructor_name_a, token);
3799                         }
3800                     }
3801                 }
3802             } else {
3803                 if (c.id !== '.' && c.id !== '[' && c.id !== '(') {
3804                     warn(bundle.bad_constructor, token);
3805                 }
3806             }
3807         } else {
3808             warn(bundle.weird_new, this);
3809         }
3810         if (nexttoken.id !== '(') {
3811             warn(bundle.missing_a, nexttoken, '()');
3812         }
3813         return this;
3814     });
3815
3816     infix('(', 160, function (left, that) {
3817         if (indent && indent.mode === 'expression') {
3818             no_space(prevtoken, token);
3819         } else {
3820             no_space_only(prevtoken, token);
3821         }
3822         if (!left.immed && left.id === 'function') {
3823             warn(bundle.wrap_immediate);
3824         }
3825         var p = [];
3826         if (left) {
3827             if (left.identifier) {
3828                 if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
3829                     if (left.value !== 'Number' && left.value !== 'String' &&
3830                             left.value !== 'Boolean' && left.value !== 'Date') {
3831                         if (left.value === 'Math' || left.value === 'JSON') {
3832                             warn(bundle.not_a_function, left);
3833                         } else if (left.value === 'Object') {
3834                             warn(bundle.use_object, token);
3835                         } else if (left.value === 'Array' || option.newcap) {
3836                             warn(bundle.missing_a, left, 'new');
3837                         }
3838                     }
3839                 }
3840             } else if (left.id === '.') {
3841                 if (option.safe && left.first.value === 'Math' &&
3842                         left.second === 'random') {
3843                     warn(bundle.adsafe, left);
3844                 }
3845             }
3846         }
3847         step_in();
3848         if (nexttoken.id !== ')') {
3849             no_space();
3850             for (;;) {
3851                 edge();
3852                 p.push(expression(10));
3853                 if (nexttoken.id !== ',') {
3854                     break;
3855                 }
3856                 comma();
3857             }
3858         }
3859         no_space();
3860         step_out(')', that);
3861         if (typeof left === 'object') {
3862             if (left.value === 'parseInt' && p.length === 1) {
3863                 warn(bundle.radix, left);
3864             }
3865             if (!option.evil) {
3866                 if (left.value === 'eval' || left.value === 'Function' ||
3867                         left.value === 'execScript') {
3868                     warn(bundle.evil, left);
3869                 } else if (p[0] && p[0].arity === 'string' &&
3870                         (left.value === 'setTimeout' ||
3871                         left.value === 'setInterval')) {
3872                     warn(bundle.implied_evil, left);
3873                 }
3874             }
3875             if (!left.identifier && left.id !== '.' && left.id !== '[' &&
3876                     left.id !== '(' && left.id !== '&&' && left.id !== '||' &&
3877                     left.id !== '?') {
3878                 warn(bundle.bad_invocation, left);
3879             }
3880         }
3881         that.first = left;
3882         that.second = p;
3883         return that;
3884     }, true);
3885
3886     prefix('(', function () {
3887         step_in('expression');
3888         discard();
3889         no_space();
3890         edge();
3891         if (nexttoken.id === 'function') {
3892             nexttoken.immed = true;
3893         }
3894         var value = expression(0);
3895         value.paren = true;
3896         no_space();
3897         step_out(')', this);
3898         discard();
3899         if (value.id === 'function') {
3900             if (nexttoken.id === '(') {
3901                 warn(bundle.move_invocation);
3902             } else {
3903                 warn(bundle.bad_wrap, this);
3904             }
3905         }
3906         return value;
3907     });
3908
3909     infix('.', 170, function (left, that) {
3910         no_space(prevtoken, token);
3911         no_space();
3912         var m = identifier();
3913         if (typeof m === 'string') {
3914             tally_member(m);
3915         }
3916         that.first = left;
3917         that.second = token;
3918         if (left && left.value === 'arguments' &&
3919                 (m === 'callee' || m === 'caller')) {
3920             warn(bundle.avoid_a, left, 'arguments.' + m);
3921         } else if (!option.evil && left && left.value === 'document' &&
3922                 (m === 'write' || m === 'writeln')) {
3923             warn(bundle.write_is_wrong, left);
3924         } else if (option.adsafe) {
3925             if (!adsafe_top && left.value === 'ADSAFE') {
3926                 if (m === 'id' || m === 'lib') {
3927                     warn(bundle.adsafe, that);
3928                 } else if (m === 'go') {
3929                     if (xmode !== 'script') {
3930                         warn(bundle.adsafe, that);
3931                     } else if (adsafe_went || nexttoken.id !== '(' ||
3932                             peek(0).arity !== 'string' ||
3933                             peek(0).value !== adsafe_id ||
3934                             peek(1).id !== ',') {
3935                         fail(bundle.adsafe_a, that, 'go');
3936                     }
3937                     adsafe_went = true;
3938                     adsafe_may = false;
3939                 }
3940             }
3941             adsafe_top = false;
3942         }
3943         if (!option.evil && (m === 'eval' || m === 'execScript')) {
3944             warn(bundle.evil);
3945         } else if (option.safe) {
3946             for (;;) {
3947                 if (banned[m] === true) {
3948                     warn(bundle.adsafe_a, token, m);
3949                 }
3950                 if (typeof predefined[left.value] !== 'boolean' ||
3951                         nexttoken.id === '(') {
3952                     break;
3953                 }
3954                 if (standard_member[m] === true) {
3955                     if (nexttoken.id === '.') {
3956                         warn(bundle.adsafe, that);
3957                     }
3958                     break;
3959                 }
3960                 if (nexttoken.id !== '.') {
3961                     warn(bundle.adsafe, that);
3962                     break;
3963                 }
3964                 advance('.');
3965                 token.first = that;
3966                 token.second = m;
3967                 that = token;
3968                 m = identifier();
3969                 if (typeof m === 'string') {
3970                     tally_member(m);
3971                 }
3972             }
3973         }
3974         return that;
3975     }, true);
3976
3977     infix('[', 170, function (left, that) {
3978         no_space_only(prevtoken, token);
3979         no_space();
3980         step_in();
3981         edge();
3982         var e = expression(0), s;
3983         if (e.arity === 'string') {
3984             if (option.safe && banned[e.value] === true) {
3985                 warn(bundle.adsafe_a, e);
3986             } else if (!option.evil &&
3987                     (e.value === 'eval' || e.value === 'execScript')) {
3988                 warn(bundle.evil, e);
3989             } else if (option.safe &&
3990                     (e.value.charAt(0) === '_' || e.value.charAt(0) === '-')) {
3991                 warn(bundle.adsafe_subscript_a, e);
3992             }
3993             tally_member(e.value);
3994             if (!option.sub && ix.test(e.value)) {
3995                 s = syntax[e.value];
3996                 if (!s || !s.reserved) {
3997                     warn(bundle.subscript, e);
3998                 }
3999             }
4000         } else if (e.arity !== 'number' || e.value < 0) {
4001             if (option.safe) {
4002                 warn(bundle.adsafe_subscript_a, e);
4003             }
4004         }
4005         step_out(']', that);
4006         discard();
4007         no_space(prevtoken, token);
4008         that.first = left;
4009         that.second = e;
4010         return that;
4011     }, true);
4012
4013     prefix('[', function () {
4014         this.arity = 'prefix';
4015         this.first = [];
4016         step_in('array');
4017         while (nexttoken.id !== '(end)') {
4018             while (nexttoken.id === ',') {
4019                 warn(bundle.unexpected_a, nexttoken);
4020                 advance(',');
4021                 discard();
4022             }
4023             if (nexttoken.id === ']') {
4024                 break;
4025             }
4026             edge();
4027             this.first.push(expression(10));
4028             if (nexttoken.id === ',') {
4029                 comma();
4030                 if (nexttoken.id === ']' && !option.es5) {
4031                     warn(bundle.unexpected_a, token);
4032                     break;
4033                 }
4034             } else {
4035                 break;
4036             }
4037         }
4038         step_out(']', this);
4039         discard();
4040         return this;
4041     }, 170);
4042
4043
4044     function property_name() {
4045         var id = optional_identifier(true);
4046         if (!id) {
4047             if (nexttoken.arity === 'string') {
4048                 id = nexttoken.value;
4049                 if (option.safe) {
4050                     if (banned[id]) {
4051                         warn(bundle.adsafe_a);
4052                     } else if (id.charAt(0) === '_' ||
4053                             id.charAt(id.length - 1) === '_') {
4054                         warn(bundle.dangling_a);
4055                     }
4056                 }
4057                 advance();
4058             } else if (nexttoken.arity === 'number') {
4059                 id = nexttoken.value.toString();
4060                 advance();
4061             }
4062         }
4063         return id;
4064     }
4065
4066
4067     function function_params() {
4068         var id, paren = nexttoken, params = [];
4069         advance('(');
4070         step_in();
4071         discard();
4072         no_space();
4073         if (nexttoken.id === ')') {
4074             no_space();
4075             step_out(')', paren);
4076             discard();
4077             return;
4078         }
4079         for (;;) {
4080             edge();
4081             id = identifier();
4082             params.push(token);
4083             add_label(id, 'parameter');
4084             if (nexttoken.id === ',') {
4085                 comma();
4086             } else {
4087                 no_space();
4088                 step_out(')', paren);
4089                 discard();
4090                 return params;
4091             }
4092         }
4093     }
4094
4095
4096     function do_function(func, name) {
4097         var old_properties = properties,
4098             old_option     = option,
4099             old_global     = global,
4100             old_scope      = scope;
4101         funct = {
4102             '(name)'     : name || '"' + anonname + '"',
4103             '(line)'     : nexttoken.line,
4104             '(context)'  : funct,
4105             '(breakage)' : 0,
4106             '(loopage)'  : 0,
4107             '(scope)'    : scope,
4108             '(token)'    : func
4109         };
4110         properties  = old_properties && Object.create(old_properties);
4111         option      = Object.create(old_option);
4112         global      = Object.create(old_global);
4113         scope       = Object.create(old_scope);
4114         token.funct = funct;
4115         functions.push(funct);
4116         if (name) {
4117             add_label(name, 'function');
4118         }
4119         func.name = name || '';
4120         func.first = funct['(params)'] = function_params();
4121         one_space();
4122         func.block = block(false);
4123         funct      = funct['(context)'];
4124         properties = old_properties;
4125         option     = old_option;
4126         global     = old_global;
4127         scope      = old_scope;
4128     }
4129
4130
4131     prefix('{', function () {
4132         var get, i, j, name, p, set, seen = {}, t;
4133         this.arity = 'prefix';
4134         this.first = [];
4135         step_in();
4136         while (nexttoken.id !== '}') {
4137
4138 // JSLint recognizes the ES5 extension for get/set in object literals,
4139 // but requires that they be used in pairs.
4140
4141             edge();
4142             if (nexttoken.value === 'get' && peek().id !== ':') {
4143                 if (!option.es5) {
4144                     warn(bundle.get_set);
4145                 }
4146                 get = nexttoken;
4147                 one_space_only();
4148                 advance('get');
4149                 name = nexttoken;
4150                 i = property_name();
4151                 if (!i) {
4152                     fail(bundle.missing_property);
4153                 }
4154                 do_function(get, '');
4155                 if (funct['(loopage)']) {
4156                     warn(bundle.function_loop, t);
4157                 }
4158                 p = get.first;
4159                 if (p) {
4160                     warn(bundle.parameter_a_get_b, t, p[0], i);
4161                 }
4162                 comma();
4163                 set = nexttoken;
4164                 spaces();
4165                 edge();
4166                 advance('set');
4167                 one_space_only();
4168                 j = property_name();
4169                 if (i !== j) {
4170                     fail(bundle.expected_a_b, token, i, j);
4171                 }
4172                 do_function(set, '');
4173                 p = set.first;
4174                 if (!p || p.length !== 1 || p[0] !== 'value') {
4175                     warn(bundle.parameter_set_a, t, i);
4176                 }
4177                 name.first = [get, set];
4178             } else {
4179                 name = nexttoken;
4180                 i = property_name();
4181                 if (typeof i !== 'string') {
4182                     fail(bundle.missing_property);
4183                 }
4184                 advance(':');
4185                 discard();
4186                 spaces();
4187                 name.first = expression(10);
4188             }
4189             this.first.push(name);
4190             if (seen[i] === true) {
4191                 warn(bundle.duplicate_a, nexttoken, i);
4192             }
4193             seen[i] = true;
4194             tally_member(i);
4195             if (nexttoken.id !== ',') {
4196                 break;
4197             }
4198             for (;;) {
4199                 comma();
4200                 if (nexttoken.id !== ',') {
4201                     break;
4202                 }
4203                 warn(bundle.unexpected_a, nexttoken);
4204             }
4205             if (nexttoken.id === '}' && !option.es5) {
4206                 warn(bundle.unexpected_a, token);
4207             }
4208         }
4209         step_out('}', this);
4210         discard();
4211         return this;
4212     });
4213
4214     stmt('{', function () {
4215         discard();
4216         warn(bundle.statement_block);
4217         this.arity = 'statement';
4218         this.block = statements();
4219         this.disrupt = this.block.disrupt;
4220         advance('}', this);
4221         discard();
4222         return this;
4223     });
4224
4225     stmt('/*properties', directive);
4226     stmt('/*members', directive);
4227     stmt('/*jslint', directive);
4228     stmt('/*global', directive);
4229
4230
4231
4232     stmt('var', function () {
4233
4234 // JavaScript does not have block scope. It only has function scope. So,
4235 // declaring a variable in a block can have unexpected consequences.
4236
4237 // var.first will contain an array, the array containing name tokens
4238 // and assignment tokens.
4239
4240         var assign, id, name;
4241
4242         if (funct['(onevar)'] && option.onevar) {
4243             warn(bundle.combine_var);
4244         } else if (!funct['(global)']) {
4245             funct['(onevar)'] = true;
4246         }
4247         this.arity = 'statement';
4248         this.first = [];
4249         step_in('var');
4250         for (;;) {
4251             name = nexttoken;
4252             id = identifier();
4253             if (funct['(global)'] && predefined[id] === false) {
4254                 warn(bundle.redefinition_a, token, id);
4255             }
4256             add_label(id, 'error');
4257
4258             if (nexttoken.id === '=') {
4259                 assign = nexttoken;
4260                 assign.first = name;
4261                 spaces();
4262                 advance('=');
4263                 spaces();
4264                 if (nexttoken.id === 'undefined') {
4265                     warn(bundle.unnecessary_initialize, token, id);
4266                 }
4267                 if (peek(0).id === '=' && nexttoken.identifier) {
4268                     fail(bundle.var_a_not);
4269                 }
4270                 assign.second = expression(0);
4271                 assign.arity = 'infix';
4272                 this.first.push(assign);
4273             } else {
4274                 this.first.push(name);
4275             }
4276             funct[id] = 'unused';
4277             if (nexttoken.id !== ',') {
4278                 break;
4279             }
4280             comma();
4281             if (var_mode && nexttoken.line === token.line &&
4282                     this.first.length === 1) {
4283                 var_mode = false;
4284                 indent.open = false;
4285                 indent.at -= option.indent;
4286             }
4287             spaces();
4288             edge();
4289         }
4290         var_mode = false;
4291         step_out();
4292         return this;
4293     });
4294
4295     stmt('function', function () {
4296         one_space();
4297         if (in_block) {
4298             warn(bundle.function_block, token);
4299         }
4300         var i = identifier();
4301         if (i) {
4302             add_label(i, 'unction');
4303             no_space();
4304         }
4305         do_function(this, i, true);
4306         if (nexttoken.id === '(' && nexttoken.line === token.line) {
4307             fail(bundle.function_statement);
4308         }
4309         this.arity = 'statement';
4310         return this;
4311     });
4312
4313     prefix('function', function () {
4314         one_space();
4315         var i = optional_identifier();
4316         if (i) {
4317             no_space();
4318         }
4319         do_function(this, i);
4320         if (funct['(loopage)']) {
4321             warn(bundle.function_loop);
4322         }
4323         this.arity = 'function';
4324         return this;
4325     });
4326
4327     stmt('if', function () {
4328         var t = nexttoken;
4329         one_space();
4330         advance('(');
4331         step_in('control');
4332         discard();
4333         no_space();
4334         edge();
4335         this.arity = 'statement';
4336         this.first = expected_condition(expected_relation(expression(0)));
4337         no_space();
4338         step_out(')', t);
4339         discard();
4340         one_space();
4341         this.block = block(true);
4342         if (nexttoken.id === 'else') {
4343             one_space();
4344             advance('else');
4345             discard();
4346             one_space();
4347             this['else'] = nexttoken.id === 'if' || nexttoken.id === 'switch' ?
4348                 statement(true) : block(true);
4349             if (this['else'].disrupt && this.block.disrupt) {
4350                 this.disrupt = true;
4351             }
4352         }
4353         return this;
4354     });
4355
4356     stmt('try', function () {
4357
4358 // try.first    The catch variable
4359 // try.second   The catch clause
4360 // try.third    The finally clause
4361 // try.block    The try block
4362
4363         var b, e, s, t;
4364         if (option.adsafe) {
4365             warn(bundle.adsafe_a, this);
4366         }
4367         one_space();
4368         this.arity = 'statement';
4369         this.block = block(false);
4370         if (nexttoken.id === 'catch') {
4371             one_space();
4372             advance('catch');
4373             discard();
4374             one_space();
4375             t = nexttoken;
4376             advance('(');
4377             step_in('control');
4378             discard();
4379             no_space();
4380             edge();
4381             s = scope;
4382             scope = Object.create(s);
4383             e = nexttoken.value;
4384             this.first = e;
4385             if (!nexttoken.identifier) {
4386                 warn(bundle.expected_identifier_a, nexttoken);
4387             } else {
4388                 add_label(e, 'exception');
4389             }
4390             advance();
4391             no_space();
4392             step_out(')', t);
4393             discard();
4394             one_space();
4395             this.second = block(false);
4396             b = true;
4397             scope = s;
4398         }
4399         if (nexttoken.id === 'finally') {
4400             discard();
4401             one_space();
4402             t = nexttoken;
4403             advance('finally');
4404             discard();
4405             one_space();
4406             this.third = block(false);
4407         } else if (!b) {
4408             fail(bundle.expected_a_b, nexttoken, 'catch', nexttoken.value);
4409         }
4410         return this;
4411     });
4412
4413
4414     labeled_stmt('while', function () {
4415         one_space();
4416         var t = nexttoken;
4417         funct['(breakage)'] += 1;
4418         funct['(loopage)'] += 1;
4419         advance('(');
4420         step_in('control');
4421         discard();
4422         no_space();
4423         edge();
4424         this.arity = 'statement';
4425         this.first = expected_relation(expression(0));
4426         if (this.first.id !== 'true') {
4427             expected_condition(this.first, bundle.unexpected_a);
4428         }
4429         no_space();
4430         step_out(')', t);
4431         discard();
4432         one_space();
4433         this.block = block(true);
4434         if (this.block.disrupt) {
4435             warn(bundle.strange_loop, prevtoken);
4436         }
4437         funct['(breakage)'] -= 1;
4438         funct['(loopage)'] -= 1;
4439         return this;
4440     });
4441
4442     reserve('with');
4443
4444     labeled_stmt('switch', function () {
4445
4446 // switch.first             the switch expression
4447 // switch.second            the array of cases. A case is 'case' or 'default' token:
4448 //    case.first            the array of case expressions
4449 //    case.second           the array of statements
4450 // If all of the arrays of statements are disrupt, then the switch is disrupt.
4451
4452         var particular,
4453             the_case = nexttoken,
4454             unbroken = true;
4455         funct['(breakage)'] += 1;
4456         one_space();
4457         advance('(');
4458         discard();
4459         no_space();
4460         step_in();
4461         this.arity = 'statement';
4462         this.first = expected_condition(expected_relation(expression(0)));
4463         no_space();
4464         step_out(')', the_case);
4465         discard();
4466         one_space();
4467         advance('{');
4468         step_in();
4469         this.second = [];
4470         while (nexttoken.id === 'case') {
4471             the_case = nexttoken;
4472             the_case.first = [];
4473             spaces();
4474             edge('case');
4475             advance('case');
4476             for (;;) {
4477                 one_space();
4478                 particular = expression(0);
4479                 the_case.first.push(particular);
4480                 if (particular.id === 'NaN') {
4481                     warn(bundle.unexpected_a, particular);
4482                 }
4483                 no_space_only();
4484                 advance(':');
4485                 discard();
4486                 if (nexttoken.id !== 'case') {
4487                     break;
4488                 }
4489                 spaces();
4490                 edge('case');
4491                 advance('case');
4492                 discard();
4493             }
4494             spaces();
4495             the_case.second = statements();
4496             if (the_case.second && the_case.second.length > 0) {
4497                 particular = the_case.second[the_case.second.length - 1];
4498                 if (particular.disrupt) {
4499                     if (particular.id === 'break') {
4500                         unbroken = false;
4501                     }
4502                 } else {
4503                     warn(bundle.missing_a_after_b, nexttoken, 'break', 'case');
4504                 }
4505             } else {
4506                 warn(bundle.empty_case);
4507             }
4508             this.second.push(the_case);
4509         }
4510         if (this.second.length === 0) {
4511             warn(bundle.missing_a, nexttoken, 'case');
4512         }
4513         if (nexttoken.id === 'default') {
4514             spaces();
4515             the_case = nexttoken;
4516             edge('case');
4517             advance('default');
4518             discard();
4519             no_space_only();
4520             advance(':');
4521             discard();
4522             spaces();
4523             the_case.second = statements();
4524             if (the_case.second && the_case.second.length > 0) {
4525                 particular = the_case.second[the_case.second.length - 1];
4526                 if (unbroken && particular.disrupt && particular.id !== 'break') {
4527                     this.disrupt = true;
4528                 }
4529             }
4530             this.second.push(the_case);
4531         }
4532         funct['(breakage)'] -= 1;
4533         spaces();
4534         step_out('}', this);
4535         return this;
4536     });
4537
4538     stmt('debugger', function () {
4539         if (!option.debug) {
4540             warn(bundle.unexpected_a, this);
4541         }
4542         this.arity = 'statement';
4543         return this;
4544     });
4545
4546     labeled_stmt('do', function () {
4547         funct['(breakage)'] += 1;
4548         funct['(loopage)'] += 1;
4549         one_space();
4550         this.arity = 'statement';
4551         this.block = block(true);
4552         if (this.block.disrupt) {
4553             warn(bundle.strange_loop, prevtoken);
4554         }
4555         one_space();
4556         advance('while');
4557         discard();
4558         var t = nexttoken;
4559         one_space();
4560         advance('(');
4561         step_in();
4562         discard();
4563         no_space();
4564         edge();
4565         this.first = expected_condition(expected_relation(expression(0)), bundle.unexpected_a);
4566         no_space();
4567         step_out(')', t);
4568         discard();
4569         funct['(breakage)'] -= 1;
4570         funct['(loopage)'] -= 1;
4571         return this;
4572     });
4573
4574     labeled_stmt('for', function () {
4575         var blok, filter, ok = false, paren = nexttoken, the_in, value;
4576         this.arity = 'statement';
4577         funct['(breakage)'] += 1;
4578         funct['(loopage)'] += 1;
4579         advance('(');
4580         step_in('control');
4581         discard();
4582         spaces(this, paren);
4583         no_space();
4584         if (nexttoken.id === 'var') {
4585             fail(bundle.move_var);
4586         }
4587         edge();
4588         if (peek(0).id === 'in') {
4589             value = nexttoken;
4590             switch (funct[value.value]) {
4591             case 'unused':
4592                 funct[value.value] = 'var';
4593                 break;
4594             case 'var':
4595                 break;
4596             default:
4597                 warn(bundle.bad_in_a, value);
4598             }
4599             advance();
4600             the_in = nexttoken;
4601             advance('in');
4602             the_in.first = value;
4603             the_in.second = expression(20);
4604             step_out(')', paren);
4605             discard();
4606             this.first = the_in;
4607             blok = block(true);
4608             if (!option.forin) {
4609                 if (blok.length === 1 && typeof blok[0] === 'object' &&
4610                         blok[0].value === 'if' && !blok[0]['else']) {
4611                     filter = blok[0].first;
4612                     while (filter.id === '&&') {
4613                         filter = filter.first;
4614                     }
4615                     switch (filter.id) {
4616                     case '===':
4617                     case '!==':
4618                         ok = filter.first.id === '[' ? (
4619                             filter.first.first.value === the_in.second.value &&
4620                             filter.first.second.value === the_in.first.value
4621                         ) : (
4622                             filter.first.id === 'typeof' &&
4623                             filter.first.first.id === '[' &&
4624                             filter.first.first.first.value === the_in.second.value &&
4625                             filter.first.first.second.value === the_in.first.value
4626                         );
4627                         break;
4628                     case '(':
4629                         ok = filter.first.id === '.' && ((
4630                             filter.first.first.value === the_in.second.value &&
4631                             filter.first.second.value === 'hasOwnProperty' &&
4632                             filter.second[0].value === the_in.first.value
4633                         ) || (
4634                             filter.first.first.value === 'ADSAFE' &&
4635                             filter.first.second.value === 'has' &&
4636                             filter.second[0].value === the_in.second.value &&
4637                             filter.second[1].value === the_in.first.value
4638                         ) || (
4639                             filter.first.first.id === '.' &&
4640                             filter.first.first.first.id === '.' &&
4641                             filter.first.first.first.first.value === 'Object' &&
4642                             filter.first.first.first.second.value === 'prototype' &&
4643                             filter.first.first.second.value === 'hasOwnProperty' &&
4644                             filter.first.second.value === 'call' &&
4645                             filter.second[0].value === the_in.second.value &&
4646                             filter.second[1].value === the_in.first.value
4647                         ));
4648                         break;
4649                     }
4650                 }
4651                 if (!ok) {
4652                     warn(bundle.for_if, this);
4653                 }
4654             }
4655         } else {
4656             if (nexttoken.id !== ';') {
4657                 edge();
4658                 this.first = [];
4659                 for (;;) {
4660                     this.first.push(expression(0, 'for'));
4661                     if (nexttoken.id !== ',') {
4662                         break;
4663                     }
4664                     comma();
4665                 }
4666             }
4667             semicolon();
4668             if (nexttoken.id !== ';') {
4669                 edge();
4670                 this.second = expected_relation(expression(0));
4671                 if (this.second.id !== 'true') {
4672                     expected_condition(this.second, bundle.unexpected_a);
4673                 }
4674             }
4675             semicolon(token);
4676             if (nexttoken.id === ';') {
4677                 fail(bundle.expected_a_b, nexttoken, ')', ';');
4678             }
4679             if (nexttoken.id !== ')') {
4680                 this.third = [];
4681                 edge();
4682                 for (;;) {
4683                     this.third.push(expression(0, 'for'));
4684                     if (nexttoken.id !== ',') {
4685                         break;
4686                     }
4687                     comma();
4688                 }
4689             }
4690             no_space();
4691             step_out(')', paren);
4692             discard();
4693             one_space();
4694             blok = block(true);
4695         }
4696         if (blok.disrupt) {
4697             warn(bundle.strange_loop, prevtoken);
4698         }
4699         this.block = blok;
4700         funct['(breakage)'] -= 1;
4701         funct['(loopage)'] -= 1;
4702         return this;
4703     });
4704
4705
4706     disrupt_stmt('break', function () {
4707         var v = nexttoken.value;
4708         this.arity = 'statement';
4709         if (funct['(breakage)'] === 0) {
4710             warn(bundle.unexpected_a, this);
4711         }
4712         if (nexttoken.identifier && token.line === nexttoken.line) {
4713             one_space_only();
4714             if (funct[v] !== 'label') {
4715                 warn(bundle.not_a_label, nexttoken);
4716             } else if (scope[v] !== funct) {
4717                 warn(bundle.not_a_scope, nexttoken);
4718             }
4719             this.first = nexttoken;
4720             advance();
4721         }
4722         return this;
4723     });
4724
4725
4726     disrupt_stmt('continue', function () {
4727         if (!option['continue']) {
4728             warn(bundle.unexpected_a, this);
4729         }
4730         var v = nexttoken.value;
4731         this.arity = 'statement';
4732         if (funct['(breakage)'] === 0) {
4733             warn(bundle.unexpected_a, this);
4734         }
4735         if (nexttoken.identifier && token.line === nexttoken.line) {
4736             one_space_only();
4737             if (funct[v] !== 'label') {
4738                 warn(bundle.not_a_label, nexttoken);
4739             } else if (scope[v] !== funct) {
4740                 warn(bundle.not_a_scope, nexttoken);
4741             }
4742             this.first = nexttoken;
4743             advance();
4744         }
4745         return this;
4746     });
4747
4748
4749     disrupt_stmt('return', function () {
4750         this.arity = 'statement';
4751         if (nexttoken.id !== ';' && nexttoken.line === token.line) {
4752             one_space_only();
4753             if (nexttoken.id === '/' || nexttoken.id === '(regexp)') {
4754                 warn(bundle.wrap_regexp);
4755             }
4756             this.first = expression(20);
4757         }
4758         return this;
4759     });
4760
4761
4762     disrupt_stmt('throw', function () {
4763         this.arity = 'statement';
4764         one_space_only();
4765         this.first = expression(20);
4766         return this;
4767     });
4768
4769
4770 //  Superfluous reserved words
4771
4772     reserve('class');
4773     reserve('const');
4774     reserve('enum');
4775     reserve('export');
4776     reserve('extends');
4777     reserve('import');
4778     reserve('super');
4779
4780 // Harmony reserved words
4781
4782     reserve('let');
4783     reserve('yield');
4784     reserve('implements');
4785     reserve('interface');
4786     reserve('package');
4787     reserve('private');
4788     reserve('protected');
4789     reserve('public');
4790     reserve('static');
4791
4792
4793 // Parse JSON
4794
4795     function json_value() {
4796
4797         function json_object() {
4798             var o = {}, t = nexttoken;
4799             advance('{');
4800             if (nexttoken.id !== '}') {
4801                 while (nexttoken.id !== '(end)') {
4802                     while (nexttoken.id === ',') {
4803                         warn(bundle.unexpected_a, nexttoken);
4804                         comma();
4805                     }
4806                     if (nexttoken.arity !== 'string') {
4807                         warn(bundle.expected_string_a);
4808                     }
4809                     if (o[nexttoken.value] === true) {
4810                         warn(bundle.duplicate_a);
4811                     } else if (nexttoken.value === '__proto__') {
4812                         warn(bundle.dangling_a);
4813                     } else {
4814                         o[nexttoken.value] = true;
4815                     }
4816                     advance();
4817                     advance(':');
4818                     json_value();
4819                     if (nexttoken.id !== ',') {
4820                         break;
4821                     }
4822                     comma();
4823                     if (nexttoken.id === '}') {
4824                         warn(bundle.unexpected_a, token);
4825                         break;
4826                     }
4827                 }
4828             }
4829             advance('}', t);
4830         }
4831
4832         function json_array() {
4833             var t = nexttoken;
4834             advance('[');
4835             if (nexttoken.id !== ']') {
4836                 while (nexttoken.id !== '(end)') {
4837                     while (nexttoken.id === ',') {
4838                         warn(bundle.unexpected_a, nexttoken);
4839                         comma();
4840                     }
4841                     json_value();
4842                     if (nexttoken.id !== ',') {
4843                         break;
4844                     }
4845                     comma();
4846                     if (nexttoken.id === ']') {
4847                         warn(bundle.unexpected_a, token);
4848                         break;
4849                     }
4850                 }
4851             }
4852             advance(']', t);
4853         }
4854
4855         switch (nexttoken.id) {
4856         case '{':
4857             json_object();
4858             break;
4859         case '[':
4860             json_array();
4861             break;
4862         case 'true':
4863         case 'false':
4864         case 'null':
4865         case '(number)':
4866         case '(string)':
4867             advance();
4868             break;
4869         case '-':
4870             advance('-');
4871             no_space_only();
4872             advance('(number)');
4873             break;
4874         default:
4875             fail(bundle.unexpected_a);
4876         }
4877     }
4878
4879
4880 // CSS parsing.
4881
4882     function css_name() {
4883         if (nexttoken.identifier) {
4884             advance();
4885             return true;
4886         }
4887     }
4888
4889
4890     function css_number() {
4891         if (nexttoken.id === '-') {
4892             advance('-');
4893             no_space_only();
4894         }
4895         if (nexttoken.arity === 'number') {
4896             advance('(number)');
4897             return true;
4898         }
4899     }
4900
4901
4902     function css_string() {
4903         if (nexttoken.arity === 'string') {
4904             advance();
4905             return true;
4906         }
4907     }
4908
4909     function css_color() {
4910         var i, number, t, value;
4911         if (nexttoken.identifier) {
4912             value = nexttoken.value;
4913             if (value === 'rgb' || value === 'rgba') {
4914                 advance();
4915                 t = nexttoken;
4916                 advance('(');
4917                 for (i = 0; i < 3; i += 1) {
4918                     if (i) {
4919                         comma();
4920                     }
4921                     number = nexttoken.value;
4922                     if (nexttoken.arity !== 'number' || number < 0) {
4923                         warn(bundle.expected_positive_a, nexttoken);
4924                         advance();
4925                     } else {
4926                         advance();
4927                         if (nexttoken.id === '%') {
4928                             advance('%');
4929                             if (number > 100) {
4930                                 warn(bundle.expected_percent_a, token, number);
4931                             }
4932                         } else {
4933                             if (number > 255) {
4934                                 warn(bundle.expected_small_a, token, number);
4935                             }
4936                         }
4937                     }
4938                 }
4939                 if (value === 'rgba') {
4940                     comma();
4941                     number = +nexttoken.value;
4942                     if (nexttoken.arity !== 'number' || number < 0 || number > 1) {
4943                         warn(bundle.expected_fraction_a, nexttoken);
4944                     }
4945                     advance();
4946                     if (nexttoken.id === '%') {
4947                         warn(bundle.unexpected_a);
4948                         advance('%');
4949                     }
4950                 }
4951                 advance(')', t);
4952                 return true;
4953             } else if (css_colorData[nexttoken.value] === true) {
4954                 advance();
4955                 return true;
4956             }
4957         } else if (nexttoken.id === '(color)') {
4958             advance();
4959             return true;
4960         }
4961         return false;
4962     }
4963
4964
4965     function css_length() {
4966         if (nexttoken.id === '-') {
4967             advance('-');
4968             no_space_only();
4969         }
4970         if (nexttoken.arity === 'number') {
4971             advance();
4972             if (nexttoken.arity !== 'string' &&
4973                     css_lengthData[nexttoken.value] === true) {
4974                 no_space_only();
4975                 advance();
4976             } else if (+token.value !== 0) {
4977                 warn(bundle.expected_linear_a);
4978             }
4979             return true;
4980         }
4981         return false;
4982     }
4983
4984
4985     function css_line_height() {
4986         if (nexttoken.id === '-') {
4987             advance('-');
4988             no_space_only();
4989         }
4990         if (nexttoken.arity === 'number') {
4991             advance();
4992             if (nexttoken.arity !== 'string' &&
4993                     css_lengthData[nexttoken.value] === true) {
4994                 no_space_only();
4995                 advance();
4996             }
4997             return true;
4998         }
4999         return false;
5000     }
5001
5002
5003     function css_width() {
5004         if (nexttoken.identifier) {
5005             switch (nexttoken.value) {
5006             case 'thin':
5007             case 'medium':
5008             case 'thick':
5009                 advance();
5010                 return true;
5011             }
5012         } else {
5013             return css_length();
5014         }
5015     }
5016
5017
5018     function css_margin() {
5019         if (nexttoken.identifier) {
5020             if (nexttoken.value === 'auto') {
5021                 advance();
5022                 return true;
5023             }
5024         } else {
5025             return css_length();
5026         }
5027     }
5028
5029     function css_attr() {
5030         if (nexttoken.identifier && nexttoken.value === 'attr') {
5031             advance();
5032             advance('(');
5033             if (!nexttoken.identifier) {
5034                 warn(bundle.expected_name_a);
5035             }
5036             advance();
5037             advance(')');
5038             return true;
5039         }
5040         return false;
5041     }
5042
5043
5044     function css_comma_list() {
5045         while (nexttoken.id !== ';') {
5046             if (!css_name() && !css_string()) {
5047                 warn(bundle.expected_name_a);
5048             }
5049             if (nexttoken.id !== ',') {
5050                 return true;
5051             }
5052             comma();
5053         }
5054     }
5055
5056
5057     function css_counter() {
5058         if (nexttoken.identifier && nexttoken.value === 'counter') {
5059             advance();
5060             advance('(');
5061             advance();
5062             if (nexttoken.id === ',') {
5063                 comma();
5064                 if (nexttoken.arity !== 'string') {
5065                     warn(bundle.expected_string_a);
5066                 }
5067                 advance();
5068             }
5069             advance(')');
5070             return true;
5071         }
5072         if (nexttoken.identifier && nexttoken.value === 'counters') {
5073             advance();
5074             advance('(');
5075             if (!nexttoken.identifier) {
5076                 warn(bundle.expected_name_a);
5077             }
5078             advance();
5079             if (nexttoken.id === ',') {
5080                 comma();
5081                 if (nexttoken.arity !== 'string') {
5082                     warn(bundle.expected_string_a);
5083                 }
5084                 advance();
5085             }
5086             if (nexttoken.id === ',') {
5087                 comma();
5088                 if (nexttoken.arity !== 'string') {
5089                     warn(bundle.expected_string_a);
5090                 }
5091                 advance();
5092             }
5093             advance(')');
5094             return true;
5095         }
5096         return false;
5097     }
5098
5099
5100     function css_shape() {
5101         var i;
5102         if (nexttoken.identifier && nexttoken.value === 'rect') {
5103             advance();
5104             advance('(');
5105             for (i = 0; i < 4; i += 1) {
5106                 if (!css_length()) {
5107                     warn(bundle.expected_number_a);
5108                     break;
5109                 }
5110             }
5111             advance(')');
5112             return true;
5113         }
5114         return false;
5115     }
5116
5117
5118     function css_url() {
5119         var c, url;
5120         if (nexttoken.identifier && nexttoken.value === 'url') {
5121             nexttoken = lex.range('(', ')');
5122             url = nexttoken.value;
5123             c = url.charAt(0);
5124             if (c === '"' || c === '\'') {
5125                 if (url.slice(-1) !== c) {
5126                     warn(bundle.bad_url);
5127                 } else {
5128                     url = url.slice(1, -1);
5129                     if (url.indexOf(c) >= 0) {
5130                         warn(bundle.bad_url);
5131                     }
5132                 }
5133             }
5134             if (!url) {
5135                 warn(bundle.missing_url);
5136             }
5137             if (option.safe && ux.test(url)) {
5138                 fail(bundle.adsafe_a, nexttoken, url);
5139             }
5140             urls.push(url);
5141             advance();
5142             return true;
5143         }
5144         return false;
5145     }
5146
5147
5148     css_any = [css_url, function () {
5149         for (;;) {
5150             if (nexttoken.identifier) {
5151                 switch (nexttoken.value.toLowerCase()) {
5152                 case 'url':
5153                     css_url();
5154                     break;
5155                 case 'expression':
5156                     warn(bundle.unexpected_a);
5157                     advance();
5158                     break;
5159                 default:
5160                     advance();
5161                 }
5162             } else {
5163                 if (nexttoken.id === ';' || nexttoken.id === '!'  ||
5164                         nexttoken.id === '(end)' || nexttoken.id === '}') {
5165                     return true;
5166                 }
5167                 advance();
5168             }
5169         }
5170     }];
5171
5172
5173     css_border_style = [
5174         'none', 'dashed', 'dotted', 'double', 'groove',
5175         'hidden', 'inset', 'outset', 'ridge', 'solid'
5176     ];
5177
5178     css_break = [
5179         'auto', 'always', 'avoid', 'left', 'right'
5180     ];
5181
5182     css_media = {
5183         'all': true,
5184         'braille': true,
5185         'embossed': true,
5186         'handheld': true,
5187         'print': true,
5188         'projection': true,
5189         'screen': true,
5190         'speech': true,
5191         'tty': true,
5192         'tv': true
5193     };
5194
5195     css_overflow = [
5196         'auto', 'hidden', 'scroll', 'visible'
5197     ];
5198
5199     css_attribute_data = {
5200         background: [
5201             true, 'background-attachment', 'background-color',
5202             'background-image', 'background-position', 'background-repeat'
5203         ],
5204         'background-attachment': ['scroll', 'fixed'],
5205         'background-color': ['transparent', css_color],
5206         'background-image': ['none', css_url],
5207         'background-position': [
5208             2, [css_length, 'top', 'bottom', 'left', 'right', 'center']
5209         ],
5210         'background-repeat': [
5211             'repeat', 'repeat-x', 'repeat-y', 'no-repeat'
5212         ],
5213         'border': [true, 'border-color', 'border-style', 'border-width'],
5214         'border-bottom': [
5215             true, 'border-bottom-color', 'border-bottom-style',
5216             'border-bottom-width'
5217         ],
5218         'border-bottom-color': css_color,
5219         'border-bottom-style': css_border_style,
5220         'border-bottom-width': css_width,
5221         'border-collapse': ['collapse', 'separate'],
5222         'border-color': ['transparent', 4, css_color],
5223         'border-left': [
5224             true, 'border-left-color', 'border-left-style', 'border-left-width'
5225         ],
5226         'border-left-color': css_color,
5227         'border-left-style': css_border_style,
5228         'border-left-width': css_width,
5229         'border-right': [
5230             true, 'border-right-color', 'border-right-style',
5231             'border-right-width'
5232         ],
5233         'border-right-color': css_color,
5234         'border-right-style': css_border_style,
5235         'border-right-width': css_width,
5236         'border-spacing': [2, css_length],
5237         'border-style': [4, css_border_style],
5238         'border-top': [
5239             true, 'border-top-color', 'border-top-style', 'border-top-width'
5240         ],
5241         'border-top-color': css_color,
5242         'border-top-style': css_border_style,
5243         'border-top-width': css_width,
5244         'border-width': [4, css_width],
5245         bottom: [css_length, 'auto'],
5246         'caption-side' : ['bottom', 'left', 'right', 'top'],
5247         clear: ['both', 'left', 'none', 'right'],
5248         clip: [css_shape, 'auto'],
5249         color: css_color,
5250         content: [
5251             'open-quote', 'close-quote', 'no-open-quote', 'no-close-quote',
5252             css_string, css_url, css_counter, css_attr
5253         ],
5254         'counter-increment': [
5255             css_name, 'none'
5256         ],
5257         'counter-reset': [
5258             css_name, 'none'
5259         ],
5260         cursor: [
5261             css_url, 'auto', 'crosshair', 'default', 'e-resize', 'help', 'move',
5262             'n-resize', 'ne-resize', 'nw-resize', 'pointer', 's-resize',
5263             'se-resize', 'sw-resize', 'w-resize', 'text', 'wait'
5264         ],
5265         direction: ['ltr', 'rtl'],
5266         display: [
5267             'block', 'compact', 'inline', 'inline-block', 'inline-table',
5268             'list-item', 'marker', 'none', 'run-in', 'table', 'table-caption',
5269             'table-cell', 'table-column', 'table-column-group',
5270             'table-footer-group', 'table-header-group', 'table-row',
5271             'table-row-group'
5272         ],
5273         'empty-cells': ['show', 'hide'],
5274         'float': ['left', 'none', 'right'],
5275         font: [
5276             'caption', 'icon', 'menu', 'message-box', 'small-caption',
5277             'status-bar', true, 'font-size', 'font-style', 'font-weight',
5278             'font-family'
5279         ],
5280         'font-family': css_comma_list,
5281         'font-size': [
5282             'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large',
5283             'xx-large', 'larger', 'smaller', css_length
5284         ],
5285         'font-size-adjust': ['none', css_number],
5286         'font-stretch': [
5287             'normal', 'wider', 'narrower', 'ultra-condensed',
5288             'extra-condensed', 'condensed', 'semi-condensed',
5289             'semi-expanded', 'expanded', 'extra-expanded'
5290         ],
5291         'font-style': [
5292             'normal', 'italic', 'oblique'
5293         ],
5294         'font-variant': [
5295             'normal', 'small-caps'
5296         ],
5297         'font-weight': [
5298             'normal', 'bold', 'bolder', 'lighter', css_number
5299         ],
5300         height: [css_length, 'auto'],
5301         left: [css_length, 'auto'],
5302         'letter-spacing': ['normal', css_length],
5303         'line-height': ['normal', css_line_height],
5304         'list-style': [
5305             true, 'list-style-image', 'list-style-position', 'list-style-type'
5306         ],
5307         'list-style-image': ['none', css_url],
5308         'list-style-position': ['inside', 'outside'],
5309         'list-style-type': [
5310             'circle', 'disc', 'square', 'decimal', 'decimal-leading-zero',
5311             'lower-roman', 'upper-roman', 'lower-greek', 'lower-alpha',
5312             'lower-latin', 'upper-alpha', 'upper-latin', 'hebrew', 'katakana',
5313             'hiragana-iroha', 'katakana-oroha', 'none'
5314         ],
5315         margin: [4, css_margin],
5316         'margin-bottom': css_margin,
5317         'margin-left': css_margin,
5318         'margin-right': css_margin,
5319         'margin-top': css_margin,
5320         'marker-offset': [css_length, 'auto'],
5321         'max-height': [css_length, 'none'],
5322         'max-width': [css_length, 'none'],
5323         'min-height': css_length,
5324         'min-width': css_length,
5325         opacity: css_number,
5326         outline: [true, 'outline-color', 'outline-style', 'outline-width'],
5327         'outline-color': ['invert', css_color],
5328         'outline-style': [
5329             'dashed', 'dotted', 'double', 'groove', 'inset', 'none',
5330             'outset', 'ridge', 'solid'
5331         ],
5332         'outline-width': css_width,
5333         overflow: css_overflow,
5334         'overflow-x': css_overflow,
5335         'overflow-y': css_overflow,
5336         padding: [4, css_length],
5337         'padding-bottom': css_length,
5338         'padding-left': css_length,
5339         'padding-right': css_length,
5340         'padding-top': css_length,
5341         'page-break-after': css_break,
5342         'page-break-before': css_break,
5343         position: ['absolute', 'fixed', 'relative', 'static'],
5344         quotes: [8, css_string],
5345         right: [css_length, 'auto'],
5346         'table-layout': ['auto', 'fixed'],
5347         'text-align': ['center', 'justify', 'left', 'right'],
5348         'text-decoration': [
5349             'none', 'underline', 'overline', 'line-through', 'blink'
5350         ],
5351         'text-indent': css_length,
5352         'text-shadow': ['none', 4, [css_color, css_length]],
5353         'text-transform': ['capitalize', 'uppercase', 'lowercase', 'none'],
5354         top: [css_length, 'auto'],
5355         'unicode-bidi': ['normal', 'embed', 'bidi-override'],
5356         'vertical-align': [
5357             'baseline', 'bottom', 'sub', 'super', 'top', 'text-top', 'middle',
5358             'text-bottom', css_length
5359         ],
5360         visibility: ['visible', 'hidden', 'collapse'],
5361         'white-space': [
5362             'normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'inherit'
5363         ],
5364         width: [css_length, 'auto'],
5365         'word-spacing': ['normal', css_length],
5366         'word-wrap': ['break-word', 'normal'],
5367         'z-index': ['auto', css_number]
5368     };
5369
5370     function style_attribute() {
5371         var v;
5372         while (nexttoken.id === '*' || nexttoken.id === '#' ||
5373                 nexttoken.value === '_') {
5374             if (!option.css) {
5375                 warn(bundle.unexpected_a);
5376             }
5377             advance();
5378         }
5379         if (nexttoken.id === '-') {
5380             if (!option.css) {
5381                 warn(bundle.unexpected_a);
5382             }
5383             advance('-');
5384             if (!nexttoken.identifier) {
5385                 warn(bundle.expected_nonstandard_style_attribute);
5386             }
5387             advance();
5388             return css_any;
5389         } else {
5390             if (!nexttoken.identifier) {
5391                 warn(bundle.expected_style_attribute);
5392             } else {
5393                 if (Object.prototype.hasOwnProperty.call(css_attribute_data, nexttoken.value)) {
5394                     v = css_attribute_data[nexttoken.value];
5395                 } else {
5396                     v = css_any;
5397                     if (!option.css) {
5398                         warn(bundle.unrecognized_style_attribute_a);
5399                     }
5400                 }
5401             }
5402             advance();
5403             return v;
5404         }
5405     }
5406
5407
5408     function style_value(v) {
5409         var i = 0,
5410             n,
5411             once,
5412             match,
5413             round,
5414             start = 0,
5415             vi;
5416         switch (typeof v) {
5417         case 'function':
5418             return v();
5419         case 'string':
5420             if (nexttoken.identifier && nexttoken.value === v) {
5421                 advance();
5422                 return true;
5423             }
5424             return false;
5425         }
5426         for (;;) {
5427             if (i >= v.length) {
5428                 return false;
5429             }
5430             vi = v[i];
5431             i += 1;
5432             if (vi === true) {
5433                 break;
5434             } else if (typeof vi === 'number') {
5435                 n = vi;
5436                 vi = v[i];
5437                 i += 1;
5438             } else {
5439                 n = 1;
5440             }
5441             match = false;
5442             while (n > 0) {
5443                 if (style_value(vi)) {
5444                     match = true;
5445                     n -= 1;
5446                 } else {
5447                     break;
5448                 }
5449             }
5450             if (match) {
5451                 return true;
5452             }
5453         }
5454         start = i;
5455         once = [];
5456         for (;;) {
5457             round = false;
5458             for (i = start; i < v.length; i += 1) {
5459                 if (!once[i]) {
5460                     if (style_value(css_attribute_data[v[i]])) {
5461                         match = true;
5462                         round = true;
5463                         once[i] = true;
5464                         break;
5465                     }
5466                 }
5467             }
5468             if (!round) {
5469                 return match;
5470             }
5471         }
5472     }
5473
5474     function style_child() {
5475         if (nexttoken.arity === 'number') {
5476             advance();
5477             if (nexttoken.value === 'n' && nexttoken.identifier) {
5478                 no_space_only();
5479                 advance();
5480                 if (nexttoken.id === '+') {
5481                     no_space_only();
5482                     advance('+');
5483                     no_space_only();
5484                     advance('(number)');
5485                 }
5486             }
5487             return;
5488         } else {
5489             if (nexttoken.identifier &&
5490                     (nexttoken.value === 'odd' || nexttoken.value === 'even')) {
5491                 advance();
5492                 return;
5493             }
5494         }
5495         warn(bundle.unexpected_a);
5496     }
5497
5498     function substyle() {
5499         var v;
5500         for (;;) {
5501             if (nexttoken.id === '}' || nexttoken.id === '(end)' ||
5502                     (xquote && nexttoken.id === xquote)) {
5503                 return;
5504             }
5505             while (nexttoken.id === ';') {
5506                 warn(bundle.unexpected_a);
5507                 semicolon();
5508             }
5509             v = style_attribute();
5510             advance(':');
5511             if (nexttoken.identifier && nexttoken.value === 'inherit') {
5512                 advance();
5513             } else {
5514                 if (!style_value(v)) {
5515                     warn(bundle.unexpected_a);
5516                     advance();
5517                 }
5518             }
5519             if (nexttoken.id === '!') {
5520                 advance('!');
5521                 no_space_only();
5522                 if (nexttoken.identifier && nexttoken.value === 'important') {
5523                     advance();
5524                 } else {
5525                     warn(bundle.expected_a_b,
5526                         nexttoken, 'important', nexttoken.value);
5527                 }
5528             }
5529             if (nexttoken.id === '}' || nexttoken.id === xquote) {
5530                 warn(bundle.expected_a_b, nexttoken, ';', nexttoken.value);
5531             } else {
5532                 semicolon();
5533             }
5534         }
5535     }
5536
5537     function style_selector() {
5538         if (nexttoken.identifier) {
5539             if (!Object.prototype.hasOwnProperty.call(html_tag, option.cap ?
5540                     nexttoken.value.toLowerCase() : nexttoken.value)) {
5541                 warn(bundle.expected_tagname_a);
5542             }
5543             advance();
5544         } else {
5545             switch (nexttoken.id) {
5546             case '>':
5547             case '+':
5548                 advance();
5549                 style_selector();
5550                 break;
5551             case ':':
5552                 advance(':');
5553                 switch (nexttoken.value) {
5554                 case 'active':
5555                 case 'after':
5556                 case 'before':
5557                 case 'checked':
5558                 case 'disabled':
5559                 case 'empty':
5560                 case 'enabled':
5561                 case 'first-child':
5562                 case 'first-letter':
5563                 case 'first-line':
5564                 case 'first-of-type':
5565                 case 'focus':
5566                 case 'hover':
5567                 case 'last-child':
5568                 case 'last-of-type':
5569                 case 'link':
5570                 case 'only-of-type':
5571                 case 'root':
5572                 case 'target':
5573                 case 'visited':
5574                     advance();
5575                     break;
5576                 case 'lang':
5577                     advance();
5578                     advance('(');
5579                     if (!nexttoken.identifier) {
5580                         warn(bundle.expected_lang_a);
5581                     }
5582                     advance(')');
5583                     break;
5584                 case 'nth-child':
5585                 case 'nth-last-child':
5586                 case 'nth-last-of-type':
5587                 case 'nth-of-type':
5588                     advance();
5589                     advance('(');
5590                     style_child();
5591                     advance(')');
5592                     break;
5593                 case 'not':
5594                     advance();
5595                     advance('(');
5596                     if (nexttoken.id === ':' && peek(0).value === 'not') {
5597                         warn(bundle.not);
5598                     }
5599                     style_selector();
5600                     advance(')');
5601                     break;
5602                 default:
5603                     warn(bundle.expected_pseudo_a);
5604                 }
5605                 break;
5606             case '#':
5607                 advance('#');
5608                 if (!nexttoken.identifier) {
5609                     warn(bundle.expected_id_a);
5610                 }
5611                 advance();
5612                 break;
5613             case '*':
5614                 advance('*');
5615                 break;
5616             case '.':
5617                 advance('.');
5618                 if (!nexttoken.identifier) {
5619                     warn(bundle.expected_class_a);
5620                 }
5621                 advance();
5622                 break;
5623             case '[':
5624                 advance('[');
5625                 if (!nexttoken.identifier) {
5626                     warn(bundle.expected_attribute_a);
5627                 }
5628                 advance();
5629                 if (nexttoken.id === '=' || nexttoken.value === '~=' ||
5630                         nexttoken.value === '$=' ||
5631                         nexttoken.value === '|=' ||
5632                         nexttoken.id === '*=' ||
5633                         nexttoken.id === '^=') {
5634                     advance();
5635                     if (nexttoken.arity !== 'string') {
5636                         warn(bundle.expected_string_a);
5637                     }
5638                     advance();
5639                 }
5640                 advance(']');
5641                 break;
5642             default:
5643                 fail(bundle.expected_selector_a);
5644             }
5645         }
5646     }
5647
5648     function style_pattern() {
5649         if (nexttoken.id === '{') {
5650             warn(bundle.expected_style_pattern);
5651         }
5652         for (;;) {
5653             style_selector();
5654             if (nexttoken.id === '</' || nexttoken.id === '{' ||
5655                     nexttoken.id === '(end)') {
5656                 return '';
5657             }
5658             if (nexttoken.id === ',') {
5659                 comma();
5660             }
5661         }
5662     }
5663
5664     function style_list() {
5665         while (nexttoken.id !== '</' && nexttoken.id !== '(end)') {
5666             style_pattern();
5667             xmode = 'styleproperty';
5668             if (nexttoken.id === ';') {
5669                 semicolon();
5670             } else {
5671                 advance('{');
5672                 substyle();
5673                 xmode = 'style';
5674                 advance('}');
5675             }
5676         }
5677     }
5678
5679     function styles() {
5680         var i;
5681         while (nexttoken.id === '@') {
5682             i = peek();
5683             advance('@');
5684             if (nexttoken.identifier) {
5685                 switch (nexttoken.value) {
5686                 case 'import':
5687                     advance();
5688                     if (!css_url()) {
5689                         warn(bundle.expected_a_b,
5690                             nexttoken, 'url', nexttoken.value);
5691                         advance();
5692                     }
5693                     semicolon();
5694                     break;
5695                 case 'media':
5696                     advance();
5697                     for (;;) {
5698                         if (!nexttoken.identifier || css_media[nexttoken.value] === true) {
5699                             fail(bundle.expected_media_a);
5700                         }
5701                         advance();
5702                         if (nexttoken.id !== ',') {
5703                             break;
5704                         }
5705                         comma();
5706                     }
5707                     advance('{');
5708                     style_list();
5709                     advance('}');
5710                     break;
5711                 default:
5712                     warn(bundle.expected_at_a);
5713                 }
5714             } else {
5715                 warn(bundle.expected_at_a);
5716             }
5717         }
5718         style_list();
5719     }
5720
5721
5722 // Parse HTML
5723
5724     function do_begin(n) {
5725         if (n !== 'html' && !option.fragment) {
5726             if (n === 'div' && option.adsafe) {
5727                 fail(bundle.adsafe_fragment);
5728             } else {
5729                 fail(bundle.expected_a_b, token, 'html', n);
5730             }
5731         }
5732         if (option.adsafe) {
5733             if (n === 'html') {
5734                 fail(bundle.adsafe_html, token);
5735             }
5736             if (option.fragment) {
5737                 if (n !== 'div') {
5738                     fail(bundle.adsafe_div, token);
5739                 }
5740             } else {
5741                 fail(bundle.adsafe_fragment, token);
5742             }
5743         }
5744         option.browser = true;
5745         assume();
5746     }
5747
5748     function do_attribute(n, a, v) {
5749         var u, x;
5750         if (a === 'id') {
5751             u = typeof v === 'string' ? v.toUpperCase() : '';
5752             if (ids[u] === true) {
5753                 warn(bundle.duplicate_a, nexttoken, v);
5754             }
5755             if (!/^[A-Za-z][A-Za-z0-9._:\-]*$/.test(v)) {
5756                 warn(bundle.bad_id_a, nexttoken, v);
5757             } else if (option.adsafe) {
5758                 if (adsafe_id) {
5759                     if (v.slice(0, adsafe_id.length) !== adsafe_id) {
5760                         warn(bundle.adsafe_prefix_a, nexttoken, adsafe_id);
5761                     } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {
5762                         warn(bundle.adsafe_bad_id);
5763                     }
5764                 } else {
5765                     adsafe_id = v;
5766                     if (!/^[A-Z]+_$/.test(v)) {
5767                         warn(bundle.adsafe_bad_id);
5768                     }
5769                 }
5770             }
5771             x = v.search(dx);
5772             if (x >= 0) {
5773                 warn(bundle.unexpected_char_a_b, token, v.charAt(x), a);
5774             }
5775             ids[u] = true;
5776         } else if (a === 'class' || a === 'type' || a === 'name') {
5777             x = v.search(qx);
5778             if (x >= 0) {
5779                 warn(bundle.unexpected_char_a_b, token, v.charAt(x), a);
5780             }
5781             ids[u] = true;
5782         } else if (a === 'href' || a === 'background' ||
5783                 a === 'content' || a === 'data' ||
5784                 a.indexOf('src') >= 0 || a.indexOf('url') >= 0) {
5785             if (option.safe && ux.test(v)) {
5786                 fail(bundle.bad_url, nexttoken, v);
5787             }
5788             urls.push(v);
5789         } else if (a === 'for') {
5790             if (option.adsafe) {
5791                 if (adsafe_id) {
5792                     if (v.slice(0, adsafe_id.length) !== adsafe_id) {
5793                         warn(bundle.adsafe_prefix_a, nexttoken, adsafe_id);
5794                     } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {
5795                         warn(bundle.adsafe_bad_id);
5796                     }
5797                 } else {
5798                     warn(bundle.adsafe_bad_id);
5799                 }
5800             }
5801         } else if (a === 'name') {
5802             if (option.adsafe && v.indexOf('_') >= 0) {
5803                 warn(bundle.adsafe_name_a, nexttoken, v);
5804             }
5805         }
5806     }
5807
5808     function do_tag(n, a) {
5809         var i, t = html_tag[n], script, x;
5810         src = false;
5811         if (!t) {
5812             fail(
5813                 bundle.unrecognized_tag_a,
5814                 nexttoken,
5815                 n === n.toLowerCase() ? n : n + ' (capitalization error)'
5816             );
5817         }
5818         if (stack.length > 0) {
5819             if (n === 'html') {
5820                 fail(bundle.unexpected_a, token, n);
5821             }
5822             x = t.parent;
5823             if (x) {
5824                 if (x.indexOf(' ' + stack[stack.length - 1].name + ' ') < 0) {
5825                     fail(bundle.tag_a_in_b, token, n, x);
5826                 }
5827             } else if (!option.adsafe && !option.fragment) {
5828                 i = stack.length;
5829                 do {
5830                     if (i <= 0) {
5831                         fail(bundle.tag_a_in_b, token, n, 'body');
5832                     }
5833                     i -= 1;
5834                 } while (stack[i].name !== 'body');
5835             }
5836         }
5837         switch (n) {
5838         case 'div':
5839             if (option.adsafe && stack.length === 1 && !adsafe_id) {
5840                 warn(bundle.adsafe_missing_id);
5841             }
5842             break;
5843         case 'script':
5844             xmode = 'script';
5845             advance('>');
5846             if (a.lang) {
5847                 warn(bundle.lang, token);
5848             }
5849             if (option.adsafe && stack.length !== 1) {
5850                 warn(bundle.adsafe_placement, token);
5851             }
5852             if (a.src) {
5853                 if (option.adsafe && (!adsafe_may || !approved[a.src])) {
5854                     warn(bundle.adsafe_source, token);
5855                 }
5856                 if (a.type) {
5857                     warn(bundle.type, token);
5858                 }
5859             } else {
5860                 step_in(nexttoken.from);
5861                 edge();
5862                 use_strict();
5863                 adsafe_top = true;
5864                 script = statements();
5865
5866 // JSLint is also the static analyzer for ADsafe. See www.ADsafe.org.
5867
5868                 if (option.adsafe) {
5869                     if (adsafe_went) {
5870                         fail(bundle.adsafe_script, token);
5871                     }
5872                     if (script.length !== 1 ||
5873                             aint(script[0],             'id',    '(') ||
5874                             aint(script[0].first,       'id',    '.') ||
5875                             aint(script[0].first.first, 'value', 'ADSAFE') ||
5876                             aint(script[0].second[0],   'value', adsafe_id)) {
5877                         fail(bundle.adsafe_id_go);
5878                     }
5879                     switch (script[0].first.second.value) {
5880                     case 'id':
5881                         if (adsafe_may || script[0].second.length !== 1) {
5882                             fail(bundle.adsafe_id, nexttoken);
5883                         }
5884                         adsafe_may = true;
5885                         break;
5886                     case 'go':
5887                         if (!adsafe_may) {
5888                             fail(bundle.adsafe_id);
5889                         }
5890                         if (script[0].second.length !== 2 ||
5891                                 aint(script[0].second[1], 'id', 'function') ||
5892                                 script[0].second[1].first.length !== 2 ||
5893                                 aint(script[0].second[1].first[0], 'value', 'dom') ||
5894                                 aint(script[0].second[1].first[1], 'value', 'lib')) {
5895                             fail(bundle.adsafe_go, nexttoken);
5896                         }
5897                         adsafe_went = true;
5898                         break;
5899                     default:
5900                         fail(bundle.adsafe_id_go);
5901                     }
5902                 }
5903                 indent = null;
5904             }
5905             xmode = 'html';
5906             advance('</');
5907             if (!nexttoken.identifier && nexttoken.value !== 'script') {
5908                 warn(bundle.expected_a_b, nexttoken, 'script', nexttoken.value);
5909             }
5910             advance();
5911             xmode = 'outer';
5912             break;
5913         case 'style':
5914             xmode = 'style';
5915             advance('>');
5916             styles();
5917             xmode = 'html';
5918             advance('</');
5919             if (!nexttoken.identifier && nexttoken.value !== 'style') {
5920                 warn(bundle.expected_a_b, nexttoken, 'style', nexttoken.value);
5921             }
5922             advance();
5923             xmode = 'outer';
5924             break;
5925         case 'input':
5926             switch (a.type) {
5927             case 'radio':
5928             case 'checkbox':
5929             case 'button':
5930             case 'reset':
5931             case 'submit':
5932                 break;
5933             case 'text':
5934             case 'file':
5935             case 'password':
5936             case 'file':
5937             case 'hidden':
5938             case 'image':
5939                 if (option.adsafe && a.autocomplete !== 'off') {
5940                     warn(bundle.adsafe_autocomplete);
5941                 }
5942                 break;
5943             default:
5944                 warn(bundle.bad_type);
5945             }
5946             break;
5947         case 'applet':
5948         case 'body':
5949         case 'embed':
5950         case 'frame':
5951         case 'frameset':
5952         case 'head':
5953         case 'iframe':
5954         case 'noembed':
5955         case 'noframes':
5956         case 'object':
5957         case 'param':
5958             if (option.adsafe) {
5959                 warn(bundle.adsafe_tag, nexttoken, n);
5960             }
5961             break;
5962         }
5963     }
5964
5965
5966     function closetag(n) {
5967         return '</' + n + '>';
5968     }
5969
5970     function html() {
5971         var a, attributes, e, n, q, t, v, w = option.white, wmode;
5972         xmode = 'html';
5973         xquote = '';
5974         stack = null;
5975         for (;;) {
5976             switch (nexttoken.value) {
5977             case '<':
5978                 xmode = 'html';
5979                 advance('<');
5980                 attributes = {};
5981                 t = nexttoken;
5982                 if (!t.identifier) {
5983                     warn(bundle.bad_name_a, t);
5984                 }
5985                 n = t.value;
5986                 if (option.cap) {
5987                     n = n.toLowerCase();
5988                 }
5989                 t.name = n;
5990                 advance();
5991                 if (!stack) {
5992                     stack = [];
5993                     do_begin(n);
5994                 }
5995                 v = html_tag[n];
5996                 if (typeof v !== 'object') {
5997                     fail(bundle.unrecognized_tag_a, t, n);
5998                 }
5999                 e = v.empty;
6000                 t.type = n;
6001                 for (;;) {
6002                     if (nexttoken.id === '/') {
6003                         advance('/');
6004                         if (nexttoken.id !== '>') {
6005                             warn(bundle.expected_a_b, nexttoken, '>', nexttoken.value);
6006                         }
6007                         break;
6008                     }
6009                     if (nexttoken.id && nexttoken.id.substr(0, 1) === '>') {
6010                         break;
6011                     }
6012                     if (!nexttoken.identifier) {
6013                         if (nexttoken.id === '(end)' || nexttoken.id === '(error)') {
6014                             warn(bundle.expected_a_b, nexttoken, '>', nexttoken.value);
6015                         }
6016                         warn(bundle.bad_name_a);
6017                     }
6018                     option.white = true;
6019                     spaces();
6020                     a = nexttoken.value;
6021                     option.white = w;
6022                     advance();
6023                     if (!option.cap && a !== a.toLowerCase()) {
6024                         warn(bundle.attribute_case_a, token);
6025                     }
6026                     a = a.toLowerCase();
6027                     xquote = '';
6028                     if (Object.prototype.hasOwnProperty.call(attributes, a)) {
6029                         warn(bundle.duplicate_a, token, a);
6030                     }
6031                     if (a.slice(0, 2) === 'on') {
6032                         if (!option.on) {
6033                             warn(bundle.html_handlers);
6034                         }
6035                         xmode = 'scriptstring';
6036                         advance('=');
6037                         q = nexttoken.id;
6038                         if (q !== '"' && q !== '\'') {
6039                             fail(bundle.expected_a_b, nexttoken, '"', nexttoken.value);
6040                         }
6041                         xquote = q;
6042                         wmode = option.white;
6043                         option.white = false;
6044                         advance(q);
6045                         use_strict();
6046                         statements();
6047                         option.white = wmode;
6048                         if (nexttoken.id !== q) {
6049                             fail(bundle.expected_a_b, nexttoken, q, nexttoken.value);
6050                         }
6051                         xmode = 'html';
6052                         xquote = '';
6053                         advance(q);
6054                         v = false;
6055                     } else if (a === 'style') {
6056                         xmode = 'scriptstring';
6057                         advance('=');
6058                         q = nexttoken.id;
6059                         if (q !== '"' && q !== '\'') {
6060                             fail(bundle.expected_a_b, nexttoken, '"', nexttoken.value);
6061                         }
6062                         xmode = 'styleproperty';
6063                         xquote = q;
6064                         advance(q);
6065                         substyle();
6066                         xmode = 'html';
6067                         xquote = '';
6068                         advance(q);
6069                         v = false;
6070                     } else {
6071                         if (nexttoken.id === '=') {
6072                             advance('=');
6073                             v = nexttoken.value;
6074                             if (!nexttoken.identifier &&
6075                                     nexttoken.id !== '"' &&
6076                                     nexttoken.id !== '\'' &&
6077                                     nexttoken.arity !== 'string' &&
6078                                     nexttoken.arity !== 'number' &&
6079                                     nexttoken.id !== '(color)') {
6080                                 warn(bundle.expected_attribute_value_a, token, a);
6081                             }
6082                             advance();
6083                         } else {
6084                             v = true;
6085                         }
6086                     }
6087                     attributes[a] = v;
6088                     do_attribute(n, a, v);
6089                 }
6090                 do_tag(n, attributes);
6091                 if (!e) {
6092                     stack.push(t);
6093                 }
6094                 xmode = 'outer';
6095                 advance('>');
6096                 break;
6097             case '</':
6098                 xmode = 'html';
6099                 advance('</');
6100                 if (!nexttoken.identifier) {
6101                     warn(bundle.bad_name_a);
6102                 }
6103                 n = nexttoken.value;
6104                 if (option.cap) {
6105                     n = n.toLowerCase();
6106                 }
6107                 advance();
6108                 if (!stack) {
6109                     fail(bundle.unexpected_a, nexttoken, closetag(n));
6110                 }
6111                 t = stack.pop();
6112                 if (!t) {
6113                     fail(bundle.unexpected_a, nexttoken, closetag(n));
6114                 }
6115                 if (t.name !== n) {
6116                     fail(bundle.expected_a_b,
6117                         nexttoken, closetag(t.name), closetag(n));
6118                 }
6119                 if (nexttoken.id !== '>') {
6120                     fail(bundle.expected_a_b, nexttoken, '>', nexttoken.value);
6121                 }
6122                 xmode = 'outer';
6123                 advance('>');
6124                 break;
6125             case '<!':
6126                 if (option.safe) {
6127                     warn(bundle.adsafe_a);
6128                 }
6129                 xmode = 'html';
6130                 for (;;) {
6131                     advance();
6132                     if (nexttoken.id === '>' || nexttoken.id === '(end)') {
6133                         break;
6134                     }
6135                     if (nexttoken.value.indexOf('--') >= 0) {
6136                         fail(bundle.unexpected_a, nexttoken, '--');
6137                     }
6138                     if (nexttoken.value.indexOf('<') >= 0) {
6139                         fail(bundle.unexpected_a, nexttoken, '<');
6140                     }
6141                     if (nexttoken.value.indexOf('>') >= 0) {
6142                         fail(bundle.unexpected_a, nexttoken, '>');
6143                     }
6144                 }
6145                 xmode = 'outer';
6146                 advance('>');
6147                 break;
6148             case '(end)':
6149                 return;
6150             default:
6151                 if (nexttoken.id === '(end)') {
6152                     fail(bundle.missing_a, nexttoken,
6153                         '</' + stack[stack.length - 1].value + '>');
6154                 } else {
6155                     advance();
6156                 }
6157             }
6158             if (stack && stack.length === 0 && (option.adsafe ||
6159                     !option.fragment || nexttoken.id === '(end)')) {
6160                 break;
6161             }
6162         }
6163         if (nexttoken.id !== '(end)') {
6164             fail(bundle.unexpected_a);
6165         }
6166     }
6167
6168
6169 // The actual JSLINT function itself.
6170
6171     var itself = function (the_source, the_option) {
6172         var i, keys, predef;
6173         JSLINT.errors = [];
6174         JSLINT.tree = '';
6175         predefined = Object.create(standard);
6176         if (the_option) {
6177             option = Object.create(the_option);
6178             predef = option.predef;
6179             if (predef) {
6180                 if (Array.isArray(predef)) {
6181                     for (i = 0; i < predef.length; i += 1) {
6182                         predefined[predef[i]] = true;
6183                     }
6184                 } else if (typeof predef === 'object') {
6185                     keys = Object.keys(predef);
6186                     for (i = 0; i < keys.length; i += 1) {
6187                         predefined[keys[i]] = !!predef[keys];
6188                     }
6189                 }
6190             }
6191             if (option.adsafe) {
6192                 option.safe = true;
6193             }
6194             if (option.safe) {
6195                 option.browser     =
6196                     option['continue'] =
6197                     option.css     =
6198                     option.debug   =
6199                     option.devel   =
6200                     option.evil    =
6201                     option.forin   =
6202                     option.on      =
6203                     option.rhino   =
6204                     option.sub     =
6205                     option.widget  =
6206                     option.windows = false;
6207
6208                 option.nomen       =
6209                     option.strict  =
6210                     option.undef   = true;
6211
6212                 predefined.Date         =
6213                     predefined['eval']  =
6214                     predefined.Function =
6215                     predefined.Object   = null;
6216
6217                 predefined.ADSAFE  =
6218                     predefined.lib = false;
6219             }
6220         } else {
6221             option = {};
6222         }
6223         option.indent = +option.indent || 0;
6224         option.maxerr = option.maxerr || 50;
6225         adsafe_id = '';
6226         adsafe_may = adsafe_top = adsafe_went = false;
6227         approved = {};
6228         if (option.approved) {
6229             for (i = 0; i < option.approved.length; i += 1) {
6230                 approved[option.approved[i]] = option.approved[i];
6231             }
6232         } else {
6233             approved.test = 'test';
6234         }
6235         tab = '';
6236         for (i = 0; i < option.indent; i += 1) {
6237             tab += ' ';
6238         }
6239         global = Object.create(predefined);
6240         scope = global;
6241         funct = {
6242             '(global)': true,
6243             '(name)': '(global)',
6244             '(scope)': scope,
6245             '(breakage)': 0,
6246             '(loopage)': 0
6247         };
6248         functions = [funct];
6249
6250         comments_off = false;
6251         ids = {};
6252         implied = {};
6253         in_block = false;
6254         indent = false;
6255         json_mode = false;
6256         lookahead = [];
6257         member = {};
6258         properties = null;
6259         prereg = true;
6260         src = false;
6261         stack = null;
6262         strict_mode = false;
6263         urls = [];
6264         var_mode = false;
6265         warnings = 0;
6266         xmode = false;
6267         lex.init(the_source);
6268
6269         prevtoken = token = nexttoken = syntax['(begin)'];
6270         assume();
6271
6272         try {
6273             advance();
6274             if (nexttoken.arity === 'number') {
6275                 fail(bundle.unexpected_a);
6276             } else if (nexttoken.value.charAt(0) === '<') {
6277                 html();
6278                 if (option.adsafe && !adsafe_went) {
6279                     warn(bundle.adsafe_go, this);
6280                 }
6281             } else {
6282                 switch (nexttoken.id) {
6283                 case '{':
6284                 case '[':
6285                     json_mode = true;
6286                     json_value();
6287                     break;
6288                 case '@':
6289                 case '*':
6290                 case '#':
6291                 case '.':
6292                 case ':':
6293                     xmode = 'style';
6294                     advance();
6295                     if (token.id !== '@' || !nexttoken.identifier ||
6296                             nexttoken.value !== 'charset' || token.line !== 1 ||
6297                             token.from !== 1) {
6298                         fail(bundle.css);
6299                     }
6300                     advance();
6301                     if (nexttoken.arity !== 'string' &&
6302                             nexttoken.value !== 'UTF-8') {
6303                         fail(bundle.css);
6304                     }
6305                     advance();
6306                     semicolon();
6307                     styles();
6308                     break;
6309
6310                 default:
6311                     if (option.adsafe && option.fragment) {
6312                         fail(bundle.expected_a_b,
6313                             nexttoken, '<div>', nexttoken.value);
6314                     }
6315
6316 // If the first token is predef semicolon, ignore it. This is sometimes used when
6317 // files are intended to be appended to files that may be sloppy. predef sloppy
6318 // file may be depending on semicolon insertion on its last line.
6319
6320                     step_in(1);
6321                     if (nexttoken.id === ';') {
6322                         semicolon();
6323                     }
6324                     if (nexttoken.value === 'use strict') {
6325                         warn(bundle.function_strict);
6326                         use_strict();
6327                     }
6328                     adsafe_top = true;
6329                     JSLINT.tree = statements();
6330                     if (option.adsafe && (JSLINT.tree.length !== 1 ||
6331                             aint(JSLINT.tree[0], 'id', '(') ||
6332                             aint(JSLINT.tree[0].first, 'id', '.') ||
6333                             aint(JSLINT.tree[0].first.first, 'value', 'ADSAFE') ||
6334                             aint(JSLINT.tree[0].first.second, 'value', 'lib') ||
6335                             JSLINT.tree[0].second.length !== 2 ||
6336                             JSLINT.tree[0].second[0].arity !== 'string' ||
6337                             aint(JSLINT.tree[0].second[1], 'id', 'function'))) {
6338                         fail(bundle.adsafe_lib);
6339                     }
6340                     if (JSLINT.tree.disrupt) {
6341                         warn(bundle.weird_program, prevtoken);
6342                     }
6343                 }
6344             }
6345             indent = null;
6346             advance('(end)');
6347         } catch (e) {
6348             if (e) {        // `~
6349                 JSLINT.errors.push({
6350                     reason    : e.message,
6351                     line      : e.line || nexttoken.line,
6352                     character : e.character || nexttoken.from
6353                 }, null);
6354             }
6355         }
6356         return JSLINT.errors.length === 0;
6357     };
6358
6359
6360 // Data summary.
6361
6362     itself.data = function () {
6363         var data = {functions: []},
6364             function_data,
6365             globals,
6366             i,
6367             implieds = [],
6368             j,
6369             kind,
6370             members = [],
6371             name,
6372             the_function,
6373             unused = [];
6374         if (itself.errors.length) {
6375             data.errors = itself.errors;
6376         }
6377
6378         if (json_mode) {
6379             data.json = true;
6380         }
6381
6382         for (name in implied) {
6383             if (Object.prototype.hasOwnProperty.call(implied, name)) {
6384                 implieds.push({
6385                     name: name,
6386                     line: implied[name]
6387                 });
6388             }
6389         }
6390         if (implieds.length > 0) {
6391             data.implieds = implieds;
6392         }
6393
6394         if (urls.length > 0) {
6395             data.urls = urls;
6396         }
6397
6398         globals = Object.keys(functions[0]).filter(function (value) {
6399             return value.charAt(0) !== '(' ? value : undefined;
6400         });
6401         if (globals.length > 0) {
6402             data.globals = globals;
6403         }
6404
6405         for (i = 1; i < functions.length; i += 1) {
6406             the_function = functions[i];
6407             function_data = {};
6408             for (j = 0; j < functionicity.length; j += 1) {
6409                 function_data[functionicity[j]] = [];
6410             }
6411             for (name in the_function) {
6412                 if (Object.prototype.hasOwnProperty.call(the_function, name)) {
6413                     if (name.charAt(0) !== '(') {
6414                         kind = the_function[name];
6415                         if (kind === 'unction') {
6416                             kind = 'unused';
6417                         } else if (typeof kind === 'boolean') {
6418                             kind = 'global';
6419                         }
6420                         if (Array.isArray(function_data[kind])) {
6421                             function_data[kind].push(name);
6422                             if (kind === 'unused') {
6423                                 unused.push({
6424                                     name: name,
6425                                     line: the_function['(line)'],
6426                                     'function': the_function['(name)']
6427                                 });
6428                             }
6429                         }
6430                     }
6431                 }
6432             }
6433             for (j = 0; j < functionicity.length; j += 1) {
6434                 if (function_data[functionicity[j]].length === 0) {
6435                     delete function_data[functionicity[j]];
6436                 }
6437             }
6438             function_data.name = the_function['(name)'];
6439             function_data.param = the_function['(params)'];
6440             function_data.line = the_function['(line)'];
6441             data.functions.push(function_data);
6442         }
6443
6444         if (unused.length > 0) {
6445             data.unused = unused;
6446         }
6447
6448         members = [];
6449         for (name in member) {
6450             if (typeof member[name] === 'number') {
6451                 data.member = member;
6452                 break;
6453             }
6454         }
6455
6456         return data;
6457     };
6458
6459
6460     itself.report = function (errors_only) {
6461         var data = itself.data();
6462
6463         var err, evidence, i, j, key, keys, length, mem = '', name, names,
6464             output = [], snippets, the_function, warning;
6465
6466         function detail(h, array) {
6467             var comma_needed, i, singularity;
6468             if (array) {
6469                 output.push('<div><i>' + h + '</i> ');
6470                 array = array.sort();
6471                 for (i = 0; i < array.length; i += 1) {
6472                     if (array[i] !== singularity) {
6473                         singularity = array[i];
6474                         output.push((comma_needed ? ', ' : '') + singularity);
6475                         comma_needed = true;
6476                     }
6477                 }
6478                 output.push('</div>');
6479             }
6480         }
6481
6482         if (data.errors || data.implieds || data.unused) {
6483             err = true;
6484             output.push('<div id=errors><i>Error:</i>');
6485             if (data.errors) {
6486                 for (i = 0; i < data.errors.length; i += 1) {
6487                     warning = data.errors[i];
6488                     if (warning) {
6489                         evidence = warning.evidence || '';
6490                         output.push('<p>Problem' + (isFinite(warning.line) ? ' at line ' +
6491                             warning.line + ' character ' + warning.character : '') +
6492                             ': ' + warning.reason.entityify() +
6493                             '</p><p class=evidence>' +
6494                             (evidence && (evidence.length > 80 ? evidence.slice(0, 77) + '...' :
6495                             evidence).entityify()) + '</p>');
6496                     }
6497                 }
6498             }
6499
6500             if (data.implieds) {
6501                 snippets = [];
6502                 for (i = 0; i < data.implieds.length; i += 1) {
6503                     snippets[i] = '<code>' + data.implieds[i].name + '</code>&nbsp;<i>' +
6504                         data.implieds[i].line + '</i>';
6505                 }
6506                 output.push('<p><i>Implied global:</i> ' + snippets.join(', ') + '</p>');
6507             }
6508
6509             if (data.unused) {
6510                 snippets = [];
6511                 for (i = 0; i < data.unused.length; i += 1) {
6512                     snippets[i] = '<code><u>' + data.unused[i].name + '</u></code>&nbsp;<i>' +
6513                         data.unused[i].line + ' </i> <small>' +
6514                         data.unused[i]['function'] + '</small>';
6515                 }
6516                 output.push('<p><i>Unused variable:</i> ' + snippets.join(', ') + '</p>');
6517             }
6518             if (data.json) {
6519                 output.push('<p>JSON: bad.</p>');
6520             }
6521             output.push('</div>');
6522         }
6523
6524         if (!errors_only) {
6525
6526             output.push('<br><div id=functions>');
6527
6528             if (data.urls) {
6529                 detail("URLs<br>", data.urls, '<br>');
6530             }
6531
6532             if (xmode === 'style') {
6533                 output.push('<p>CSS.</p>');
6534             } else if (data.json && !err) {
6535                 output.push('<p>JSON: good.</p>');
6536             } else if (data.globals) {
6537                 output.push('<div><i>Global</i> ' +
6538                     data.globals.sort().join(', ') + '</div>');
6539             } else {
6540                 output.push('<div><i>No new global variables introduced.</i></div>');
6541             }
6542
6543             for (i = 0; i < data.functions.length; i += 1) {
6544                 the_function = data.functions[i];
6545                 names = [];
6546                 if (the_function.param) {
6547                     for (j = 0; j < the_function.param.length; j += 1) {
6548                         names[j] = the_function.param[j].value;
6549                     }
6550                 }
6551                 output.push('<br><div class=function><i>' + the_function.line + '</i> ' +
6552                     (the_function.name || '') + '(' + names.join(', ') + ')</div>');
6553                 detail('<big><b>Unused</b></big>', the_function.unused);
6554                 detail('Closure', the_function.closure);
6555                 detail('Variable', the_function['var']);
6556                 detail('Exception', the_function.exception);
6557                 detail('Outer', the_function.outer);
6558                 detail('Global', the_function.global);
6559                 detail('Label', the_function.label);
6560             }
6561
6562             if (data.member) {
6563                 keys = Object.keys(data.member);
6564                 if (keys.length) {
6565                     keys = keys.sort();
6566                     mem = '<br><pre id=properties>/*properties ';
6567                     length = 13;
6568                     for (i = 0; i < keys.length; i += 1) {
6569                         key = keys[i];
6570                         name = key.name();
6571                         if (length + name.length > 72) {
6572                             output.push(mem + '<br>');
6573                             mem = '    ';
6574                             length = 1;
6575                         }
6576                         length += name.length + 2;
6577                         if (data.member[key] === 1) {
6578                             name = '<i>' + name + '</i>';
6579                         }
6580                         if (i < keys.length - 1) {
6581                             name += ', ';
6582                         }
6583                         mem += name;
6584                     }
6585                     output.push(mem + '<br>*/</pre>');
6586                 }
6587                 output.push('</div>');
6588             }
6589         }
6590         return output.join('');
6591     };
6592     itself.jslint = itself;
6593
6594     itself.edition = '2011-03-07';
6595
6596     return itself;
6597
6598 }());