1 //<Script type="text/javascript">
10 * // FIXME - I need this to do next() without doccomments..
13 Walker2 = XObject.define(
18 this.indexedScopes = {};
20 //this.timer = new Date() * 1;
28 timerPrint: function (str) {
29 var ntime = new Date() * 1;
30 var tdif = ntime -this.timer;
33 if (tdif > 100) { //slower ones..
36 print(pref+'['+tdif+']'+str);
41 //this.warnings.push(s);
42 print("WARNING:" + htmlescape(s) + "<BR>");
44 // defaults should not be initialized here =- otherwise they get duped on new, rather than initalized..
49 mode : "", //"BUILDING_SYMBOL_TREE",
51 indexedScopes : false,
53 symbols: false, /// object store of sumbols..
58 buildSymbolTree : function()
63 this.braceNesting = 0;
67 this.globalScope = new Scope(-1, false, -1, '$global$');
68 indexedScopes = { 0 : this.globalScope };
70 this.mode = 'BUILDING_SYMBOL_TREE';
71 this.parseScope(this.globalScope);
78 //print("<B>LOG:</B>" + htmlescape(str) + "<BR/>\n");
82 //print("<B>LOG:</B>" + str + "<BR/>");
89 parseScope : function(scope, ealiases) // parse a token stream..
91 //this.timerPrint("parseScope EnterScope");
94 var fixAlias = function(str, nomore)
96 var ar = str.split('.');
99 //print(str +"?=" +aliases.toSource());
100 if (aliases[m] == undefined) {
103 var ret = aliases[m] + (ar.length? '.' : '' )+ ar.join('.');
104 if (nomore !== true) {
105 ret = fixAlias(ret, true);
115 if (ealiases != undefined) {
117 for(var i in ealiases) {
118 aliases[i] = ealiases[i];
125 //print("STARTING SCOPE WITH: " + ealiases.toSource());
131 var expressionBraceNesting = this.braceNesting;
132 var bracketNesting = 0;
133 var parensNesting = 0;
136 var l1 = '', l2 = '';
140 var locBraceNest = 0;
141 // determines if we are in object literals...
143 var isObjectLitAr = [ false ];
144 //print("SCOPE: ------------------START ----------------");
145 this.scopesIn(scope);
146 var scopeLen = this.scopes.length;
148 if (this.ts.cursor < 1) {
149 this.ts.cursor--; // hopeflly this kludge will work
155 while (false != (token = this.ts.next())) {
156 //print("TOK"+ token.toString());
157 // this.timerPrint("parseScope AFTER lookT: " + token.toString());
159 if (token.tokN == Script.TOKwhitespace) {
165 if (this.currentDoc) {
166 // add it to the current scope????
168 this.addSymbol('', true);
171 //throw "Unconsumed Doc (TOKwhitespace): " + this.currentDoc.toSource();
175 var newDoc = new DocComment(token.data);
177 // it's a scope changer..
178 if (newDoc.getTag("scope").length) {
179 //print(newDoc.getTag("scope").toSource());
181 scope.ident = '$private$|' + newDoc.getTag("scope")[0].desc;
185 // it's a scope changer..
186 if (newDoc.getTag("scopeAlias").length) {
187 //print(newDoc.getTag("scopeAlias").toSource());
189 var sal = newDoc.getTag("scopeAlias")[0].desc.split("=");
190 aliases[sal[0]] = sal[1];
196 /// got a doc comment..
197 //token.data might be this.??? (not sure though)
198 this.currentDoc = newDoc;
202 // catch the various issues .. - scoe changes or doc actions..
206 // things that stop comments carrying on...??
208 if (this.currentDoc && (
209 token.tokN == Script.TOKsemicolon ||
210 token.tokN == Script.TOKrbrace)) {
211 this.addSymbol('', true);
212 //throw "Unconsumed Doc ("+ token.toString() +"): " + this.currentDoc.toSource();
216 // the rest are scoping issues...
220 if (token.tokN == Script.TOKvar &&
222 this.ts.lookT(1).tokN == Script.TOKidentifier &&
223 this.ts.lookT(2).tokN == Script.TOKassign &&
224 this.ts.lookT(3).tokN == Script.TOKidentifier &&
225 this.ts.lookT(4).tokN == Script.TOKsemicolon
229 //print("SET ALIAS:" + this.ts.lookT(1).data +'=' + this.ts.lookT(3).data);
231 aliases[this.ts.lookT(1).data] = this.ts.lookT(3).data;
238 // extends scoping *** not sure if the can be x = Roo.apply(....)
239 // xxx.extends(a,b, {
240 // $this$=b|b.prototype
245 if (token.tokN == Script.TOKidentifier) {
247 //print("TOK(ident)"+ token.toString());
253 if (/\.extend$/.test(token.data) &&
254 this.ts.lookT(1).tokN == Script.TOKlparen &&
255 this.ts.lookT(2).tokN == Script.TOKidentifier &&
256 this.ts.lookT(3).tokN == Script.TOKcomma &&
257 this.ts.lookT(4).tokN == Script.TOKidentifier &&
258 this.ts.lookT(5).tokN == Script.TOKcomma &&
259 this.ts.lookT(6).tokN == Script.TOKlbrace
261 // ignore test for ( a and ,
262 this.ts.nextT(); /// (
263 token = this.ts.nextT(); // a
264 scopeName = token.data;
266 if (this.currentDoc) {
267 this.addSymbol(scopeName,false,'OBJECT');
270 this.ts.nextT(); // ,
271 this.ts.nextT(); // b
274 this.ts.nextT(); // ,
275 token = this.ts.nextT(); // {
277 scopeName = fixAlias(scopeName);
279 var fnScope = new Scope(this.braceNesting, scope, token.n,
280 '$this$=' + scopeName + '|'+scopeName+'.prototype');
281 this.indexedScopes[this.ts.cursor] = fnScope;
283 this.scopesIn(fnScope);
286 //print(">>" +locBraceNest);
287 continue; // no more processing..
291 // a = Roo.extend(parentname, {
293 if (/\.extend$/.test(token.data) &&
294 this.ts.lookT(-2).tokN == Script.TOKidentifier &&
295 this.ts.lookT(-1).tokN == Script.TOKassign &&
296 this.ts.lookT(1).tokN == Script.TOKlparen &&
297 this.ts.lookT(2).tokN == Script.TOKidentifier &&
298 this.ts.lookT(3).tokN == Script.TOKcomma &&
299 this.ts.lookT(4).tokN == Script.TOKlbrace
301 // ignore test for ( a and ,
302 token = this.ts.lookT(-2);
303 scopeName = token.data;
304 if (this.currentDoc) {
305 this.addSymbol(scopeName,false,'OBJECT');
308 this.ts.nextT(); /// (
309 this.ts.nextT(); // parent
311 this.ts.nextT(); // ,
312 token = this.ts.nextT(); // {
315 scopeName = fixAlias(scopeName);
316 var fnScope = new Scope(this.braceNesting, scope, token.n,
317 '$this$=' + scopeName + '|'+scopeName+'.prototype');
318 this.indexedScopes[this.ts.cursor] = fnScope;
320 this.scopesIn(fnScope);
323 //print(">>" +locBraceNest);
324 continue; // no more processing..
330 if (/\.(applyIf|apply)$/.test(token.data) &&
331 this.ts.lookT(1).tokN == Script.TOKlparen &&
332 this.ts.lookT(2).tokN == Script.TOKidentifier &&
333 this.ts.lookT(3).tokN == Script.TOKcomma &&
334 this.ts.lookT(4).tokN == Script.TOKlbrace
337 this.ts.nextT(); /// (
339 //print("GOT : applyIF!");
341 token = this.ts.nextT(); // b
342 scopeName = token.data;
345 if (this.currentDoc) {
346 this.addSymbol(scopeName,false,'OBJECT');
352 this.ts.nextT(); /// ,
353 this.ts.nextT(); // {
354 scopeName = fixAlias(scopeName);
355 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
356 this.indexedScopes[this.ts.cursor] = fnScope;
358 this.scopesIn(fnScope);
361 //print(">>" +locBraceNest);
362 continue; // no more processing..
368 // change scope to xxxx
370 if ( this.ts.lookT(1).tokN == Script.TOKassign &&
371 this.ts.lookT(2).tokN == Script.TOKnew &&
372 this.ts.lookT(3).tokN == Script.TOKidentifier &&
373 this.ts.lookT(4).tokN == Script.TOKlparen &&
374 this.ts.lookT(5).tokN == Script.TOKlbrace
376 scopeName = token.data;
377 if (this.currentDoc) {
378 this.addSymbol(scopeName,false,'OBJECT');
382 this.ts.nextT(); /// =
383 this.ts.nextT(); /// new
384 this.ts.nextT(); /// yyy
385 this.ts.nextT(); /// (
386 this.ts.nextT(); /// {
388 scopeName = fixAlias(scopeName);
389 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
390 this.indexedScopes[this.ts.cursor] = fnScope;
392 this.scopesIn(fnScope);
395 //print(">>" +locBraceNest);
397 continue; // no more processing..
418 // eval can be prefixed with a hint hider for the compresser..
419 if ((token.data == 'eval') || /\.eval$/.test(token.data)) {
420 this.currentDoc = false;
424 if (this.currentDoc) {
425 //print(token.toString());
427 // ident : function ()
428 // ident = function ()
429 var atype = 'OBJECT';
431 if (((this.ts.lookT(1).tokN == Script.TOKcolon )|| (this.ts.lookT(1).tokN == Script.TOKassign)) &&
432 (this.ts.lookT(2).tokN == Script.TOKfunction)
437 //print("ADD SYM:" + atype + ":" + token.toString() + this.ts.lookT(1).toString() + this.ts.lookT(2).toString());
440 this.ts.lookT(-1).tokN == Script.TOKdot ? token.data : fixAlias(token.data),
447 continue; // dont care about other idents..
450 if (token.tokN == Script.TOKstring) {
451 if (this.currentDoc) {
452 this.addSymbol(token.data.substring(1,token.data.length-1),false,'OBJECT');
457 // really we only have to deal with object constructs and function calls that change the scope...
460 if (token.tokN == Script.TOKfunction) {
462 // see if we have an unconsumed doc...
464 if (this.currentDoc) {
465 print(this.ts.dumpToCur());
466 throw "Unhandled doc (TOKfunction)" + token.toString();
467 //this.addSymbol(this.currentDoc.getTag('class')[0].name, true);
469 //throw "Unconsumed Doc: (TOKrbrace)" + this.currentDoc.toSource();
476 /// foo = function() {} << really it set's the 'this' scope to foo.prototype
477 //$this$=foo.prototype|$private$|foo.prototype
480 (this.ts.lookT(-1).tokN == Script.TOKassign) &&
481 (this.ts.lookT(-2).tokN == Script.TOKidentifier)
483 scopeName = this.ts.lookT(-2).data;
484 this.ts.balanceN(Script.TOKlparen);
485 token = this.ts.nextT(); // should be {
486 //print("FOO=FUNCITON() {}" + this.ts.context() + "\n" + token.toString());
489 scopeName = fixAlias(scopeName);
490 var fnScope = new Scope(this.braceNesting, scope, token.n,
491 '$this$='+scopeName+'.prototype|$private$|'+scopeName+'.prototype');
492 this.indexedScopes[this.ts.cursor] = fnScope;
494 //this.scopesIn(fnScope);
495 this.parseScope(fnScope, aliases);
500 //print(">>" +locBraceNest);
501 continue; // no more processing..
507 // foo = new function() {}
508 // is this actually used much!?!?!
512 (this.ts.lookT(-1).tokN == Script.TOKnew) &&
513 (this.ts.lookT(-2).tokN == Script.TOKassign)
514 (this.ts.lookT(-3).tokN == Script.TOKidentifier)
516 //scopeName = this.ts.look(-3).data;
517 this.ts.balanceN(Script.TOKlparen);
518 token = this.ts.nextT(); // should be {
519 scopeName = fixAlias(scopeName);
520 var fnScope = new Scope(this.braceNesting, scope, token.n, '$private$');
521 this.indexedScopes[this.ts.cursor] = fnScope;
523 //this.scopesIn(fnScope);
524 this.parseScope(fnScope, aliases);
527 //print(">>" +locBraceNest);
528 continue; // no more processing..
534 ///==== check/set isObjectLitAr ??
537 // foo: function() {}
538 // no change to scoping..
540 //print("checking for : function() {");
541 //print( [this.ts.lookT(-3).type , this.ts.lookT(-2).type , this.ts.lookT(-1).type ].join(":"));
543 (this.ts.lookT(-1).tokN == Script.TOKcolon) &&
544 (this.ts.lookT(-2).tokN == Script.TOKidentifier) &&
545 (this.ts.lookT(-3).tokN == Script.TOKlbrace || this.ts.lookT(-3).tokN == Script.TOKcomma)
547 //print("got for : function() {");
549 //scopeName = this.ts.look(-3).data;
550 this.ts.balanceN(Script.TOKlparen);
551 //print(token.toString())
552 token = this.ts.nextT(); // should be {
553 //print(token.toString())
554 scopeName = fixAlias(scopeName);
555 var fnScope = new Scope(this.braceNesting, scope, token.n, '');
556 this.indexedScopes[this.ts.cursor] = fnScope;
558 //this.scopesIn(fnScope);
559 this.parseScope(fnScope, aliases);
561 //print(">>" +locBraceNest);
562 continue; // no more processing..
565 /// function foo() {} << really it set's the 'this' scope to foo.prototype
566 //$this$=foo|$private$
570 (this.ts.lookT(1).tokN == Script.TOKidentifier)
572 //scopeName = this.ts.look(-3).data;
573 this.ts.balanceN(Script.TOKlparen);
574 token = this.ts.nextT(); // should be {
576 var fnScope = new Scope(this.braceNesting, scope, token.n, '');
577 this.indexedScopes[this.ts.cursor] = fnScope;
579 //this.scopesIn(fnScope);
580 this.parseScope(fnScope, aliases);
582 //print(">>" +locBraceNest);
583 continue; // no more processing..
588 // foo = new (function() { }
590 // RETURN function(...) {
593 // (this.ts.lookT(-1).tokN == Script.TOKlparen) &&
594 (this.ts.lookT(1).tokN != Script.TOKidentifier)
596 // (this.ts.lookT(-2).tokN == Script.TOKnew) &&
597 // (this.ts.lookT(-3).tokN == Script.TOKassign) &&
598 // (this.ts.lookT(-4).tokN == Script.TOKidentifier)
600 //scopeName = this.ts.look(-3).data;
601 this.ts.balanceN(Script.TOKlparen);
602 token = this.ts.nextT(); // should be {
603 var fnScope = new Scope(this.braceNesting, scope, token.n, '$private$');
604 this.indexedScopes[this.ts.cursor] = fnScope;
606 //this.scopesIn(fnScope);
607 this.parseScope(fnScope, aliases);
609 //print(">>" +locBraceNest);
610 continue; // no more processing..
616 print(this.ts.context());
617 throw "dont know how to handle function syntax??";
624 } // end checking for TOKfunction
626 if (token.tokN == Script.TOKlbrace) {
628 // foo = { // !var!!!
633 (this.ts.lookT(-1).tokN == Script.TOKassign) &&
634 (this.ts.lookT(-2).tokN == Script.TOKidentifier) &&
635 (this.ts.lookT(-3).tokN != Script.TOKvar)
638 scopeName = this.ts.look(-2).data;
639 scopeName = fixAlias(scopeName);
640 var fnScope = new Scope(this.braceNesting, scope, token.n,
641 '$this$='+scopeName + '|'+scopeName
643 this.indexedScopes[this.ts.cursor] = fnScope;
645 this.scopesIn(fnScope);
649 //print(">>" +locBraceNest);
650 continue; // no more processing..
655 //print("GOT LBRACE : check for :");
657 (this.ts.lookT(-1).tokN == Script.TOKcolon) &&
658 (this.ts.lookT(-2).tokN == Script.TOKidentifier) &&
659 (this.ts.lookT(-3).tokN != Script.TOKvar)
662 scopeName = this.ts.lookT(-2).data;
663 scopeName = fixAlias(scopeName);
664 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
665 this.indexedScopes[this.ts.cursor] = fnScope;
667 this.scopesIn(fnScope);
670 //print(">>" +locBraceNest);
671 continue; // no more processing..
673 var fnScope = new Scope(this.braceNesting, scope, token.n, '');
674 this.indexedScopes[this.ts.cursor] = fnScope;
676 this.scopesIn(fnScope);
679 //print(">>" +locBraceNest);
683 if (token.tokN == Script.TOKrbrace) {
686 if (this.currentDoc) {
687 this.addSymbol('', true);
689 //throw "Unconsumed Doc: (TOKrbrace)" + this.currentDoc.toSource();
695 //assert braceNesting >= scope.getBraceNesting();
696 var closescope = this.scopeOut();
697 scope = this.scopes[this.scopes.length-1];
698 //print("<<:" + locBraceNest)
699 //print("<<<<<< " + locBraceNest );
700 if (locBraceNest < 0) {
701 // print("POPED OF END OF SCOPE!");
703 //var ls = this.scopeOut();
704 //ls.getUsedSymbols();
717 addSymbol: function(lastIdent, appendIt, atype )
720 /*if (!this.currentDoc.tags.length) {
723 //print(this.currentDoc.toSource());
724 // this.currentDoc = false;
726 print("SKIP ADD SYM: no tags");
727 print(this.currentDoc.src);
731 if (this.currentDoc.getTag('private').length) {
734 //print(this.currentDoc.toSource());
735 this.currentDoc = false;
736 print("SKIP ADD SYM: it's private");
740 var token = this.ts.cur();
741 if (typeof(appendIt) == 'undefined') {
744 // print(this.currentDoc.toSource(););
745 if (this.currentDoc.getTag('event').length) {
746 //?? why does it end up in desc - and not name/...
747 print(this.currentDoc.getTag('event')[0]);
748 lastIdent = '*' + this.currentDoc.getTag('event')[0].desc;
749 //lastIdent = '*' + lastIdent ;
751 if (!lastIdent.length && this.currentDoc.getTag('property').length) {
752 lastIdent = this.currentDoc.getTag('property')[0].name;
753 //lastIdent = '*' + lastIdent ;
757 if (!/\./.test(_s)) {
759 //print("WALKER ADDsymbol: " + lastIdent);
762 for (var i = 0; i < this.scopes.length;i++) {
763 s.push(this.scopes[i].ident);
767 var s = s.join('|').split('|');
768 print("Walker:ADDSymbol: " + s.join('|') );
773 for (var i = 0; i < s.length;i++) {
778 if ((s[i] == '$private$') || (s[i] == '$global$')) {
782 if (s[i].substring(0,6) == '$this$') {
783 var ts = s[i].split('=');
787 // when to use $this$ (probabl for events)
788 _s += _s.length ? '.' : '';
794 //print("ADDING SYMBOL: "+ s.join('|') +"\n"+ _s + "\n" +Script.prettyDump(this.currentDoc.toSource()));
796 if (appendIt && !lastIdent.length) {
798 // append, and no symbol???
800 // see if it's a @class
801 if (this.currentDoc.getTag('class').length) {
802 _s = this.currentDoc.getTag('class')[0].desc;
803 var symbol = new Symbol(_s, [], "CONSTRUCTOR", this.currentDoc);
804 Parser.addSymbol(symbol);
805 this.symbols[_s] = symbol;
809 // if (this.currentDoc.getTag('property').length) {
810 // print(Script.pretStringtyDump(this.currentDoc.toSource));
811 // throw "Add Prop?";
814 _s = _s.replace(/\.prototype.*$/, '');
815 if (typeof(this.symbols[_s]) == 'undefined') {
816 print("Symbol:" + _s);
817 print(this.currentDoc.src);
819 throw "Trying to append symbol, but no doc available";
822 for (var i =0; i < this.currentDoc.tags.length;i++) {
823 this.symbols[_s].addDocTag(this.currentDoc.tags[i]);
825 this.currentDoc = false;
829 if (typeof(this.symbols[_s]) != 'undefined') {
831 if (this.symbols[_s].comment.hasTags) {
832 // then existing comment doesnt has tags
833 throw "DUPLICATE Symbol " + _s;
835 // otherwise existing comment has tags - overwrite..
839 if (typeof(atype) == "undefined") {
840 atype = 'OBJECT'; //this.currentDoc.getTag('class').length ? 'OBJECT' : 'FUNCTION';;
843 var symbol = new Symbol(_s, [], atype, this.currentDoc);
845 Parser.addSymbol(symbol);
846 this.symbols[_s] = symbol;
848 this.currentDoc = false;
855 scopesIn : function(s)
858 //print(">>>" + this.ts.context() + "\n>>>"+this.scopes.length+":" +this.scopeListToStr());
861 scopeOut : function()
864 // print("<<<" + this.ts.context() + "\n<<<"+this.scopes.length+":" +this.scopeListToStr());
865 return this.scopes.pop();
869 scopeListToStr : function()
872 for (var i = 0; i < this.scopes.length;i++) {
873 s.push(this.scopes[i].ident);
875 return s.join('\n\t');