resources/RooUsage.txt
[app.Builder.js] / old-javascript / JsParser.js
1 //<script type="text/javscript">
2
3 XObject = imports.XObject.XObject;
4 console     = imports.console.console;
5 Collapse = imports.JSDOC.Collapse.Collapse;
6 /**
7  * 
8  * this takes our collased file, and turns it into the config array..
9  * 
10  * @see rconv.js (our tester file)
11  * 
12  * STATUS:
13  *
14  *  - Pman.Tab.* appears to work.
15  * .. next up ..Dialog...
16  *
17  *
18  *
19  * Current issues:
20  *  - xtype is combined on generated files. (not xns + xtype)
21  *  - listeners are prefixed with '|' ... 
22  *  - modkey is not getting picked up..
23  *  - suspect some of the elements are not getting flattened
24  *  - parent on 
25  */
26
27 JsParser  =  XObject.define(
28     function (ar)
29     {
30         JsParser.superclass.constructor.call(this, ar);
31        // console.log("STARTING OUTPUT");
32         
33          
34
35     },
36     Collapse, 
37     {
38         
39         cfg : { },
40
41         parse: function()
42         {
43             // standard pman dialog
44             if (this.tokens[0].data == 'Pman.on') {
45                 this.parsePmanLayout();
46                 return;
47             }
48          
49             
50             // Standard Pman Dialog - 
51             if (this.tokens[2].props && typeof(this.tokens[2].props.create) != 'undefined') {
52                 this.parsePmanDialog();
53                 return;
54             }
55             
56             
57             // Seed Gtk XObject application. 
58             if (this.tokens.length > 2 && this.tokens[2].data.match(/^imports\./)) {
59                 this.parseXObject();
60                 return;
61             }
62             
63             Seed.print("Unknown format");
64             Seed.print(JSON.stringify(this.tokens,null,4));
65             Seed.quit();
66             
67             
68             
69             
70             
71             
72             
73             
74             // perfect for dialogs... - is this our 'generic, non-pman code?'
75             
76             
77             var pos = this.lookFor( 'function');
78             
79             // XXXXX = function(
80             var cfg = {};
81             
82             if (pos > -1 && (this.tokens[pos-1].data == '=') && (this.tokens[pos-2].type == 'NAME')) {
83                 
84                 this.cfg = {
85                     '*class' : this.tokens[pos-2].data,
86                     '*extends' : '',
87                     '//constructor' :  this.tokens[pos-2].prefix,
88                     '|constructor' : 'function ' + this.tokens[pos+1].toRaw() + 
89                             this.tokens[pos+2].toRaw()
90                     
91                 };
92                 this.cursor = pos+2;
93                 
94             }
95             
96             if (pos < 0) {
97                 // no function - we have a static one...
98                 pos = this.lookFor( '=');
99                 if (pos > 1 && 
100                     (this.tokens[pos-1].type == 'NAME') &&
101                     (this.tokens[pos+1].data == '{')
102                 ) {
103                     this.cfg = {
104                         '*class' : this.tokens[pos-1].data,
105                         '//*class' :  this.tokens[pos-1].prefix
106                         
107                         
108                     };
109                     XObject.extend(this.cfg, this.parseProps(this.tokens[pos+1].props));
110                     return;
111                     
112                 }
113                 
114                 
115                 
116             }
117             
118             
119               // Roo.apply (l
120             var pos = this.lookFor( 'Roo.apply');
121             //console.dump(this.tokens);
122             
123             
124             if (
125                 (pos > -1) &&
126                 (this.tokens[pos+1].items[0][0].data  == this.cfg['*class'] + '.prototype')
127             ) {
128                 // XXXXXx.prototype = {
129                 
130                 
131                     
132                 XObject.extend(this.cfg, this.parseProps(this.tokens[pos+1].items[1][0].props));
133                 return;
134                 
135             }
136             
137             
138             var pos = this.lookFor('new');
139             
140             if (pos > -1 && 
141                 (this.tokens[pos-2].type == 'NAME') &&
142                 (this.tokens[pos-1].data == '=') && 
143                 (this.tokens[pos+1].type == 'NAME') &&
144                 (this.tokens[pos+2].data == '(') 
145             ) {
146                 
147                 this.cfg = {
148                     '//*class' : this.tokens[pos-2].prefix,
149                     '*class' : this.tokens[pos-2].data,
150                     '*extends' : this.tokens[pos+1].data
151                 };
152                     
153                 XObject.extend(this.cfg, this.parseProps(this.tokens[pos+2].items[0][0].props));
154                 
155                 return;
156                 
157             }
158             
159             ///Builder.Provider.ProjectManager = new Roo.Observable({
160                 
161             
162             
163             var pos = this.lookFor( 'Roo.extend');
164             if (pos > -1) {
165                 
166                 this.cfg['*extends'] = this.tokens[pos+1].items[1][0].data;
167                 XObject.extend(this.cfg, this.parseProps(this.tokens[pos+1].items[2][0].props));
168                 
169                 // no more..
170                 return;
171             }
172             
173              
174                 
175             var pos = this.lookFor( 'Roo.extend');
176             if (pos > -1) {
177                 
178                 this.cfg['*extends'] = this.tokens[pos+1].items[1][0].data;
179                 XObject.extend(this.cfg, this.parseProps(this.tokens[pos+1].items[2][0].props));
180                 
181                 // no more..
182                 return;
183             }
184             
185             
186             
187             //console.dump(cfg);
188             //Seed.quit();
189             
190             
191             
192             // other type of layout
193           //  console.dump(this.tokens);
194             
195             // this type of file..
196             // xxxx.xxx = function
197             // -> into |constructor..
198             // -> extend + prototype
199              
200             
201             
202                 
203         },
204         
205         
206         parsePmanLayout : function()
207         {
208                 // then it's a layout style..
209             
210             //Seed.quit();
211             
212             
213             //console.dump(this.tokens);
214             //              the list of statements inside of function..?
215             
216             
217             var stmts =  this.tokens[1].items[1][2].items;
218             
219             // look for register..
220             var topp = false;
221             stmts.map( function(s, i) {
222                 if (s[0].data == 'Pman.register') {
223                     topp = brace = s[1].items[0][0].props;
224                 }
225             });
226             if (!topp) {
227                 console.dump(this.tokens);
228                 throw "could not find top props...";
229                 
230             }
231             //print(JSON.stringify(topp,null,4));
232             
233             this.cfg = this.parseProps(topp);
234             for(var k in this.cfg) {
235                 this.cfg[k.replace(/^\|/, '')] = this.cfg[k];
236             }
237             if (this.cfg.name) {
238                 this.cfg.title = this.cfg.name;
239                 delete this.cfg.name;
240             }
241            // this.cfg.fullname = this.cfg.name;
242             this.cfg.type = 'Roo';
243             
244             
245             
246             // looking for parent / name..
247             
248             
249             this.cfg.modOrder = this.cfg.modKey.split('-').shift(); 
250             print(JSON.stringify(this.cfg,null,4));
251             
252             
253             //                  (            {          add    { this.panel (  {
254             var cfg = this.tokens[7].items[0][0].props.add.val[2].items[2][3].items[0][0].props;
255             this.cfg.items = [ this.parseProps(cfg) ];
256             //console.dump(this.cfg); 
257         },
258         
259         
260         parsePmanDialog : function() {
261             
262             //console.dump(this.tokens);
263             this.cfg.name = this.tokens[0].data;
264             
265             
266             
267             var cfg = this.tokens[2].props.create.val[2].items[1][3].items[0][0].props;
268             this.cfg.type = 'Roo';
269             //console.dump(this.tokens);
270             //print(JSON.stringify(cfg,null,4)); Seed.quit();
271             
272            // print("Trying standard dialog");Seed.quit();;
273             
274             this.cfg.items = [ this.parseProps(cfg) ];
275             return;
276             
277         },
278         
279         // Seed xobject file.
280         parseXObject : function() {
281             
282             this.parseImports();
283               
284             var pos = this.lookFor('XObject');
285             if (pos < 0)  {
286                 throw "Can not find XObject";
287             }
288             this.cfg.name = this.tokens[pos-3].data;
289             this.cfg.type = 'Gtk';
290             var cfg = this.tokens[pos+1].items[0][0].props;
291             this.cfg.items = [ this.parseProps(cfg) ];
292             
293             //print(JSON.stringify(this.tokens[pos]));
294             
295             //print(JSON.stringify(this.tokens,null,4)); Seed.quit();
296             //Seed.quit();
297             
298         },
299         
300         
301         
302         /**
303          *  parse Imports lines.
304          *
305          */
306         
307         parseImports : function()
308         {
309            // console.dump(this.tokens);
310             this.cfg.giImports = [];
311             this.cfg.imports= [];
312             while (true) {
313                 var pos = this.lookFor('=');
314                 if (pos < 0)  {
315                     break;
316                 }
317                 this.cursor = pos;
318                 var k = this.look(-1, true);
319                 var v = this.look(1, true);
320                // Seed.print(k.data + " => " + v.data);
321                
322                 /// finish!!! - not an import ...
323                
324                 if (!v.data.match(/^imports/)) {
325                     return; ///
326                     
327                     this.cursor++;
328                     continue;
329                 }
330                 if (v.data.match(/^imports\.gi/)) {
331                     // gi import..
332                     this.cfg.giImports.push(v.data.replace(/imports\.gi\./, ''));
333                     
334                     this.cursor++;
335                     continue;
336                 }
337                   
338                 // two types of import left
339                 // imports.xnew
340                 if (v.data.match(/^imports\./)) {
341                     this.cfg.imports[k.data] = v.data.replace(/imports\./, '') + '.js';
342                     this.cursor++;
343                     continue;
344                 }
345                 // imports[.....]
346                 this.cursor++;
347                 if (this.lookFor('[') > this.lookFor('=')) {
348                     continue;
349                 }
350                 var bpos = this.lookFor('[');
351                // console.dump(this.tokens[bpos]);
352                 
353                 this.cfg.imports[k.data] = this.tokens[bpos].items[0][0].toJS();
354                 
355                 this.cursor++;
356                 
357             }
358         //    console.dump(this.giImports);
359           //  console.dump(this.imports);
360             //Seed.quit();
361             
362         },
363         
364         ///------------------- GENERIC PARSING ------------------
365         
366         
367         
368         
369         
370         
371         parseProps:  function(o)
372         {
373             //print(JSON.stringify(o,null,4));
374             
375             var ret = { };
376             var fakeItems =  [];
377             for(var k in o) {
378                 
379                 //print( "parsing prop: " + k);
380                 if (o[k].key.data == '}') {
381                     // typo trailing comma in object def.
382                     continue;
383                 }
384                 
385                 var kv = k;
386                 if (o[k].key.type == 'STRN') {
387                     kv = o[k].key.toJS();
388                 }
389                 if (!o[k].val.length) {
390                     console.dump(o[k]);
391                 }
392                 
393                 //console.dump(o[k]);
394                 if (o[k].val[0].data == "function") {
395                     // add comments..
396                   //   console.dump(o[k].key.prefix); 
397                     var pr = typeof(o[k].key.prefix) == 'undefined' ? '' : o[k].key.prefix ;
398                     pr = this.clean_prefix( pr) ;
399                     if (pr.length) {
400                         ret['//' +kv ] =  pr;
401                     }
402                     //print("running expand");
403                     ret['|' +kv ] =  this.clean_body( this.expand(o[k].val));
404                     continue;
405                 }
406                 
407                 
408                 if (o[k].val[0].data == "[") {
409                     
410                     if (o[k].val[0].items[0][0].data == '{') {
411                         // array of objects..
412                         
413                         // this works for items..
414                         
415                         // used elsewhere for buttons: -> in which case we have a fake xtype
416                         
417                         
418                         
419                         // if K is not ITEMS - we need to add '*prop' -> and add it to the items array..
420                         var add = this.parseArray(o[k].val[0].items);
421                         if (kv == 'items') {
422                             ret[kv] = add;
423                             continue;
424                         }
425                         add.forEach(function(a) {
426                             a['*prop'] = kv + '[]';
427                             fakeItems.push(a);
428                         });
429                         
430                         continue;
431                     } 
432                     // raw array 
433                     
434                     
435                     ret['|' +kv ] =  this.clean_body(this.expand(o[k].val)); // remove ','...
436                     continue;
437                 }
438                 if (o[k].val[0].data == "(") {
439                     ret['|' +kv ] =  this.expand(o[k].val);
440                     continue;
441                 }
442                 // value is an object..
443                 
444                 if (o[k].val[0].data == "{") {
445                     
446                     // things that can be property of object type:
447                     // listeners, set, 
448                     var add = this.parseProps(o[k].val[0].props);
449                     
450                     
451                     
452                     if (kv == 'set' || kv =='listeners') {
453                         ret[kv ] = add;
454                         continue;
455                     }
456                     if ((typeof(add.xtype) != 'undefined') ||  ['sortInfo', 'center', 'east', 'west', 'north', 'south'].indexOf(kv) > -1) {
457                         add['*prop'] =  kv;
458                         fakeItems.push(add);
459                         continue;
460                     }
461                     
462                     
463                     ret[ '|' + kv ] =  this.expand(o[k].val);
464                     
465                     
466                     // this hsould be added to 'items', with a *prop element..
467                     continue;
468                 }
469                 //console.dump(o[k].val);
470                 
471                 if (o[k].val[1].data == ',' || o[k].val[1].data == '}') {
472                     // single item piece of data...
473                     var t1= o[k].val[0];
474                     switch(o[k].val[0].type) {
475                         case 'STRN':
476                         case 'NUMB':
477                         case 'KEYW':
478                             ret[  kv ]  = t1.toJS();
479                             continue;
480                         case 'NAME':
481                             ret[ '|' + kv ] =  t1.data;
482                             continue;
483                         
484                     }
485                 }
486                 // finally give up..
487                 ret[ '|' + kv ] =  this.clean_body(this.expand(o[k].val));
488                 
489             }
490             if (!ret.items && fakeItems.length) {
491                 ret.items = [];
492             }
493             fakeItems.forEach(  function(e) {
494                 ret.items.push(e);
495             });
496             // merge fakeItems;
497             //console.dump(ret);
498             
499             return ret;
500         },
501         parseArray: function(ar) {
502           // console.dump(ar);
503            // Seed.quit();
504             var ret = [];
505             ar.map(function (e) {
506                 // has no props...
507                 if (typeof(e[0].props) == 'undefined') {
508                     return;
509                 }
510                
511                 
512                 ret.push( this.parseProps(e[0].props));
513                      
514             },this);
515              
516             return ret;
517           
518         },
519         
520         /**
521          * convert a function call token array back into a string
522          */
523         expand: function(ar)
524         {
525             var ret = '';
526             //print(JSON.stringify(ar,null,4));
527              
528             for(var i =0 ; i < ar.length -1; i++) {
529                 ret += ar[i].toRaw();
530             }
531             
532             return ret;
533             
534             
535         },
536         
537         /***
538          * change the indentation on a function 
539          *
540          */
541         clean_body : function(str)
542         {
543             var lns = str.split("\n");
544             var mindent = -1;
545             lns.map( function(l, i) {
546                 if (!i || !l.length || l.match(/^\s+$/)) {
547                     return;
548                 }
549                 
550                 var spc = l.match(/\s+/);
551                 if (!spc || !spc[0].length) {
552                     return;
553                 }
554                 mindent = mindent < 0 ? spc[0].length : Math.min(spc[0].length, mindent);
555                 
556             });
557             //console.log(mindent + ":" + lns[0]);
558             var ar = [];
559             if (mindent < 0) {
560                 return str;
561             }
562             lns.map( function(l,i) {
563                 if (!i) {
564                     ar.push(l.replace(/^\s+/, ''));
565                     return;
566                 }
567                 ar.push(l.substring(mindent));
568             });
569             //print(str);
570             //print(JSON.stringify(ar,null,4));
571             
572             
573             return ar.join("\n");
574         },
575         clean_prefix: function(str) {
576             
577             
578             
579             if (!str.length) {
580                 return '';
581             }
582             var ret = str.replace(/^\s+/gm, "\n").replace(/\n+/gm, "\n");
583             return ret == "\n" ? '' : ret;
584             
585         }    
586              
587     
588 });