diff --git a/HISTORY.md b/HISTORY.md index a17f41308b..a1064e52ae 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,12 @@ # History +## not yet released, version 3.5.2 + +- Fixed numbers ending with a decimal mark (like `2.`) not being supported by + the parser, solved the ambiguity in the parser. See #707, #711. + + ## 2016-09-12, version 3.5.1 - Removed a left over console.log statement. Thanks @eknkc. diff --git a/lib/expression/parse.js b/lib/expression/parse.js index 4f10c6dcb8..ca40823061 100644 --- a/lib/expression/parse.js +++ b/lib/expression/parse.js @@ -207,7 +207,7 @@ function factory (type, config, load, typed) { // skip over whitespaces // space, tab, and newline when inside parameters - while (c == ' ' || c == '\t' || (c == '\n' && nesting_level)) { + while (isWhitespace(c)) { // TODO: also take '\r' carriage return as newline? Or does that give problems on mac? next(); } @@ -283,7 +283,7 @@ function factory (type, config, load, typed) { token += c; next(); } - if (c == '.' && isDigit(nextPreview())) { + if (isDecimalMark(c, nextPreview())) { token += c; next(); } @@ -315,7 +315,7 @@ function factory (type, config, load, typed) { next(); } - if (c == '.' && isDigit(nextPreview())) { + if (isDecimalMark(c, nextPreview())) { throw createSyntaxError('Digit expected, got "' + c + '"'); } } @@ -417,6 +417,27 @@ function factory (type, config, load, typed) { || isValidMathSymbol(cPrev, c); } + /** + * check whether given character c is a white space character: space, tab, or enter + * @param {string} c + * @return {boolean} + * @private + */ + function isWhitespace (c) { + return c == ' ' || c == '\t' || (c == '\n' && nesting_level > 0) + } + + /** + * Test whether the character c is a decimal mark (dot). + * This depends on whether it's followed by a digit or whitespace + * @param {string} c + * @param {string} cNext + * @return {boolean} + */ + function isDecimalMark (c, cNext) { + return c == '.' && (isDigit(cNext) || isWhitespace(cNext) || cNext == '') + } + /** * checks if the given char c is a digit or dot * @param {string} c a string with one character diff --git a/test/expression/parse.test.js b/test/expression/parse.test.js index 7b3f71fb18..ca12da8d88 100644 --- a/test/expression/parse.test.js +++ b/test/expression/parse.test.js @@ -223,6 +223,9 @@ describe('parse', function() { assert.equal(parseAndEval('0'), 0); assert.equal(parseAndEval('3'), 3); assert.equal(parseAndEval('3.2'), 3.2); + assert.equal(parseAndEval('3.'), 3); + assert.equal(parseAndEval('3. '), 3); + assert.equal(parseAndEval('3.\t'), 3); assert.equal(parseAndEval('003.2'), 3.2); assert.equal(parseAndEval('003.200'), 3.2); assert.equal(parseAndEval('.2'), 0.2); @@ -240,7 +243,6 @@ describe('parse', function() { it('should throw an error with invalid numbers', function() { assert.throws(function () {parseAndEval('.'); }, /Value expected/); - assert.throws(function () {parseAndEval('4.'); }, /Unexpected operator ./); assert.throws(function () {parseAndEval('3.2.2'); }, SyntaxError); assert.throws(function () {parseAndEval('3.2e2.2'); }, SyntaxError);