and/or for mixin guards

This commit is contained in:
Alexis Sellier
2012-01-03 22:27:54 +01:00
parent b43d442d55
commit a40a9ee4db
4 changed files with 63 additions and 20 deletions

View File

@@ -785,7 +785,7 @@ less.Parser = function Parser(env) {
memo = i;
if ($(/^when/)) { // Guard
cond = expect(this.condition, 'expected condition');
cond = expect(this.conditions, 'expected condition');
}
ruleset = $(this.block);
@@ -1158,22 +1158,33 @@ less.Parser = function Parser(env) {
return operation || m;
}
},
conditions: function () {
var a, b, index = i, condition;
if (a = $(this.condition)) {
while ($(',') && (b = $(this.condition))) {
condition = new(tree.Condition)('or', condition || a, b, index);
}
return condition || a;
}
},
condition: function () {
var a, b, op, index = i, negate = false;
var a, b, c, op, index = i, negate = false;
expect('(');
if ($('!')) { negate = true }
if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) {
if (op = $(/^(?:>=|=<|\!=|[<=>])/)) {
if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) {
expect(')');
return new(tree.Condition)(op, a, b, index);
c = new(tree.Condition)(op, a, b, index);
} else {
error('expected expression');
}
} else {
expect(')');
return new(tree.Condition)(negate ? '!=' : '=', a, new(tree.Keyword)('true'), index);
c = new(tree.Condition)(negate ? '!=' : '=', a, new(tree.Keyword)('true'), index);
}
expect(')');
return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c;
}
},

View File

@@ -11,20 +11,27 @@ tree.Condition.prototype.eval = function (env) {
b = this.rvalue.eval(env);
var i = this.index, result
if (a.compare) {
result = a.compare(b);
} else if (b.compare) {
result = b.compare(a);
} else {
throw { type: "Type",
message: "Unable to perform comparison",
index: i };
}
switch (result) {
case -1: return this.op === '<' || this.op === '=<' || this.op === '!=';
case 0: return this.op === '=' || this.op === '>=' || this.op === '=<';
case 1: return this.op === '>' || this.op === '>=' || this.op === '!=';
switch (this.op) {
case 'and':
return a && b;
case 'or':
return a || b;
default:
if (a.compare) {
result = a.compare(b);
} else if (b.compare) {
result = b.compare(a);
} else {
throw { type: "Type",
message: "Unable to perform comparison",
index: i };
}
switch (result) {
case -1: return this.op === '<' || this.op === '=<' || this.op === '!=';
case 0: return this.op === '=' || this.op === '>=' || this.op === '=<';
case 1: return this.op === '>' || this.op === '>=' || this.op === '!=';
}
}
};

View File

@@ -45,3 +45,12 @@
.test5 {
content: "false.";
}
.bool1 {
content: true and true;
content: true;
content: false, true;
content: false and true and true, true;
content: false, true and true;
content: false, false, true;
content: false, true and true and true, false;
}

View File

@@ -72,3 +72,19 @@
.test3 { .test(1) }
.test4 { .test(boo) }
.test5 { .test("true") }
// Boolean expressions
.bool () when (true) and (false) { content: true and false } // FALSE
.bool () when (true) and (true) { content: true and true } // TRUE
.bool () when (true) { content: true } // TRUE
.bool () when (false) and (false) { content: true } // FALSE
.bool () when (false), (true) { content: false, true } // TRUE
.bool () when (false) and (true) and (true), (true) { content: false and true and true, true } // TRUE
.bool () when (true) and (true) and (false), (false) { content: true and true and false, false } // FALSE
.bool () when (false), (true) and (true) { content: false, true and true } // TRUE
.bool () when (false), (false), (true) { content: false, false, true } // TRUE
.bool () when (false), (false) and (true), (false) { content: false, false and true, false } // FALSE
.bool () when (false), (true) and (true) and (true), (false) { content: false, true and true and true, false } // TRUE
.bool1 { .bool }