mochiscript 0.4.0.pre10 → 0.4.0.pre12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/mochiscript.rb CHANGED
@@ -1,1054 +1,2 @@
1
- require 'v8'
2
- require 'json'
3
-
4
- module Mochiscript
5
- VERSION = "0.4.0-pre10".sub("-", '.')
6
- class Context
7
- def initialize
8
- @ctx = V8::Context.new
9
- @ctx['_$m_adapter'] = Adapter.new
10
- @ctx.eval(Parser::JAVASCRIPT)
11
- end
12
-
13
- def parse(str)
14
- @ctx.eval_js("$m.parse(#{str.to_json})")
15
- end
16
-
17
- def eval_ms(str)
18
- @ctx.eval_js(parse(str))
19
- end
20
-
21
- protected
22
-
23
- def method_missing(name, *args, &block)
24
- @ctx.send(name, *args, &block)
25
- end
26
- end
27
-
28
- class Adapter
29
- def out(arg)
30
- print arg
31
- end
32
-
33
- def outs(arg)
34
- puts arg
35
- end
36
- end
37
-
38
- class Parser
39
- JAVASCRIPT = <<'FINISH'
40
- var $m = { ROOT: this, ADAPTER: _$m_adapter };
41
- var JS2 = $m;
42
- (function () {
43
-
44
- // CLASS HELPERS
45
- (function (undefined, $m) {
46
-
47
- var OO = function (klass, par) {
48
- this.klass = klass;
49
- this.par = par;
50
-
51
- this.members = {};
52
- this.staticMembers = {};
53
- this.children = [];
54
- this.included = [];
55
-
56
- if (this.par) this.par.OO.children.push(klass);
57
- };
58
-
59
- OO.prototype = {
60
- forbiddenMembers: {
61
- 'prototype': undefined,
62
- 'OO': undefined
63
- },
64
-
65
- include: function(module) {
66
- this.included.push(module);
67
- var members = module.OO.members;
68
- for (var name in members) {
69
- if (members.hasOwnProperty(name)) {
70
- this.addMember(name, members[name]);
71
- }
72
- }
73
-
74
- var staticMembers = module.OO.staticMembers;
75
- for (var name in staticMembers) {
76
- if (staticMembers.hasOwnProperty(name)) {
77
- this.addStaticMember(name, staticMembers[name]);
78
- }
79
- }
80
-
81
- if (typeof staticMembers['included'] == 'function') {
82
- staticMembers['included'](this.klass);
83
- }
84
- },
85
-
86
- createNamespace: function(name) {
87
- var splitted = name.split('.');
88
- var klassName = splitted.pop();
89
- var root = $m.ROOT;
90
-
91
- while (splitted.length > 0) {
92
- var name = splitted.shift();
93
- if (!root[name]) root[name] = $m.Class.extend({});
94
- root = root[name];
95
- }
96
-
97
- return [ root, klassName ];
98
- },
99
-
100
- makeSuper: function(newMethod, oldMethod) {
101
- if (!oldMethod) return newMethod;
102
-
103
- return function() {
104
- this.$super = oldMethod;
105
- return newMethod.apply(this, arguments);
106
- };
107
- },
108
-
109
- addMember: function(name, member) {
110
- if (this.forbiddenMembers.hasOwnProperty(name)) return;
111
-
112
- var proto = this.klass.prototype;
113
- if (typeof proto[name] == 'function' && !(proto[name] instanceof RegExp)) {
114
- member = this.makeSuper(member, proto[name]);
115
- }
116
-
117
- proto[name] = member;
118
- this.members[name] = member;
119
- },
120
-
121
- addStaticMember: function(name, member) {
122
- if (this.forbiddenMembers.hasOwnProperty(name)) return;
123
-
124
- if (typeof this.klass[name] == 'function') {
125
- if (!this.klass.hasOwnProperty(name)) {
126
- member = this.makeSuper(member, this.klass[name]);
127
- }
128
- }
129
-
130
- this.klass[name] = member;
131
- this.staticMembers[name] = member;
132
- }
133
- };
134
-
135
- $m.Class = function() { this.initialize.apply(this, arguments); };
136
- $m.Class.OO = new OO($m.Class);
137
- $m.Class.prototype = {
138
- initialize: function () {},
139
- oo: $m.Class.OO
140
- };
141
-
142
- var namedClasses = {};
143
- $m.getClass = function(name) {
144
- return namedClasses[name];
145
- };
146
-
147
- var noInit = false;
148
- $m.Class.extend = function(name, klassDef) {
149
- var klass = function() { if (!noInit) this.initialize.apply(this, arguments); };
150
- klass.OO = new OO(klass, this);
151
-
152
- if (typeof name != 'string') {
153
- klassDef = name;
154
- } else {
155
- namedClasses[name] = klass;
156
- var namespace = this.OO.createNamespace(name);
157
- namespace[0][namespace[1]] = klass;
158
- }
159
-
160
- // create instance of this as prototype for new this
161
- noInit = true;
162
- var proto = new this();
163
- noInit = false;
164
-
165
- klass.prototype = proto;
166
- var oo = klass.OO;
167
- proto.OO = oo;
168
-
169
- for (var name in this) {
170
- oo.addStaticMember(name, this[name]);
171
- }
172
-
173
- if (typeof klassDef == 'function') {
174
- klassDef(klass, oo);
175
- } else {
176
- for (var name in klassDef) {
177
- oo.addMember(name, klassDef[name]);
178
- }
179
- }
180
-
181
- return klass;
182
- };
183
-
184
- $m.Module = $m.Class;
185
-
186
- var assert = {
187
- 'eq': function(expected, actual) { if (expected != actual) $m.outs("Expected "+expected+", but got "+actual+".") },
188
- 'isFalse': function(val) { if (val) $m.outs("Expected false, but got "+JSON.stringify(val)+".") },
189
- 'isTrue': function(val) { if (!val) $m.outs("Expected true, but got " +val+".") }
190
- };
191
-
192
- $m.test = function(message, callback) {
193
- if (!callback) callback = message;
194
- callback(assert);
195
- };
196
-
197
- function addListener(type, listener) {
198
- var events = this.__$events || (this.__$events = {});
199
- this.emit('newListener', type, listener);
200
- if (!events[type]) events[type] = [];
201
- events[type].push(listener);
202
- }
203
-
204
- $m.EventEmitter = $m.Module.extend({
205
- emit: function () {
206
- // TODO optimize
207
- var type = arguments[0];
208
- var events = this.__$events || (this.__$events = {});
209
- var handlers = events[type];
210
-
211
- if (!handlers) return false;
212
-
213
- var args = [];
214
- for (var i=1,len=arguments.length; i<len; i++) args[i-1] = arguments[i];
215
- for (var i=0,len=handlers.length; i<len; i++) handlers[i].apply(this, args);
216
- },
217
-
218
- addListener: addListener,
219
- on: addListener
220
- });
221
-
222
- $m.out = function () {
223
- for(var i=0,_c1=arguments,_l1=_c1.length,arg;(arg=_c1[i])||(i<_l1);i++){
224
- $m.ADAPTER.out(arg);
225
- if (i < arguments.length-1) {
226
- $m.ADAPTER.out(',');
227
- }
228
- }
229
- };
230
-
231
- $m.outs = function () {
232
- for(var _i1=0,_c1=arguments,_l1=_c1.length,arg;(arg=_c1[_i1])||(_i1<_l1);_i1++){
233
- $m.ADAPTER.outs(arg);
234
- }
235
- };
236
-
237
-
238
- return $m;
239
- })(undefined, $m);
240
-
241
-
242
- var IDENT = "[\\$\\w]+";
243
- var TOKENS = [
244
- [ "SPACE", "\\s+" ],
245
-
246
- [ "STATIC", "static\\b" ],
247
- [ "MODULE", "module\\b", 'ModuleParser' ],
248
- [ "CLASS", "class\\b", 'ClassParser' ],
249
- [ "FUNCTION", "function\\b" ],
250
- [ "INCLUDE", "include\\b" ],
251
- [ "VAR", "var\\b" ],
252
- [ "PRIVATE", "private\\b" ],
253
- [ "EXTENDS", "extends\\b" ],
254
- [ "FOREACH", "foreach\\b", 'ForeachParser' ],
255
-
256
- [ "SHORTHAND_FUNCTION", "#(?:{|\\()", 'ShorthandFunctionParser' ],
257
- [ "ISTRING_START", "%{", 'IStringParser' ],
258
- [ "HEREDOC", "<<[A-Z][0-9A-Z]*", 'HereDocParser' ],
259
-
260
- [ "DSTRING", "\"(?:\\\\.|[^\"])*\"" ],
261
- [ "SSTRING", "\'(?:\\\\.|[^\'])*\'" ],
262
-
263
- [ "SEMICOLON", ";" ],
264
- [ "OPERATOR", "\\+|\\-|\\++" ],
265
- [ "EQUALS", "=" ],
266
-
267
- [ "COMMENT", "\\/\\/|\\/\\*", "CommentParser" ],
268
- [ "REGEX", "/", 'RegexParser' ],
269
-
270
- [ "LBRACE", "\\(" ],
271
- [ "RBRACE", "\\)" ],
272
- [ "LCURLY", "\\{" ],
273
- [ "RCURLY", "\\}" ],
274
-
275
- [ "IDENT", IDENT ],
276
- [ "WHATEVER", "." ]
277
- ];
278
-
279
- var $c = $m.ROOT;
280
- var TYPES = {};
281
- var REGEXES = [];
282
- var MAIN_REGEX = null;
283
-
284
- for(var i=0,_c1=TOKENS,_l1=_c1.length,t;(t=_c1[i])||(i<_l1);i++){
285
- TYPES[t[0]] = i;
286
- REGEXES.push("(" + t[1] + ")");
287
- }
288
-
289
- var EXTRA_REGEX_STRINGS = {
290
- ARGS: "\\(\s*(?:" + IDENT + ")?(?:\\s*,\\s*" + IDENT + ")*\s*\\)",
291
- CLASSNAME: "[\\$\\w\\.]+"
292
- };
293
-
294
- var MAIN_REGEX = new RegExp("^" + REGEXES.join('|'));
295
-
296
- JS2.Class.extend('Tokens', function(KLASS, OO){
297
- OO.addMember("initialize",function (str) {
298
- this.orig = str;
299
- this.str = str;
300
- this.iterator = 0;
301
- this.consumed = 0;
302
- });
303
-
304
- OO.addMember("peek",function () {
305
- if (this._peek) return this._peek;
306
-
307
- var m = this.str.match(MAIN_REGEX);
308
- if (!m) return null;
309
-
310
- for(var i=0,_c1=TOKENS,_l1=_c1.length,ele;(ele=_c1[i])||(i<_l1);i++){
311
- if (m[i+1]) return this._peek = [ i, m[i+1], ele[2] ];
312
- }
313
- });
314
-
315
- OO.addStaticMember("regex",function (str) {
316
- var regexStr = str.replace(/\*\*/g, "\\s*").replace(/\s+/g, "\\s+").replace(/\>\</g, ">\\s*<").replace(/\<(\w+)\>/g, function($1,$2,$3){
317
- return "(" + (EXTRA_REGEX_STRINGS[$2] || TOKENS[TYPES[$2]][1]) + ")";
318
- });
319
-
320
- return new RegExp("^" + regexStr);
321
- });
322
-
323
- OO.addMember("consume",function (n) {
324
- this.str = this.str.substr(n, this.str.length-n);
325
- this._peek = null;
326
- this.consumed += n;
327
- });
328
-
329
- OO.addMember("length",function () {
330
- return this.str.length;
331
- });
332
-
333
- OO.addMember("lookback",function (n) {
334
- var starting = this.consumed;
335
- while (this.orig.charAt(starting).match(/\s/)) starting--;
336
- return this.orig.substr(starting-1-n, n);
337
- });
338
-
339
- OO.addMember("lookahead",function (n) {
340
- var starting = this.consumed;
341
- while (this.orig.charAt(starting).match(/\s/)) starting++;
342
- return this.orig.substr(starting, n);
343
- });
344
-
345
-
346
- OO.addMember("any",function () {
347
- return this.str.length > 0;
348
- });
349
-
350
- OO.addMember("match",function (regex) {
351
- return this.str.match(regex);
352
- });
353
- });
354
- var Tokens = $c.Tokens;
355
-
356
-
357
- $m.parse = function (str) {
358
- var parser = new $c.RootParser();
359
- parser.parse(new $c.Tokens(str));
360
- return parser.toString();
361
- };
362
-
363
- JS2.Class.extend('RootParser', function(KLASS, OO){
364
- OO.addMember("handlers",{});
365
-
366
- OO.addMember("initialize",function () {
367
- this.out = [];
368
- this.finished = false;
369
- });
370
-
371
- OO.addMember("parse",function (tokens) {
372
- var len = tokens.length();
373
- if (this.startParse(tokens) === false || this.parseTokens(tokens) === false || this.endParse(tokens) === false) return false
374
- return len != tokens.length();
375
- });
376
-
377
- OO.addMember("parseTokens",function (tokens) {
378
- var sanity = 100;
379
- var origLen = tokens.length();
380
-
381
- while (tokens.any()) {
382
- var token = tokens.peek();
383
- if (!token) break;
384
-
385
- // has a parser class associated with this token
386
- var handlerClass = this.getHandler(token) || token[2];
387
- if (handlerClass) {
388
- var handler = new $c[handlerClass];
389
- if (handler.parse(tokens) !== false) {
390
- this.out.push(handler);
391
- tokens.lastHandler = handler;
392
- } else {
393
- this.handleToken(token, tokens);
394
- }
395
- }
396
-
397
- // no parser class, use "this" to just consume it
398
- else {
399
- this.handleToken(token, tokens);
400
- }
401
-
402
- if (this.finished) break;
403
-
404
- if (origLen == tokens.length() && sanity-- == 0) {
405
- throw "parse error";
406
- } else {
407
- sanity = 100;
408
- }
409
- }
410
- });
411
-
412
- OO.addMember("startParse",function () { });
413
- OO.addMember("endParse",function () { });
414
-
415
- OO.addMember("handleToken",function (token, tokens) {
416
- this.out.push(token[1]);
417
- tokens.consume(token[1].length);
418
- });
419
-
420
- OO.addMember("toString",function () {
421
- var ret = [];
422
- for(var _i1=0,_c1=this.out,_l1=_c1.length,ele;(ele=_c1[_i1])||(_i1<_l1);_i1++){
423
- ret.push(ele.toString());
424
- }
425
- return ret.join("");
426
- });
427
-
428
- // intercepts parser class for special cases
429
- OO.addMember("getHandler",function (token) {
430
- return null;
431
- });
432
-
433
- OO.addMember("chop",function () {
434
- this.out.pop();
435
- });
436
- });
437
-
438
- var RootParser = $c.RootParser;
439
-
440
- RootParser.extend('ClassParser', function(KLASS, OO){
441
- // private closure
442
-
443
- var REGEX = Tokens.regex("<CLASS> <CLASSNAME><LCURLY>");
444
- var EXTENDS = Tokens.regex("<CLASS> <CLASSNAME><EXTENDS><CLASSNAME><LCURLY>");
445
-
446
-
447
- OO.addMember("parse",function (tokens) {
448
- var m = tokens.match(REGEX) || tokens.match(EXTENDS);
449
- var name = m[2];
450
- var extending = m[4] || "$m.Class";
451
-
452
- tokens.consume(m[0].length-1);
453
-
454
- var content = new $c.ClassContentParser();
455
- content.parse(tokens);
456
-
457
- this.out = [ "var ", name, " = " + extending + ".extend(function(KLASS, OO)", content, ");" ];
458
- });
459
- });
460
-
461
- RootParser.extend('ModuleParser', function(KLASS, OO){
462
- // private closure
463
-
464
- var REGEX = Tokens.regex("<MODULE> <CLASSNAME><LCURLY>");
465
-
466
-
467
- OO.addMember("parse",function (tokens) {
468
- var m = tokens.match(REGEX);
469
- if (!m) return false;
470
- var name = m[2];
471
- tokens.consume(m[0].length-1);
472
-
473
- var content = new $c.ClassContentParser();
474
- content.parse(tokens);
475
-
476
- this.out = [ "var ", name, " = $m.Module.extend(function(KLASS, OO)", content, ");" ];
477
- });
478
- });
479
-
480
- RootParser.extend('CurlyParser', function(KLASS, OO){
481
- OO.addMember("initialize",function (chop) {
482
- this.chop = chop;
483
- this.$super();
484
- });
485
-
486
- OO.addMember("handleToken",function (token, tokens) {
487
- if (this.curly === undefined) this.curly = 0;
488
- if (token[0] == TYPES.RCURLY) {
489
- this.curly--;
490
- } else if (token[0] == TYPES.LCURLY) {
491
- this.curly++;
492
- }
493
-
494
- this.$super(token, tokens);
495
- if (this.curly == 0) this.finished = true;
496
- });
497
-
498
- OO.addMember("endParse",function (tokens) {
499
- if (this.chop) {
500
- this.out.pop();
501
- this.out.shift();
502
- }
503
- });
504
- });
505
-
506
- var CurlyParser = $c.CurlyParser;
507
-
508
- CurlyParser.extend('ClassContentParser', function(KLASS, OO){
509
- OO.addMember("getHandler",function (token) {
510
- switch(token[0]) {
511
- case TYPES.STATIC: return "StaticParser";
512
- case TYPES.VAR: return "MemberParser";
513
- case TYPES.FUNCTION: return "MethodParser";
514
- case TYPES.PRIVATE: return "PrivateParser";
515
- case TYPES.INCLUDE: return "IncludeParser";
516
- }
517
- });
518
-
519
- });
520
-
521
- RootParser.extend('LineParser', function(KLASS, OO){
522
- OO.addMember("handleToken",function (token, tokens) {
523
- this.$super(token, tokens);
524
- if (token[0] == TYPES.SEMICOLON) {
525
- this.finished = true;
526
- }
527
- });
528
- });
529
-
530
- CurlyParser.extend('PrivateParser', function(KLASS, OO){
531
- // private closure
532
-
533
- var REGEX = Tokens.regex("<PRIVATE>\\s*");
534
-
535
-
536
- OO.addMember("startParse",function (tokens) {
537
- var m = tokens.match(REGEX);
538
- tokens.consume(m[0].length);
539
- });
540
-
541
- OO.addMember("endParse",function (tokens) {
542
- this.out.pop();
543
- this.out.shift();
544
- });
545
- });
546
-
547
-
548
- RootParser.extend('IStringParser', function(KLASS, OO){
549
- // private closure
550
-
551
- var BEGIN = Tokens.regex("<ISTRING_START>");
552
-
553
-
554
- OO.addMember("parse",function (tokens) {
555
- var m = tokens.match(BEGIN);
556
- tokens.consume(m[0].length);
557
- this.out.push('"');
558
-
559
- while (1) {
560
- var m = tokens.match(/^((?:\\.|.)*?)(#\{|})/);
561
- var str = m[1];
562
- var len = m[0].length;
563
- str.replace(/"/, '\\"');
564
-
565
- if (m[2] == '#{') {
566
- this.out.push(str+'"+(');
567
- tokens.consume(len-1);
568
- this.parseMiddle(tokens);
569
- this.out.push(')+"');
570
- }
571
-
572
- else if (m[2] == '}') {
573
- this.out.push(str);
574
- this.out.push('"');
575
- tokens.consume(len);
576
- return;
577
- }
578
- }
579
- });
580
-
581
- OO.addMember("parseMiddle",function (tokens) {
582
- var parser = new CurlyParser(true);
583
- parser.parse(tokens);
584
- this.out.push(parser);
585
- });
586
- });
587
-
588
- RootParser.extend('StaticParser', function(KLASS, OO){
589
- // private closure
590
-
591
- var VAR_REGEX = Tokens.regex("(<STATIC>(\\s+))<VAR>");
592
- var FUNCT_REGEX = Tokens.regex("(<STATIC>(\\s+))<FUNCTION>");
593
-
594
-
595
- OO.addMember("parseTokens",function (tokens) {
596
- var varMatch = tokens.match(VAR_REGEX);
597
- if (varMatch) {
598
- tokens.consume(varMatch[1].length);
599
- var parser = new MemberParser();
600
- parser.isStatic = true;
601
- parser.parse(tokens);
602
- this.out.push(parser);
603
- }
604
-
605
- else {
606
- var functMatch = tokens.match(FUNCT_REGEX);
607
- tokens.consume(functMatch[1].length);
608
-
609
- var parser = new MethodParser();
610
- parser.isStatic = true;
611
- parser.parse(tokens);
612
- this.out.push(parser);
613
- }
614
- });
615
- });
616
-
617
- RootParser.extend('MemberParser', function(KLASS, OO){
618
- // private closure
619
-
620
- var REGEX = Tokens.regex("var <IDENT>\\s*=\\s*?");
621
-
622
-
623
- OO.addMember("parse",function (tokens) {
624
- var m = tokens.str.match(REGEX);
625
- this.name = m[1];
626
- tokens.consume(m[0].length);
627
-
628
- var parser = new $c.LineParser();
629
- parser.parse(tokens);
630
- parser.chop();
631
- var addMethod = this.isStatic ? 'addStaticMember' : 'addMember';
632
-
633
- this.out = [ "OO." + addMethod + "(", JSON.stringify(this.name), ",", parser, ");" ];
634
- });
635
- });
636
-
637
-
638
-
639
- RootParser.extend('IncludeParser', function(KLASS, OO){
640
- // private closure
641
-
642
- var REGEX = Tokens.regex("<INCLUDE> <CLASSNAME><SEMICOLON>");
643
-
644
-
645
- OO.addMember("parse",function (tokens) {
646
- var m = tokens.match(REGEX);
647
- tokens.consume(m[0].length);
648
- this.out = [ 'OO.include(', m[2], ');' ];
649
- });
650
- });
651
-
652
- RootParser.extend('HereDocParser', function(KLASS, OO){
653
- // private closure
654
-
655
- var REGEX = Tokens.regex("<HEREDOC>");
656
-
657
-
658
- OO.addMember("parse",function (tokens) {
659
- var beginning = tokens.match(/^<<(\w+)\s*([;\)])*\n/);
660
- tokens.consume(beginning[0].length);
661
-
662
- var spacing = tokens.match(/^(\s*)/);
663
- var regexSub = new RegExp("^" + (spacing[0] || ''), "mg");
664
-
665
-
666
- var strMatch = tokens.match(new RegExp("^([\\s\\S]*?)\\n\\s*" + beginning[1] + "\\s*\\n"));
667
- var toParse = strMatch[1] || '';
668
-
669
- toParse = toParse.replace(regexSub, '');
670
- toParse = toParse.replace("\n", "\\n");
671
-
672
- var string = $m.parse('%{' + toParse + '}');
673
- tokens.consume(strMatch[0] ? strMatch[0].length : 0);
674
-
675
- this.out = [ string, beginning[2] || ';' ];
676
- });
677
- });
678
-
679
- RootParser.extend('MethodParser', function(KLASS, OO){
680
- // private closure
681
-
682
- var REGEX = Tokens.regex("<FUNCTION> <IDENT><ARGS><SPACE>");
683
-
684
-
685
- OO.addMember("parse",function (tokens) {
686
- var m = tokens.str.match(REGEX);
687
- tokens.consume(m[0].length);
688
- var name = m[2];
689
- var args = m[3];
690
-
691
- var body = new CurlyParser();
692
- body.parse(tokens);
693
-
694
- var addMethod = this.isStatic ? 'addStaticMember' : 'addMember';
695
-
696
-
697
- this.out = [ 'OO.' + addMethod + '(', JSON.stringify(name), ', function', args, body, ');' ];
698
- });
699
- });
700
-
701
- RootParser.extend('ShorthandFunctionParser', function(KLASS, OO){
702
- // private closure
703
-
704
- var ARGS_REGEX = Tokens.regex("<ARGS>\\s*");
705
-
706
-
707
- OO.addMember("parse",function (tokens) {
708
- tokens.consume(1);
709
- var argsMatch = tokens.match(ARGS_REGEX);
710
- var args = null;
711
-
712
- if (argsMatch) {
713
- args = argsMatch[0];
714
- tokens.consume(argsMatch[0].length);
715
- } else {
716
- args = "($1,$2,$3)";
717
- }
718
-
719
- var body = new CurlyParser();
720
- body.parse(tokens);
721
- var semi = tokens.match(/^\s*[,;\)]/) ? '' : ';';
722
-
723
- this.out = [ 'function', args, body, semi ];
724
- });
725
- });
726
-
727
- RootParser.extend('CommentParser', function(KLASS, OO){
728
- OO.addMember("parse",function (tokens) {
729
- var m = tokens.match(/^\/\/.*?\n/);
730
- if (m) {
731
- tokens.consume(m[0].length);
732
- this.out = [ m[0] ];
733
- return;
734
- }
735
-
736
- var m2 = tokens.match(/^\/\*[\s\S]*?\*\//);
737
- if (m2) {
738
- tokens.consume(m2[0].length);
739
- this.out = [ m2[0] ];
740
- return;
741
- }
742
-
743
- return false;
744
- });
745
- });
746
-
747
- RootParser.extend('RegexParser', function(KLASS, OO){
748
- // private closure
749
-
750
- var REGEX = /^\/(\\.|[^\/])+\/[imgy]{0,4}/;
751
- var DIVIDE = /(\}|\)|\+\+|\-\-|[\w\$])$/;
752
-
753
-
754
- OO.addMember("parseTokens",function (tokens) {
755
- var back = tokens.lookback(2);
756
- if (back.match(DIVIDE)) {
757
- tokens.consume(1);
758
- this.out.push("/");
759
- }
760
-
761
- else {
762
- var m = tokens.match(REGEX);
763
- if (m) {
764
- this.out.push(m[0]);
765
- tokens.consume(m[0].length);
766
- } else {
767
- return false;
768
- }
769
- }
770
- });
771
-
772
- });
773
-
774
- CurlyParser.extend('ForeachParser', function(KLASS, OO){
775
- // private closure
776
-
777
- var REGEX = Tokens.regex("<FOREACH><LBRACE><VAR> <IDENT>(?:**:**<IDENT>)? in (.*?)**<RBRACE>**{");
778
-
779
-
780
- OO.addMember("startParse",function (tokens) {
781
- var m = tokens.match(REGEX);
782
- namespace = tokens.iterator++;
783
-
784
- this.item = m[4];
785
- this.iterator = m[5] || "_i_" + namespace;
786
- this.list = m[6];
787
-
788
- // TODO ugly, revisit this later
789
- tokens.consume(m[0].length-1);
790
- var declare = [ this.iterator + "=0", this.item + "=null", "_list_" + namespace + "=" + this.list, "_len_" + namespace + "=_list_" + namespace + ".length" ].join(',');
791
-
792
- var bool = "(" + this.item + "=" + "_list_" + namespace + "[" + this.iterator + "])||" + this.iterator + "<_len_" + namespace;
793
-
794
- this.out = [ "for (", declare, ";", bool, ';', this.iterator + "++)" ];
795
- });
796
-
797
- OO.addMember("endParse",function (tokens) {
798
- tokens.iterator--;
799
- });
800
-
801
- });
802
-
803
-
804
- JS2.Class.extend('JSML', function(KLASS, OO){
805
- OO.addStaticMember("process",function (txt) {
806
- return new KLASS(txt);
807
- });
808
-
809
- OO.addMember("initialize",function (txt) {
810
- var lines = txt.split(/\n/);
811
- this.root = new JS2.JSMLElement();
812
- this.stack = [ this.root ];
813
-
814
- for(var _i1=0,_c1=lines,_l1=_c1.length,l;(l=_c1[_i1])||(_i1<_l1);_i1++){
815
- if (l.match(/^\s*$/)) continue;
816
- this.processLine(l);
817
- }
818
-
819
- var toEval = 'function process() { var out = [];\n' + this.flatten().join('') + '\n return out.join("");\n}';
820
- eval(toEval);
821
-
822
- this.result = function(bound) {
823
- bound = bound || {};
824
- return process.call(bound);
825
- };
826
- });
827
-
828
- OO.addMember("flatten",function () {
829
- return this.root.flatten();
830
- });
831
-
832
- OO.addMember("processLine",function (line) {
833
- if (line.match(/^\s*$/)) return;
834
-
835
- var ele = new JS2.JSMLElement(line);
836
- var scope = this.getScope();
837
-
838
- if (ele.scope == scope) {
839
- this.stack.pop();
840
- this.getLast().push(ele);
841
- this.stack.push(ele);
842
- } else if (ele.scope > scope) {
843
- this.getLast().push(ele);
844
- this.stack.push(ele);
845
- } else if (ele.scope < scope) {
846
- var diff = scope - ele.scope + 1;
847
- while(diff-- > 0) {
848
- this.stack.pop();
849
- }
850
- this.getLast().push(ele);
851
- this.stack.push(ele);
852
- }
853
- });
854
-
855
-
856
- OO.addMember("getScope",function () {
857
- return this.stack.length - 1;
858
- });
859
-
860
- OO.addMember("getLast",function () {
861
- return this.stack[this.stack.length-1];
862
- });
863
-
864
- });
865
-
866
- JS2.Class.extend('JSMLElement', function(KLASS, OO){
867
- OO.addMember("SCOPE_REGEX",/^(\s*)(.*)$/);
868
- OO.addMember("SPLIT_REGEX",/^((?:\.|\#|\%)[^=\s\{]*)?(\{.*\})?(=|-)?(?:\s*)(.*)$/);
869
- OO.addMember("TOKEN_REGEX",/(\%|\#|\.)([\w][\w\-]*)/g);
870
- OO.addMember("JS_REGEX",/^(-|=)(.*)$/g);
871
- OO.addMember("SCOPE_OFFSET",1);
872
- OO.addMember("SELF_CLOSING",{ area: null, basefont: null, br: null, hr: null, input: null, img: null, link: null, meta: null });
873
-
874
- OO.addMember("initialize",function (line) {
875
- this.children = [];
876
-
877
- if (line == null) {
878
- this.scope = this.SCOPE_OFFSET;
879
- return;
880
- }
881
-
882
- var spaceMatch = line.match(this.SCOPE_REGEX);
883
- this.scope = spaceMatch[1].length / 2 + this.SCOPE_OFFSET;
884
-
885
- this.classes = [];
886
- this.nodeID = null;
887
-
888
- this.parse(spaceMatch[2]);
889
- });
890
-
891
- OO.addMember("push",function (child) {
892
- this.children.push(child);
893
- });
894
-
895
- OO.addMember("parse",function (line) {
896
- this.attributes;
897
- this.line = line;
898
- var self = this;
899
-
900
- var splitted = line.match(this.SPLIT_REGEX);
901
- var tokens = splitted[1];
902
- var attrs = splitted[2];
903
- var jsType = splitted[3];
904
- var content = splitted[4];
905
-
906
- if (tokens) {
907
- tokens.replace(this.TOKEN_REGEX, function(match, type, name){
908
- switch(type) {
909
- case '%': self.nodeType = name; break;
910
- case '.': self.classes.push(name); break;
911
- case '#': self.nodeID = name; break;
912
- }
913
- return '';
914
- });
915
- }
916
-
917
- if (jsType == '=') {
918
- this.jsEQ = content;
919
- } else if (jsType == '-') {
920
- this.jsExec = content;
921
- } else {
922
- this.content = content;
923
- }
924
-
925
- if (attrs) {
926
- this.attributes = attrs;
927
- }
928
-
929
- if (!this.nodeType && (this.classes.length || this.nodeID)) {
930
- this.nodeType = 'div';
931
- }
932
-
933
- if (this.SELF_CLOSING.hasOwnProperty(this.nodeType) && this.children.length == 0) {
934
- this.selfClose = '/';
935
- } else {
936
- this.selfClose = '';
937
- }
938
- });
939
-
940
- OO.addMember("flatten",function () {
941
- var out = [];
942
-
943
- for(var _i1=0,_c1=this.children,_l1=_c1.length,c;(c=_c1[_i1])||(_i1<_l1);_i1++){
944
- var arr = c.flatten();
945
- for(var _i2=0,_c2=arr,_l2=_c2.length,item;(item=_c2[_i2])||(_i2<_l2);_i2++){
946
- out.push(item);
947
- }
948
- }
949
-
950
- if (this.nodeType) {
951
- this.handleJsEQ(out);
952
- this.handleContent(out);
953
- out.unshift('out.push("<' + this.nodeType + '"+JS2.JSMLElement.parseAttributes(' + (this.attributes || "{}") + ', ' + JSON.stringify(this.classes || []) + ', ' + JSON.stringify(this.id || null) + ')+"' + this.selfClose + '>");\n');
954
- if (this.selfClose == '') {
955
- out.push('out.push(' + JSON.stringify("</"+(this.nodeType)+">") + ');\n');
956
- }
957
- } else {
958
- this.handleJsExec(out);
959
- this.handleJsEQ(out);
960
- this.handleContent(out);
961
- }
962
-
963
- return out;
964
- });
965
-
966
- OO.addMember("handleJsEQ",function (out) {
967
- if (this.jsEQ) {
968
- this.jsEQ = this.jsEQ.replace(/;\s*$/, '');
969
- out.unshift('out.push(' + this.jsEQ + ');\n');
970
- }
971
- });
972
-
973
- OO.addMember("handleContent",function (out) {
974
- if (this.content != null && this.content.length > 0) {
975
- out.unshift('out.push(' + JSON.stringify(this.content) + ');\n');
976
- }
977
- });
978
-
979
-
980
- OO.addMember("handleJsExec",function (out) {
981
- if (this.jsExec) {
982
- out.unshift(this.jsExec);
983
- if (this.jsExec.match(/\{\s*$/)) {
984
- out.push("}\n");
985
- }
986
- }
987
- });
988
-
989
- OO.addStaticMember("parseAttributes",function (hash, classes, id) {
990
- var out = [];
991
- classes = classes || [];
992
- if (hash['class']) classes.push(hash['class']);
993
- if (classes.length) hash['class'] = classes.join(" ");
994
-
995
- for (var k in hash) {
996
- if (hash.hasOwnProperty(k)) {
997
- out.push(k + '=' + JSON.stringify(hash[k]));
998
- }
999
- }
1000
- return (out.length ? ' ' : '') + out.join(' ');
1001
- });
1002
- });
1003
-
1004
-
1005
- JS2.Class.extend('CLI', function(KLASS, OO){
1006
- // private closure
1007
-
1008
- var COMMANDS = {
1009
- help: 'help',
1010
- render: 'render',
1011
- compile: 'compile',
1012
- watch: 'watch'
1013
- };
1014
-
1015
-
1016
- OO.addMember("run",function (args) {
1017
- var opts = this.parseOpts(args);
1018
- var options = opts[0];
1019
- var command = opts[1];
1020
- var files = opts[2];
1021
- });
1022
-
1023
- OO.addMember("parseOpts",function (args) {
1024
- var files = [];
1025
- var options = {};
1026
- var command = null;
1027
-
1028
- var endedArgs = false;
1029
-
1030
- for(var i=0,_c1=args,_l1=_c1.length,arg;(arg=_c1[i])||(i<_l1);i++){
1031
- if (endedArgs) {
1032
- files.push(arg);
1033
- }
1034
-
1035
- else if (COMMANDS[arg]) {
1036
- command = arg;
1037
- endedArgs = true;
1038
- }
1039
-
1040
- else {
1041
- var setting = arg.match(/^(\w+)(?:=(.*))?$/);
1042
- if (setting) options[setting[0]] = setting[1] || 'true';
1043
- }
1044
- }
1045
-
1046
- return [ options, command, files ];
1047
- });
1048
- });
1049
-
1050
-
1051
- })();
1052
- FINISH
1053
- end
1054
- end
1
+ require File.dirname(__FILE__) + '/mochiscript/core'
2
+ require File.dirname(__FILE__) + '/mochiscript/rails/engine' if defined?(::Rails)