diff --git a/lib/less/parser/parser.js b/lib/less/parser/parser.js index 145f442f3..f63d6ba56 100644 --- a/lib/less/parser/parser.js +++ b/lib/less/parser/parser.js @@ -54,14 +54,16 @@ var Parser = function Parser(context, imports, fileInfo) { ); } - function expect(arg, msg, index) { + function expect(arg, msg) { // some older browsers return typeof 'function' for RegExp var result = (arg instanceof Function) ? arg.call(parsers) : parserInput.$re(arg); if (result) { return result; } - error(msg || (typeof arg === 'string' ? 'expected \'' + arg + '\' got \'' + parserInput.currentChar() + '\'' - : 'unexpected token')); + + error(msg || (typeof arg === 'string' + ? 'expected \'' + arg + '\' got \'' + parserInput.currentChar() + '\'' + : 'unexpected token')); } // Specialization of expect() @@ -1963,13 +1965,13 @@ var Parser = function Parser(context, imports, fileInfo) { conditions: function () { var a, b, index = parserInput.i, condition; - a = this.condition(); + a = this.condition(true); if (a) { while (true) { if (!parserInput.peek(/^,\s*(not\s*)?\(/) || !parserInput.$char(',')) { break; } - b = this.condition(); + b = this.condition(true); if (!b) { break; } @@ -1978,19 +1980,19 @@ var Parser = function Parser(context, imports, fileInfo) { return condition || a; } }, - condition: function () { + condition: function (needsParens) { var result, logical, next; function or() { return parserInput.$str('or'); } - result = this.conditionAnd(this); + result = this.conditionAnd(needsParens); if (!result) { return ; } logical = or(); if (logical) { - next = this.condition(); + next = this.condition(needsParens); if (next) { result = new(tree.Condition)(logical, result, next); } else { @@ -1999,22 +2001,26 @@ var Parser = function Parser(context, imports, fileInfo) { } return result; }, - conditionAnd: function () { - var result, logical, next; - function insideCondition(me) { - return me.negatedCondition() || me.parenthesisCondition(); + conditionAnd: function (needsParens) { + var result, logical, next, self = this; + function insideCondition() { + var cond = self.negatedCondition(needsParens) || self.parenthesisCondition(needsParens); + if (!cond && !needsParens) { + return self.atomicCondition(needsParens); + } + return cond; } function and() { return parserInput.$str('and'); } - result = insideCondition(this); + result = insideCondition(); if (!result) { return ; } logical = and(); if (logical) { - next = this.conditionAnd(); + next = this.conditionAnd(needsParens); if (next) { result = new(tree.Condition)(logical, result, next); } else { @@ -2023,20 +2029,20 @@ var Parser = function Parser(context, imports, fileInfo) { } return result; }, - negatedCondition: function () { + negatedCondition: function (needsParens) { if (parserInput.$str('not')) { - var result = this.parenthesisCondition(); + var result = this.parenthesisCondition(needsParens); if (result) { result.negate = !result.negate; } return result; } }, - parenthesisCondition: function () { + parenthesisCondition: function (needsParens) { function tryConditionFollowedByParenthesis(me) { var body; parserInput.save(); - body = me.condition(); + body = me.condition(needsParens); if (!body) { parserInput.restore(); return ; @@ -2061,7 +2067,7 @@ var Parser = function Parser(context, imports, fileInfo) { return body; } - body = this.atomicCondition(); + body = this.atomicCondition(needsParens); if (!body) { parserInput.restore(); return ; @@ -2073,7 +2079,7 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.forget(); return body; }, - atomicCondition: function () { + atomicCondition: function (needsParens) { var entities = this.entities, index = parserInput.i, a, b, c, op; function cond() { diff --git a/test/css/functions.css b/test/css/functions.css index 6f52648d7..35803f56a 100644 --- a/test/css/functions.css +++ b/test/css/functions.css @@ -222,5 +222,10 @@ html { c: 3; e: ; f: 6; + g: 3; + h: 5; + i: 6; + j: 8; + k: 1; /* results in void */ } diff --git a/test/less/errors/mixins-guards-cond-expected.less b/test/less/errors/mixins-guards-cond-expected.less new file mode 100644 index 000000000..e645e416f --- /dev/null +++ b/test/less/errors/mixins-guards-cond-expected.less @@ -0,0 +1,5 @@ +.max (@a, @b) when @a { + width: @b; +} + +.max1 { .max(3, 6) } \ No newline at end of file diff --git a/test/less/errors/mixins-guards-cond-expected.txt b/test/less/errors/mixins-guards-cond-expected.txt new file mode 100644 index 000000000..15161ad65 --- /dev/null +++ b/test/less/errors/mixins-guards-cond-expected.txt @@ -0,0 +1,3 @@ +SyntaxError: expected condition in {path}mixins-guards-cond-expected.less on line 1, column 20: +1 .max (@a, @b) when @a { +2 width: @b; diff --git a/test/less/functions.less b/test/less/functions.less index d2744f33a..0228bf0cb 100644 --- a/test/less/functions.less +++ b/test/less/functions.less @@ -246,7 +246,7 @@ html { #boolean { a: boolean(not(2 < 1)); b: boolean(not(2 > 1) and (true)); - c: boolean(not(boolean((true)))); + c: boolean(not(boolean(true))); } #if { @@ -255,8 +255,13 @@ html { @1: if(not(false), {c: 3}, {d: 4}); @1(); e: if(not(true), 5); - @f: boolean((3 = 4)); + @f: boolean(3 = 4); f: if(not(@f), 6); + g: if(true, 3, 5); + h: if(false, 3, 5); + i: if(true and isnumber(6), 6, 8); + j: if(not(true) and true, 6, 8); + k: if(true or true, 1); - if((false), {g: 7}); /* results in void */ + if(false, {g: 7}); /* results in void */ }