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