1 //<Script type="text/javascript">
2 XObject = imports.XObject.XObject;
4 Scope = imports.Scope.Scope;
5 DocComment = imports.DocComment.DocComment;
6 Symbol = imports.Symbol.Symbol;
7 Parser = imports.Parser.Parser;
12 * // FIXME - I need this to do next() without doccomments..
15 Walker2 = XObject.define(
20 this.indexedScopes = {};
22 //this.timer = new Date() * 1;
30 timerPrint: function (str) {
31 var ntime = new Date() * 1;
32 var tdif = ntime -this.timer;
35 if (tdif > 100) { //slower ones..
38 print(pref+'['+tdif+']'+str);
43 //this.warnings.push(s);
44 print("WARNING:" + htmlescape(s) + "<BR>");
46 // defaults should not be initialized here =- otherwise they get duped on new, rather than initalized..
51 mode : "", //"BUILDING_SYMBOL_TREE",
53 indexedScopes : false,
55 symbols: false, /// object store of sumbols..
60 buildSymbolTree : function()
65 this.braceNesting = 0;
69 this.globalScope = new Scope(-1, false, -1, '$global$');
70 indexedScopes = { 0 : this.globalScope };
72 this.mode = 'BUILDING_SYMBOL_TREE';
73 this.parseScope(this.globalScope);
81 //print("<B>LOG:</B>" + htmlescape(str) + "<BR/>\n");
85 //print("<B>LOG:</B>" + str + "<BR/>");
92 parseScope : function(scope, ealiases) // parse a token stream..
94 //this.timerPrint("parseScope EnterScope");
97 var fixAlias = function(str, nomore)
99 var ar = str.split('.');
102 //print(str +"?=" +aliases.toSource());
103 if (aliases[m] == undefined) {
106 var ret = aliases[m] + (ar.length? '.' : '' )+ ar.join('.');
107 if (nomore !== true) {
108 ret = fixAlias(ret, true);
118 if (ealiases != undefined) {
120 for(var i in ealiases) {
121 aliases[i] = ealiases[i];
128 //print("STARTING SCOPE WITH: " + ealiases.toSource());
134 var expressionBraceNesting = this.braceNesting;
135 var bracketNesting = 0;
136 var parensNesting = 0;
139 var l1 = '', l2 = '';
143 var locBraceNest = 0;
144 // determines if we are in object literals...
146 var isObjectLitAr = [ false ];
147 //print("SCOPE: ------------------START ----------------");
148 this.scopesIn(scope);
149 var scopeLen = this.scopes.length;
151 if (this.ts.cursor < 1) {
152 // this.ts.cursor--; // hopeflly this kludge will work
156 //print(JSON.stringify(this.ts, null, 4)); Seed.quit();
158 while (null != (token = this.ts.next())) {
159 print("TOK"+ token.toString());
160 // this.timerPrint("parseScope AFTER lookT: " + token.toString());
162 if (token.is('WHIT')) {
165 if (token.name != 'JSDOC') {
168 if (this.currentDoc) {
169 // add it to the current scope????
171 this.addSymbol('', true);
173 //throw "Unconsumed Doc (TOKwhitespace): " + this.currentDoc.toSource();
177 var newDoc = new DocComment(token.data);
179 // it's a scope changer..
180 if (newDoc.getTag("scope").length) {
181 //print(newDoc.getTag("scope").toSource());
183 scope.ident = '$private$|' + newDoc.getTag("scope")[0].desc;
187 // it's a scope changer..
188 if (newDoc.getTag("scopeAlias").length) {
189 //print(newDoc.getTag("scopeAlias").toSource());
191 var sal = newDoc.getTag("scopeAlias")[0].desc.split("=");
192 aliases[sal[0]] = sal[1];
198 /// got a doc comment..
199 //token.data might be this.??? (not sure though)
200 this.currentDoc = newDoc;
204 // catch the various issues .. - scoe changes or doc actions..
208 // things that stop comments carrying on...??
210 if (this.currentDoc && (
211 token.tokN.data == ';' ||
212 token.tokN.data == '}')) {
213 this.addSymbol('', true);
214 //throw "Unconsumed Doc ("+ token.toString() +"): " + this.currentDoc.toSource();
218 // the rest are scoping issues...
222 if (token.name == 'VAR' &&
224 this.ts.lookTok(1).type == 'NAME' &&
225 this.ts.lookTok(2).data == '-' &&
226 this.ts.lookTok(3).type == 'NAME' &&
227 this.ts.lookTok(4).data == ';'
231 //print("SET ALIAS:" + this.ts.lookTok(1).data +'=' + this.ts.lookTok(3).data);
233 aliases[this.ts.lookTok(1).data] = this.ts.lookTok(3).data;
240 // extends scoping *** not sure if the can be x = Roo.apply(....)
241 // xxx.extends(a,b, {
242 // $this$=b|b.prototype
247 if (token.type = 'NAME') {
249 //print("TOK(ident)"+ token.toString());
255 if (/\.extend$/.test(token.data) &&
256 this.ts.lookTok(1).data == '(' &&
257 this.ts.lookTok(2).type == 'NAME' &&
258 this.ts.lookTok(3).data == ',' &&
259 this.ts.lookTok(4).type == 'NAME' &&
260 this.ts.lookTok(5).data == ',' &&
261 this.ts.lookTok(6).data == '{'
264 // ignore test for ( a and ,
265 this.ts.nextTok(); /// (
266 token = this.ts.nextTok(); // a
267 scopeName = token.data;
269 if (this.currentDoc) {
270 this.addSymbol(scopeName,false,'OBJECT');
273 this.ts.nextTok(); // ,
274 this.ts.nextTok(); // b
277 this.ts.nextTok(); // ,
278 token = this.ts.nextTok(); // {
280 scopeName = fixAlias(scopeName);
282 var fnScope = new Scope(this.braceNesting, scope, token.n,
283 '$this$=' + scopeName + '|'+scopeName+'.prototype');
284 this.indexedScopes[this.ts.cursor] = fnScope;
286 this.scopesIn(fnScope);
289 //print(">>" +locBraceNest);
290 continue; // no more processing..
294 // a = Roo.extend(parentname, {
296 if (/\.extend$/.test(token.data) &&
297 this.ts.lookTok(-2).type == 'NAME' &&
298 this.ts.lookTok(-1).data == '=' &&
299 this.ts.lookTok(1).data == '(' &&
300 this.ts.lookTok(2).type == 'NAME' &&
301 this.ts.lookTok(3).data == ',' &&
302 this.ts.lookTok(4).data == '{'
304 // ignore test for ( a and ,
305 token = this.ts.lookTok(-2);
306 scopeName = token.data;
307 if (this.currentDoc) {
308 this.addSymbol(scopeName,false,'OBJECT');
311 this.ts.nextTok(); /// (
312 this.ts.nextTok(); // parent
314 this.ts.nextTok(); // ,
315 token = this.ts.nextTok(); // {
318 scopeName = fixAlias(scopeName);
319 var fnScope = new Scope(this.braceNesting, scope, token.n,
320 '$this$=' + scopeName + '|'+scopeName+'.prototype');
321 this.indexedScopes[this.ts.cursor] = fnScope;
323 this.scopesIn(fnScope);
326 //print(">>" +locBraceNest);
327 continue; // no more processing..
334 print(JSON.stringify([
336 this.ts.lookTok(1).data ,
337 this.ts.lookTok(2).type ,
338 this.ts.lookTok(3).data ,
339 this.ts.lookTok(4).data
343 if (/\.(applyIf|apply)$/.test(token.data) &&
344 this.ts.lookTok(1).data == '(' &&
345 this.ts.lookTok(2).type == 'NAME' &&
346 this.ts.lookTok(3).data == ',' &&
347 this.ts.lookTok(4).data == '{'
350 this.ts.nextTok(); /// (
352 //print("GOT : applyIF!");
354 token = this.ts.nextTok(); // b
355 scopeName = token.data;
358 if (this.currentDoc) {
359 this.addSymbol(scopeName,false,'OBJECT');
365 this.ts.nextTok(); /// ,
366 this.ts.nextTok(); // {
367 scopeName = fixAlias(scopeName);
368 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
369 this.indexedScopes[this.ts.cursor] = fnScope;
371 this.scopesIn(fnScope);
374 //print(">>" +locBraceNest);
375 continue; // no more processing..
381 // change scope to xxxx
383 print(JSON.stringify([
384 this.ts.lookTok(1).data ,
385 this.ts.lookTok(2).name ,
386 this.ts.lookTok(3).type ,
387 this.ts.lookTok(4).data ,
388 this.ts.lookTok(5).data
391 if ( this.ts.lookTok(1).data == '=' &&
392 this.ts.lookTok(2).name == 'NEW' &&
393 this.ts.lookTok(3).type == 'NAME' &&
394 this.ts.lookTok(4).data == '(' &&
395 this.ts.lookTok(5).data == '{'
397 scopeName = token.data;
398 if (this.currentDoc) {
399 this.addSymbol(scopeName,false,'OBJECT');
403 this.ts.nextTok(); /// =
404 this.ts.nextTok(); /// new
405 this.ts.nextTok(); /// yyy
406 this.ts.nextTok(); /// (
407 this.ts.nextTok(); /// {
409 scopeName = fixAlias(scopeName);
410 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
411 this.indexedScopes[this.ts.cursor] = fnScope;
413 this.scopesIn(fnScope);
416 //print(">>" +locBraceNest);
418 continue; // no more processing..
439 // eval can be prefixed with a hint hider for the compresser..
440 if ((token.data == 'eval') || /\.eval$/.test(token.data)) {
441 this.currentDoc = false;
445 if (this.currentDoc) {
446 //print(token.toString());
448 // ident : function ()
449 // ident = function ()
450 var atype = 'OBJECT';
452 if (((this.ts.lookTok(1).data == ':' )|| (this.ts.lookTok(1).data == '=')) &&
453 (this.ts.lookTok(2).name == "FUNCTION")
458 //print("ADD SYM:" + atype + ":" + token.toString() + this.ts.lookTok(1).toString() + this.ts.lookTok(2).toString());
461 this.ts.lookTok(-1).tokN == Script.TOKdot ? token.data : fixAlias(token.data),
468 continue; // dont care about other idents..
471 if (token.type == "STRN") {
472 if (this.currentDoc) {
473 this.addSymbol(token.data.substring(1,token.data.length-1),false,'OBJECT');
478 // really we only have to deal with object constructs and function calls that change the scope...
481 if (token.name == 'FUNCTION') {
483 // see if we have an unconsumed doc...
485 if (this.currentDoc) {
486 print(this.ts.dumpToCur());
487 throw "Unhandled doc (TOKfunction)" + token.toString();
488 //this.addSymbol(this.currentDoc.getTag('class')[0].name, true);
490 //throw "Unconsumed Doc: (TOKrbrace)" + this.currentDoc.toSource();
497 /// foo = function() {} << really it set's the 'this' scope to foo.prototype
498 //$this$=foo.prototype|$private$|foo.prototype
501 (this.ts.lookTok(-1).data == '=') &&
502 (this.ts.lookTok(-2).type == 'NAME')
504 scopeName = this.ts.lookTok(-2).data;
505 this.ts.balanceN('(');
506 token = this.ts.nextTok(); // should be {
507 //print("FOO=FUNCITON() {}" + this.ts.context() + "\n" + token.toString());
510 scopeName = fixAlias(scopeName);
511 var fnScope = new Scope(this.braceNesting, scope, token.n,
512 '$this$='+scopeName+'.prototype|$private$|'+scopeName+'.prototype');
513 this.indexedScopes[this.ts.cursor] = fnScope;
515 //this.scopesIn(fnScope);
516 this.parseScope(fnScope, aliases);
521 //print(">>" +locBraceNest);
522 continue; // no more processing..
528 // foo = new function() {}
529 // is this actually used much!?!?!
533 (this.ts.lookTok(-1).name == 'NEW') &&
534 (this.ts.lookTok(-2).data == '=') &&
535 (this.ts.lookTok(-3).type = 'FUNCTION')
537 //scopeName = this.ts.look(-3).data;
538 this.ts.balanceN(Script.TOKlparen);
539 token = this.ts.nextTok(); // should be {
540 scopeName = fixAlias(scopeName);
541 var fnScope = new Scope(this.braceNesting, scope, token.n, '$private$');
542 this.indexedScopes[this.ts.cursor] = fnScope;
544 //this.scopesIn(fnScope);
545 this.parseScope(fnScope, aliases);
548 //print(">>" +locBraceNest);
549 continue; // no more processing..
555 ///==== check/set isObjectLitAr ??
558 // foo: function() {}
559 // no change to scoping..
561 //print("checking for : function() {");
562 //print( [this.ts.lookTok(-3).type , this.ts.lookTok(-2).type , this.ts.lookTok(-1).type ].join(":"));
564 (this.ts.lookTok(-1).data == ':') &&
565 (this.ts.lookTok(-2).type == 'NAME') &&
566 (this.ts.lookTok(-3).data == '(' || this.ts.lookTok(-3).data== ',')
568 //print("got for : function() {");
570 //scopeName = this.ts.look(-3).data;
571 this.ts.balanceN(Script.TOKlparen);
572 //print(token.toString())
573 token = this.ts.nextTok(); // should be {
574 //print(token.toString())
575 scopeName = fixAlias(scopeName);
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..
586 /// function foo() {} << really it set's the 'this' scope to foo.prototype
587 //$this$=foo|$private$
591 (this.ts.lookTok(1).type == 'NAME')
593 //scopeName = this.ts.look(-3).data;
594 this.ts.balanceN('(');
595 token = this.ts.nextTok(); // should be {
597 var fnScope = new Scope(this.braceNesting, scope, token.n, '');
598 this.indexedScopes[this.ts.cursor] = fnScope;
600 //this.scopesIn(fnScope);
601 this.parseScope(fnScope, aliases);
603 //print(">>" +locBraceNest);
604 continue; // no more processing..
609 // foo = new (function() { }
611 // RETURN function(...) {
614 // (this.ts.lookTok(-1).tokN == Script.TOKlparen) &&
615 (this.ts.lookTok(1).name != 'NAME')
617 // (this.ts.lookTok(-2).tokN == Script.TOKnew) &&
618 // (this.ts.lookTok(-3).tokN == Script.TOKassign) &&
619 // (this.ts.lookTok(-4).tokN == Script.TOKidentifier)
621 //scopeName = this.ts.look(-3).data;
622 this.ts.balanceN('(');
623 token = this.ts.nextTok(); // should be {
624 var fnScope = new Scope(this.braceNesting, scope, token.n, '$private$');
625 this.indexedScopes[this.ts.cursor] = fnScope;
627 //this.scopesIn(fnScope);
628 this.parseScope(fnScope, aliases);
630 //print(">>" +locBraceNest);
631 continue; // no more processing..
637 print(this.ts.context());
638 throw "dont know how to handle function syntax??";
645 } // end checking for TOKfunction
647 if (token.data == '{') {
649 // foo = { // !var!!!
654 (this.ts.lookTok(-1).data == '=') &&
655 (this.ts.lookTok(-2).type == 'NAME') &&
656 (this.ts.lookTok(-3).nane != 'VAR')
659 scopeName = this.ts.look(-2).data;
660 scopeName = fixAlias(scopeName);
661 var fnScope = new Scope(this.braceNesting, scope, token.n,
662 '$this$='+scopeName + '|'+scopeName
664 this.indexedScopes[this.ts.cursor] = fnScope;
666 this.scopesIn(fnScope);
670 //print(">>" +locBraceNest);
671 continue; // no more processing..
676 //print("GOT LBRACE : check for :");
678 (this.ts.lookTok(-1).data == ':') &&
679 (this.ts.lookTok(-2).type == 'NAME') &&
680 (this.ts.lookTok(-3).name != 'VAR')
683 scopeName = this.ts.lookTok(-2).data;
684 scopeName = fixAlias(scopeName);
685 var fnScope = new Scope(this.braceNesting, scope, token.n, scopeName);
686 this.indexedScopes[this.ts.cursor] = fnScope;
688 this.scopesIn(fnScope);
691 //print(">>" +locBraceNest);
692 continue; // no more processing..
694 var fnScope = new Scope(this.braceNesting, scope, token.n, '');
695 this.indexedScopes[this.ts.cursor] = fnScope;
697 this.scopesIn(fnScope);
700 //print(">>" +locBraceNest);
704 if (token.data == '{') {
707 if (this.currentDoc) {
708 this.addSymbol('', true);
710 //throw "Unconsumed Doc: (TOKrbrace)" + this.currentDoc.toSource();
716 //assert braceNesting >= scope.getBraceNesting();
717 var closescope = this.scopeOut();
718 scope = this.scopes[this.scopes.length-1];
719 //print("<<:" + locBraceNest)
720 //print("<<<<<< " + locBraceNest );
721 if (locBraceNest < 0) {
722 // print("POPED OF END OF SCOPE!");
724 //var ls = this.scopeOut();
725 //ls.getUsedSymbols();
738 addSymbol: function(lastIdent, appendIt, atype )
741 /*if (!this.currentDoc.tags.length) {
744 //print(this.currentDoc.toSource());
745 // this.currentDoc = false;
747 print("SKIP ADD SYM: no tags");
748 print(this.currentDoc.src);
752 if (this.currentDoc.getTag('private').length) {
755 //print(this.currentDoc.toSource());
756 this.currentDoc = false;
757 print("SKIP ADD SYM: it's private");
761 var token = this.ts.cur();
762 if (typeof(appendIt) == 'undefined') {
765 // print(this.currentDoc.toSource(););
766 if (this.currentDoc.getTag('event').length) {
767 //?? why does it end up in desc - and not name/...
768 print(this.currentDoc.getTag('event')[0]);
769 lastIdent = '*' + this.currentDoc.getTag('event')[0].desc;
770 //lastIdent = '*' + lastIdent ;
772 if (!lastIdent.length && this.currentDoc.getTag('property').length) {
773 lastIdent = this.currentDoc.getTag('property')[0].name;
774 //lastIdent = '*' + lastIdent ;
778 if (!/\./.test(_s)) {
780 //print("WALKER ADDsymbol: " + lastIdent);
783 for (var i = 0; i < this.scopes.length;i++) {
784 s.push(this.scopes[i].ident);
788 var s = s.join('|').split('|');
789 print("Walker:ADDSymbol: " + s.join('|') );
794 for (var i = 0; i < s.length;i++) {
799 if ((s[i] == '$private$') || (s[i] == '$global$')) {
803 if (s[i].substring(0,6) == '$this$') {
804 var ts = s[i].split('=');
808 // when to use $this$ (probabl for events)
809 _s += _s.length ? '.' : '';
815 //print("ADDING SYMBOL: "+ s.join('|') +"\n"+ _s + "\n" +Script.prettyDump(this.currentDoc.toSource()));
817 if (appendIt && !lastIdent.length) {
819 // append, and no symbol???
821 // see if it's a @class
822 if (this.currentDoc.getTag('class').length) {
823 _s = this.currentDoc.getTag('class')[0].desc;
824 var symbol = new Symbol(_s, [], "CONSTRUCTOR", this.currentDoc);
825 Parser.addSymbol(symbol);
826 this.symbols[_s] = symbol;
830 // if (this.currentDoc.getTag('property').length) {
831 // print(Script.pretStringtyDump(this.currentDoc.toSource));
832 // throw "Add Prop?";
835 _s = _s.replace(/\.prototype.*$/, '');
836 if (typeof(this.symbols[_s]) == 'undefined') {
837 print("Symbol:" + _s);
838 print(this.currentDoc.src);
840 throw "Trying to append symbol, but no doc available";
843 for (var i =0; i < this.currentDoc.tags.length;i++) {
844 this.symbols[_s].addDocTag(this.currentDoc.tags[i]);
846 this.currentDoc = false;
850 if (typeof(this.symbols[_s]) != 'undefined') {
852 if (this.symbols[_s].comment.hasTags) {
853 // then existing comment doesnt has tags
854 throw "DUPLICATE Symbol " + _s;
856 // otherwise existing comment has tags - overwrite..
860 if (typeof(atype) == "undefined") {
861 atype = 'OBJECT'; //this.currentDoc.getTag('class').length ? 'OBJECT' : 'FUNCTION';;
864 var symbol = new Symbol(_s, [], atype, this.currentDoc);
866 Parser.addSymbol(symbol);
867 this.symbols[_s] = symbol;
869 this.currentDoc = false;
876 scopesIn : function(s)
879 //print(">>>" + this.ts.context() + "\n>>>"+this.scopes.length+":" +this.scopeListToStr());
882 scopeOut : function()
885 // print("<<<" + this.ts.context() + "\n<<<"+this.scopes.length+":" +this.scopeListToStr());
886 return this.scopes.pop();
890 scopeListToStr : function()
893 for (var i = 0; i < this.scopes.length;i++) {
894 s.push(this.scopes[i].ident);
896 return s.join('\n\t');