diff --git a/src/expression/parse.js b/src/expression/parse.js index 8eab0230db..4bb9de056b 100644 --- a/src/expression/parse.js +++ b/src/expression/parse.js @@ -346,7 +346,10 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({ next(state) state.token += currentCharacter(state) next(state) - while (parse.isHexDigit(currentCharacter(state))) { + while ( + parse.isAlpha(currentCharacter(state), prevCharacter(state), nextCharacter(state)) || + parse.isDigit(currentCharacter(state)) + ) { state.token += currentCharacter(state) next(state) } @@ -355,7 +358,10 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({ state.token += '.' next(state) // get the digits after the radix - while (parse.isHexDigit(currentCharacter(state))) { + while ( + parse.isAlpha(currentCharacter(state), prevCharacter(state), nextCharacter(state)) || + parse.isDigit(currentCharacter(state)) + ) { state.token += currentCharacter(state) next(state) } @@ -574,17 +580,6 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({ return (c >= '0' && c <= '9') } - /** - * checks if the given char c is a hex digit - * @param {string} c a string with one character - * @return {boolean} - */ - parse.isHexDigit = function isHexDigit (c) { - return ((c >= '0' && c <= '9') || - (c >= 'a' && c <= 'f') || - (c >= 'A' && c <= 'F')) - } - /** * Start of the parse levels below, in order of precedence * @return {Node} node diff --git a/test/unit-tests/expression/parse.test.js b/test/unit-tests/expression/parse.test.js index d0eec260a9..27f3e2a1f6 100644 --- a/test/unit-tests/expression/parse.test.js +++ b/test/unit-tests/expression/parse.test.js @@ -286,6 +286,21 @@ describe('parse', function () { assert.strictEqual(parseAndEval('0x1.'), 1) }) + it('should require hex, bin, oct values to be followed by whitespace or a delimiter', function () { + assert.throws(() => parseAndEval('0b0a'), /SyntaxError: String "0b0a" is not a valid number/) + assert.throws(() => parseAndEval('0x1k'), /SyntaxError: String "0x1k" is not a valid number/) + assert.throws(() => parseAndEval('0o1k'), /SyntaxError: String "0o1k" is not a valid number/) + assert.throws(() => parseAndEval('0b1k'), /SyntaxError: String "0b1k" is not a valid number/) + + assert.strictEqual(parseAndEval('0x1 k', { k: 2 }), 2) + assert.strictEqual(parseAndEval('0o1 k', { k: 2 }), 2) + assert.strictEqual(parseAndEval('0b1 k', { k: 2 }), 2) + + assert.strictEqual(parseAndEval('0x1*k', { k: 2 }), 2) + assert.strictEqual(parseAndEval('0o1*k', { k: 2 }), 2) + assert.strictEqual(parseAndEval('0b1*k', { k: 2 }), 2) + }) + it('should parse a number followed by e', function () { approxEqual(parseAndEval('2e'), 2 * Math.E) }) @@ -334,7 +349,7 @@ describe('parse', function () { assert.throws(function () { parseAndEval('0b123.45') }, /SyntaxError: String "0b123\.45" is not a valid number/) assert.throws(function () { parseAndEval('0o89.89') }, /SyntaxError: String "0o89\.89" is not a valid number/) - assert.throws(function () { parseAndEval('0xghji.xyz') }, /SyntaxError: String "0x" is not a valid number/) + assert.throws(function () { parseAndEval('0xghji.xyz') }, /SyntaxError: String "0xghji.xyz" is not a valid number/) }) })