Permalink
Browse files

Added while loop support

  • Loading branch information...
1 parent 27fcfe7 commit 5353fa1cf8bc71f2bac31b67e64cb70abe4d2774 @mekto committed Aug 16, 2012
Showing with 85 additions and 1 deletion.
  1. +1 −1 lib/lexer.js
  2. +1 −0 lib/nodes/index.js
  3. +48 −0 lib/nodes/loop.js
  4. +16 −0 lib/parser.js
  5. +19 −0 lib/visitor/evaluator.js
View
2 lib/lexer.js
@@ -358,7 +358,7 @@ Lexer.prototype = {
keyword: function() {
var captures;
- if (captures = /^(return|if|else|unless|for|in)\b[ \t]*/.exec(this.str)) {
+ if (captures = /^(return|if|else|unless|for|in|while)\b[ \t]*/.exec(this.str)) {
var keyword = captures[1];
this.skip(captures);
return new Token(keyword, keyword);
View
1 lib/nodes/index.js
@@ -13,6 +13,7 @@ exports.Node = require('./node');
exports.Root = require('./root');
exports.Null = require('./null');
exports.Each = require('./each');
+exports.Loop = require('./loop');
exports.If = require('./if');
exports.Call = require('./call');
exports.Page = require('./page');
View
48 lib/nodes/loop.js
@@ -0,0 +1,48 @@
+
+/*!
+ * Stylus - Loop
+ * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var Node = require('./node');
+
+/**
+ * Initialize a new `Loop` with the given `cond`.
+ *
+ * @param {Expression} cond
+ * @param {Boolean|Block} negate, block
+ * @api public
+ */
+
+var Loop = module.exports = function Loop(cond, block){
+ Node.call(this);
+ this.cond = cond;
+ this.block = block;
+};
+
+/**
+ * Inherit from `Node.prototype`.
+ */
+
+Loop.prototype.__proto__ = Node.prototype;
+
+/**
+ * Return a clone of this node.
+ *
+ * @return {Node}
+ * @api public
+ */
+
+Loop.prototype.clone = function(){
+ var clone = new Loop(
+ this.cond.clone()
+ , this.block.clone());
+ clone.lineno = this.lineno;
+ clone.filename = this.filename;
+ return clone;
+};
View
16 lib/parser.js
@@ -444,6 +444,7 @@ Parser.prototype = {
case 'font-face':
case 'media':
case 'for':
+ case 'loop':
return true;
}
},
@@ -543,6 +544,7 @@ Parser.prototype = {
case 'function':
case 'for':
case 'if':
+ case 'while':
return this[type]();
case 'return':
return this.return();
@@ -653,6 +655,19 @@ Parser.prototype = {
this.state.pop();
return each;
},
+
+ /**
+ * while expression block
+ */
+
+ while: function() {
+ this.expect('while');
+ var node = new nodes.Loop(this.expression());
+ this.state.push('loop');
+ node.block = this.block(node, false);
+ this.state.pop();
+ return node;
+ },
/**
* return expression
@@ -960,6 +975,7 @@ Parser.prototype = {
case 'root':
return this.selector();
case 'for':
+ case 'loop':
case 'page':
case 'media':
case 'font-face':
View
19 lib/visitor/evaluator.js
@@ -287,6 +287,25 @@ Evaluator.prototype.visitEach = function(each){
};
/**
+ * Visit Loop.
+ */
+
+Evaluator.prototype.visitLoop = function(loop){
+ var ret
+ , block = this.currentBlock
+ , vals = []
+ , body;
+
+ while (this.visit(loop.cond.clone()).first.toBoolean().isTrue) {
+ body = this.visit(loop.block.clone());
+ vals = vals.concat(body.nodes);
+ }
+
+ this.mixin(vals, block);
+ return vals[vals.length - 1] || nodes.null;
+};
+
+/**
* Visit Call.
*/

0 comments on commit 5353fa1

Please sign in to comment.