Skip to content

Commit

Permalink
Fixed #711: parser accepts numbers ending with a decimal mark again l…
Browse files Browse the repository at this point in the history
…ike `2.`.
  • Loading branch information
josdejong committed Sep 20, 2016
1 parent d7d25e8 commit 9199ae5
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 4 deletions.
6 changes: 6 additions & 0 deletions 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.
Expand Down
27 changes: 24 additions & 3 deletions lib/expression/parse.js
Expand Up @@ -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();
}
Expand Down Expand Up @@ -283,7 +283,7 @@ function factory (type, config, load, typed) {
token += c;
next();
}
if (c == '.' && isDigit(nextPreview())) {
if (isDecimalMark(c, nextPreview())) {
token += c;
next();
}
Expand Down Expand Up @@ -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 + '"');
}
}
Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion test/expression/parse.test.js
Expand Up @@ -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);
Expand All @@ -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);

Expand Down

0 comments on commit 9199ae5

Please sign in to comment.