~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to utilities/build/fulljslint.js

jsbuild works.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// jslint.js
2
 
// 2008-10-10
3
 
 
4
 
 
5
 
/*
6
 
Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)
7
 
 
8
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
9
 
this software and associated documentation files (the "Software"), to deal in
10
 
the Software without restriction, including without limitation the rights to
11
 
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12
 
of the Software, and to permit persons to whom the Software is furnished to do
13
 
so, subject to the following conditions:
14
 
 
15
 
The above copyright notice and this permission notice shall be included in all
16
 
copies or substantial portions of the Software.
17
 
 
18
 
The Software shall be used for Good, not Evil.
19
 
 
20
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
 
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
 
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
 
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
 
SOFTWARE.
27
 
*/
28
 
 
29
 
/*
30
 
    JSLINT is a global function. It takes two parameters.
31
 
 
32
 
        var myResult = JSLINT(source, option);
33
 
 
34
 
    The first parameter is either a string or an array of strings. If it is a
35
 
    string, it will be split on '\n' or '\r'. If it is an array of strings, it
36
 
    is assumed that each string represents one line. The source can be a
37
 
    JavaScript text, or HTML text, or a Konfabulator text.
38
 
 
39
 
    The second parameter is an optional object of options which control the
40
 
    operation of JSLINT. Most of the options are booleans: They are all are
41
 
    optional and have a default value of false.
42
 
 
43
 
    If it checks out, JSLINT returns true. Otherwise, it returns false.
44
 
 
45
 
    If false, you can inspect JSLINT.errors to find out the problems.
46
 
    JSLINT.errors is an array of objects containing these members:
47
 
 
48
 
    {
49
 
        line      : The line (relative to 0) at which the lint was found
50
 
        character : The character (relative to 0) at which the lint was found
51
 
        reason    : The problem
52
 
        evidence  : The text line in which the problem occurred
53
 
        raw       : The raw message before the details were inserted
54
 
        a         : The first detail
55
 
        b         : The second detail
56
 
        c         : The third detail
57
 
        d         : The fourth detail
58
 
    }
59
 
 
60
 
    If a fatal error was found, a null will be the last element of the
61
 
    JSLINT.errors array.
62
 
 
63
 
    You can request a Function Report, which shows all of the functions
64
 
    and the parameters and vars that they use. This can be used to find
65
 
    implied global variables and other problems. The report is in HTML and
66
 
    can be inserted in an HTML <body>.
67
 
 
68
 
        var myReport = JSLINT.report(limited);
69
 
 
70
 
    If limited is true, then the report will be limited to only errors.
71
 
*/
72
 
 
73
 
/*jslint evil: true, nomen: false, onevar: false */
74
 
 
75
 
 
76
 
/*global JSLINT*/
77
 
 
78
 
 
79
 
// We build the application inside a function so that we produce only a single
80
 
// global variable. The function will be invoked, its return value is the JSLINT
81
 
// application itself.
82
 
 
83
 
"use strict";
84
 
 
85
 
JSLINT = function () {
86
 
    var adsafe_id,      // The widget's ADsafe id.
87
 
        adsafe_may,     // The widget may load approved scripts.
88
 
        adsafe_went,    // ADSAFE.go has been called.
89
 
        anonname,       // The guessed name for anonymous functions.
90
 
        approved,       // ADsafe approved urls.
91
 
 
92
 
        atrule = {
93
 
            'import'   : true,
94
 
            media      : true,
95
 
            'font-face': true,
96
 
            page       : true
97
 
        },
98
 
 
99
 
        badbreak = {
100
 
            ')': true,
101
 
            ']': true,
102
 
            '++': true,
103
 
            '--': true
104
 
        },
105
 
 
106
 
// These are members that should not be permitted in third party ads.
107
 
 
108
 
        banned = {              // the member names that ADsafe prohibits.
109
 
            apply           : true,
110
 
            'arguments'     : true,
111
 
            call            : true,
112
 
            callee          : true,
113
 
            caller          : true,
114
 
            constructor     : true,
115
 
            'eval'          : true,
116
 
            prototype       : true,
117
 
            unwatch         : true,
118
 
            valueOf         : true,
119
 
            watch           : true
120
 
        },
121
 
 
122
 
 
123
 
// These are the JSLint boolean options.
124
 
 
125
 
        boolOptions = {
126
 
            adsafe     : true, // if ADsafe should be enforced
127
 
            bitwise    : true, // if bitwise operators should not be allowed
128
 
            browser    : true, // if the standard browser globals should be predefined
129
 
            cap        : true, // if upper case HTML should be allowed
130
 
            css        : true, // if CSS workarounds should be tolerated
131
 
            debug      : true, // if debugger statements should be allowed
132
 
            eqeqeq     : true, // if === should be required
133
 
            evil       : true, // if eval should be allowed
134
 
            forin      : true, // if for in statements must filter
135
 
            fragment   : true, // if HTML fragments should be allowed
136
 
            laxbreak   : true, // if line breaks should not be checked
137
 
            nomen      : true, // if names should be checked
138
 
            on         : true, // if HTML event handlers should be allowed
139
 
            onevar     : true, // if only one var statement per function should be allowed
140
 
            passfail   : true, // if the scan should stop on first error
141
 
            plusplus   : true, // if increment/decrement should not be allowed
142
 
            regexp     : true, // if the . should not be allowed in regexp literals
143
 
            rhino      : true, // if the Rhino environment globals should be predefined
144
 
            undef      : true, // if variables should be declared before used
145
 
            safe       : true, // if use of some browser features should be restricted
146
 
            sidebar    : true, // if the System object should be predefined
147
 
            strict     : true, // require the "use strict"; pragma
148
 
            sub        : true, // if all forms of subscript notation are tolerated
149
 
            white      : true, // if strict whitespace rules apply
150
 
            widget     : true  // if the Yahoo Widgets globals should be predefined
151
 
        },
152
 
 
153
 
// browser contains a set of global names which are commonly provided by a
154
 
// web browser environment.
155
 
 
156
 
        browser = {
157
 
            alert           : true,
158
 
            blur            : true,
159
 
            clearInterval   : true,
160
 
            clearTimeout    : true,
161
 
            close           : true,
162
 
            closed          : true,
163
 
            confirm         : true,
164
 
            console         : true,
165
 
            Debug           : true,
166
 
            defaultStatus   : true,
167
 
            document        : true,
168
 
            event           : true,
169
 
            focus           : true,
170
 
            frames          : true,
171
 
            getComputedStyle: true,
172
 
            history         : true,
173
 
            Image           : true,
174
 
            length          : true,
175
 
            location        : true,
176
 
            moveBy          : true,
177
 
            moveTo          : true,
178
 
            name            : true,
179
 
            navigator       : true,
180
 
            onblur          : true,
181
 
            onerror         : true,
182
 
            onfocus         : true,
183
 
            onload          : true,
184
 
            onresize        : true,
185
 
            onunload        : true,
186
 
            open            : true,
187
 
            opener          : true,
188
 
            opera           : true,
189
 
            Option          : true,
190
 
            parent          : true,
191
 
            print           : true,
192
 
            prompt          : true,
193
 
            resizeBy        : true,
194
 
            resizeTo        : true,
195
 
            screen          : true,
196
 
            scroll          : true,
197
 
            scrollBy        : true,
198
 
            scrollTo        : true,
199
 
            self            : true,
200
 
            setInterval     : true,
201
 
            setTimeout      : true,
202
 
            status          : true,
203
 
            top             : true,
204
 
            window          : true,
205
 
            XMLHttpRequest  : true
206
 
        },
207
 
 
208
 
        cssAttributeData,
209
 
        cssAny,
210
 
 
211
 
        cssColorData = {
212
 
            "aliceblue": true,
213
 
            "antiquewhite": true,
214
 
            "aqua": true,
215
 
            "aquamarine": true,
216
 
            "azure": true,
217
 
            "beige": true,
218
 
            "bisque": true,
219
 
            "black": true,
220
 
            "blanchedalmond": true,
221
 
            "blue": true,
222
 
            "blueviolet": true,
223
 
            "brown": true,
224
 
            "burlywood": true,
225
 
            "cadetblue": true,
226
 
            "chartreuse": true,
227
 
            "chocolate": true,
228
 
            "coral": true,
229
 
            "cornflowerblue": true,
230
 
            "cornsilk": true,
231
 
            "crimson": true,
232
 
            "cyan": true,
233
 
            "darkblue": true,
234
 
            "darkcyan": true,
235
 
            "darkgoldenrod": true,
236
 
            "darkgray": true,
237
 
            "darkgreen": true,
238
 
            "darkkhaki": true,
239
 
            "darkmagenta": true,
240
 
            "darkolivegreen": true,
241
 
            "darkorange": true,
242
 
            "darkorchid": true,
243
 
            "darkred": true,
244
 
            "darksalmon": true,
245
 
            "darkseagreen": true,
246
 
            "darkslateblue": true,
247
 
            "darkslategray": true,
248
 
            "darkturquoise": true,
249
 
            "darkviolet": true,
250
 
            "deeppink": true,
251
 
            "deepskyblue": true,
252
 
            "dimgray": true,
253
 
            "dodgerblue": true,
254
 
            "firebrick": true,
255
 
            "floralwhite": true,
256
 
            "forestgreen": true,
257
 
            "fuchsia": true,
258
 
            "gainsboro": true,
259
 
            "ghostwhite": true,
260
 
            "gold": true,
261
 
            "goldenrod": true,
262
 
            "gray": true,
263
 
            "green": true,
264
 
            "greenyellow": true,
265
 
            "honeydew": true,
266
 
            "hotpink": true,
267
 
            "indianred": true,
268
 
            "indigo": true,
269
 
            "ivory": true,
270
 
            "khaki": true,
271
 
            "lavender": true,
272
 
            "lavenderblush": true,
273
 
            "lawngreen": true,
274
 
            "lemonchiffon": true,
275
 
            "lightblue": true,
276
 
            "lightcoral": true,
277
 
            "lightcyan": true,
278
 
            "lightgoldenrodyellow": true,
279
 
            "lightgreen": true,
280
 
            "lightpink": true,
281
 
            "lightsalmon": true,
282
 
            "lightseagreen": true,
283
 
            "lightskyblue": true,
284
 
            "lightslategray": true,
285
 
            "lightsteelblue": true,
286
 
            "lightyellow": true,
287
 
            "lime": true,
288
 
            "limegreen": true,
289
 
            "linen": true,
290
 
            "magenta": true,
291
 
            "maroon": true,
292
 
            "mediumaquamarine": true,
293
 
            "mediumblue": true,
294
 
            "mediumorchid": true,
295
 
            "mediumpurple": true,
296
 
            "mediumseagreen": true,
297
 
            "mediumslateblue": true,
298
 
            "mediumspringgreen": true,
299
 
            "mediumturquoise": true,
300
 
            "mediumvioletred": true,
301
 
            "midnightblue": true,
302
 
            "mintcream": true,
303
 
            "mistyrose": true,
304
 
            "moccasin": true,
305
 
            "navajowhite": true,
306
 
            "navy": true,
307
 
            "oldlace": true,
308
 
            "olive": true,
309
 
            "olivedrab": true,
310
 
            "orange": true,
311
 
            "orangered": true,
312
 
            "orchid": true,
313
 
            "palegoldenrod": true,
314
 
            "palegreen": true,
315
 
            "paleturquoise": true,
316
 
            "palevioletred": true,
317
 
            "papayawhip": true,
318
 
            "peachpuff": true,
319
 
            "peru": true,
320
 
            "pink": true,
321
 
            "plum": true,
322
 
            "powderblue": true,
323
 
            "purple": true,
324
 
            "red": true,
325
 
            "rosybrown": true,
326
 
            "royalblue": true,
327
 
            "saddlebrown": true,
328
 
            "salmon": true,
329
 
            "sandybrown": true,
330
 
            "seagreen": true,
331
 
            "seashell": true,
332
 
            "sienna": true,
333
 
            "silver": true,
334
 
            "skyblue": true,
335
 
            "slateblue": true,
336
 
            "slategray": true,
337
 
            "snow": true,
338
 
            "springgreen": true,
339
 
            "steelblue": true,
340
 
            "tan": true,
341
 
            "teal": true,
342
 
            "thistle": true,
343
 
            "tomato": true,
344
 
            "turquoise": true,
345
 
            "violet": true,
346
 
            "wheat": true,
347
 
            "white": true,
348
 
            "whitesmoke": true,
349
 
            "yellow": true,
350
 
            "yellowgreen": true
351
 
        },
352
 
 
353
 
        cssBorderStyle,
354
 
 
355
 
        cssLengthData = {
356
 
            '%': true,
357
 
            'cm': true,
358
 
            'em': true,
359
 
            'ex': true,
360
 
            'in': true,
361
 
            'mm': true,
362
 
            'pc': true,
363
 
            'pt': true,
364
 
            'px': true
365
 
        },
366
 
 
367
 
        escapes = {
368
 
            '\b': '\\b',
369
 
            '\t': '\\t',
370
 
            '\n': '\\n',
371
 
            '\f': '\\f',
372
 
            '\r': '\\r',
373
 
            '"' : '\\"',
374
 
            '/' : '\\/',
375
 
            '\\': '\\\\'
376
 
        },
377
 
 
378
 
        funct,          // The current function
379
 
        functions,      // All of the functions
380
 
 
381
 
        global,         // The global scope
382
 
        htmltag = {
383
 
            a:        {},
384
 
            abbr:     {},
385
 
            acronym:  {},
386
 
            address:  {},
387
 
            applet:   {},
388
 
            area:     {empty: true, parent: ' map '},
389
 
            b:        {},
390
 
            base:     {empty: true, parent: ' head '},
391
 
            bdo:      {},
392
 
            big:      {},
393
 
            blockquote: {},
394
 
            body:     {parent: ' html noframes '},
395
 
            br:       {empty: true},
396
 
            button:   {},
397
 
            canvas:   {parent: ' body p div th td '},
398
 
            caption:  {parent: ' table '},
399
 
            center:   {},
400
 
            cite:     {},
401
 
            code:     {},
402
 
            col:      {empty: true, parent: ' table colgroup '},
403
 
            colgroup: {parent: ' table '},
404
 
            dd:       {parent: ' dl '},
405
 
            del:      {},
406
 
            dfn:      {},
407
 
            dir:      {},
408
 
            div:      {},
409
 
            dl:       {},
410
 
            dt:       {parent: ' dl '},
411
 
            em:       {},
412
 
            embed:    {},
413
 
            fieldset: {},
414
 
            font:     {},
415
 
            form:     {},
416
 
            frame:    {empty: true, parent: ' frameset '},
417
 
            frameset: {parent: ' html frameset '},
418
 
            h1:       {},
419
 
            h2:       {},
420
 
            h3:       {},
421
 
            h4:       {},
422
 
            h5:       {},
423
 
            h6:       {},
424
 
            head:     {parent: ' html '},
425
 
            html:     {parent: '*'},
426
 
            hr:       {empty: true},
427
 
            i:        {},
428
 
            iframe:   {},
429
 
            img:      {empty: true},
430
 
            input:    {empty: true},
431
 
            ins:      {},
432
 
            kbd:      {},
433
 
            label:    {},
434
 
            legend:   {parent: ' fieldset '},
435
 
            li:       {parent: ' dir menu ol ul '},
436
 
            link:     {empty: true, parent: ' head '},
437
 
            map:      {},
438
 
            menu:     {},
439
 
            meta:     {empty: true, parent: ' head noframes noscript '},
440
 
            noframes: {parent: ' html body '},
441
 
            noscript: {parent: ' body head noframes '},
442
 
            object:   {},
443
 
            ol:       {},
444
 
            optgroup: {parent: ' select '},
445
 
            option:   {parent: ' optgroup select '},
446
 
            p:        {},
447
 
            param:    {empty: true, parent: ' applet object '},
448
 
            pre:      {},
449
 
            q:        {},
450
 
            samp:     {},
451
 
            script:   {empty: true, parent: ' body div frame head iframe p pre span '},
452
 
            select:   {},
453
 
            small:    {},
454
 
            span:     {},
455
 
            strong:   {},
456
 
            style:    {parent: ' head ', empty: true},
457
 
            sub:      {},
458
 
            sup:      {},
459
 
            table:    {},
460
 
            tbody:    {parent: ' table '},
461
 
            td:       {parent: ' tr '},
462
 
            textarea: {},
463
 
            tfoot:    {parent: ' table '},
464
 
            th:       {parent: ' tr '},
465
 
            thead:    {parent: ' table '},
466
 
            title:    {parent: ' head '},
467
 
            tr:       {parent: ' table tbody thead tfoot '},
468
 
            tt:       {},
469
 
            u:        {},
470
 
            ul:       {},
471
 
            'var':    {}
472
 
        },
473
 
 
474
 
        ids,            // HTML ids
475
 
        implied,        // Implied globals
476
 
        inblock,
477
 
        indent,
478
 
        jsonmode,
479
 
        lines,
480
 
        lookahead,
481
 
        member,
482
 
        membersOnly,
483
 
        nexttoken,
484
 
        noreach,
485
 
        option,
486
 
        predefined,     // Global variables defined by option
487
 
        prereg,
488
 
        prevtoken,
489
 
 
490
 
        pseudorule = {
491
 
            'first-child': true,
492
 
            link         : true,
493
 
            visited      : true,
494
 
            hover        : true,
495
 
            active       : true,
496
 
            focus        : true,
497
 
            lang         : true,
498
 
            'first-letter' : true,
499
 
            'first-line' : true,
500
 
            before       : true,
501
 
            after        : true
502
 
        },
503
 
 
504
 
        rhino = {
505
 
            defineClass : true,
506
 
            deserialize : true,
507
 
            gc          : true,
508
 
            help        : true,
509
 
            load        : true,
510
 
            loadClass   : true,
511
 
            print       : true,
512
 
            quit        : true,
513
 
            readFile    : true,
514
 
            readUrl     : true,
515
 
            runCommand  : true,
516
 
            seal        : true,
517
 
            serialize   : true,
518
 
            spawn       : true,
519
 
            sync        : true,
520
 
            toint32     : true,
521
 
            version     : true
522
 
        },
523
 
 
524
 
        scope,      // The current scope
525
 
 
526
 
        sidebar = {
527
 
            System      : true
528
 
        },
529
 
 
530
 
        src,
531
 
        stack,
532
 
 
533
 
// standard contains the global names that are provided by the
534
 
// ECMAScript standard.
535
 
 
536
 
        standard = {
537
 
            Array               : true,
538
 
            Boolean             : true,
539
 
            Date                : true,
540
 
            decodeURI           : true,
541
 
            decodeURIComponent  : true,
542
 
            encodeURI           : true,
543
 
            encodeURIComponent  : true,
544
 
            Error               : true,
545
 
            'eval'              : true,
546
 
            EvalError           : true,
547
 
            Function            : true,
548
 
            isFinite            : true,
549
 
            isNaN               : true,
550
 
            JSON                : true,
551
 
            Math                : true,
552
 
            Number              : true,
553
 
            Object              : true,
554
 
            parseInt            : true,
555
 
            parseFloat          : true,
556
 
            RangeError          : true,
557
 
            ReferenceError      : true,
558
 
            RegExp              : true,
559
 
            String              : true,
560
 
            SyntaxError         : true,
561
 
            TypeError           : true,
562
 
            URIError            : true
563
 
        },
564
 
 
565
 
        standard_member = {
566
 
            E                   : true,
567
 
            LN2                 : true,
568
 
            LN10                : true,
569
 
            LOG2E               : true,
570
 
            LOG10E              : true,
571
 
            PI                  : true,
572
 
            SQRT1_2             : true,
573
 
            SQRT2               : true,
574
 
            MAX_VALUE           : true,
575
 
            MIN_VALUE           : true,
576
 
            NEGATIVE_INFINITY   : true,
577
 
            POSITIVE_INFINITY   : true
578
 
        },
579
 
 
580
 
        syntax = {},
581
 
        tab,
582
 
        token,
583
 
        urls,
584
 
        warnings,
585
 
 
586
 
// widget contains the global names which are provided to a Yahoo
587
 
// (fna Konfabulator) widget.
588
 
 
589
 
        widget = {
590
 
            alert                   : true,
591
 
            appleScript             : true,
592
 
            animator                : true,
593
 
            appleScript             : true,
594
 
            beep                    : true,
595
 
            bytesToUIString         : true,
596
 
            Canvas                  : true,
597
 
            chooseColor             : true,
598
 
            chooseFile              : true,
599
 
            chooseFolder            : true,
600
 
            closeWidget             : true,
601
 
            COM                     : true,
602
 
            convertPathToHFS        : true,
603
 
            convertPathToPlatform   : true,
604
 
            CustomAnimation         : true,
605
 
            escape                  : true,
606
 
            FadeAnimation           : true,
607
 
            filesystem              : true,
608
 
            focusWidget             : true,
609
 
            form                    : true,
610
 
            FormField               : true,
611
 
            Frame                   : true,
612
 
            HotKey                  : true,
613
 
            Image                   : true,
614
 
            include                 : true,
615
 
            isApplicationRunning    : true,
616
 
            iTunes                  : true,
617
 
            konfabulatorVersion     : true,
618
 
            log                     : true,
619
 
            MenuItem                : true,
620
 
            MoveAnimation           : true,
621
 
            openURL                 : true,
622
 
            play                    : true,
623
 
            Point                   : true,
624
 
            popupMenu               : true,
625
 
            preferenceGroups        : true,
626
 
            preferences             : true,
627
 
            print                   : true,
628
 
            prompt                  : true,
629
 
            random                  : true,
630
 
            reloadWidget            : true,
631
 
            resolvePath             : true,
632
 
            resumeUpdates           : true,
633
 
            RotateAnimation         : true,
634
 
            runCommand              : true,
635
 
            runCommandInBg          : true,
636
 
            saveAs                  : true,
637
 
            savePreferences         : true,
638
 
            screen                  : true,
639
 
            ScrollBar               : true,
640
 
            showWidgetPreferences   : true,
641
 
            sleep                   : true,
642
 
            speak                   : true,
643
 
            suppressUpdates         : true,
644
 
            system                  : true,
645
 
            tellWidget              : true,
646
 
            Text                    : true,
647
 
            TextArea                : true,
648
 
            Timer                   : true,
649
 
            unescape                : true,
650
 
            updateNow               : true,
651
 
            URL                     : true,
652
 
            widget                  : true,
653
 
            Window                  : true,
654
 
            XMLDOM                  : true,
655
 
            XMLHttpRequest          : true,
656
 
            yahooCheckLogin         : true,
657
 
            yahooLogin              : true,
658
 
            yahooLogout             : true
659
 
        },
660
 
 
661
 
//  xmode is used to adapt to the exceptions in html parsing.
662
 
//  It can have these states:
663
 
//      false   .js script file
664
 
//      html
665
 
//      outer
666
 
//      script
667
 
//      style
668
 
//      scriptstring
669
 
//      styleproperty
670
 
 
671
 
        xmode,
672
 
        xquote,
673
 
 
674
 
// unsafe comment or string
675
 
        ax = /@cc|<\/?|script|\]*s\]|<\s*!|&lt/i,
676
 
// unsafe character
677
 
        cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,
678
 
// token
679
 
        tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(global|extern|jslint|member|members)?|=|\/)?|\*[\/=]?|\+[+=]?|-[\-=]?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/,
680
 
// html token
681
 
        hx = /^\s*(['"=>\/&#]|<[\/!]?|[a-zA-Z][a-zA-Z0-9_\-]*|--)/,
682
 
// outer html token
683
 
        ox = /[>&]|<[\/!]?|--/,
684
 
// star slash
685
 
        lx = /\*\/|\/\*/,
686
 
// identifier
687
 
        ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,
688
 
// javascript url
689
 
        jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i,
690
 
// url badness
691
 
        ux = /&|\+|\u00AD|\.\.|\/\*|%[^;]|base64|url|expression|data|mailto/i,
692
 
// style
693
 
        sx = /^\s*([{:#*%.=,>+\[\]@()"';*]|[a-zA-Z0-9_][a-zA-Z0-9_\-]*|<\/|\/\*)/,
694
 
        ssx = /^\s*([@#!"'};:\-\/%.=,+\[\]()*_]|[a-zA-Z][a-zA-Z0-9._\-]*|\d+(?:\.\d+)?|<\/)/,
695
 
 
696
 
        rx = {
697
 
            outer: hx,
698
 
            html: hx,
699
 
            style: sx,
700
 
            styleproperty: ssx
701
 
        };
702
 
 
703
 
    function F() {}
704
 
 
705
 
    if (typeof Object.create !== 'function') {
706
 
        Object.create = function (o) {
707
 
            F.prototype = o;
708
 
            return new F();
709
 
        };
710
 
    }
711
 
    Object.prototype.union = function (o) {
712
 
        var n;
713
 
        for (n in o) {
714
 
            if (o.hasOwnProperty(n)) {
715
 
                this[n] = o[n];
716
 
            }
717
 
        }
718
 
    };
719
 
 
720
 
    String.prototype.entityify = function () {
721
 
        return this.
722
 
            replace(/&/g, '&amp;').
723
 
            replace(/</g, '&lt;').
724
 
            replace(/>/g, '&gt;');
725
 
    };
726
 
 
727
 
    String.prototype.isAlpha = function () {
728
 
        return (this >= 'a' && this <= 'z\uffff') ||
729
 
            (this >= 'A' && this <= 'Z\uffff');
730
 
    };
731
 
 
732
 
 
733
 
    String.prototype.isDigit = function () {
734
 
        return (this >= '0' && this <= '9');
735
 
    };
736
 
 
737
 
 
738
 
    String.prototype.supplant = function (o) {
739
 
        return this.replace(/\{([^{}]*)\}/g, function (a, b) {
740
 
            var r = o[b];
741
 
            return typeof r === 'string' || typeof r === 'number' ? r : a;
742
 
        });
743
 
    };
744
 
 
745
 
    String.prototype.name = function () {
746
 
 
747
 
// If the string looks like an identifier, then we can return it as is.
748
 
// If the string contains no control characters, no quote characters, and no
749
 
// backslash characters, then we can simply slap some quotes around it.
750
 
// Otherwise we must also replace the offending characters with safe
751
 
// sequences.
752
 
 
753
 
 
754
 
        if (ix.test(this)) {
755
 
            return this;
756
 
        }
757
 
        if (/[&<"\/\\\x00-\x1f]/.test(this)) {
758
 
            return '"' + this.replace(/[&<"\/\\\x00-\x1f]/g, function (a) {
759
 
                var c = escapes[a];
760
 
                if (c) {
761
 
                    return c;
762
 
                }
763
 
                c = a.charCodeAt();
764
 
                return '\\u00' +
765
 
                    Math.floor(c / 16).toString(16) +
766
 
                    (c % 16).toString(16);
767
 
            }) + '"';
768
 
        }
769
 
        return '"' + this + '"';
770
 
    };
771
 
 
772
 
 
773
 
    function assume() {
774
 
        if (!option.safe) {
775
 
            if (option.rhino) {
776
 
                predefined.union(rhino);
777
 
            }
778
 
            if (option.browser || option.sidebar) {
779
 
                predefined.union(browser);
780
 
            }
781
 
            if (option.sidebar) {
782
 
                predefined.union(sidebar);
783
 
            }
784
 
            if (option.widget) {
785
 
                predefined.union(widget);
786
 
            }
787
 
        }
788
 
    }
789
 
 
790
 
 
791
 
// Produce an error warning.
792
 
 
793
 
    function quit(m, l, ch) {
794
 
        throw {
795
 
            name: 'JSLintError',
796
 
            line: l,
797
 
            character: ch,
798
 
            message: m + " (" + Math.floor((l / lines.length) * 100) +
799
 
                    "% scanned)."
800
 
        };
801
 
    }
802
 
 
803
 
    function warning(m, t, a, b, c, d) {
804
 
        var ch, l, w;
805
 
        t = t || nexttoken;
806
 
        if (t.id === '(end)') {  // `~
807
 
            t = token;
808
 
        }
809
 
        l = t.line || 0;
810
 
        ch = t.from || 0;
811
 
        w = {
812
 
            id: '(error)',
813
 
            raw: m,
814
 
            evidence: lines[l] || '',
815
 
            line: l,
816
 
            character: ch,
817
 
            a: a,
818
 
            b: b,
819
 
            c: c,
820
 
            d: d
821
 
        };
822
 
        w.reason = m.supplant(w);
823
 
        JSLINT.errors.push(w);
824
 
        if (option.passfail) {
825
 
            quit('Stopping. ', l, ch);
826
 
        }
827
 
        warnings += 1;
828
 
        if (warnings === 50) {
829
 
            quit("Too many errors.", l, ch);
830
 
        }
831
 
        return w;
832
 
    }
833
 
 
834
 
    function warningAt(m, l, ch, a, b, c, d) {
835
 
        return warning(m, {
836
 
            line: l,
837
 
            from: ch
838
 
        }, a, b, c, d);
839
 
    }
840
 
 
841
 
    function error(m, t, a, b, c, d) {
842
 
        var w = warning(m, t, a, b, c, d);
843
 
        quit("Stopping, unable to continue.", w.line, w.character);
844
 
    }
845
 
 
846
 
    function errorAt(m, l, ch, a, b, c, d) {
847
 
        return error(m, {
848
 
            line: l,
849
 
            from: ch
850
 
        }, a, b, c, d);
851
 
    }
852
 
 
853
 
 
854
 
 
855
 
// lexical analysis
856
 
 
857
 
    var lex = function lex() {
858
 
        var character, from, line, s;
859
 
 
860
 
// Private lex methods
861
 
 
862
 
        function nextLine() {
863
 
            var at;
864
 
            line += 1;
865
 
            if (line >= lines.length) {
866
 
                return false;
867
 
            }
868
 
            character = 0;
869
 
            s = lines[line].replace(/\t/g, tab);
870
 
            at = s.search(cx);
871
 
            if (at >= 0) {
872
 
                warningAt("Unsafe character.", line, at);
873
 
            }
874
 
            return true;
875
 
        }
876
 
 
877
 
// Produce a token object.  The token inherits from a syntax symbol.
878
 
 
879
 
        function it(type, value) {
880
 
            var i, t;
881
 
            if (type === '(color)') {
882
 
                t = {type: type};
883
 
            } else if (type === '(punctuator)' ||
884
 
                    (type === '(identifier)' && syntax.hasOwnProperty(value))) {
885
 
                t = syntax[value];
886
 
 
887
 
// Mozilla bug workaround.
888
 
 
889
 
                if (!t.id) {
890
 
                    t = syntax[type];
891
 
                }
892
 
            } else {
893
 
                t = syntax[type];
894
 
            }
895
 
            t = Object.create(t);
896
 
            if (type === '(string)' || type === '(range)') {
897
 
                if (jx.test(value)) {
898
 
                    warningAt("Script URL.", line, from);
899
 
                }
900
 
            }
901
 
            if (type === '(identifier)') {
902
 
                t.identifier = true;
903
 
                if (option.nomen && value.charAt(0) === '_') {
904
 
                    warningAt("Unexpected '_' in '{a}'.", line, from, value);
905
 
                }
906
 
            }
907
 
            t.value = value;
908
 
            t.line = line;
909
 
            t.character = character;
910
 
            t.from = from;
911
 
            i = t.id;
912
 
            if (i !== '(endline)') {
913
 
                prereg = i &&
914
 
                        (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) ||
915
 
                        i === 'return');
916
 
            }
917
 
            return t;
918
 
        }
919
 
 
920
 
// Public lex methods
921
 
 
922
 
        return {
923
 
            init: function (source) {
924
 
                if (typeof source === 'string') {
925
 
                    lines = source.
926
 
                        replace(/\r\n/g, '\n').
927
 
                        replace(/\r/g, '\n').
928
 
                        split('\n');
929
 
                } else {
930
 
                    lines = source;
931
 
                }
932
 
                line = -1;
933
 
                nextLine();
934
 
                from = 0;
935
 
            },
936
 
 
937
 
            range: function (begin, end) {
938
 
                var c, value = '';
939
 
                from = character;
940
 
                if (s.charAt(0) !== begin) {
941
 
                    errorAt("Expected '{a}' and instead saw '{b}'.",
942
 
                            line, character, begin, s.charAt(0));
943
 
                }
944
 
                for (;;) {
945
 
                    s = s.slice(1);
946
 
                    character += 1;
947
 
                    c = s.charAt(0);
948
 
                    switch (c) {
949
 
                    case '':
950
 
                        errorAt("Missing '{a}'.", line, character, c);
951
 
                        break;
952
 
                    case end:
953
 
                        s = s.slice(1);
954
 
                        character += 1;
955
 
                        return it('(range)', value);
956
 
                    case xquote:
957
 
                    case '\\':
958
 
                    case '\'':
959
 
                    case '"':
960
 
                        warningAt("Unexpected '{a}'.", line, character, c);
961
 
                    }
962
 
                    value += c;
963
 
                }
964
 
 
965
 
            },
966
 
 
967
 
// token -- this is called by advance to get the next token.
968
 
 
969
 
            token: function () {
970
 
                var b, c, captures, d, depth, high, i, l, low, q, t;
971
 
 
972
 
                function match(x) {
973
 
                    var r = x.exec(s), r1;
974
 
                    if (r) {
975
 
                        l = r[0].length;
976
 
                        r1 = r[1];
977
 
                        c = r1.charAt(0);
978
 
                        s = s.substr(l);
979
 
                        character += l;
980
 
                        from = character - r1.length;
981
 
                        return r1;
982
 
                    }
983
 
                }
984
 
 
985
 
                function string(x) {
986
 
                    var c, j, r = '';
987
 
 
988
 
                    if (jsonmode && x !== '"') {
989
 
                        warningAt("Strings must use doublequote.",
990
 
                                line, character);
991
 
                    }
992
 
 
993
 
                    if (xquote === x || (xmode === 'scriptstring' && !xquote)) {
994
 
                        return it('(punctuator)', x);
995
 
                    }
996
 
 
997
 
                    function esc(n) {
998
 
                        var i = parseInt(s.substr(j + 1, n), 16);
999
 
                        j += n;
1000
 
                        if (i >= 32 && i <= 127 &&
1001
 
                                i !== 34 && i !== 92 && i !== 39) {
1002
 
                            warningAt("Unnecessary escapement.", line, character);
1003
 
                        }
1004
 
                        character += n;
1005
 
                        c = String.fromCharCode(i);
1006
 
                    }
1007
 
                    j = 0;
1008
 
                    for (;;) {
1009
 
                        while (j >= s.length) {
1010
 
                            j = 0;
1011
 
                            if (xmode !== 'html' || !nextLine()) {
1012
 
                                errorAt("Unclosed string.", line, from);
1013
 
                            }
1014
 
                        }
1015
 
                        c = s.charAt(j);
1016
 
                        if (c === x) {
1017
 
                            character += 1;
1018
 
                            s = s.substr(j + 1);
1019
 
                            return it('(string)', r, x);
1020
 
                        }
1021
 
                        if (c < ' ') {
1022
 
                            if (c === '\n' || c === '\r') {
1023
 
                                break;
1024
 
                            }
1025
 
                            warningAt("Control character in string: {a}.",
1026
 
                                    line, character + j, s.slice(0, j));
1027
 
                        } else if (c === xquote) {
1028
 
                            warningAt("Bad HTML string", line, character + j);
1029
 
                        } else if (c === '<') {
1030
 
                            if (option.safe && xmode === 'html') {
1031
 
                                warningAt("ADsafe string violation.",
1032
 
                                        line, character + j);
1033
 
                            } else if (s.charAt(j + 1) === '/' && (xmode || option.safe)) {
1034
 
                                warningAt("Expected '<\\/' and instead saw '</'.", line, character);
1035
 
                            } else if (s.charAt(j + 1) === '!' && (xmode || option.safe)) {
1036
 
                                warningAt("Unexpected '<!' in a string.", line, character);
1037
 
                            }
1038
 
                        } else if (c === '\\') {
1039
 
                            if (xmode === 'html') {
1040
 
                                if (option.safe) {
1041
 
                                    warningAt("ADsafe string violation.",
1042
 
                                            line, character + j);
1043
 
                                }
1044
 
                            } else if (xmode === 'styleproperty') {
1045
 
                                j += 1;
1046
 
                                character += 1;
1047
 
                                c = s.charAt(j);
1048
 
                                if (c !== x) {
1049
 
                                    warningAt("Escapement in style string.",
1050
 
                                            line, character + j);
1051
 
                                }
1052
 
                            } else {
1053
 
                                j += 1;
1054
 
                                character += 1;
1055
 
                                c = s.charAt(j);
1056
 
                                switch (c) {
1057
 
                                case xquote:
1058
 
                                    warningAt("Bad HTML string", line,
1059
 
                                        character + j);
1060
 
                                    break;
1061
 
                                case '\\':
1062
 
                                case '\'':
1063
 
                                case '"':
1064
 
                                case '/':
1065
 
                                    break;
1066
 
                                case 'b':
1067
 
                                    c = '\b';
1068
 
                                    break;
1069
 
                                case 'f':
1070
 
                                    c = '\f';
1071
 
                                    break;
1072
 
                                case 'n':
1073
 
                                    c = '\n';
1074
 
                                    break;
1075
 
                                case 'r':
1076
 
                                    c = '\r';
1077
 
                                    break;
1078
 
                                case 't':
1079
 
                                    c = '\t';
1080
 
                                    break;
1081
 
                                case 'u':
1082
 
                                    esc(4);
1083
 
                                    break;
1084
 
                                case 'v':
1085
 
                                    c = '\v';
1086
 
                                    break;
1087
 
                                case 'x':
1088
 
                                    if (jsonmode) {
1089
 
                                        warningAt("Avoid \\x-.", line, character);
1090
 
                                    }
1091
 
                                    esc(2);
1092
 
                                    break;
1093
 
                                default:
1094
 
                                    warningAt("Bad escapement.", line, character);
1095
 
                                }
1096
 
                            }
1097
 
                        }
1098
 
                        r += c;
1099
 
                        character += 1;
1100
 
                        j += 1;
1101
 
                    }
1102
 
                }
1103
 
 
1104
 
                for (;;) {
1105
 
                    if (!s) {
1106
 
                        return it(nextLine() ? '(endline)' : '(end)', '');
1107
 
                    }
1108
 
                    while (xmode === 'outer') {
1109
 
                        i = s.search(ox);
1110
 
                        if (i === 0) {
1111
 
                            break;
1112
 
                        } else if (i > 0) {
1113
 
                            character += 1;
1114
 
                            s = s.slice(i);
1115
 
                            break;
1116
 
                        } else {
1117
 
                            if (!nextLine()) {
1118
 
                                return it('(end)', '');
1119
 
                            }
1120
 
                        }
1121
 
                    }
1122
 
                    t = match(rx[xmode] || tx);
1123
 
                    if (!t) {
1124
 
                        if (xmode === 'html') {
1125
 
                            return it('(error)', s.charAt(0));
1126
 
                        } else {
1127
 
                            t = '';
1128
 
                            c = '';
1129
 
                            while (s && s < '!') {
1130
 
                                s = s.substr(1);
1131
 
                            }
1132
 
                            if (s) {
1133
 
                                errorAt("Unexpected '{a}'.",
1134
 
                                        line, character, s.substr(0, 1));
1135
 
                            }
1136
 
                        }
1137
 
                    } else {
1138
 
 
1139
 
    //      identifier
1140
 
 
1141
 
                        if (c.isAlpha() || c === '_' || c === '$') {
1142
 
                            return it('(identifier)', t);
1143
 
                        }
1144
 
 
1145
 
    //      number
1146
 
 
1147
 
                        if (c.isDigit()) {
1148
 
                            if (xmode !== 'style' && !isFinite(Number(t))) {
1149
 
                                warningAt("Bad number '{a}'.",
1150
 
                                    line, character, t);
1151
 
                            }
1152
 
                            if (xmode !== 'styleproperty' && s.substr(0, 1).isAlpha()) {
1153
 
                                warningAt("Missing space after '{a}'.",
1154
 
                                        line, character, t);
1155
 
                            }
1156
 
                            if (c === '0') {
1157
 
                                d = t.substr(1, 1);
1158
 
                                if (d.isDigit()) {
1159
 
                                    if (token.id !== '.' && xmode !== 'styleproperty') {
1160
 
                                        warningAt("Don't use extra leading zeros '{a}'.",
1161
 
                                            line, character, t);
1162
 
                                    }
1163
 
                                } else if (jsonmode && (d === 'x' || d === 'X')) {
1164
 
                                    warningAt("Avoid 0x-. '{a}'.",
1165
 
                                            line, character, t);
1166
 
                                }
1167
 
                            }
1168
 
                            if (t.substr(t.length - 1) === '.') {
1169
 
                                warningAt(
1170
 
        "A trailing decimal point can be confused with a dot '{a}'.",
1171
 
                                        line, character, t);
1172
 
                            }
1173
 
                            return it('(number)', t);
1174
 
                        }
1175
 
                        switch (t) {
1176
 
 
1177
 
    //      string
1178
 
 
1179
 
                        case '"':
1180
 
                        case "'":
1181
 
                            return string(t);
1182
 
 
1183
 
    //      // comment
1184
 
 
1185
 
                        case '//':
1186
 
                            if (src || (xmode && xmode !== 'script')) {
1187
 
                                warningAt("Unexpected comment.", line, character);
1188
 
                            } else if (xmode === 'script' && /<\s*\//i.test(s)) {
1189
 
                                warningAt("Unexpected <\/ in comment.", line, character);
1190
 
                            } else if ((option.safe || xmode === 'script') && ax.test(s)) {
1191
 
                                warningAt("Dangerous comment.", line, character);
1192
 
                            }
1193
 
                            s = '';
1194
 
                            token.comment = true;
1195
 
                            break;
1196
 
 
1197
 
    //      /* comment
1198
 
 
1199
 
                        case '/*':
1200
 
                            if (src || (xmode && xmode !== 'script' && xmode !== 'style' && xmode !== 'styleproperty')) {
1201
 
                                warningAt("Unexpected comment.", line, character);
1202
 
                            }
1203
 
                            if (option.safe && ax.test(s)) {
1204
 
                                warningAt("ADsafe comment violation.", line, character);
1205
 
                            }
1206
 
                            for (;;) {
1207
 
                                i = s.search(lx);
1208
 
                                if (i >= 0) {
1209
 
                                    break;
1210
 
                                }
1211
 
                                if (!nextLine()) {
1212
 
                                    errorAt("Unclosed comment.", line, character);
1213
 
                                } else {
1214
 
                                    if (option.safe && ax.test(s)) {
1215
 
                                        warningAt("ADsafe comment violation.", line, character);
1216
 
                                    }
1217
 
                                }
1218
 
                            }
1219
 
                            character += i + 2;
1220
 
                            if (s.substr(i, 1) === '/') {
1221
 
                                errorAt("Nested comment.", line, character);
1222
 
                            }
1223
 
                            s = s.substr(i + 2);
1224
 
                            token.comment = true;
1225
 
                            break;
1226
 
 
1227
 
    //      /*global /*extern /*members /*jslint */
1228
 
 
1229
 
                        case '/*global':
1230
 
                        case '/*extern':
1231
 
                        case '/*members':
1232
 
                        case '/*member':
1233
 
                        case '/*jslint':
1234
 
                        case '*/':
1235
 
                            return {
1236
 
                                value: t,
1237
 
                                type: 'special',
1238
 
                                line: line,
1239
 
                                character: character,
1240
 
                                from: from
1241
 
                            };
1242
 
 
1243
 
                        case '':
1244
 
                            break;
1245
 
    //      /
1246
 
                        case '/':
1247
 
                            if (prereg) {
1248
 
                                depth = 0;
1249
 
                                captures = 0;
1250
 
                                l = 0;
1251
 
                                for (;;) {
1252
 
                                    b = true;
1253
 
                                    c = s.charAt(l);
1254
 
                                    l += 1;
1255
 
                                    switch (c) {
1256
 
                                    case '':
1257
 
                                        errorAt("Unclosed regular expression.", line, from);
1258
 
                                        return;
1259
 
                                    case '/':
1260
 
                                        if (depth > 0) {
1261
 
                                            warningAt("Unescaped '{a}'.", line, from + l, '/');
1262
 
                                        }
1263
 
                                        c = s.substr(0, l - 1);
1264
 
                                        q = {
1265
 
                                            g: true,
1266
 
                                            i: true,
1267
 
                                            m: true
1268
 
                                        };
1269
 
                                        while (q[s.charAt(l)] === true) {
1270
 
                                            q[s.charAt(l)] = false;
1271
 
                                            l += 1;
1272
 
                                        }
1273
 
                                        character += l;
1274
 
                                        s = s.substr(l);
1275
 
                                        return it('(regex)', c);
1276
 
                                    case '\\':
1277
 
                                        c = s.charAt(l);
1278
 
                                        if (c < ' ') {
1279
 
                                            warningAt("Unexpected control character in regular expression.", line, from + l);
1280
 
                                        } else if (c === '<') {
1281
 
                                            warningAt("Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
1282
 
                                        }
1283
 
                                        l += 1;
1284
 
                                        break;
1285
 
                                    case '(':
1286
 
                                        depth += 1;
1287
 
                                        b = false;
1288
 
                                        if (s.charAt(l) === '?') {
1289
 
                                            l += 1;
1290
 
                                            switch (s.charAt(l)) {
1291
 
                                            case ':':
1292
 
                                            case '=':
1293
 
                                            case '!':
1294
 
                                                l += 1;
1295
 
                                                break;
1296
 
                                            default:
1297
 
                                                warningAt("Expected '{a}' and instead saw '{b}'.", line, from + l, ':', s.charAt(l));
1298
 
                                            }
1299
 
                                        } else {
1300
 
                                            captures += 1;
1301
 
                                        }
1302
 
                                        break;
1303
 
                                    case ')':
1304
 
                                        if (depth === 0) {
1305
 
                                            warningAt("Unescaped '{a}'.", line, from + l, ')');
1306
 
                                        } else {
1307
 
                                            depth -= 1;
1308
 
                                        }
1309
 
                                        break;
1310
 
                                    case ' ':
1311
 
                                        q = 1;
1312
 
                                        while (s.charAt(l) === ' ') {
1313
 
                                            l += 1;
1314
 
                                            q += 1;
1315
 
                                        }
1316
 
                                        if (q > 1) {
1317
 
                                            warningAt("Spaces are hard to count. Use {{a}}.", line, from + l, q);
1318
 
                                        }
1319
 
                                        break;
1320
 
                                    case '[':
1321
 
                                        if (s.charAt(l) === '^') {
1322
 
                                            l += 1;
1323
 
                                        }
1324
 
                                        q = false;
1325
 
    klass:                              do {
1326
 
                                            c = s.charAt(l);
1327
 
                                            l += 1;
1328
 
                                            switch (c) {
1329
 
                                            case '[':
1330
 
                                            case '^':
1331
 
                                                warningAt("Unescaped '{a}'.", line, from + l, c);
1332
 
                                                q = true;
1333
 
                                                break;
1334
 
                                            case '-':
1335
 
                                                if (q) {
1336
 
                                                    q = false;
1337
 
                                                } else {
1338
 
                                                    warningAt("Unescaped '{a}'.", line, from + l, '-');
1339
 
                                                    q = true;
1340
 
                                                }
1341
 
                                                break;
1342
 
                                            case ']':
1343
 
                                                if (!q) {
1344
 
                                                    warningAt("Unescaped '{a}'.", line, from + l - 1, '-');
1345
 
                                                }
1346
 
                                                break klass;
1347
 
                                            case '\\':
1348
 
                                                c = s.charAt(l);
1349
 
                                                if (c < ' ') {
1350
 
                                                    warningAt("Unexpected control character in regular expression.", line, from + l);
1351
 
                                                } else if (c === '<') {
1352
 
                                                    warningAt("Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
1353
 
                                                }
1354
 
                                                l += 1;
1355
 
                                                q = true;
1356
 
                                                break;
1357
 
                                            case '/':
1358
 
                                                warningAt("Unescaped '{a}'.", line, from + l - 1, '/');
1359
 
                                                q = true;
1360
 
                                                break;
1361
 
                                            case '<':
1362
 
                                                if (xmode === 'script') {
1363
 
                                                    c = s.charAt(l);
1364
 
                                                    if (c === '!' || c === '/') {
1365
 
                                                        warningAt("HTML confusion in regular expression '<{a}'.", line, from + l, c);
1366
 
                                                    }
1367
 
                                                }
1368
 
                                                q = true;
1369
 
                                                break;
1370
 
                                            default:
1371
 
                                                q = true;
1372
 
                                            }
1373
 
                                        } while (c);
1374
 
                                        break;
1375
 
                                    case '.':
1376
 
                                        if (option.regexp) {
1377
 
                                            warningAt("Unexpected '{a}'.", line, from + l, c);
1378
 
                                        }
1379
 
                                        break;
1380
 
                                    case ']':
1381
 
                                    case '?':
1382
 
                                    case '{':
1383
 
                                    case '}':
1384
 
                                    case '+':
1385
 
                                    case '*':
1386
 
                                        warningAt("Unescaped '{a}'.", line, from + l, c);
1387
 
                                        break;
1388
 
                                    case '<':
1389
 
                                        if (xmode === 'script') {
1390
 
                                            c = s.charAt(l);
1391
 
                                            if (c === '!' || c === '/') {
1392
 
                                                warningAt("HTML confusion in regular expression '<{a}'.", line, from + l, c);
1393
 
                                            }
1394
 
                                        }
1395
 
                                    }
1396
 
                                    if (b) {
1397
 
                                        switch (s.charAt(l)) {
1398
 
                                        case '?':
1399
 
                                        case '+':
1400
 
                                        case '*':
1401
 
                                            l += 1;
1402
 
                                            if (s.charAt(l) === '?') {
1403
 
                                                l += 1;
1404
 
                                            }
1405
 
                                            break;
1406
 
                                        case '{':
1407
 
                                            l += 1;
1408
 
                                            c = s.charAt(l);
1409
 
                                            if (c < '0' || c > '9') {
1410
 
                                                warningAt("Expected a number and instead saw '{a}'.", line, from + l, c);
1411
 
                                            }
1412
 
                                            l += 1;
1413
 
                                            low = +c;
1414
 
                                            for (;;) {
1415
 
                                                c = s.charAt(l);
1416
 
                                                if (c < '0' || c > '9') {
1417
 
                                                    break;
1418
 
                                                }
1419
 
                                                l += 1;
1420
 
                                                low = +c + (low * 10);
1421
 
                                            }
1422
 
                                            high = low;
1423
 
                                            if (c === ',') {
1424
 
                                                l += 1;
1425
 
                                                high = Infinity;
1426
 
                                                c = s.charAt(l);
1427
 
                                                if (c >= '0' && c <= '9') {
1428
 
                                                    l += 1;
1429
 
                                                    high = +c;
1430
 
                                                    for (;;) {
1431
 
                                                        c = s.charAt(l);
1432
 
                                                        if (c < '0' || c > '9') {
1433
 
                                                            break;
1434
 
                                                        }
1435
 
                                                        l += 1;
1436
 
                                                        high = +c + (high * 10);
1437
 
                                                    }
1438
 
                                                }
1439
 
                                            }
1440
 
                                            if (s.charAt(l) !== '}') {
1441
 
                                                warningAt("Expected '{a}' and instead saw '{b}'.", line, from + l, '}', c);
1442
 
                                            } else {
1443
 
                                                l += 1;
1444
 
                                            }
1445
 
                                            if (s.charAt(l) === '?') {
1446
 
                                                l += 1;
1447
 
                                            }
1448
 
                                            if (low > high) {
1449
 
                                                warningAt("'{a}' should not be greater than '{b}'.", line, from + l, low, high);
1450
 
                                            }
1451
 
                                        }
1452
 
                                    }
1453
 
                                }
1454
 
                                c = s.substr(0, l - 1);
1455
 
                                character += l;
1456
 
                                s = s.substr(l);
1457
 
                                return it('(regex)', c);
1458
 
                            }
1459
 
                            return it('(punctuator)', t);
1460
 
 
1461
 
    //      punctuator
1462
 
 
1463
 
                        case '#':
1464
 
                            if (xmode === 'html' || xmode === 'styleproperty') {
1465
 
                                for (;;) {
1466
 
                                    c = s.charAt(0);
1467
 
                                    if ((c < '0' || c > '9') &&
1468
 
                                            (c < 'a' || c > 'f') &&
1469
 
                                            (c < 'A' || c > 'F')) {
1470
 
                                        break;
1471
 
                                    }
1472
 
                                    character += 1;
1473
 
                                    s = s.substr(1);
1474
 
                                    t += c;
1475
 
                                }
1476
 
                                if (t.length !== 4 && t.length !== 7) {
1477
 
                                    warningAt("Bad hex color '{a}'.", line,
1478
 
                                        from + l, t);
1479
 
                                }
1480
 
                                return it('(color)', t);
1481
 
                            }
1482
 
                            return it('(punctuator)', t);
1483
 
                        default:
1484
 
                            if (xmode === 'outer' && c === '&') {
1485
 
                                character += 1;
1486
 
                                s = s.substr(1);
1487
 
                                for (;;) {
1488
 
                                    c = s.charAt(0);
1489
 
                                    character += 1;
1490
 
                                    s = s.substr(1);
1491
 
                                    if (c === ';') {
1492
 
                                        break;
1493
 
                                    }
1494
 
                                    if (!((c >= '0' && c <= '9') ||
1495
 
                                            (c >= 'a' && c <= 'z') ||
1496
 
                                            c === '#')) {
1497
 
                                        errorAt("Bad entity", line, from + l,
1498
 
                                        character);
1499
 
                                    }
1500
 
                                }
1501
 
                                break;
1502
 
                            }
1503
 
                            return it('(punctuator)', t);
1504
 
                        }
1505
 
                    }
1506
 
                }
1507
 
            }
1508
 
        };
1509
 
    }();
1510
 
 
1511
 
 
1512
 
    function addlabel(t, type) {
1513
 
 
1514
 
        if (t === 'hasOwnProperty') {
1515
 
            error("'hasOwnProperty' is a really bad name.");
1516
 
        }
1517
 
        if (option.safe && funct['(global)']) {
1518
 
            warning('ADsafe global: ' + t + '.', token);
1519
 
        }
1520
 
 
1521
 
// Define t in the current function in the current scope.
1522
 
 
1523
 
        if (funct.hasOwnProperty(t)) {
1524
 
            warning(funct[t] === true ?
1525
 
                "'{a}' was used before it was defined." :
1526
 
                "'{a}' is already defined.",
1527
 
                nexttoken, t);
1528
 
        }
1529
 
        funct[t] = type;
1530
 
        if (type === 'label') {
1531
 
            scope[t] = funct;
1532
 
        } else if (funct['(global)']) {
1533
 
            global[t] = funct;
1534
 
            if (implied.hasOwnProperty(t)) {
1535
 
                warning("'{a}' was used before it was defined.", nexttoken, t);
1536
 
                delete implied[t];
1537
 
            }
1538
 
        } else {
1539
 
            funct['(scope)'][t] = funct;
1540
 
        }
1541
 
    }
1542
 
 
1543
 
 
1544
 
    function doOption() {
1545
 
        var b, obj, filter, o = nexttoken.value, t, v;
1546
 
        switch (o) {
1547
 
        case '*/':
1548
 
            error("Unbegun comment.");
1549
 
            break;
1550
 
        case '/*global':
1551
 
        case '/*extern':
1552
 
            if (option.safe) {
1553
 
                warning("ADsafe restriction.");
1554
 
            }
1555
 
            obj = predefined;
1556
 
            break;
1557
 
        case '/*members':
1558
 
        case '/*member':
1559
 
            o = '/*members';
1560
 
            if (!membersOnly) {
1561
 
                membersOnly = {};
1562
 
            }
1563
 
            obj = membersOnly;
1564
 
            break;
1565
 
        case '/*jslint':
1566
 
            if (option.safe) {
1567
 
                warning("ADsafe restriction.");
1568
 
            }
1569
 
            obj = option;
1570
 
            filter = boolOptions;
1571
 
        }
1572
 
        for (;;) {
1573
 
            t = lex.token();
1574
 
            if (t.id === ',') {
1575
 
                t = lex.token();
1576
 
            }
1577
 
            while (t.id === '(endline)') {
1578
 
                t = lex.token();
1579
 
            }
1580
 
            if (t.type === 'special' && t.value === '*/') {
1581
 
                break;
1582
 
            }
1583
 
            if (t.type !== '(string)' && t.type !== '(identifier)' &&
1584
 
                    o !== '/*members') {
1585
 
                error("Bad option.", t);
1586
 
            }
1587
 
            if (filter) {
1588
 
                if (filter[t.value] !== true) {
1589
 
                    error("Bad option.", t);
1590
 
                }
1591
 
                v = lex.token();
1592
 
                if (v.id !== ':') {
1593
 
                    error("Expected '{a}' and instead saw '{b}'.",
1594
 
                            t, ':', t.value);
1595
 
                }
1596
 
                v = lex.token();
1597
 
                if (v.value === 'true') {
1598
 
                    b = true;
1599
 
                } else if (v.value === 'false') {
1600
 
                    b = false;
1601
 
                } else {
1602
 
                    error("Expected '{a}' and instead saw '{b}'.",
1603
 
                            t, 'true', t.value);
1604
 
                }
1605
 
            } else {
1606
 
                b = true;
1607
 
            }
1608
 
            obj[t.value] = b;
1609
 
        }
1610
 
        if (filter) {
1611
 
            assume();
1612
 
        }
1613
 
    }
1614
 
 
1615
 
 
1616
 
// We need a peek function. If it has an argument, it peeks that much farther
1617
 
// ahead. It is used to distinguish
1618
 
//     for ( var i in ...
1619
 
// from
1620
 
//     for ( var i = ...
1621
 
 
1622
 
    function peek(p) {
1623
 
        var i = p || 0, j = 0, t;
1624
 
 
1625
 
        while (j <= i) {
1626
 
            t = lookahead[j];
1627
 
            if (!t) {
1628
 
                t = lookahead[j] = lex.token();
1629
 
            }
1630
 
            j += 1;
1631
 
        }
1632
 
        return t;
1633
 
    }
1634
 
 
1635
 
 
1636
 
 
1637
 
// Produce the next token. It looks for programming errors.
1638
 
 
1639
 
    function advance(id, t) {
1640
 
        var l;
1641
 
        switch (token.id) {
1642
 
        case '(number)':
1643
 
            if (nexttoken.id === '.') {
1644
 
                warning(
1645
 
"A dot following a number can be confused with a decimal point.", token);
1646
 
            }
1647
 
            break;
1648
 
        case '-':
1649
 
            if (nexttoken.id === '-' || nexttoken.id === '--') {
1650
 
                warning("Confusing minusses.");
1651
 
            }
1652
 
            break;
1653
 
        case '+':
1654
 
            if (nexttoken.id === '+' || nexttoken.id === '++') {
1655
 
                warning("Confusing plusses.");
1656
 
            }
1657
 
            break;
1658
 
        }
1659
 
        if (token.type === '(string)' || token.identifier) {
1660
 
            anonname = token.value;
1661
 
        }
1662
 
 
1663
 
        if (id && nexttoken.id !== id) {
1664
 
            if (t) {
1665
 
                if (nexttoken.id === '(end)') {
1666
 
                    warning("Unmatched '{a}'.", t, t.id);
1667
 
                } else {
1668
 
                    warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
1669
 
                            nexttoken, id, t.id, t.line + 1, nexttoken.value);
1670
 
                }
1671
 
            } else if (nexttoken.type !== '(identifier)' ||
1672
 
                            nexttoken.value !== id) {
1673
 
                warning("Expected '{a}' and instead saw '{b}'.",
1674
 
                        nexttoken, id, nexttoken.value);
1675
 
            }
1676
 
        }
1677
 
        prevtoken = token;
1678
 
        token = nexttoken;
1679
 
        for (;;) {
1680
 
            nexttoken = lookahead.shift() || lex.token();
1681
 
            if (nexttoken.id === '(end)' || nexttoken.id === '(error)') {
1682
 
                return;
1683
 
            }
1684
 
            if (nexttoken.type === 'special') {
1685
 
                doOption();
1686
 
            } else {
1687
 
                if (nexttoken.id !== '(endline)') {
1688
 
                    break;
1689
 
                }
1690
 
                l = !xmode && !option.laxbreak &&
1691
 
                    (token.type === '(string)' || token.type === '(number)' ||
1692
 
                    token.type === '(identifier)' || badbreak[token.id]);
1693
 
            }
1694
 
        }
1695
 
        if (l) {
1696
 
            switch (nexttoken.id) {
1697
 
            case '{':
1698
 
            case '}':
1699
 
            case ']':
1700
 
            case '.':
1701
 
                break;
1702
 
            case ')':
1703
 
                switch (token.id) {
1704
 
                case ')':
1705
 
                case '}':
1706
 
                case ']':
1707
 
                    break;
1708
 
                default:
1709
 
                    warning("Line breaking error '{a}'.", token, ')');
1710
 
                }
1711
 
                break;
1712
 
            default:
1713
 
                warning("Line breaking error '{a}'.",
1714
 
                        token, token.value);
1715
 
            }
1716
 
        }
1717
 
    }
1718
 
 
1719
 
 
1720
 
// This is the heart of JSLINT, the Pratt parser. In addition to parsing, it
1721
 
// is looking for ad hoc lint patterns. We add to Pratt's model .fud, which is
1722
 
// like nud except that it is only used on the first token of a statement.
1723
 
// Having .fud makes it much easier to define JavaScript. I retained Pratt's
1724
 
// nomenclature.
1725
 
 
1726
 
// .nud     Null denotation
1727
 
// .fud     First null denotation
1728
 
// .led     Left denotation
1729
 
//  lbp     Left binding power
1730
 
//  rbp     Right binding power
1731
 
 
1732
 
// They are key to the parsing method called Top Down Operator Precedence.
1733
 
 
1734
 
    function parse(rbp, initial) {
1735
 
        var left, o;
1736
 
        if (nexttoken.id === '(end)') {
1737
 
            error("Unexpected early end of program.", token);
1738
 
        }
1739
 
        advance();
1740
 
        if (option.safe && predefined[token.value] === true &&
1741
 
                (nexttoken.id !== '(' && nexttoken.id !== '.')) {
1742
 
            warning('ADsafe violation.', token);
1743
 
        }
1744
 
        if (initial) {
1745
 
            anonname = 'anonymous';
1746
 
            funct['(verb)'] = token.value;
1747
 
        }
1748
 
        if (initial === true && token.fud) {
1749
 
            left = token.fud();
1750
 
        } else {
1751
 
            if (token.nud) {
1752
 
                o = token.exps;
1753
 
                left = token.nud();
1754
 
            } else {
1755
 
                if (nexttoken.type === '(number)' && token.id === '.') {
1756
 
                    warning(
1757
 
"A leading decimal point can be confused with a dot: '.{a}'.",
1758
 
                            token, nexttoken.value);
1759
 
                    advance();
1760
 
                    return token;
1761
 
                } else {
1762
 
                    error("Expected an identifier and instead saw '{a}'.",
1763
 
                            token, token.id);
1764
 
                }
1765
 
            }
1766
 
            while (rbp < nexttoken.lbp) {
1767
 
                o = nexttoken.exps;
1768
 
                advance();
1769
 
                if (token.led) {
1770
 
                    left = token.led(left);
1771
 
                } else {
1772
 
                    error("Expected an operator and instead saw '{a}'.",
1773
 
                        token, token.id);
1774
 
                }
1775
 
            }
1776
 
            if (initial && !o) {
1777
 
                warning(
1778
 
"Expected an assignment or function call and instead saw an expression.",
1779
 
                        token);
1780
 
            }
1781
 
        }
1782
 
        if (!option.evil && left && left.value === 'eval') {
1783
 
            warning("eval is evil.", left);
1784
 
        }
1785
 
        return left;
1786
 
    }
1787
 
 
1788
 
 
1789
 
// Functions for conformance of style.
1790
 
 
1791
 
    function adjacent(left, right) {
1792
 
        left = left || token;
1793
 
        right = right || nexttoken;
1794
 
        if (option.white || xmode === 'styleproperty' || xmode === 'style') {
1795
 
            if (left.character !== right.from && left.line === right.line) {
1796
 
                warning("Unexpected space after '{a}'.",
1797
 
                        nexttoken, left.value);
1798
 
            }
1799
 
        }
1800
 
    }
1801
 
 
1802
 
 
1803
 
    function nospace(left, right) {
1804
 
        left = left || token;
1805
 
        right = right || nexttoken;
1806
 
        if (option.white && !left.comment) {
1807
 
            if (left.line === right.line) {
1808
 
                adjacent(left, right);
1809
 
            }
1810
 
        }
1811
 
    }
1812
 
 
1813
 
 
1814
 
    function nonadjacent(left, right) {
1815
 
        left = left || token;
1816
 
        right = right || nexttoken;
1817
 
        if (option.white) {
1818
 
            if (left.character === right.from) {
1819
 
                warning("Missing space after '{a}'.",
1820
 
                        nexttoken, left.value);
1821
 
            }
1822
 
        }
1823
 
    }
1824
 
 
1825
 
    function indentation(bias) {
1826
 
        var i;
1827
 
        if (option.white && nexttoken.id !== '(end)') {
1828
 
            i = indent + (bias || 0);
1829
 
            if (nexttoken.from !== i) {
1830
 
                warning("Expected '{a}' to have an indentation of {b} instead of {c}.",
1831
 
                        nexttoken, nexttoken.value, i, nexttoken.from);
1832
 
            }
1833
 
        }
1834
 
    }
1835
 
 
1836
 
    function nolinebreak(t) {
1837
 
        if (t.line !== nexttoken.line) {
1838
 
            warning("Line breaking error '{a}'.", t, t.id);
1839
 
        }
1840
 
    }
1841
 
 
1842
 
 
1843
 
// Parasitic constructors for making the symbols that will be inherited by
1844
 
// tokens.
1845
 
 
1846
 
    function symbol(s, p) {
1847
 
        var x = syntax[s];
1848
 
        if (!x || typeof x !== 'object') {
1849
 
            syntax[s] = x = {
1850
 
                id: s,
1851
 
                lbp: p,
1852
 
                value: s
1853
 
            };
1854
 
        }
1855
 
        return x;
1856
 
    }
1857
 
 
1858
 
 
1859
 
    function delim(s) {
1860
 
        return symbol(s, 0);
1861
 
    }
1862
 
 
1863
 
 
1864
 
    function stmt(s, f) {
1865
 
        var x = delim(s);
1866
 
        x.identifier = x.reserved = true;
1867
 
        x.fud = f;
1868
 
        return x;
1869
 
    }
1870
 
 
1871
 
 
1872
 
    function blockstmt(s, f) {
1873
 
        var x = stmt(s, f);
1874
 
        x.block = true;
1875
 
        return x;
1876
 
    }
1877
 
 
1878
 
 
1879
 
    function reserveName(x) {
1880
 
        var c = x.id.charAt(0);
1881
 
        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1882
 
            x.identifier = x.reserved = true;
1883
 
        }
1884
 
        return x;
1885
 
    }
1886
 
 
1887
 
 
1888
 
    function prefix(s, f) {
1889
 
        var x = symbol(s, 150);
1890
 
        reserveName(x);
1891
 
        x.nud = (typeof f === 'function') ? f : function () {
1892
 
            if (option.plusplus && (this.id === '++' || this.id === '--')) {
1893
 
                warning("Unexpected use of '{a}'.", this, this.id);
1894
 
            }
1895
 
            this.right = parse(150);
1896
 
            this.arity = 'unary';
1897
 
            return this;
1898
 
        };
1899
 
        return x;
1900
 
    }
1901
 
 
1902
 
 
1903
 
    function type(s, f) {
1904
 
        var x = delim(s);
1905
 
        x.type = s;
1906
 
        x.nud = f;
1907
 
        return x;
1908
 
    }
1909
 
 
1910
 
 
1911
 
    function reserve(s, f) {
1912
 
        var x = type(s, f);
1913
 
        x.identifier = x.reserved = true;
1914
 
        return x;
1915
 
    }
1916
 
 
1917
 
 
1918
 
    function reservevar(s) {
1919
 
        return reserve(s, function () {
1920
 
            if (this.id === 'this') {
1921
 
                if (option.safe) {
1922
 
                    warning("ADsafe violation.", this);
1923
 
                }
1924
 
            }
1925
 
            return this;
1926
 
        });
1927
 
    }
1928
 
 
1929
 
 
1930
 
    function infix(s, f, p) {
1931
 
        var x = symbol(s, p);
1932
 
        reserveName(x);
1933
 
        x.led = (typeof f === 'function') ? f : function (left) {
1934
 
            nonadjacent(prevtoken, token);
1935
 
            nonadjacent(token, nexttoken);
1936
 
            this.left = left;
1937
 
            this.right = parse(p);
1938
 
            return this;
1939
 
        };
1940
 
        return x;
1941
 
    }
1942
 
 
1943
 
 
1944
 
    function relation(s, f) {
1945
 
        var x = symbol(s, 100);
1946
 
        x.led = function (left) {
1947
 
            nonadjacent(prevtoken, token);
1948
 
            nonadjacent(token, nexttoken);
1949
 
            var right = parse(100);
1950
 
            if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) {
1951
 
                warning("Use the isNaN function to compare with NaN.", this);
1952
 
            } else if (f) {
1953
 
                f.apply(this, [left, right]);
1954
 
            }
1955
 
            this.left = left;
1956
 
            this.right = right;
1957
 
            return this;
1958
 
        };
1959
 
        return x;
1960
 
    }
1961
 
 
1962
 
 
1963
 
    function isPoorRelation(node) {
1964
 
        var n = +node.value; // Safari workaround
1965
 
        return (node.type === '(number)' && !n) ||
1966
 
               (node.type === '(string)' && !node.value) ||
1967
 
                node.type === 'true' ||
1968
 
                node.type === 'false' ||
1969
 
                node.type === 'undefined' ||
1970
 
                node.type === 'null';
1971
 
    }
1972
 
 
1973
 
 
1974
 
    function assignop(s, f) {
1975
 
        symbol(s, 20).exps = true;
1976
 
        return infix(s, function (left) {
1977
 
            var l;
1978
 
            this.left = left;
1979
 
            nonadjacent(prevtoken, token);
1980
 
            nonadjacent(token, nexttoken);
1981
 
            if (option.safe) {
1982
 
                l = left;
1983
 
                do {
1984
 
                    if (predefined[l.value] === true) {
1985
 
                        warning('ADsafe violation.', l);
1986
 
                    }
1987
 
                    l = l.left;
1988
 
                } while (l);
1989
 
            }
1990
 
            if (left) {
1991
 
                if (left.id === '.' || left.id === '[') {
1992
 
                    if (left.left.value === 'arguments') {
1993
 
                        warning('Bad assignment.', this);
1994
 
                    }
1995
 
                    this.right = parse(19);
1996
 
                    return this;
1997
 
                } else if (left.identifier && !left.reserved) {
1998
 
                    this.right = parse(19);
1999
 
                    return this;
2000
 
                }
2001
 
                if (left === syntax['function']) {
2002
 
                    warning(
2003
 
"Expected an identifier in an assignment and instead saw a function invocation.",
2004
 
                                token);
2005
 
                }
2006
 
            }
2007
 
            error("Bad assignment.", this);
2008
 
        }, 20);
2009
 
    }
2010
 
 
2011
 
    function bitwise(s, f, p) {
2012
 
        var x = symbol(s, p);
2013
 
        reserveName(x);
2014
 
        x.led = (typeof f === 'function') ? f : function (left) {
2015
 
            if (option.bitwise) {
2016
 
                warning("Unexpected use of '{a}'.", this, this.id);
2017
 
            }
2018
 
            nonadjacent(prevtoken, token);
2019
 
            nonadjacent(token, nexttoken);
2020
 
            this.left = left;
2021
 
            this.right = parse(p);
2022
 
            return this;
2023
 
        };
2024
 
        return x;
2025
 
    }
2026
 
 
2027
 
    function bitwiseassignop(s) {
2028
 
        symbol(s, 20).exps = true;
2029
 
        return infix(s, function (left) {
2030
 
            if (option.bitwise) {
2031
 
                warning("Unexpected use of '{a}'.", this, this.id);
2032
 
            }
2033
 
            nonadjacent(prevtoken, token);
2034
 
            nonadjacent(token, nexttoken);
2035
 
            if (left) {
2036
 
                if (left.id === '.' || left.id === '[' ||
2037
 
                        (left.identifier && !left.reserved)) {
2038
 
                    parse(19);
2039
 
                    return left;
2040
 
                }
2041
 
                if (left === syntax['function']) {
2042
 
                    warning(
2043
 
"Expected an identifier in an assignment, and instead saw a function invocation.",
2044
 
                                token);
2045
 
                }
2046
 
            }
2047
 
            error("Bad assignment.", this);
2048
 
        }, 20);
2049
 
    }
2050
 
 
2051
 
 
2052
 
    function suffix(s, f) {
2053
 
        var x = symbol(s, 150);
2054
 
        x.led = function (left) {
2055
 
            if (option.plusplus) {
2056
 
                warning("Unexpected use of '{a}'.", this, this.id);
2057
 
            }
2058
 
            this.left = left;
2059
 
            return this;
2060
 
        };
2061
 
        return x;
2062
 
    }
2063
 
 
2064
 
 
2065
 
    function optionalidentifier() {
2066
 
        if (nexttoken.reserved) {
2067
 
            warning("Expected an identifier and instead saw '{a}' (a reserved word).",
2068
 
                    nexttoken, nexttoken.id);
2069
 
        }
2070
 
        if (nexttoken.identifier) {
2071
 
            advance();
2072
 
            return token.value;
2073
 
        }
2074
 
    }
2075
 
 
2076
 
 
2077
 
    function identifier() {
2078
 
        var i = optionalidentifier();
2079
 
        if (i) {
2080
 
            return i;
2081
 
        }
2082
 
        if (token.id === 'function' && nexttoken.id === '(') {
2083
 
            warning("Missing name in function statement.");
2084
 
        } else {
2085
 
            error("Expected an identifier and instead saw '{a}'.",
2086
 
                    nexttoken, nexttoken.value);
2087
 
        }
2088
 
    }
2089
 
 
2090
 
    function reachable(s) {
2091
 
        var i = 0, t;
2092
 
        if (nexttoken.id !== ';' || noreach) {
2093
 
            return;
2094
 
        }
2095
 
        for (;;) {
2096
 
            t = peek(i);
2097
 
            if (t.reach) {
2098
 
                return;
2099
 
            }
2100
 
            if (t.id !== '(endline)') {
2101
 
                if (t.id === 'function') {
2102
 
                    warning(
2103
 
"Inner functions should be listed at the top of the outer function.", t);
2104
 
                    break;
2105
 
                }
2106
 
                warning("Unreachable '{a}' after '{b}'.", t, t.value, s);
2107
 
                break;
2108
 
            }
2109
 
            i += 1;
2110
 
        }
2111
 
    }
2112
 
 
2113
 
 
2114
 
    function statement(noindent) {
2115
 
        var i = indent, r, s = scope, t = nexttoken;
2116
 
 
2117
 
// We don't like the empty statement.
2118
 
 
2119
 
        if (t.id === ';') {
2120
 
            warning("Unnecessary semicolon.", t);
2121
 
            advance(';');
2122
 
            return;
2123
 
        }
2124
 
 
2125
 
// Is this a labelled statement?
2126
 
 
2127
 
        if (t.identifier && !t.reserved && peek().id === ':') {
2128
 
            advance();
2129
 
            advance(':');
2130
 
            scope = Object.create(s);
2131
 
            addlabel(t.value, 'label');
2132
 
            if (!nexttoken.labelled) {
2133
 
                warning("Label '{a}' on {b} statement.",
2134
 
                        nexttoken, t.value, nexttoken.value);
2135
 
            }
2136
 
            if (jx.test(t.value + ':')) {
2137
 
                warning("Label '{a}' looks like a javascript url.",
2138
 
                        t, t.value);
2139
 
            }
2140
 
            nexttoken.label = t.value;
2141
 
            t = nexttoken;
2142
 
        }
2143
 
 
2144
 
// Parse the statement.
2145
 
 
2146
 
        if (!noindent) {
2147
 
            indentation();
2148
 
        }
2149
 
        r = parse(0, true);
2150
 
 
2151
 
// Look for the final semicolon.
2152
 
 
2153
 
        if (!t.block) {
2154
 
            if (nexttoken.id !== ';') {
2155
 
                warningAt("Missing semicolon.", token.line,
2156
 
                        token.from + token.value.length);
2157
 
            } else {
2158
 
                adjacent(token, nexttoken);
2159
 
                advance(';');
2160
 
                nonadjacent(token, nexttoken);
2161
 
            }
2162
 
        }
2163
 
 
2164
 
// Restore the indentation.
2165
 
 
2166
 
        indent = i;
2167
 
        scope = s;
2168
 
        return r;
2169
 
    }
2170
 
 
2171
 
 
2172
 
    function statements(begin) {
2173
 
        var a = [];
2174
 
        if (begin) {
2175
 
            if (option.strict && nexttoken.type !== '(string)') {
2176
 
                warning('Missing "use strict" statement.',
2177
 
                    nexttoken);
2178
 
            }
2179
 
            if (nexttoken.type === '(string)' &&
2180
 
                    nexttoken.value === 'use strict') {
2181
 
                advance();
2182
 
                advance(';');
2183
 
            }
2184
 
        }
2185
 
        if (option.adsafe) {
2186
 
            switch (begin) {
2187
 
            case 'script':
2188
 
                if (!adsafe_may) {
2189
 
                    if (nexttoken.value !== 'ADSAFE' ||
2190
 
                            peek(0).id !== '.' ||
2191
 
                            (peek(1).value !== 'id' &&
2192
 
                            peek(1).value !== 'go')) {
2193
 
                        error('ADsafe violation: Missing ADSAFE.id or ADSAFE.go.',
2194
 
                            nexttoken);
2195
 
                    }
2196
 
                }
2197
 
                if (nexttoken.value === 'ADSAFE' &&
2198
 
                        peek(0).id === '.' &&
2199
 
                        peek(1).value === 'id') {
2200
 
                    if (adsafe_may) {
2201
 
                        error('ADsafe violation.', nexttoken);
2202
 
                    }
2203
 
                    advance('ADSAFE');
2204
 
                    advance('.');
2205
 
                    advance('id');
2206
 
                    advance('(');
2207
 
                    if (nexttoken.value !== adsafe_id) {
2208
 
                        error('ADsafe violation: id does not match.', nexttoken);
2209
 
                    }
2210
 
                    advance('(string)');
2211
 
                    advance(')');
2212
 
                    advance(';');
2213
 
                    adsafe_may = true;
2214
 
                }
2215
 
                break;
2216
 
            case 'lib':
2217
 
                if (nexttoken.value === 'ADSAFE') {
2218
 
                    advance('ADSAFE');
2219
 
                    advance('.');
2220
 
                    advance('lib');
2221
 
                    advance('(');
2222
 
                    advance('(string)');
2223
 
                    advance(',');
2224
 
                    parse(0);
2225
 
                    advance(')');
2226
 
                    advance(';');
2227
 
                    return a;
2228
 
                } else {
2229
 
                    error("ADsafe lib violation.");
2230
 
                }
2231
 
            }
2232
 
        }
2233
 
        while (!nexttoken.reach && nexttoken.id !== '(end)') {
2234
 
            if (nexttoken.id === ';') {
2235
 
                warning("Unnecessary semicolon.");
2236
 
                advance(';');
2237
 
            } else {
2238
 
                a.push(statement());
2239
 
            }
2240
 
        }
2241
 
        return a;
2242
 
    }
2243
 
 
2244
 
 
2245
 
    function block(f) {
2246
 
        var a, b = inblock, s = scope, t;
2247
 
        inblock = f;
2248
 
        if (f) {
2249
 
            scope = Object.create(scope);
2250
 
        }
2251
 
        nonadjacent(token, nexttoken);
2252
 
        t = nexttoken;
2253
 
        if (nexttoken.id === '{') {
2254
 
            advance('{');
2255
 
            if (nexttoken.id !== '}' || token.line !== nexttoken.line) {
2256
 
                indent += option.indent;
2257
 
                if (!f && nexttoken.from === indent + option.indent) {
2258
 
                    indent += option.indent;
2259
 
                }
2260
 
                a = statements();
2261
 
                indent -= option.indent;
2262
 
                indentation();
2263
 
            }
2264
 
            advance('}', t);
2265
 
        } else {
2266
 
            warning("Expected '{a}' and instead saw '{b}'.",
2267
 
                    nexttoken, '{', nexttoken.value);
2268
 
            noreach = true;
2269
 
            a = [statement()];
2270
 
            noreach = false;
2271
 
        }
2272
 
        funct['(verb)'] = null;
2273
 
        scope = s;
2274
 
        inblock = b;
2275
 
        return a;
2276
 
    }
2277
 
 
2278
 
 
2279
 
// An identity function, used by string and number tokens.
2280
 
 
2281
 
    function idValue() {
2282
 
        return this;
2283
 
    }
2284
 
 
2285
 
 
2286
 
    function countMember(m) {
2287
 
        if (membersOnly && membersOnly[m] !== true) {
2288
 
            warning("Unexpected /*member '{a}'.", nexttoken, m);
2289
 
        }
2290
 
        if (typeof member[m] === 'number') {
2291
 
            member[m] += 1;
2292
 
        } else {
2293
 
            member[m] = 1;
2294
 
        }
2295
 
    }
2296
 
 
2297
 
    function note_implied(token) {
2298
 
        var name = token.value, line = token.line + 1, a = implied[name];
2299
 
        if (!a) {
2300
 
            a = [line];
2301
 
            implied[name] = a;
2302
 
        } else if (a[a.length - 1] !== line) {
2303
 
            a.push(line);
2304
 
        }
2305
 
    }
2306
 
 
2307
 
// CSS parsing.
2308
 
 
2309
 
 
2310
 
    function cssName() {
2311
 
        if (nexttoken.identifier) {
2312
 
            advance();
2313
 
            return true;
2314
 
        }
2315
 
    }
2316
 
 
2317
 
    function cssNumber() {
2318
 
        if (nexttoken.id === '-') {
2319
 
            advance('-');
2320
 
            advance('(number)');
2321
 
        }
2322
 
        if (nexttoken.type === '(number)') {
2323
 
            advance();
2324
 
            return true;
2325
 
        }
2326
 
    }
2327
 
 
2328
 
    function cssString() {
2329
 
        if (nexttoken.type === '(string)') {
2330
 
            advance();
2331
 
            return true;
2332
 
        }
2333
 
    }
2334
 
 
2335
 
    function cssColor() {
2336
 
        var i, number;
2337
 
        if (nexttoken.identifier) {
2338
 
            if (nexttoken.value === 'rgb') {
2339
 
                advance();
2340
 
                advance('(');
2341
 
                for (i = 0; i < 3; i += 1) {
2342
 
                    number = nexttoken.value;
2343
 
                    if (nexttoken.type !== '(number)' || number < 0) {
2344
 
                        warning("Expected a positive number and instead saw '{a}'",
2345
 
                            nexttoken, number);
2346
 
                        advance();
2347
 
                    } else {
2348
 
                        advance();
2349
 
                        if (nexttoken.id === '%') {
2350
 
                            advance('%');
2351
 
                            if (number > 100) {
2352
 
                                warning("Expected a percentage and instead saw '{a}'",
2353
 
                                    token, number);
2354
 
                            }
2355
 
                        } else {
2356
 
                            if (number > 255) {
2357
 
                                warning("Expected a small number and instead saw '{a}'",
2358
 
                                    token, number);
2359
 
                            }
2360
 
                        }
2361
 
                    }
2362
 
                }
2363
 
                advance(')');
2364
 
                return true;
2365
 
            } else if (cssColorData[nexttoken.value] === true) {
2366
 
                advance();
2367
 
                return true;
2368
 
            }
2369
 
        } else if (nexttoken.type === '(color)') {
2370
 
            advance();
2371
 
            return true;
2372
 
        }
2373
 
        return false;
2374
 
    }
2375
 
 
2376
 
    function cssLength() {
2377
 
        if (nexttoken.id === '-') {
2378
 
            advance('-');
2379
 
            adjacent();
2380
 
        }
2381
 
        if (nexttoken.type === '(number)') {
2382
 
            advance();
2383
 
            if (nexttoken.type !== '(string)' &&
2384
 
                    cssLengthData[nexttoken.value] === true) {
2385
 
                adjacent();
2386
 
                advance();
2387
 
            } else if (+token.value !== 0) {
2388
 
                warning("Expected a linear unit and instead saw '{a}'.",
2389
 
                    nexttoken, nexttoken.value);
2390
 
            }
2391
 
            return true;
2392
 
        }
2393
 
        return false;
2394
 
    }
2395
 
 
2396
 
    function cssLineHeight() {
2397
 
        if (nexttoken.id === '-') {
2398
 
            advance('-');
2399
 
            adjacent();
2400
 
        }
2401
 
        if (nexttoken.type === '(number)') {
2402
 
            advance();
2403
 
            if (nexttoken.type !== '(string)' &&
2404
 
                    cssLengthData[nexttoken.value] === true) {
2405
 
                adjacent();
2406
 
                advance();
2407
 
            }
2408
 
            return true;
2409
 
        }
2410
 
        return false;
2411
 
    }
2412
 
 
2413
 
    function cssWidth() {
2414
 
        if (nexttoken.identifier) {
2415
 
            switch (nexttoken.value) {
2416
 
            case 'thin':
2417
 
            case 'medium':
2418
 
            case 'thick':
2419
 
                advance();
2420
 
                return true;
2421
 
            }
2422
 
        } else {
2423
 
            return cssLength();
2424
 
        }
2425
 
    }
2426
 
 
2427
 
    function cssMargin() {
2428
 
        if (nexttoken.identifier) {
2429
 
            if (nexttoken.value === 'auto') {
2430
 
                advance();
2431
 
                return true;
2432
 
            }
2433
 
        } else {
2434
 
            return cssLength();
2435
 
        }
2436
 
    }
2437
 
 
2438
 
    function cssAttr() {
2439
 
        if (nexttoken.identifier && nexttoken.value === 'attr') {
2440
 
            advance();
2441
 
            advance('(');
2442
 
            if (!nexttoken.identifier) {
2443
 
                warning("Expected a name and instead saw '{a}'.",
2444
 
                        nexttoken, nexttoken.value);
2445
 
            }
2446
 
            advance();
2447
 
            advance(')');
2448
 
            return true;
2449
 
        }
2450
 
        return false;
2451
 
    }
2452
 
 
2453
 
    function cssCommaList() {
2454
 
        while (nexttoken.id !== ';') {
2455
 
            if (!cssName() && !cssString()) {
2456
 
                warning("Expected a name and instead saw '{a}'.",
2457
 
                        nexttoken, nexttoken.value);
2458
 
            }
2459
 
            if (nexttoken.id !== ',') {
2460
 
                return true;
2461
 
            }
2462
 
            advance(',');
2463
 
        }
2464
 
    }
2465
 
 
2466
 
    function cssCounter() {
2467
 
        if (nexttoken.identifier && nexttoken.value === 'counter') {
2468
 
            advance();
2469
 
            advance('(');
2470
 
            if (!nexttoken.identifier) {
2471
 
            }
2472
 
            advance();
2473
 
            if (nexttoken.id === ',') {
2474
 
                advance(',');
2475
 
                if (nexttoken.type !== '(string)') {
2476
 
                    warning("Expected a string and instead saw '{a}'.",
2477
 
                        nexttoken, nexttoken.value);
2478
 
                }
2479
 
                advance();
2480
 
            }
2481
 
            advance(')');
2482
 
            return true;
2483
 
        }
2484
 
        if (nexttoken.identifier && nexttoken.value === 'counters') {
2485
 
            advance();
2486
 
            advance('(');
2487
 
            if (!nexttoken.identifier) {
2488
 
                warning("Expected a name and instead saw '{a}'.",
2489
 
                        nexttoken, nexttoken.value);
2490
 
            }
2491
 
            advance();
2492
 
            if (nexttoken.id === ',') {
2493
 
                advance(',');
2494
 
                if (nexttoken.type !== '(string)') {
2495
 
                    warning("Expected a string and instead saw '{a}'.",
2496
 
                        nexttoken, nexttoken.value);
2497
 
                }
2498
 
                advance();
2499
 
            }
2500
 
            if (nexttoken.id === ',') {
2501
 
                advance(',');
2502
 
                if (nexttoken.type !== '(string)') {
2503
 
                    warning("Expected a string and instead saw '{a}'.",
2504
 
                        nexttoken, nexttoken.value);
2505
 
                }
2506
 
                advance();
2507
 
            }
2508
 
            advance(')');
2509
 
            return true;
2510
 
        }
2511
 
        return false;
2512
 
    }
2513
 
 
2514
 
 
2515
 
    function cssShape() {
2516
 
        var i;
2517
 
        if (nexttoken.identifier && nexttoken.value === 'rect') {
2518
 
            advance();
2519
 
            advance('(');
2520
 
            for (i = 0; i < 4; i += 1) {
2521
 
                if (!cssLength()) {
2522
 
                    warning("Expected a number and instead saw '{a}'.",
2523
 
                        nexttoken, nexttoken.value);
2524
 
                    break;
2525
 
                }
2526
 
            }
2527
 
            advance(')');
2528
 
            return true;
2529
 
        }
2530
 
        return false;
2531
 
    }
2532
 
 
2533
 
    function cssUrl() {
2534
 
        var url;
2535
 
        if (nexttoken.identifier && nexttoken.value === 'url') {
2536
 
            nexttoken = lex.range('(', ')');
2537
 
            url = nexttoken.value;
2538
 
            advance();
2539
 
            if (option.safe && ux.test(url)) {
2540
 
                error("ADsafe URL violation.");
2541
 
            }
2542
 
            urls.push(url);
2543
 
            return true;
2544
 
        }
2545
 
        return false;
2546
 
    }
2547
 
 
2548
 
    cssAny = [cssUrl, function () {
2549
 
        for (;;) {
2550
 
            if (nexttoken.identifier) {
2551
 
                switch (nexttoken.value.toLowerCase()) {
2552
 
                case 'url':
2553
 
                    cssUrl();
2554
 
                    break;
2555
 
                case 'expression':
2556
 
                    warning("Unexpected expression '{a}'.",
2557
 
                        nexttoken, nexttoken.value);
2558
 
                    advance();
2559
 
                    break;
2560
 
                default:
2561
 
                    advance();
2562
 
                }
2563
 
            } else {
2564
 
                if (nexttoken.id === ';' || nexttoken.id === '!'  ||
2565
 
                        nexttoken.id === '(end)' || nexttoken.id === '}') {
2566
 
                    return true;
2567
 
                }
2568
 
                advance();
2569
 
            }
2570
 
        }
2571
 
    }];
2572
 
 
2573
 
    cssBorderStyle = [
2574
 
        'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'ridge',
2575
 
        'inset', 'outset'
2576
 
    ];
2577
 
 
2578
 
    cssAttributeData = {
2579
 
        background: [
2580
 
            true, 'background-attachment', 'background-color',
2581
 
            'background-image', 'background-position', 'background-repeat'
2582
 
        ],
2583
 
        'background-attachment': ['scroll', 'fixed'],
2584
 
        'background-color': ['transparent', cssColor],
2585
 
        'background-image': ['none', cssUrl],
2586
 
        'background-position': [
2587
 
            2, [cssLength, 'top', 'bottom', 'left', 'right', 'center']
2588
 
        ],
2589
 
        'background-repeat': [
2590
 
            'repeat', 'repeat-x', 'repeat-y', 'no-repeat'
2591
 
        ],
2592
 
        'border': [true, 'border-color', 'border-style', 'border-width'],
2593
 
        'border-bottom': [true, 'border-bottom-color', 'border-bottom-style', 'border-bottom-width'],
2594
 
        'border-bottom-color': cssColor,
2595
 
        'border-bottom-style': cssBorderStyle,
2596
 
        'border-bottom-width': cssWidth,
2597
 
        'border-collapse': ['collapse', 'separate'],
2598
 
        'border-color': ['transparent', 4, cssColor],
2599
 
        'border-left': [
2600
 
            true, 'border-left-color', 'border-left-style', 'border-left-width'
2601
 
        ],
2602
 
        'border-left-color': cssColor,
2603
 
        'border-left-style': cssBorderStyle,
2604
 
        'border-left-width': cssWidth,
2605
 
        'border-right': [
2606
 
            true, 'border-right-color', 'border-right-style', 'border-right-width'
2607
 
        ],
2608
 
        'border-right-color': cssColor,
2609
 
        'border-right-style': cssBorderStyle,
2610
 
        'border-right-width': cssWidth,
2611
 
        'border-spacing': [2, cssLength],
2612
 
        'border-style': [4, cssBorderStyle],
2613
 
        'border-top': [
2614
 
            true, 'border-top-color', 'border-top-style', 'border-top-width'
2615
 
        ],
2616
 
        'border-top-color': cssColor,
2617
 
        'border-top-style': cssBorderStyle,
2618
 
        'border-top-width': cssWidth,
2619
 
        'border-width': [4, cssWidth],
2620
 
        bottom: [cssLength, 'auto'],
2621
 
        'caption-side' : ['bottom', 'left', 'right', 'top'],
2622
 
        clear: ['both', 'left', 'none', 'right'],
2623
 
        clip: [cssShape, 'auto'],
2624
 
        color: cssColor,
2625
 
        content: [
2626
 
            'open-quote', 'close-quote', 'no-open-quote', 'no-close-quote',
2627
 
            cssString, cssUrl, cssCounter, cssAttr
2628
 
        ],
2629
 
        'counter-increment': [
2630
 
            cssName, 'none'
2631
 
        ],
2632
 
        'counter-reset': [
2633
 
            cssName, 'none'
2634
 
        ],
2635
 
        cursor: [
2636
 
            cssUrl, 'auto', 'crosshair', 'default', 'e-resize', 'help', 'move',
2637
 
            'n-resize', 'ne-resize', 'nw-resize', 'pointer', 's-resize',
2638
 
            'se-resize', 'sw-resize', 'w-resize', 'text', 'wait'
2639
 
        ],
2640
 
        direction: ['ltr', 'rtl'],
2641
 
        display: [
2642
 
            'block', 'compact', 'inline', 'inline-block', 'inline-table',
2643
 
            'list-item', 'marker', 'none', 'run-in', 'table', 'table-caption',
2644
 
            'table-column', 'table-column-group', 'table-footer-group',
2645
 
            'table-header-group', 'table-row', 'table-row-group'
2646
 
        ],
2647
 
        'empty-cells': ['show', 'hide'],
2648
 
        'float': ['left', 'none', 'right'],
2649
 
        font: [
2650
 
            'caption', 'icon', 'menu', 'message-box', 'small-caption', 'status-bar',
2651
 
            true, 'font-size', 'font-style', 'font-weight', 'font-family'
2652
 
        ],
2653
 
        'font-family': cssCommaList,
2654
 
        'font-size': [
2655
 
            'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large',
2656
 
            'xx-large', 'larger', 'smaller', cssLength
2657
 
        ],
2658
 
        'font-size-adjust': ['none', cssNumber],
2659
 
        'font-stretch': [
2660
 
            'normal', 'wider', 'narrower', 'ultra-condensed',
2661
 
            'extra-condensed', 'condensed', 'semi-condensed',
2662
 
            'semi-expanded', 'expanded', 'extra-expanded'
2663
 
        ],
2664
 
        'font-style': [
2665
 
            'normal', 'italic', 'oblique'
2666
 
        ],
2667
 
        'font-variant': [
2668
 
            'normal', 'small-caps'
2669
 
        ],
2670
 
        'font-weight': [
2671
 
            'normal', 'bold', 'bolder', 'lighter', cssNumber
2672
 
        ],
2673
 
        height: [cssLength, 'auto'],
2674
 
        left: [cssLength, 'auto'],
2675
 
        'letter-spacing': ['normal', cssLength],
2676
 
        'line-height': ['normal', cssLineHeight],
2677
 
        'list-style': [
2678
 
            true, 'list-style-image', 'list-style-position', 'list-style-type'
2679
 
        ],
2680
 
        'list-style-image': ['none', cssUrl],
2681
 
        'list-style-position': ['inside', 'outside'],
2682
 
        'list-style-type': [
2683
 
            'circle', 'disc', 'square', 'decimal', 'decimal-leading-zero',
2684
 
            'lower-roman', 'upper-roman', 'lower-greek', 'lower-alpha',
2685
 
            'lower-latin', 'upper-alpha', 'upper-latin', 'hebrew', 'katakana',
2686
 
            'hiragana-iroha', 'katakana-oroha', 'none'
2687
 
        ],
2688
 
        margin: [4, cssMargin],
2689
 
        'margin-bottom': cssMargin,
2690
 
        'margin-left': cssMargin,
2691
 
        'margin-right': cssMargin,
2692
 
        'margin-top': cssMargin,
2693
 
        'marker-offset': [cssLength, 'auto'],
2694
 
        'max-height': [cssLength, 'none'],
2695
 
        'max-width': [cssLength, 'none'],
2696
 
        'min-height': cssLength,
2697
 
        'min-width': cssLength,
2698
 
        opacity: cssNumber,
2699
 
        outline: [true, 'outline-color', 'outline-style', 'outline-width'],
2700
 
        'outline-color': ['invert', cssColor],
2701
 
        'outline-style': [
2702
 
            'dashed', 'dotted', 'double', 'groove', 'inset', 'none',
2703
 
            'outset', 'ridge', 'solid'
2704
 
        ],
2705
 
        'outline-width': cssWidth,
2706
 
        overflow: ['auto', 'hidden', 'scroll', 'visible'],
2707
 
        padding: [4, cssLength],
2708
 
        'padding-bottom': cssLength,
2709
 
        'padding-left': cssLength,
2710
 
        'padding-right': cssLength,
2711
 
        'padding-top': cssLength,
2712
 
        position: ['absolute', 'fixed', 'relative', 'static'],
2713
 
        quotes: [8, cssString],
2714
 
        right: [cssLength, 'auto'],
2715
 
        'table-layout': ['auto', 'fixed'],
2716
 
        'text-align': ['center', 'justify', 'left', 'right'],
2717
 
        'text-decoration': ['none', 'underline', 'overline', 'line-through', 'blink'],
2718
 
        'text-indent': cssLength,
2719
 
        'text-shadow': ['none', 4, [cssColor, cssLength]],
2720
 
        'text-transform': ['capitalize', 'uppercase', 'lowercase', 'none'],
2721
 
        top: [cssLength, 'auto'],
2722
 
        'unicode-bidi': ['normal', 'embed', 'bidi-override'],
2723
 
        'vertical-align': [
2724
 
            'baseline', 'bottom', 'sub', 'super', 'top', 'text-top', 'middle',
2725
 
            'text-bottom', cssLength
2726
 
        ],
2727
 
        visibility: ['visible', 'hidden', 'collapse'],
2728
 
        'white-space': ['normal', 'pre', 'nowrap'],
2729
 
        width: [cssLength, 'auto'],
2730
 
        'word-spacing': ['normal', cssLength],
2731
 
        'z-index': ['auto', cssNumber]
2732
 
    };
2733
 
 
2734
 
    function styleAttribute() {
2735
 
        var v;
2736
 
        while (nexttoken.id === '*' || nexttoken.id === '#' || nexttoken.value === '_') {
2737
 
            if (!option.css) {
2738
 
                warning("Unexpected '{a}'.", nexttoken, nexttoken.value);
2739
 
            }
2740
 
            advance();
2741
 
        }
2742
 
        if (nexttoken.id === '-') {
2743
 
            if (!option.css) {
2744
 
                warning("Unexpected '{a}'.", nexttoken, nexttoken.value);
2745
 
            }
2746
 
            advance('-');
2747
 
            if (!nexttoken.identifier) {
2748
 
                warning("Expected a non-standard style attribute and instead saw '{a}'.",
2749
 
                    nexttoken, nexttoken.value);
2750
 
            }
2751
 
            advance();
2752
 
            return cssAny;
2753
 
        } else {
2754
 
            if (!nexttoken.identifier) {
2755
 
                warning("Excepted a style attribute, and instead saw '{a}'.",
2756
 
                    nexttoken, nexttoken.value);
2757
 
            } else {
2758
 
                if (cssAttributeData.hasOwnProperty(nexttoken.value)) {
2759
 
                    v = cssAttributeData[nexttoken.value];
2760
 
                } else {
2761
 
                    v = cssAny;
2762
 
                    if (!option.css) {
2763
 
                        warning("Unrecognized style attribute '{a}'.",
2764
 
                                nexttoken, nexttoken.value);
2765
 
                    }
2766
 
                }
2767
 
            }
2768
 
            advance();
2769
 
            return v;
2770
 
        }
2771
 
    }
2772
 
 
2773
 
    function styleValue(v) {
2774
 
        var i = 0,
2775
 
            n,
2776
 
            once,
2777
 
            match,
2778
 
            round,
2779
 
            start = 0,
2780
 
            vi;
2781
 
        switch (typeof v) {
2782
 
        case 'function':
2783
 
            return v();
2784
 
        case 'string':
2785
 
            if (nexttoken.identifier && nexttoken.value === v) {
2786
 
                advance();
2787
 
                return true;
2788
 
            }
2789
 
            return false;
2790
 
        }
2791
 
        for (;;) {
2792
 
            if (i >= v.length) {
2793
 
                return false;
2794
 
            }
2795
 
            vi = v[i];
2796
 
            i += 1;
2797
 
            if (vi === true) {
2798
 
                break;
2799
 
            } else if (typeof vi === 'number') {
2800
 
                n = vi;
2801
 
                vi = v[i];
2802
 
                i += 1;
2803
 
            } else {
2804
 
                n = 1;
2805
 
            }
2806
 
            match = false;
2807
 
            while (n > 0) {
2808
 
                if (styleValue(vi)) {
2809
 
                    match = true;
2810
 
                    n -= 1;
2811
 
                } else {
2812
 
                    break;
2813
 
                }
2814
 
            }
2815
 
            if (match) {
2816
 
                return true;
2817
 
            }
2818
 
        }
2819
 
        start = i;
2820
 
        once = [];
2821
 
        for (;;) {
2822
 
            round = false;
2823
 
            for (i = start; i < v.length; i += 1) {
2824
 
                if (!once[i]) {
2825
 
                    if (styleValue(cssAttributeData[v[i]])) {
2826
 
                        match = true;
2827
 
                        round = true;
2828
 
                        once[i] = true;
2829
 
                        break;
2830
 
                    }
2831
 
                }
2832
 
            }
2833
 
            if (!round) {
2834
 
                return match;
2835
 
            }
2836
 
        }
2837
 
    }
2838
 
 
2839
 
    function substyle() {
2840
 
        var v;
2841
 
        for (;;) {
2842
 
            if (nexttoken.id === '}' || nexttoken.id === '(end)' ||
2843
 
                    xquote && nexttoken.id === xquote) {
2844
 
                return;
2845
 
            }
2846
 
            while (nexttoken.id === ';') {
2847
 
                warning("Misplaced ';'.");
2848
 
                advance(';');
2849
 
            }
2850
 
            v = styleAttribute();
2851
 
            advance(':');
2852
 
            if (nexttoken.identifier && nexttoken.value === 'inherit') {
2853
 
                advance();
2854
 
            } else {
2855
 
                styleValue(v);
2856
 
            }
2857
 
            while (nexttoken.id !== ';' && nexttoken.id !== '!' &&
2858
 
                    nexttoken.id !== '}' && nexttoken.id !== '(end)' &&
2859
 
                    nexttoken.id !== xquote) {
2860
 
                warning("Unexpected token '{a}'.", nexttoken, nexttoken.value);
2861
 
                advance();
2862
 
            }
2863
 
            if (nexttoken.id === '!') {
2864
 
                advance('!');
2865
 
                adjacent();
2866
 
                if (nexttoken.identifier && nexttoken.value === 'important') {
2867
 
                    advance();
2868
 
                } else {
2869
 
                    warning("Expected '{a}' and instead saw '{b}'.",
2870
 
                        nexttoken, 'important', nexttoken.value);
2871
 
                }
2872
 
            }
2873
 
            if (nexttoken.id === '}' || nexttoken.id === xquote) {
2874
 
                warning("Missing '{a}'.", nexttoken, ';');
2875
 
            } else {
2876
 
                advance(';');
2877
 
            }
2878
 
        }
2879
 
    }
2880
 
 
2881
 
    function stylePattern() {
2882
 
        var name;
2883
 
        if (nexttoken.id === '{') {
2884
 
            warning("Expected a style pattern, and instead saw '{a}'.", nexttoken,
2885
 
                nexttoken.id);
2886
 
        } else if (nexttoken.id === '@') {
2887
 
            advance('@');
2888
 
            name = nexttoken.value;
2889
 
            if (nexttoken.identifier && atrule[name] === true) {
2890
 
                advance();
2891
 
                return name;
2892
 
            }
2893
 
            warning("Expected an at-rule, and instead saw @{a}.", nexttoken, name);
2894
 
        }
2895
 
        for (;;) {
2896
 
            if (nexttoken.identifier) {
2897
 
                if (!htmltag.hasOwnProperty(nexttoken.value)) {
2898
 
                    warning("Expected a tagName, and instead saw {a}.",
2899
 
                        nexttoken, nexttoken.value);
2900
 
                }
2901
 
                advance();
2902
 
            } else {
2903
 
                switch (nexttoken.id) {
2904
 
                case '>':
2905
 
                case '+':
2906
 
                    advance();
2907
 
                    if (!nexttoken.identifier ||
2908
 
                            !htmltag.hasOwnProperty(nexttoken.value)) {
2909
 
                        warning("Expected a tagName, and instead saw {a}.",
2910
 
                            nexttoken, nexttoken.value);
2911
 
                    }
2912
 
                    advance();
2913
 
                    break;
2914
 
                case ':':
2915
 
                    advance(':');
2916
 
                    if (pseudorule[nexttoken.value] !== true) {
2917
 
                        warning("Expected a pseudo, and instead saw :{a}.",
2918
 
                            nexttoken, nexttoken.value);
2919
 
                    }
2920
 
                    advance();
2921
 
                    if (nexttoken.value === 'lang') {
2922
 
                        advance('(');
2923
 
                        if (!nexttoken.identifier) {
2924
 
                            warning("Expected a lang code, and instead saw :{a}.",
2925
 
                                nexttoken, nexttoken.value);
2926
 
                        }
2927
 
                        advance(')');
2928
 
                    }
2929
 
                    break;
2930
 
                case '#':
2931
 
                    advance('#');
2932
 
                    if (!nexttoken.identifier) {
2933
 
                        warning("Expected an id, and instead saw #{a}.",
2934
 
                            nexttoken, nexttoken.value);
2935
 
                    }
2936
 
                    advance();
2937
 
                    break;
2938
 
                case '*':
2939
 
                    advance('*');
2940
 
                    break;
2941
 
                case '.':
2942
 
                    advance('.');
2943
 
                    if (!nexttoken.identifier) {
2944
 
                        warning("Expected a class, and instead saw #.{a}.",
2945
 
                            nexttoken, nexttoken.value);
2946
 
                    }
2947
 
                    advance();
2948
 
                    break;
2949
 
                case '[':
2950
 
                    advance('[');
2951
 
                    if (!nexttoken.identifier) {
2952
 
                        warning("Expected an attribute, and instead saw [{a}].",
2953
 
                            nexttoken, nexttoken.value);
2954
 
                    }
2955
 
                    advance();
2956
 
                    if (nexttoken.id === '=' || nexttoken.id === '~=' ||
2957
 
                            nexttoken.id === '|=') {
2958
 
                        advance();
2959
 
                        if (nexttoken.type !== '(string)') {
2960
 
                            warning("Expected a string, and instead saw {a}.",
2961
 
                                nexttoken, nexttoken.value);
2962
 
                        }
2963
 
                        advance();
2964
 
                    }
2965
 
                    advance(']');
2966
 
                    break;
2967
 
                default:
2968
 
                    error("Expected a CSS selector, and instead saw {a}.",
2969
 
                        nexttoken, nexttoken.value);
2970
 
                }
2971
 
            }
2972
 
            if (nexttoken.id === '</' || nexttoken.id === '{' ||
2973
 
                    nexttoken.id === '(end)') {
2974
 
                return '';
2975
 
            }
2976
 
            if (nexttoken.id === ',') {
2977
 
                advance(',');
2978
 
            }
2979
 
        }
2980
 
    }
2981
 
 
2982
 
    function styles() {
2983
 
        while (nexttoken.id !== '</' && nexttoken.id !== '(end)') {
2984
 
            stylePattern();
2985
 
            xmode = 'styleproperty';
2986
 
            if (nexttoken.id === ';') {
2987
 
                advance(';');
2988
 
            } else {
2989
 
                advance('{');
2990
 
                substyle();
2991
 
                xmode = 'style';
2992
 
                advance('}');
2993
 
            }
2994
 
        }
2995
 
    }
2996
 
 
2997
 
 
2998
 
// HTML parsing.
2999
 
 
3000
 
    function doBegin(n) {
3001
 
        if (n !== 'html' && !option.fragment) {
3002
 
            if (n === 'div' && option.adsafe) {
3003
 
                error("ADSAFE: Use the fragment option.");
3004
 
            } else {
3005
 
                error("Expected '{a}' and instead saw '{b}'.",
3006
 
                    token, 'html', n);
3007
 
            }
3008
 
        }
3009
 
        if (option.adsafe) {
3010
 
            if (n === 'html') {
3011
 
                error("Currently, ADsafe does not operate on whole HTML documents. It operates on <div> fragments and .js files.", token);
3012
 
            }
3013
 
            if (option.fragment) {
3014
 
                if (n !== 'div') {
3015
 
                    error("ADsafe violation: Wrap the widget in a div.", token);
3016
 
                }
3017
 
            } else {
3018
 
                error("Use the fragment option.", token);
3019
 
            }
3020
 
        }
3021
 
        option.browser = true;
3022
 
        assume();
3023
 
    }
3024
 
 
3025
 
    function doAttribute(n, a, v) {
3026
 
        var u;
3027
 
        if (a === 'id') {
3028
 
            u = typeof v === 'string' ? v.toUpperCase() : '';
3029
 
            if (ids[u] === true) {
3030
 
                warning("Duplicate id='{a}'.", nexttoken, v);
3031
 
            }
3032
 
            ids[u] = true;
3033
 
            if (option.adsafe) {
3034
 
                if (adsafe_id) {
3035
 
                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {
3036
 
                        warning("ADsafe violation: An id must have a '{a}' prefix",
3037
 
                                nexttoken, adsafe_id);
3038
 
                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {
3039
 
                        warning("ADSAFE violation: bad id.");
3040
 
                    }
3041
 
                } else {
3042
 
                    adsafe_id = v;
3043
 
                    if (!/^[A-Z]+_$/.test(v)) {
3044
 
                        warning("ADSAFE violation: bad id.");
3045
 
                    }
3046
 
                }
3047
 
            }
3048
 
        } else if (a === 'href' || a === 'background' ||
3049
 
                a === 'content' || a === 'data' ||
3050
 
                a.indexOf('src') >= 0 || a.indexOf('url') >= 0) {
3051
 
            if (option.safe && ux.test(v)) {
3052
 
                error("ADsafe URL violation.");
3053
 
            }
3054
 
            urls.push(v);
3055
 
        } else if (a === 'for') {
3056
 
            if (option.adsafe) {
3057
 
                if (adsafe_id) {
3058
 
                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {
3059
 
                        warning("ADsafe violation: An id must have a '{a}' prefix",
3060
 
                                nexttoken, adsafe_id);
3061
 
                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {
3062
 
                        warning("ADSAFE violation: bad id.");
3063
 
                    }
3064
 
                } else {
3065
 
                    warning("ADSAFE violation: bad id.");
3066
 
                }
3067
 
            }
3068
 
        } else if (a === 'name') {
3069
 
            if (option.adsafe && v.indexOf('_') >= 0) {
3070
 
                warning("ADsafe name violation.");
3071
 
            }
3072
 
        }
3073
 
    }
3074
 
 
3075
 
    function doTag(n, a) {
3076
 
        var i, t = htmltag[n], x;
3077
 
        src = false;
3078
 
        if (!t) {
3079
 
            error("Unrecognized tag '<{a}>'.",
3080
 
                    nexttoken,
3081
 
                    n === n.toLowerCase() ? n :
3082
 
                        n + ' (capitalization error)');
3083
 
        }
3084
 
        if (stack.length > 0) {
3085
 
            if (n === 'html') {
3086
 
                error("Too many <html> tags.", token);
3087
 
            }
3088
 
            x = t.parent;
3089
 
            if (x) {
3090
 
                if (x.indexOf(' ' + stack[stack.length - 1].name + ' ') < 0) {
3091
 
                    error("A '<{a}>' must be within '<{b}>'.",
3092
 
                            token, n, x);
3093
 
                }
3094
 
            } else if (!option.adsafe || !option.fragment) {
3095
 
                i = stack.length;
3096
 
                do {
3097
 
                    if (i <= 0) {
3098
 
                        error("A '<{a}>' must be within '<{b}>'.",
3099
 
                                token, n, 'body');
3100
 
                    }
3101
 
                    i -= 1;
3102
 
                } while (stack[i].name !== 'body');
3103
 
            }
3104
 
        }
3105
 
        switch (n) {
3106
 
        case 'div':
3107
 
            if (option.adsafe && stack.length === 1 && !adsafe_id) {
3108
 
                warning("ADSAFE violation: missing ID_.");
3109
 
            }
3110
 
            break;
3111
 
        case 'script':
3112
 
            xmode = 'script';
3113
 
            advance('>');
3114
 
            indent = nexttoken.from;
3115
 
            if (a.lang) {
3116
 
                warning("lang is deprecated.", token);
3117
 
            }
3118
 
            if (option.adsafe && stack.length !== 1) {
3119
 
                warning("ADsafe script placement violation.", token);
3120
 
            }
3121
 
            if (a.src) {
3122
 
                if (option.adsafe && (!adsafe_may || !approved[a.src])) {
3123
 
                    warning("ADsafe unapproved script source.", token);
3124
 
                }
3125
 
                if (a.type) {
3126
 
                    warning("type is unnecessary.", token);
3127
 
                }
3128
 
            } else {
3129
 
                if (adsafe_went) {
3130
 
                    error("ADsafe script violation.", token);
3131
 
                }
3132
 
                statements('script');
3133
 
            }
3134
 
            xmode = 'html';
3135
 
            advance('</');
3136
 
            if (!nexttoken.identifier && nexttoken.value !== 'script') {
3137
 
                warning("Expected '{a}' and instead saw '{b}'.",
3138
 
                        nexttoken, 'script', nexttoken.value);
3139
 
            }
3140
 
            advance();
3141
 
            xmode = 'outer';
3142
 
            break;
3143
 
        case 'style':
3144
 
            xmode = 'style';
3145
 
            advance('>');
3146
 
            styles();
3147
 
            xmode = 'html';
3148
 
            advance('</');
3149
 
            if (!nexttoken.identifier && nexttoken.value !== 'style') {
3150
 
                warning("Expected '{a}' and instead saw '{b}'.",
3151
 
                        nexttoken, 'style', nexttoken.value);
3152
 
            }
3153
 
            advance();
3154
 
            xmode = 'outer';
3155
 
            break;
3156
 
        case 'input':
3157
 
            switch (a.type) {
3158
 
            case 'radio':
3159
 
            case 'checkbox':
3160
 
            case 'text':
3161
 
            case 'button':
3162
 
            case 'file':
3163
 
            case 'reset':
3164
 
            case 'submit':
3165
 
            case 'password':
3166
 
            case 'file':
3167
 
            case 'hidden':
3168
 
            case 'image':
3169
 
                break;
3170
 
            default:
3171
 
                warning("Bad input type.");
3172
 
            }
3173
 
            if (option.adsafe && a.autocomplete !== 'off') {
3174
 
                warning("ADsafe autocomplete violation.");
3175
 
            }
3176
 
            break;
3177
 
        case 'applet':
3178
 
        case 'body':
3179
 
        case 'embed':
3180
 
        case 'frame':
3181
 
        case 'frameset':
3182
 
        case 'head':
3183
 
        case 'iframe':
3184
 
        case 'img':
3185
 
        case 'object':
3186
 
        case 'param':
3187
 
            if (option.adsafe) {
3188
 
                warning("ADsafe violation: Disallowed tag: " + n);
3189
 
            }
3190
 
            break;
3191
 
        }
3192
 
    }
3193
 
 
3194
 
 
3195
 
    function closetag(n) {
3196
 
        return '</' + n + '>';
3197
 
    }
3198
 
 
3199
 
    function html() {
3200
 
        var a, attributes, e, n, q, t, v, wmode;
3201
 
        xmode = 'html';
3202
 
        xquote = '';
3203
 
        stack = null;
3204
 
        for (;;) {
3205
 
            switch (nexttoken.value) {
3206
 
            case '<':
3207
 
                xmode = 'html';
3208
 
                advance('<');
3209
 
                attributes = {};
3210
 
                t = nexttoken;
3211
 
                if (!t.identifier) {
3212
 
                    warning("Bad identifier {a}.", t, t.value);
3213
 
                }
3214
 
                n = t.value;
3215
 
                if (option.cap) {
3216
 
                    n = n.toLowerCase();
3217
 
                }
3218
 
                t.name = n;
3219
 
                advance();
3220
 
                if (!stack) {
3221
 
                    stack = [];
3222
 
                    doBegin(n);
3223
 
                }
3224
 
                v = htmltag[n];
3225
 
                if (typeof v !== 'object') {
3226
 
                    error("Unrecognized tag '<{a}>'.", t, n);
3227
 
                }
3228
 
                e = v.empty;
3229
 
                t.type = n;
3230
 
                for (;;) {
3231
 
                    if (nexttoken.id === '/') {
3232
 
                        advance('/');
3233
 
                        if (nexttoken.id !== '>') {
3234
 
                            warning("Expected '{a}' and instead saw '{b}'.",
3235
 
                                    nexttoken, '>', nexttoken.value);
3236
 
                        }
3237
 
                        break;
3238
 
                    }
3239
 
                    if (nexttoken.id && nexttoken.id.substr(0, 1) === '>') {
3240
 
                        break;
3241
 
                    }
3242
 
                    if (!nexttoken.identifier) {
3243
 
                        if (nexttoken.id === '(end)' || nexttoken.id === '(error)') {
3244
 
                            error("Missing '>'.", nexttoken);
3245
 
                        }
3246
 
                        warning("Bad identifier.");
3247
 
                    }
3248
 
                    a = nexttoken.value;
3249
 
                    advance();
3250
 
                    if (!option.cap && a !== a.toLowerCase()) {
3251
 
                        warning("Attribute '{a}' not all lower case.", nexttoken, a);
3252
 
                    }
3253
 
                    a = a.toLowerCase();
3254
 
                    xquote = '';
3255
 
                    if (attributes.hasOwnProperty(a)) {
3256
 
                        warning("Attribute '{a}' repeated.", nexttoken, a);
3257
 
                    }
3258
 
                    if (a.slice(0, 2) === 'on') {
3259
 
                        if (!option.on) {
3260
 
                            warning("Avoid HTML event handlers.");
3261
 
                        }
3262
 
                        xmode = 'scriptstring';
3263
 
                        advance('=');
3264
 
                        q = nexttoken.id;
3265
 
                        if (q !== '"' && q !== "'") {
3266
 
                            error("Missing quote.");
3267
 
                        }
3268
 
                        xquote = q;
3269
 
                        wmode = option.white;
3270
 
                        option.white = false;
3271
 
                        advance(q);
3272
 
                        statements('on');
3273
 
                        option.white = wmode;
3274
 
                        if (nexttoken.id !== q) {
3275
 
                            error("Missing close quote on script attribute.");
3276
 
                        }
3277
 
                        xmode = 'html';
3278
 
                        xquote = '';
3279
 
                        advance(q);
3280
 
                        v = false;
3281
 
                    } else if (a === 'style') {
3282
 
                        xmode = 'scriptstring';
3283
 
                        advance('=');
3284
 
                        q = nexttoken.id;
3285
 
                        if (q !== '"' && q !== "'") {
3286
 
                            error("Missing quote.");
3287
 
                        }
3288
 
                        xmode = 'styleproperty';
3289
 
                        xquote = q;
3290
 
                        advance(q);
3291
 
                        substyle();
3292
 
                        xmode = 'html';
3293
 
                        xquote = '';
3294
 
                        advance(q);
3295
 
                        v = false;
3296
 
                    } else {
3297
 
                        if (nexttoken.id === '=') {
3298
 
                            advance('=');
3299
 
                            v = nexttoken.value;
3300
 
                            if (!nexttoken.identifier &&
3301
 
                                    nexttoken.id !== '"' &&
3302
 
                                    nexttoken.id !== '\'' &&
3303
 
                                    nexttoken.type !== '(string)' &&
3304
 
                                    nexttoken.type !== '(number)' &&
3305
 
                                    nexttoken.type !== '(color)') {
3306
 
                                warning("Expected an attribute value and instead saw '{a}'.", token, a);
3307
 
                            }
3308
 
                            advance();
3309
 
                        } else {
3310
 
                            v = true;
3311
 
                        }
3312
 
                    }
3313
 
                    attributes[a] = v;
3314
 
                    doAttribute(n, a, v);
3315
 
                }
3316
 
                doTag(n, attributes);
3317
 
                if (!e) {
3318
 
                    stack.push(t);
3319
 
                }
3320
 
                xmode = 'outer';
3321
 
                advance('>');
3322
 
                break;
3323
 
            case '</':
3324
 
                xmode = 'html';
3325
 
                advance('</');
3326
 
                if (!nexttoken.identifier) {
3327
 
                    warning("Bad identifier.");
3328
 
                }
3329
 
                n = nexttoken.value;
3330
 
                if (option.cap) {
3331
 
                    n = n.toLowerCase();
3332
 
                }
3333
 
                advance();
3334
 
                if (!stack) {
3335
 
                    error("Unexpected '{a}'.", nexttoken, closetag(n));
3336
 
                }
3337
 
                t = stack.pop();
3338
 
                if (!t) {
3339
 
                    error("Unexpected '{a}'.", nexttoken, closetag(n));
3340
 
                }
3341
 
                if (t.name !== n) {
3342
 
                    error("Expected '{a}' and instead saw '{b}'.",
3343
 
                            nexttoken, closetag(t.name), closetag(n));
3344
 
                }
3345
 
                if (nexttoken.id !== '>') {
3346
 
                    error("Missing '{a}'.", nexttoken, '>');
3347
 
                }
3348
 
                xmode = 'outer';
3349
 
                advance('>');
3350
 
                break;
3351
 
            case '<!':
3352
 
                if (option.safe) {
3353
 
                    error("ADsafe HTML violation.");
3354
 
                }
3355
 
                xmode = 'outer';
3356
 
                v = false;
3357
 
                for (;;) {
3358
 
                    advance();
3359
 
                    if (nexttoken.id === '>') {
3360
 
                        break;
3361
 
                    }
3362
 
                    if (nexttoken.id === '<' || nexttoken.id === '(end)') {
3363
 
                        error("Missing '{a}'.", token, '>');
3364
 
                    }
3365
 
                    if (nexttoken.id === '--') {
3366
 
                        v = !v;
3367
 
                    }
3368
 
                }
3369
 
                if (v) {
3370
 
                    warning("Misshapen HTML comment.");
3371
 
                }
3372
 
                xmode = 'html';
3373
 
                advance('>');
3374
 
                break;
3375
 
            case '(end)':
3376
 
                return;
3377
 
            default:
3378
 
                if (nexttoken.id === '(end)') {
3379
 
                    error("Missing '{a}'.", nexttoken, '</html>');
3380
 
                } else if (nexttoken.id !== '--' && nexttoken.id !== '#') {
3381
 
                    error("Unexpected '{a}'.", nexttoken, nexttoken.value);
3382
 
                } else {
3383
 
                    advance();
3384
 
                }
3385
 
            }
3386
 
            if (stack && stack.length === 0) {
3387
 
                break;
3388
 
            }
3389
 
        }
3390
 
        if (nexttoken.id !== '(end)') {
3391
 
            error("Unexpected material after the end.");
3392
 
        }
3393
 
    }
3394
 
 
3395
 
 
3396
 
// Build the syntax table by declaring the syntactic elements of the language.
3397
 
 
3398
 
    type('(number)', idValue);
3399
 
    type('(string)', idValue);
3400
 
 
3401
 
    syntax['(identifier)'] = {
3402
 
        type: '(identifier)',
3403
 
        lbp: 0,
3404
 
        identifier: true,
3405
 
        nud: function () {
3406
 
            var v = this.value,
3407
 
                s = scope[v];
3408
 
 
3409
 
// The name is in scope and defined in the current function.
3410
 
 
3411
 
            if (s && (s === funct || s === funct['(global)'])) {
3412
 
 
3413
 
//      If we are not also in the global scope, change 'unused' to 'var',
3414
 
//      and reject labels.
3415
 
 
3416
 
                if (!funct['(global)']) {
3417
 
                    switch (funct[v]) {
3418
 
                    case 'unused':
3419
 
                        funct[v] = 'var';
3420
 
                        break;
3421
 
                    case 'label':
3422
 
                        warning("'{a}' is a statement label.", token, v);
3423
 
                        break;
3424
 
                    }
3425
 
                }
3426
 
 
3427
 
// The name is not defined in the function.  If we are in the global scope,
3428
 
// then we have an undefined variable.
3429
 
 
3430
 
            } else if (funct['(global)']) {
3431
 
                if (option.undef) {
3432
 
                    warning("'{a}' is undefined.", token, v);
3433
 
                }
3434
 
                note_implied(token);
3435
 
 
3436
 
// If the name is already defined in the current
3437
 
// function, but not as outer, then there is a scope error.
3438
 
 
3439
 
            } else {
3440
 
                switch (funct[v]) {
3441
 
                case 'closure':
3442
 
                case 'function':
3443
 
                case 'var':
3444
 
                case 'unused':
3445
 
                    warning("'{a}' used out of scope.", token, v);
3446
 
                    break;
3447
 
                case 'label':
3448
 
                    warning("'{a}' is a statement label.", token, v);
3449
 
                    break;
3450
 
                case 'outer':
3451
 
                case true:
3452
 
                    break;
3453
 
                default:
3454
 
 
3455
 
// If the name is defined in an outer function, make an outer entry, and if
3456
 
// it was unused, make it var.
3457
 
 
3458
 
                    if (s === true) {
3459
 
                        funct[v] = true;
3460
 
                    } else if (typeof s !== 'object') {
3461
 
                        if (option.undef) {
3462
 
                            warning("'{a}' is undefined.", token, v);
3463
 
                        } else {
3464
 
                            funct[v] = true;
3465
 
                        }
3466
 
                        note_implied(token);
3467
 
                    } else {
3468
 
                        switch (s[v]) {
3469
 
                        case 'function':
3470
 
                        case 'var':
3471
 
                        case 'unused':
3472
 
                            s[v] = 'closure';
3473
 
                            funct[v] = 'outer';
3474
 
                            break;
3475
 
                        case 'closure':
3476
 
                        case 'parameter':
3477
 
                            funct[v] = 'outer';
3478
 
                            break;
3479
 
                        case 'label':
3480
 
                            warning("'{a}' is a statement label.", token, v);
3481
 
                        }
3482
 
                    }
3483
 
                }
3484
 
            }
3485
 
            return this;
3486
 
        },
3487
 
        led: function () {
3488
 
            error("Expected an operator and instead saw '{a}'.",
3489
 
                    nexttoken, nexttoken.value);
3490
 
        }
3491
 
    };
3492
 
 
3493
 
    type('(regex)', function () {
3494
 
        return this;
3495
 
    });
3496
 
 
3497
 
    delim('(endline)');
3498
 
    delim('(begin)');
3499
 
    delim('(end)').reach = true;
3500
 
    delim('</').reach = true;
3501
 
    delim('<!');
3502
 
    delim('(error)').reach = true;
3503
 
    delim('}').reach = true;
3504
 
    delim(')');
3505
 
    delim(']');
3506
 
    delim('"').reach = true;
3507
 
    delim("'").reach = true;
3508
 
    delim(';');
3509
 
    delim(':').reach = true;
3510
 
    delim(',');
3511
 
    delim('#');
3512
 
    delim('@');
3513
 
    reserve('else');
3514
 
    reserve('case').reach = true;
3515
 
    reserve('catch');
3516
 
    reserve('default').reach = true;
3517
 
    reserve('finally');
3518
 
    reservevar('arguments');
3519
 
    reservevar('eval');
3520
 
    reservevar('false');
3521
 
    reservevar('Infinity');
3522
 
    reservevar('NaN');
3523
 
    reservevar('null');
3524
 
    reservevar('this');
3525
 
    reservevar('true');
3526
 
    reservevar('undefined');
3527
 
    assignop('=', 'assign', 20);
3528
 
    assignop('+=', 'assignadd', 20);
3529
 
    assignop('-=', 'assignsub', 20);
3530
 
    assignop('*=', 'assignmult', 20);
3531
 
    assignop('/=', 'assigndiv', 20).nud = function () {
3532
 
        error("A regular expression literal can be confused with '/='.");
3533
 
    };
3534
 
    assignop('%=', 'assignmod', 20);
3535
 
    bitwiseassignop('&=', 'assignbitand', 20);
3536
 
    bitwiseassignop('|=', 'assignbitor', 20);
3537
 
    bitwiseassignop('^=', 'assignbitxor', 20);
3538
 
    bitwiseassignop('<<=', 'assignshiftleft', 20);
3539
 
    bitwiseassignop('>>=', 'assignshiftright', 20);
3540
 
    bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20);
3541
 
    infix('?', function (left) {
3542
 
        parse(10);
3543
 
        advance(':');
3544
 
        parse(10);
3545
 
    }, 30);
3546
 
 
3547
 
    infix('||', 'or', 40);
3548
 
    infix('&&', 'and', 50);
3549
 
    bitwise('|', 'bitor', 70);
3550
 
    bitwise('^', 'bitxor', 80);
3551
 
    bitwise('&', 'bitand', 90);
3552
 
    relation('==', function (left, right) {
3553
 
        if (option.eqeqeq) {
3554
 
            warning("Expected '{a}' and instead saw '{b}'.",
3555
 
                    this, '===', '==');
3556
 
        } else if (isPoorRelation(left)) {
3557
 
            warning("Use '{a}' to compare with '{b}'.",
3558
 
                this, '===', left.value);
3559
 
        } else if (isPoorRelation(right)) {
3560
 
            warning("Use '{a}' to compare with '{b}'.",
3561
 
                this, '===', right.value);
3562
 
        }
3563
 
        return this;
3564
 
    });
3565
 
    relation('===');
3566
 
    relation('!=', function (left, right) {
3567
 
        if (option.eqeqeq) {
3568
 
            warning("Expected '{a}' and instead saw '{b}'.",
3569
 
                    this, '!==', '!=');
3570
 
        } else if (isPoorRelation(left)) {
3571
 
            warning("Use '{a}' to compare with '{b}'.",
3572
 
                    this, '!==', left.value);
3573
 
        } else if (isPoorRelation(right)) {
3574
 
            warning("Use '{a}' to compare with '{b}'.",
3575
 
                    this, '!==', right.value);
3576
 
        }
3577
 
        return this;
3578
 
    });
3579
 
    relation('!==');
3580
 
    relation('<');
3581
 
    relation('>');
3582
 
    relation('<=');
3583
 
    relation('>=');
3584
 
    bitwise('<<', 'shiftleft', 120);
3585
 
    bitwise('>>', 'shiftright', 120);
3586
 
    bitwise('>>>', 'shiftrightunsigned', 120);
3587
 
    infix('in', 'in', 120);
3588
 
    infix('instanceof', 'instanceof', 120);
3589
 
    infix('+', function (left) {
3590
 
        nonadjacent(prevtoken, token);
3591
 
        nonadjacent(token, nexttoken);
3592
 
        var right = parse(130);
3593
 
        if (left && right && left.id === '(string)' && right.id === '(string)') {
3594
 
            left.value += right.value;
3595
 
            left.character = right.character;
3596
 
            if (jx.test(left.value)) {
3597
 
                warning("JavaScript URL.", left);
3598
 
            }
3599
 
            return left;
3600
 
        }
3601
 
        this.left = left;
3602
 
        this.right = right;
3603
 
        return this;
3604
 
    }, 130);
3605
 
    prefix('+', 'num');
3606
 
    infix('-', 'sub', 130);
3607
 
    prefix('-', 'neg');
3608
 
    infix('*', 'mult', 140);
3609
 
    infix('/', 'div', 140);
3610
 
    infix('%', 'mod', 140);
3611
 
 
3612
 
    suffix('++', 'postinc');
3613
 
    prefix('++', 'preinc');
3614
 
    syntax['++'].exps = true;
3615
 
 
3616
 
    suffix('--', 'postdec');
3617
 
    prefix('--', 'predec');
3618
 
    syntax['--'].exps = true;
3619
 
    prefix('delete', function () {
3620
 
        var p = parse(0);
3621
 
        if (p.id !== '.' && p.id !== '[') {
3622
 
            warning("Expected '{a}' and instead saw '{b}'.",
3623
 
                    nexttoken, '.', nexttoken.value);
3624
 
        }
3625
 
    }).exps = true;
3626
 
 
3627
 
 
3628
 
    prefix('~', function () {
3629
 
        if (option.bitwise) {
3630
 
            warning("Unexpected '{a}'.", this, '~');
3631
 
        }
3632
 
        parse(150);
3633
 
        return this;
3634
 
    });
3635
 
    prefix('!', 'not');
3636
 
    prefix('typeof', 'typeof');
3637
 
    prefix('new', function () {
3638
 
        var c = parse(155), i;
3639
 
        if (c && c.id !== 'function') {
3640
 
            if (c.identifier) {
3641
 
                c['new'] = true;
3642
 
                switch (c.value) {
3643
 
                case 'Object':
3644
 
                    warning("Use the object literal notation {}.", token);
3645
 
                    break;
3646
 
                case 'Array':
3647
 
                    warning("Use the array literal notation [].", token);
3648
 
                    break;
3649
 
                case 'Number':
3650
 
                case 'String':
3651
 
                case 'Boolean':
3652
 
                case 'Math':
3653
 
                    warning("Do not use the {a} function as a constructor.",
3654
 
                            token, c.value);
3655
 
                    break;
3656
 
                case 'Function':
3657
 
                    if (!option.evil) {
3658
 
                        warning("The Function constructor is eval.");
3659
 
                    }
3660
 
                    break;
3661
 
                case 'Date':
3662
 
                case 'RegExp':
3663
 
                    break;
3664
 
                default:
3665
 
                    if (c.id !== 'function') {
3666
 
                        i = c.value.substr(0, 1);
3667
 
                        if (i < 'A' || i > 'Z') {
3668
 
                            warning(
3669
 
                    "A constructor name should start with an uppercase letter.",
3670
 
                                token);
3671
 
                        }
3672
 
                    }
3673
 
                }
3674
 
            } else {
3675
 
                if (c.id !== '.' && c.id !== '[' && c.id !== '(') {
3676
 
                    warning("Bad constructor.", token);
3677
 
                }
3678
 
            }
3679
 
        } else {
3680
 
            warning("Weird construction. Delete 'new'.", this);
3681
 
        }
3682
 
        adjacent(token, nexttoken);
3683
 
        if (nexttoken.id !== '(') {
3684
 
            warning("Missing '()' invoking a constructor.");
3685
 
        }
3686
 
        this.first = c;
3687
 
        return this;
3688
 
    });
3689
 
    syntax['new'].exps = true;
3690
 
 
3691
 
    infix('.', function (left) {
3692
 
        adjacent(prevtoken, token);
3693
 
        var t = this, m = identifier();
3694
 
        if (typeof m === 'string') {
3695
 
            countMember(m);
3696
 
        }
3697
 
        t.left = left;
3698
 
        t.right = m;
3699
 
        if (!option.evil && left && left.value === 'document' &&
3700
 
                (m === 'write' || m === 'writeln')) {
3701
 
            warning("document.write can be a form of eval.", left);
3702
 
        }
3703
 
        if (option.adsafe) {
3704
 
            if (left && left.value === 'ADSAFE') {
3705
 
                if (m === 'id' || m === 'lib') {
3706
 
                    warning("ADsafe violation.", this);
3707
 
                } else if (m === 'go') {
3708
 
                    if (xmode !== 'script') {
3709
 
                        warning("ADsafe violation.", this);
3710
 
                    } else if (adsafe_went || nexttoken.id !== '(' ||
3711
 
                            peek(0).id !== '(string)' ||
3712
 
                            peek(0).value !== adsafe_id ||
3713
 
                            peek(1).id !== ',') {
3714
 
                        error("ADsafe violation: go.", this);
3715
 
                    }
3716
 
                    adsafe_went = true;
3717
 
                    adsafe_may = false;
3718
 
                }
3719
 
            }
3720
 
            for (;;) {
3721
 
                if (banned[m] === true) {
3722
 
                    warning("ADsafe restricted word '{a}'.", token, m);
3723
 
                }
3724
 
                if (predefined[left.value] !== true ||
3725
 
                        nexttoken.id === '(') {
3726
 
                    break;
3727
 
                }
3728
 
                if (standard_member[m] === true) {
3729
 
                    if (nexttoken.id === '.') {
3730
 
                        warning("ADsafe violation.", this);
3731
 
                    }
3732
 
                    break;
3733
 
                }
3734
 
                if (nexttoken.id !== '.') {
3735
 
                    warning("ADsafe violation.", this);
3736
 
                    break;
3737
 
                }
3738
 
                advance('.');
3739
 
                token.left = t;
3740
 
                token.right = m;
3741
 
                t = token;
3742
 
                m = identifier();
3743
 
                if (typeof m === 'string') {
3744
 
                    countMember(m);
3745
 
                }
3746
 
            }
3747
 
        }
3748
 
        return t;
3749
 
    }, 160);
3750
 
 
3751
 
    infix('(', function (left) {
3752
 
        adjacent(prevtoken, token);
3753
 
        nospace();
3754
 
        var n = 0,
3755
 
            p = [];
3756
 
        if (left) {
3757
 
            if (left.type === '(identifier)') {
3758
 
                if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
3759
 
                    if (left.value !== 'Number' && left.value !== 'String' &&
3760
 
                            left.value !== 'Boolean' && left.value !== 'Date') {
3761
 
                        if (left.value === 'Math') {
3762
 
                            warning("Math is not a function.", left);
3763
 
                        } else {
3764
 
                            warning("Missing 'new' prefix when invoking a constructor.",
3765
 
                                left);
3766
 
                        }
3767
 
                    }
3768
 
                }
3769
 
            } else if (left.id === '.') {
3770
 
                if (option.safe && left.left.value === 'Math' && left.right === 'random') {
3771
 
                    warning("ADsafe violation.", left);
3772
 
                }
3773
 
            }
3774
 
        }
3775
 
        if (nexttoken.id !== ')') {
3776
 
            for (;;) {
3777
 
                p[p.length] = parse(10);
3778
 
                n += 1;
3779
 
                if (nexttoken.id !== ',') {
3780
 
                    break;
3781
 
                }
3782
 
                advance(',');
3783
 
                nonadjacent(token, nexttoken);
3784
 
            }
3785
 
        }
3786
 
        advance(')');
3787
 
        nospace(prevtoken, token);
3788
 
        if (typeof left === 'object') {
3789
 
            if (left.value === 'parseInt' && n === 1) {
3790
 
                warning("Missing radix parameter.", left);
3791
 
            }
3792
 
            if (!option.evil) {
3793
 
                if (left.value === 'eval' || left.value === 'Function' || left.value === 'execScript') {
3794
 
                    warning("eval is evil.", left);
3795
 
                } else if (p[0] && p[0].id === '(string)' &&
3796
 
                       (left.value === 'setTimeout' ||
3797
 
                        left.value === 'setInterval')) {
3798
 
                    warning(
3799
 
    "Implied eval is evil. Pass a function instead of a string.", left);
3800
 
                }
3801
 
            }
3802
 
            if (!left.identifier && left.id !== '.' && left.id !== '[' &&
3803
 
                    left.id !== '(' && left.id !== '&&' && left.id !== '||' &&
3804
 
                    left.id !== '?') {
3805
 
                warning("Bad invocation.", left);
3806
 
            }
3807
 
 
3808
 
        }
3809
 
        this.left = left;
3810
 
        return this;
3811
 
    }, 155).exps = true;
3812
 
 
3813
 
    prefix('(', function () {
3814
 
        nospace();
3815
 
        var v = parse(0);
3816
 
        advance(')', this);
3817
 
        nospace(prevtoken, token);
3818
 
        if (v && (v.id === 'function' || v.id === 'new' || v.id === '.' ||
3819
 
                v.id === '[' || v.id === '(')) {
3820
 
            warning("Parens are not needed here.", this);
3821
 
        }
3822
 
        return v;
3823
 
    }).fud = function () {
3824
 
        nospace();
3825
 
        var v = parse(0);
3826
 
        advance(')', this);
3827
 
        if (v) {
3828
 
            if (v.id === 'function') {
3829
 
                advance('(');
3830
 
                return token.led(v);
3831
 
            }
3832
 
        }
3833
 
        nospace(prevtoken, token);
3834
 
        return v;
3835
 
    };
3836
 
 
3837
 
    infix('[', function (left) {
3838
 
        nospace();
3839
 
        var e = parse(0), s;
3840
 
        if (e && e.type === '(string)') {
3841
 
            if (option.safe && banned[e.value] === true) {
3842
 
                warning("ADsafe restricted word '{a}'.", this, e.value);
3843
 
            }
3844
 
            countMember(e.value);
3845
 
            if (!option.sub && ix.test(e.value)) {
3846
 
                s = syntax[e.value];
3847
 
                if (!s || !s.reserved) {
3848
 
                    warning("['{a}'] is better written in dot notation.",
3849
 
                            e, e.value);
3850
 
                }
3851
 
            }
3852
 
        } else if (!e || (e.type !== '(number)' &&
3853
 
                (e.id !== '+' || e.arity !== 'unary'))) {
3854
 
            if (option.safe) {
3855
 
                warning('ADsafe subscripting.');
3856
 
            }
3857
 
        }
3858
 
        advance(']', this);
3859
 
        nospace(prevtoken, token);
3860
 
        this.left = left;
3861
 
        this.right = e;
3862
 
        return this;
3863
 
    }, 160);
3864
 
 
3865
 
    prefix('[', function () {
3866
 
        if (nexttoken.id === ']') {
3867
 
            advance(']');
3868
 
            return;
3869
 
        }
3870
 
        var b = token.line !== nexttoken.line;
3871
 
        if (b) {
3872
 
            indent += option.indent;
3873
 
            if (nexttoken.from === indent + option.indent) {
3874
 
                indent += option.indent;
3875
 
            }
3876
 
        }
3877
 
        for (;;) {
3878
 
            if (b && token.line !== nexttoken.line) {
3879
 
                indentation();
3880
 
            }
3881
 
            parse(10);
3882
 
            if (nexttoken.id === ',') {
3883
 
                adjacent(token, nexttoken);
3884
 
                advance(',');
3885
 
                if (nexttoken.id === ',') {
3886
 
                    warning("Extra comma.", token);
3887
 
                } else if (nexttoken.id === ']') {
3888
 
                    warning("Extra comma.", token);
3889
 
                    break;
3890
 
                }
3891
 
                nonadjacent(token, nexttoken);
3892
 
            } else {
3893
 
                if (b) {
3894
 
                    indent -= option.indent;
3895
 
                    indentation();
3896
 
                }
3897
 
                break;
3898
 
            }
3899
 
        }
3900
 
        advance(']', this);
3901
 
        return;
3902
 
    }, 160);
3903
 
 
3904
 
    (function (x) {
3905
 
        x.nud = function () {
3906
 
            var b, i, s;
3907
 
            if (nexttoken.id === '}') {
3908
 
                advance('}');
3909
 
                return;
3910
 
            }
3911
 
            b = token.line !== nexttoken.line;
3912
 
            if (b) {
3913
 
                indent += option.indent;
3914
 
                if (nexttoken.from === indent + option.indent) {
3915
 
                    indent += option.indent;
3916
 
                }
3917
 
            }
3918
 
            for (;;) {
3919
 
                if (b) {
3920
 
                    indentation();
3921
 
                }
3922
 
                i = optionalidentifier(true);
3923
 
                if (!i) {
3924
 
                    if (nexttoken.id === '(string)') {
3925
 
                        i = nexttoken.value;
3926
 
                        if (ix.test(i)) {
3927
 
                            s = syntax[i];
3928
 
                        }
3929
 
                        advance();
3930
 
                    } else if (nexttoken.id === '(number)') {
3931
 
                        i = nexttoken.value.toString();
3932
 
                        advance();
3933
 
                    } else {
3934
 
                        error("Expected '{a}' and instead saw '{b}'.",
3935
 
                                nexttoken, '}', nexttoken.value);
3936
 
                    }
3937
 
                }
3938
 
                countMember(i);
3939
 
                advance(':');
3940
 
                nonadjacent(token, nexttoken);
3941
 
                parse(10);
3942
 
                if (nexttoken.id === ',') {
3943
 
                    adjacent(token, nexttoken);
3944
 
                    advance(',');
3945
 
                    if (nexttoken.id === ',' || nexttoken.id === '}') {
3946
 
                        warning("Extra comma.", token);
3947
 
                    }
3948
 
                    nonadjacent(token, nexttoken);
3949
 
                } else {
3950
 
                    if (b) {
3951
 
                        indent -= option.indent;
3952
 
                        indentation();
3953
 
                    }
3954
 
                    advance('}', this);
3955
 
                    return;
3956
 
                }
3957
 
            }
3958
 
        };
3959
 
        x.fud = function () {
3960
 
            error("Expected to see a statement and instead saw a block.", token);
3961
 
        };
3962
 
    })(delim('{'));
3963
 
 
3964
 
 
3965
 
    function varstatement(prefix) {
3966
 
 
3967
 
// JavaScript does not have block scope. It only has function scope. So,
3968
 
// declaring a variable in a block can have unexpected consequences.
3969
 
 
3970
 
        if (funct['(onevar)'] && option.onevar) {
3971
 
            warning("Too many var statements.");
3972
 
        } else if (!funct['(global)']) {
3973
 
            funct['(onevar)'] = true;
3974
 
        }
3975
 
        for (;;) {
3976
 
            nonadjacent(token, nexttoken);
3977
 
            addlabel(identifier(), 'unused');
3978
 
            if (prefix) {
3979
 
                return;
3980
 
            }
3981
 
            if (nexttoken.id === '=') {
3982
 
                nonadjacent(token, nexttoken);
3983
 
                advance('=');
3984
 
                nonadjacent(token, nexttoken);
3985
 
                if (peek(0).id === '=') {
3986
 
                    error("Variable {a} was not declared correctly.",
3987
 
                            nexttoken, nexttoken.value);
3988
 
                }
3989
 
                parse(20);
3990
 
            }
3991
 
            if (nexttoken.id !== ',') {
3992
 
                return;
3993
 
            }
3994
 
            adjacent(token, nexttoken);
3995
 
            advance(',');
3996
 
            nonadjacent(token, nexttoken);
3997
 
        }
3998
 
    }
3999
 
 
4000
 
 
4001
 
    stmt('var', varstatement);
4002
 
 
4003
 
    stmt('new', function () {
4004
 
        error("'new' should not be used as a statement.");
4005
 
    });
4006
 
 
4007
 
 
4008
 
    function functionparams() {
4009
 
        var i, t = nexttoken, p = [];
4010
 
        advance('(');
4011
 
        nospace();
4012
 
        if (nexttoken.id === ')') {
4013
 
            advance(')');
4014
 
            nospace(prevtoken, token);
4015
 
            return;
4016
 
        }
4017
 
        for (;;) {
4018
 
            i = identifier();
4019
 
            p.push(i);
4020
 
            addlabel(i, 'parameter');
4021
 
            if (nexttoken.id === ',') {
4022
 
                advance(',');
4023
 
                nonadjacent(token, nexttoken);
4024
 
            } else {
4025
 
                advance(')', t);
4026
 
                nospace(prevtoken, token);
4027
 
                return p.join(', ');
4028
 
            }
4029
 
        }
4030
 
    }
4031
 
 
4032
 
    function doFunction(i) {
4033
 
        var s = scope;
4034
 
        scope = Object.create(s);
4035
 
        funct = {
4036
 
            '(name)'    : i || '"' + anonname + '"',
4037
 
            '(line)'    : nexttoken.line + 1,
4038
 
            '(context)' : funct,
4039
 
            '(breakage)': 0,
4040
 
            '(loopage)' : 0,
4041
 
            '(scope)'   : scope
4042
 
        };
4043
 
        functions.push(funct);
4044
 
        if (i) {
4045
 
            addlabel(i, 'function');
4046
 
        }
4047
 
        funct['(params)'] = functionparams();
4048
 
 
4049
 
        block(false);
4050
 
        scope = s;
4051
 
        funct = funct['(context)'];
4052
 
    }
4053
 
 
4054
 
 
4055
 
    blockstmt('function', function () {
4056
 
        if (inblock) {
4057
 
            warning(
4058
 
"Function statements cannot be placed in blocks. Use a function expression or move the statement to the top of the outer function.", token);
4059
 
 
4060
 
        }
4061
 
        var i = identifier();
4062
 
        adjacent(token, nexttoken);
4063
 
        addlabel(i, 'unused');
4064
 
        doFunction(i);
4065
 
        if (nexttoken.id === '(' && nexttoken.line === token.line) {
4066
 
            error(
4067
 
"Function statements are not invocable. Wrap the function expression in parens.");
4068
 
        }
4069
 
    });
4070
 
 
4071
 
    prefix('function', function () {
4072
 
        var i = optionalidentifier();
4073
 
        if (i) {
4074
 
            adjacent(token, nexttoken);
4075
 
        } else {
4076
 
            nonadjacent(token, nexttoken);
4077
 
        }
4078
 
        doFunction(i);
4079
 
        if (funct['(loopage)'] && nexttoken.id !== '(') {
4080
 
            warning("Be careful when making functions within a loop. Consider putting the function in a closure.");
4081
 
        }
4082
 
        return this;
4083
 
    });
4084
 
 
4085
 
    blockstmt('if', function () {
4086
 
        var t = nexttoken;
4087
 
        advance('(');
4088
 
        nonadjacent(this, t);
4089
 
        nospace();
4090
 
        parse(20);
4091
 
        if (nexttoken.id === '=') {
4092
 
            warning("Expected a conditional expression and instead saw an assignment.");
4093
 
            advance('=');
4094
 
            parse(20);
4095
 
        }
4096
 
        advance(')', t);
4097
 
        nospace(prevtoken, token);
4098
 
        block(true);
4099
 
        if (nexttoken.id === 'else') {
4100
 
            nonadjacent(token, nexttoken);
4101
 
            advance('else');
4102
 
            if (nexttoken.id === 'if' || nexttoken.id === 'switch') {
4103
 
                statement(true);
4104
 
            } else {
4105
 
                block(true);
4106
 
            }
4107
 
        }
4108
 
        return this;
4109
 
    });
4110
 
 
4111
 
    blockstmt('try', function () {
4112
 
        var b, e, s;
4113
 
        if (option.adsafe) {
4114
 
            warning("ADsafe try violation.", this);
4115
 
        }
4116
 
        block(false);
4117
 
        if (nexttoken.id === 'catch') {
4118
 
            advance('catch');
4119
 
            nonadjacent(token, nexttoken);
4120
 
            advance('(');
4121
 
            s = scope;
4122
 
            scope = Object.create(s);
4123
 
            e = nexttoken.value;
4124
 
            if (nexttoken.type !== '(identifier)') {
4125
 
                warning("Expected an identifier and instead saw '{a}'.",
4126
 
                    nexttoken, e);
4127
 
            } else {
4128
 
                addlabel(e, 'unused');
4129
 
            }
4130
 
            advance();
4131
 
            advance(')');
4132
 
            block(false);
4133
 
            b = true;
4134
 
            scope = s;
4135
 
        }
4136
 
        if (nexttoken.id === 'finally') {
4137
 
            advance('finally');
4138
 
            block(false);
4139
 
            return;
4140
 
        } else if (!b) {
4141
 
            error("Expected '{a}' and instead saw '{b}'.",
4142
 
                    nexttoken, 'catch', nexttoken.value);
4143
 
        }
4144
 
    });
4145
 
 
4146
 
    blockstmt('while', function () {
4147
 
        var t = nexttoken;
4148
 
        funct['(breakage)'] += 1;
4149
 
        funct['(loopage)'] += 1;
4150
 
        advance('(');
4151
 
        nonadjacent(this, t);
4152
 
        nospace();
4153
 
        parse(20);
4154
 
        if (nexttoken.id === '=') {
4155
 
            warning("Expected a conditional expression and instead saw an assignment.");
4156
 
            advance('=');
4157
 
            parse(20);
4158
 
        }
4159
 
        advance(')', t);
4160
 
        nospace(prevtoken, token);
4161
 
        block(true);
4162
 
        funct['(breakage)'] -= 1;
4163
 
        funct['(loopage)'] -= 1;
4164
 
    }).labelled = true;
4165
 
 
4166
 
    reserve('with');
4167
 
 
4168
 
    blockstmt('switch', function () {
4169
 
        var t = nexttoken,
4170
 
            g = false;
4171
 
        funct['(breakage)'] += 1;
4172
 
        advance('(');
4173
 
        nonadjacent(this, t);
4174
 
        nospace();
4175
 
        this.condition = parse(20);
4176
 
        advance(')', t);
4177
 
        nospace(prevtoken, token);
4178
 
        nonadjacent(token, nexttoken);
4179
 
        t = nexttoken;
4180
 
        advance('{');
4181
 
        nonadjacent(token, nexttoken);
4182
 
        indent += option.indent;
4183
 
        this.cases = [];
4184
 
        for (;;) {
4185
 
            switch (nexttoken.id) {
4186
 
            case 'case':
4187
 
                switch (funct['(verb)']) {
4188
 
                case 'break':
4189
 
                case 'case':
4190
 
                case 'continue':
4191
 
                case 'return':
4192
 
                case 'switch':
4193
 
                case 'throw':
4194
 
                    break;
4195
 
                default:
4196
 
                    warning(
4197
 
                        "Expected a 'break' statement before 'case'.",
4198
 
                        token);
4199
 
                }
4200
 
                indentation(-option.indent);
4201
 
                advance('case');
4202
 
                this.cases.push(parse(20));
4203
 
                g = true;
4204
 
                advance(':');
4205
 
                funct['(verb)'] = 'case';
4206
 
                break;
4207
 
            case 'default':
4208
 
                switch (funct['(verb)']) {
4209
 
                case 'break':
4210
 
                case 'continue':
4211
 
                case 'return':
4212
 
                case 'throw':
4213
 
                    break;
4214
 
                default:
4215
 
                    warning(
4216
 
                        "Expected a 'break' statement before 'default'.",
4217
 
                        token);
4218
 
                }
4219
 
                indentation(-option.indent);
4220
 
                advance('default');
4221
 
                g = true;
4222
 
                advance(':');
4223
 
                break;
4224
 
            case '}':
4225
 
                indent -= option.indent;
4226
 
                indentation();
4227
 
                advance('}', t);
4228
 
                if (this.cases.length === 1 || this.condition.id === 'true' ||
4229
 
                        this.condition.id === 'false') {
4230
 
                    warning("This 'switch' should be an 'if'.", this);
4231
 
                }
4232
 
                funct['(breakage)'] -= 1;
4233
 
                funct['(verb)'] = undefined;
4234
 
                return;
4235
 
            case '(end)':
4236
 
                error("Missing '{a}'.", nexttoken, '}');
4237
 
                return;
4238
 
            default:
4239
 
                if (g) {
4240
 
                    switch (token.id) {
4241
 
                    case ',':
4242
 
                        error("Each value should have its own case label.");
4243
 
                        return;
4244
 
                    case ':':
4245
 
                        statements();
4246
 
                        break;
4247
 
                    default:
4248
 
                        error("Missing ':' on a case clause.", token);
4249
 
                    }
4250
 
                } else {
4251
 
                    error("Expected '{a}' and instead saw '{b}'.",
4252
 
                        nexttoken, 'case', nexttoken.value);
4253
 
                }
4254
 
            }
4255
 
        }
4256
 
    }).labelled = true;
4257
 
 
4258
 
    stmt('debugger', function () {
4259
 
        if (!option.debug) {
4260
 
            warning("All 'debugger' statements should be removed.");
4261
 
        }
4262
 
    });
4263
 
 
4264
 
    stmt('do', function () {
4265
 
        funct['(breakage)'] += 1;
4266
 
        funct['(loopage)'] += 1;
4267
 
        block(true);
4268
 
        advance('while');
4269
 
        var t = nexttoken;
4270
 
        nonadjacent(token, t);
4271
 
        advance('(');
4272
 
        nospace();
4273
 
        parse(20);
4274
 
        if (nexttoken.id === '=') {
4275
 
            warning("Expected a conditional expression and instead saw an assignment.");
4276
 
            advance('=');
4277
 
            parse(20);
4278
 
        }
4279
 
        advance(')', t);
4280
 
        nospace(prevtoken, token);
4281
 
        funct['(breakage)'] -= 1;
4282
 
        funct['(loopage)'] -= 1;
4283
 
    }).labelled = true;
4284
 
 
4285
 
    blockstmt('for', function () {
4286
 
        var s, t = nexttoken;
4287
 
        funct['(breakage)'] += 1;
4288
 
        funct['(loopage)'] += 1;
4289
 
        advance('(');
4290
 
        nonadjacent(this, t);
4291
 
        nospace();
4292
 
        if (peek(nexttoken.id === 'var' ? 1 : 0).id === 'in') {
4293
 
            if (nexttoken.id === 'var') {
4294
 
                advance('var');
4295
 
                varstatement(true);
4296
 
            } else {
4297
 
                advance();
4298
 
            }
4299
 
            advance('in');
4300
 
            parse(20);
4301
 
            advance(')', t);
4302
 
            s = block(true);
4303
 
            if (!option.forin && (s.length > 1 || typeof s[0] !== 'object' ||
4304
 
                    s[0].value !== 'if')) {
4305
 
                warning("The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.", this);
4306
 
            }
4307
 
            funct['(breakage)'] -= 1;
4308
 
            funct['(loopage)'] -= 1;
4309
 
            return this;
4310
 
        } else {
4311
 
            if (nexttoken.id !== ';') {
4312
 
                if (nexttoken.id === 'var') {
4313
 
                    advance('var');
4314
 
                    varstatement();
4315
 
                } else {
4316
 
                    for (;;) {
4317
 
                        parse(0, 'for');
4318
 
                        if (nexttoken.id !== ',') {
4319
 
                            break;
4320
 
                        }
4321
 
                        advance(',');
4322
 
                    }
4323
 
                }
4324
 
            }
4325
 
            advance(';');
4326
 
            if (nexttoken.id !== ';') {
4327
 
                parse(20);
4328
 
                if (nexttoken.id === '=') {
4329
 
                    warning("Expected a conditional expression and instead saw an assignment.");
4330
 
                    advance('=');
4331
 
                    parse(20);
4332
 
                }
4333
 
            }
4334
 
            advance(';');
4335
 
            if (nexttoken.id === ';') {
4336
 
                error("Expected '{a}' and instead saw '{b}'.",
4337
 
                        nexttoken, ')', ';');
4338
 
            }
4339
 
            if (nexttoken.id !== ')') {
4340
 
                for (;;) {
4341
 
                    parse(0, 'for');
4342
 
                    if (nexttoken.id !== ',') {
4343
 
                        break;
4344
 
                    }
4345
 
                    advance(',');
4346
 
                }
4347
 
            }
4348
 
            advance(')', t);
4349
 
            nospace(prevtoken, token);
4350
 
            block(true);
4351
 
            funct['(breakage)'] -= 1;
4352
 
            funct['(loopage)'] -= 1;
4353
 
        }
4354
 
    }).labelled = true;
4355
 
 
4356
 
 
4357
 
    stmt('break', function () {
4358
 
        var v = nexttoken.value;
4359
 
        if (funct['(breakage)'] === 0) {
4360
 
            warning("Unexpected '{a}'.", nexttoken, this.value);
4361
 
        }
4362
 
        nolinebreak(this);
4363
 
        if (nexttoken.id !== ';') {
4364
 
            if (funct[v] !== 'label') {
4365
 
                warning("'{a}' is not a statement label.", nexttoken, v);
4366
 
            } else if (scope[v] !== funct) {
4367
 
                warning("'{a}' is out of scope.", nexttoken, v);
4368
 
            }
4369
 
            advance();
4370
 
        }
4371
 
        reachable('break');
4372
 
    });
4373
 
 
4374
 
 
4375
 
    stmt('continue', function () {
4376
 
        var v = nexttoken.value;
4377
 
        nolinebreak(this);
4378
 
        if (nexttoken.id !== ';') {
4379
 
            if (funct[v] !== 'label') {
4380
 
                warning("'{a}' is not a statement label.", nexttoken, v);
4381
 
            } else if (scope[v] !== funct) {
4382
 
                warning("'{a}' is out of scope.", nexttoken, v);
4383
 
            }
4384
 
            advance();
4385
 
        }
4386
 
        reachable('continue');
4387
 
    });
4388
 
 
4389
 
 
4390
 
    stmt('return', function () {
4391
 
        nolinebreak(this);
4392
 
        if (nexttoken.id !== ';' && !nexttoken.reach) {
4393
 
            nonadjacent(token, nexttoken);
4394
 
            parse(20);
4395
 
        }
4396
 
        reachable('return');
4397
 
    });
4398
 
 
4399
 
 
4400
 
    stmt('throw', function () {
4401
 
        nolinebreak(this);
4402
 
        nonadjacent(token, nexttoken);
4403
 
        parse(20);
4404
 
        reachable('throw');
4405
 
    });
4406
 
 
4407
 
    reserve('void');
4408
 
 
4409
 
//  Superfluous reserved words
4410
 
 
4411
 
    reserve('class');
4412
 
    reserve('const');
4413
 
    reserve('enum');
4414
 
    reserve('export');
4415
 
    reserve('extends');
4416
 
    reserve('float');
4417
 
    reserve('goto');
4418
 
    reserve('import');
4419
 
    reserve('super');
4420
 
 
4421
 
    function jsonValue() {
4422
 
 
4423
 
        function jsonObject() {
4424
 
            var t = nexttoken;
4425
 
            advance('{');
4426
 
            if (nexttoken.id !== '}') {
4427
 
                for (;;) {
4428
 
                    if (nexttoken.id === '(end)') {
4429
 
                        error("Missing '}' to match '{' from line {a}.",
4430
 
                                nexttoken, t.line + 1);
4431
 
                    } else if (nexttoken.id === '}') {
4432
 
                        warning("Unexpected comma.", token);
4433
 
                        break;
4434
 
                    } else if (nexttoken.id === ',') {
4435
 
                        error("Unexpected comma.", nexttoken);
4436
 
                    } else if (nexttoken.id !== '(string)') {
4437
 
                        warning("Expected a string and instead saw {a}.",
4438
 
                                nexttoken, nexttoken.value);
4439
 
                    }
4440
 
                    advance();
4441
 
                    advance(':');
4442
 
                    jsonValue();
4443
 
                    if (nexttoken.id !== ',') {
4444
 
                        break;
4445
 
                    }
4446
 
                    advance(',');
4447
 
                }
4448
 
            }
4449
 
            advance('}');
4450
 
        }
4451
 
 
4452
 
        function jsonArray() {
4453
 
            var t = nexttoken;
4454
 
            advance('[');
4455
 
            if (nexttoken.id !== ']') {
4456
 
                for (;;) {
4457
 
                    if (nexttoken.id === '(end)') {
4458
 
                        error("Missing ']' to match '[' from line {a}.",
4459
 
                                nexttoken, t.line + 1);
4460
 
                    } else if (nexttoken.id === ']') {
4461
 
                        warning("Unexpected comma.", token);
4462
 
                        break;
4463
 
                    } else if (nexttoken.id === ',') {
4464
 
                        error("Unexpected comma.", nexttoken);
4465
 
                    }
4466
 
                    jsonValue();
4467
 
                    if (nexttoken.id !== ',') {
4468
 
                        break;
4469
 
                    }
4470
 
                    advance(',');
4471
 
                }
4472
 
            }
4473
 
            advance(']');
4474
 
        }
4475
 
 
4476
 
        switch (nexttoken.id) {
4477
 
        case '{':
4478
 
            jsonObject();
4479
 
            break;
4480
 
        case '[':
4481
 
            jsonArray();
4482
 
            break;
4483
 
        case 'true':
4484
 
        case 'false':
4485
 
        case 'null':
4486
 
        case '(number)':
4487
 
        case '(string)':
4488
 
            advance();
4489
 
            break;
4490
 
        case '-':
4491
 
            advance('-');
4492
 
            if (token.character !== nexttoken.from) {
4493
 
                warning("Unexpected space after '-'.", token);
4494
 
            }
4495
 
            adjacent(token, nexttoken);
4496
 
            advance('(number)');
4497
 
            break;
4498
 
        default:
4499
 
            error("Expected a JSON value.", nexttoken);
4500
 
        }
4501
 
    }
4502
 
 
4503
 
 
4504
 
// The actual JSLINT function itself.
4505
 
 
4506
 
    var itself = function (s, o) {
4507
 
        var a, i;
4508
 
        JSLINT.errors = [];
4509
 
        predefined = Object.create(standard);
4510
 
        if (o) {
4511
 
            a = o.predef;
4512
 
            if (a instanceof Array) {
4513
 
                for (i = 0; i < a.length; i += 1) {
4514
 
                    predefined[a[i]] = true;
4515
 
                }
4516
 
            }
4517
 
            if (o.adsafe) {
4518
 
                o.safe = true;
4519
 
            }
4520
 
            if (o.safe) {
4521
 
                o.browser = false;
4522
 
                o.css     = false;
4523
 
                o.debug   = false;
4524
 
                o.eqeqeq  = true;
4525
 
                o.evil    = false;
4526
 
                o.forin   = false;
4527
 
                o.nomen   = true;
4528
 
                o.on      = false;
4529
 
                o.rhino   = false;
4530
 
                o.safe    = true;
4531
 
                o.sidebar = false;
4532
 
                o.strict  = true;
4533
 
                o.sub     = false;
4534
 
                o.undef   = true;
4535
 
                o.widget  = false;
4536
 
                predefined.Date = false;
4537
 
                predefined['eval'] = false;
4538
 
                predefined.Function = false;
4539
 
                predefined.Object = false;
4540
 
                predefined.ADSAFE = true;
4541
 
            }
4542
 
            option = o;
4543
 
        } else {
4544
 
            option = {};
4545
 
        }
4546
 
        option.indent = option.indent || 4;
4547
 
        adsafe_id = '';
4548
 
        adsafe_may = false;
4549
 
        adsafe_went = false;
4550
 
        approved = {};
4551
 
        if (option.approved) {
4552
 
            for (i = 0; i < option.approved.length; i += 1) {
4553
 
                approved[option.approved[i]] = option.approved[i];
4554
 
            }
4555
 
        }
4556
 
        approved.test = 'test'; ///////////////////////////////////////
4557
 
        tab = '';
4558
 
        for (i = 0; i < option.indent; i += 1) {
4559
 
            tab += ' ';
4560
 
        }
4561
 
        indent = 0;
4562
 
        global = Object.create(predefined);
4563
 
        scope = global;
4564
 
        funct = {
4565
 
            '(global)': true,
4566
 
            '(name)': '(global)',
4567
 
            '(scope)': scope,
4568
 
            '(breakage)': 0,
4569
 
            '(loopage)': 0
4570
 
        };
4571
 
        functions = [];
4572
 
        ids = {};
4573
 
        urls = [];
4574
 
        src = false;
4575
 
        xmode = false;
4576
 
        stack = null;
4577
 
        member = {};
4578
 
        membersOnly = null;
4579
 
        implied = {};
4580
 
        inblock = false;
4581
 
        lookahead = [];
4582
 
        jsonmode = false;
4583
 
        warnings = 0;
4584
 
        lex.init(s);
4585
 
        prereg = true;
4586
 
 
4587
 
        prevtoken = token = nexttoken = syntax['(begin)'];
4588
 
        assume();
4589
 
 
4590
 
        try {
4591
 
            advance();
4592
 
            if (nexttoken.value.charAt(0) === '<') {
4593
 
                html();
4594
 
                if (option.adsafe && !adsafe_went) {
4595
 
                    warning("ADsafe violation: Missing ADSAFE.go.", this);
4596
 
                }
4597
 
            } else {
4598
 
                switch (nexttoken.id) {
4599
 
                case '{':
4600
 
                case '[':
4601
 
                    option.laxbreak = true;
4602
 
                    jsonmode = true;
4603
 
                    jsonValue();
4604
 
                    break;
4605
 
                case '@':
4606
 
                case '*':
4607
 
                case '#':
4608
 
                case '.':
4609
 
                case ':':
4610
 
                    xmode = 'style';
4611
 
                    advance();
4612
 
                    if (token.id !== '@' || !nexttoken.identifier ||
4613
 
                            nexttoken.value !== 'charset') {
4614
 
                        error('A css file should begin with @charset "UTF-8";');
4615
 
                    }
4616
 
                    advance();
4617
 
                    if (nexttoken.type !== '(string)' &&
4618
 
                            nexttoken.value !== 'UTF-8') {
4619
 
                        error('A css file should begin with @charset "UTF-8";');
4620
 
                    }
4621
 
                    advance();
4622
 
                    advance(';');
4623
 
                    styles();
4624
 
                    break;
4625
 
 
4626
 
                default:
4627
 
                    if (option.adsafe && option.fragment) {
4628
 
                        warning("ADsafe violation.", this);
4629
 
                    }
4630
 
                    statements('lib');
4631
 
                }
4632
 
            }
4633
 
            advance('(end)');
4634
 
        } catch (e) {
4635
 
            if (e) {
4636
 
                JSLINT.errors.push({
4637
 
                    reason    : e.message,
4638
 
                    line      : e.line || nexttoken.line,
4639
 
                    character : e.character || nexttoken.from
4640
 
                }, null);
4641
 
            }
4642
 
        }
4643
 
        return JSLINT.errors.length === 0;
4644
 
    };
4645
 
 
4646
 
    function to_array(o) {
4647
 
        var a = [], k;
4648
 
        for (k in o) {
4649
 
            if (o.hasOwnProperty(k)) {
4650
 
                a.push(k);
4651
 
            }
4652
 
        }
4653
 
        return a;
4654
 
    }
4655
 
 
4656
 
// Report generator.
4657
 
 
4658
 
    itself.report = function (option, sep) {
4659
 
        var a = [], c, e, f, i, k, l, m = '', n, o = [], s, v, cl, va, un, ou, gl, la;
4660
 
 
4661
 
        function detail(h, s, sep) {
4662
 
            if (s.length) {
4663
 
                o.push('<div><i>' + h + '</i> ' +
4664
 
                        s.sort().join(sep || ', ') + '</div>');
4665
 
            }
4666
 
        }
4667
 
 
4668
 
        s = to_array(implied);
4669
 
 
4670
 
        k = JSLINT.errors.length;
4671
 
        if (k || s.length > 0) {
4672
 
            o.push('<div id=errors><i>Error:</i>');
4673
 
            if (s.length > 0) {
4674
 
                s.sort();
4675
 
                for (i = 0; i < s.length; i += 1) {
4676
 
                    s[i] = '<code>' + s[i] + '</code>&nbsp;<i>' +
4677
 
                        implied[s[i]].join(' ') +
4678
 
                        '</i>';
4679
 
                }
4680
 
                o.push('<p><i>Implied global:</i> ' + s.join(', ') + '</p>');
4681
 
                c = true;
4682
 
            }
4683
 
            for (i = 0; i < k; i += 1) {
4684
 
                c = JSLINT.errors[i];
4685
 
                if (c) {
4686
 
                    e = c.evidence || '';
4687
 
                    o.push('<p>Problem' + (isFinite(c.line) ? ' at line ' + (c.line + 1) +
4688
 
                            ' character ' + (c.character + 1) : '') +
4689
 
                            ': ' + c.reason.entityify() +
4690
 
                            '</p><p class=evidence>' +
4691
 
                            (e && (e.length > 80 ? e.slice(0, 77) + '...' :
4692
 
                            e).entityify()) + '</p>');
4693
 
                }
4694
 
            }
4695
 
            o.push('</div>');
4696
 
            if (!c) {
4697
 
                return o.join('');
4698
 
            }
4699
 
        }
4700
 
 
4701
 
        if (!option) {
4702
 
 
4703
 
            o.push('<br><div id=functions>');
4704
 
 
4705
 
            if (urls.length > 0) {
4706
 
                detail("URLs<br>", urls, '<br>');
4707
 
            }
4708
 
 
4709
 
            s = to_array(scope);
4710
 
            if (s.length === 0) {
4711
 
                if (jsonmode) {
4712
 
                    if (k === 0) {
4713
 
                        o.push('<p>JSON: good.</p>');
4714
 
                    } else {
4715
 
                        o.push('<p>JSON: bad.</p>');
4716
 
                    }
4717
 
                } else {
4718
 
                    o.push('<div><i>No new global variables introduced.</i></div>');
4719
 
                }
4720
 
            } else {
4721
 
                o.push('<div><i>Global</i> ' + s.sort().join(', ') + '</div>');
4722
 
            }
4723
 
 
4724
 
            for (i = 0; i < functions.length; i += 1) {
4725
 
                f = functions[i];
4726
 
                cl = [];
4727
 
                va = [];
4728
 
                un = [];
4729
 
                ou = [];
4730
 
                gl = [];
4731
 
                la = [];
4732
 
                for (k in f) {
4733
 
                    if (f.hasOwnProperty(k) && k.charAt(0) !== '(') {
4734
 
                        v = f[k];
4735
 
                        switch (v) {
4736
 
                        case 'closure':
4737
 
                            cl.push(k);
4738
 
                            break;
4739
 
                        case 'var':
4740
 
                            va.push(k);
4741
 
                            break;
4742
 
                        case 'unused':
4743
 
                            un.push(k);
4744
 
                            break;
4745
 
                        case 'label':
4746
 
                            la.push(k);
4747
 
                            break;
4748
 
                        case 'outer':
4749
 
                            ou.push(k);
4750
 
                            break;
4751
 
                        case true:
4752
 
                            gl.push(k);
4753
 
                            break;
4754
 
                        }
4755
 
                    }
4756
 
                }
4757
 
                o.push('<br><div class=function><i>' + f['(line)'] + '</i> ' +
4758
 
                        (f['(name)'] || '') + '(' +
4759
 
                        (f['(params)'] || '') + ')</div>');
4760
 
                detail('Closure', cl);
4761
 
                detail('Variable', va);
4762
 
                detail('<big><b>Unused</b></big>', un);
4763
 
                detail('Label', la);
4764
 
                detail('Outer', ou);
4765
 
                detail('Global', gl);
4766
 
            }
4767
 
            a = [];
4768
 
            for (k in member) {
4769
 
                if (typeof member[k] === 'number') {
4770
 
                    a.push(k);
4771
 
                }
4772
 
            }
4773
 
            if (a.length) {
4774
 
                a = a.sort();
4775
 
                m = '<br><pre>/*members ';
4776
 
                l = 10;
4777
 
                for (i = 0; i < a.length; i += 1) {
4778
 
                    k = a[i];
4779
 
                    n = k.name();
4780
 
                    if (l + n.length > 72) {
4781
 
                        o.push(m + '<br>');
4782
 
                        m = '    ';
4783
 
                        l = 1;
4784
 
                    }
4785
 
                    l += n.length + 2;
4786
 
                    if (member[k] === 1) {
4787
 
                        n = '<i>' + n + '</i>';
4788
 
                    }
4789
 
                    if (i < a.length - 1) {
4790
 
                        n += ', ';
4791
 
                    }
4792
 
                    m += n;
4793
 
                }
4794
 
                o.push(m + '<br>*/</pre>');
4795
 
            }
4796
 
            o.push('</div>');
4797
 
        }
4798
 
        return o.join('');
4799
 
    };
4800
 
 
4801
 
    return itself;
4802
 
 
4803
 
}();
 
 
b'\\ No newline at end of file'