diff --git a/src/expression/parse.js b/src/expression/parse.js index 45df38c985..ef7a8e00b0 100644 --- a/src/expression/parse.js +++ b/src/expression/parse.js @@ -1544,8 +1544,10 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({ while (state.token === ';') { // eslint-disable-line no-unmodified-loop-condition getToken(state) - params[rows] = parseRow(state) - rows++ + if (state.token !== ']') { + params[rows] = parseRow(state) + rows++ + } } if (state.token !== ']') { @@ -1599,8 +1601,10 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({ getToken(state) // parse expression - params[len] = parseAssignment(state) - len++ + if (state.token !== ']' && state.token !== ';') { + params[len] = parseAssignment(state) + len++ + } } return new ArrayNode(params) diff --git a/test/unit-tests/expression/parse.test.js b/test/unit-tests/expression/parse.test.js index fe3190ea5c..2bd7641926 100644 --- a/test/unit-tests/expression/parse.test.js +++ b/test/unit-tests/expression/parse.test.js @@ -621,6 +621,43 @@ describe('parse', function () { assert.deepStrictEqual(parseAndEval('[[[1],[2]],[[3],[4]]]'), math.matrix([[[1], [2]], [[3], [4]]])) }) + it('should parse a matrix with trailing commas', function () { + assert.ok(parseAndEval('[1,2;3,4;]') instanceof Matrix) + + const m = parseAndEval('[1,2,3;4,5,6;]') + assert.deepStrictEqual(m.size(), [2, 3]) + assert.deepStrictEqual(m, math.matrix([[1, 2, 3], [4, 5, 6]])) + + const b = parseAndEval('[5, 6; 1, 1;]') + assert.deepStrictEqual(b.size(), [2, 2]) + assert.deepStrictEqual(b, math.matrix([[5, 6], [1, 1]])) + + // from 1 to n dimensions + assert.deepStrictEqual(parseAndEval('[ ]'), math.matrix([])) + assert.deepStrictEqual(parseAndEval('[1,2,3,]'), math.matrix([1, 2, 3])) + assert.deepStrictEqual(parseAndEval('[1;2;3;]'), math.matrix([[1], [2], [3]])) + assert.deepStrictEqual(parseAndEval('[[1,2],[3,4],]'), math.matrix([[1, 2], [3, 4]])) + assert.deepStrictEqual(parseAndEval('[[[1],[2]],[[3],[4]],]'), math.matrix([[[1], [2]], [[3], [4]]])) + }) + + it('should throw an error when multiple trailing commas/semicolons are in a matrix', function () { + assert.throws(function () { + parseAndEval('[1,2,3,,] ') + }, /SyntaxError: Value expected/) + + assert.throws(function () { + parseAndEval('[1,2;3,4;,] ') + }, /SyntaxError: Value expected/) + + assert.throws(function () { + parseAndEval('[1;2;3;;]') + }, /SyntaxError: Value expected/) + + assert.throws(function () { + parseAndEval('[[[1],[2]],[[3],[4]],,]') + }, /SyntaxError: Value expected/) + }) + it('should parse an empty matrix', function () { assert.deepStrictEqual(parseAndEval('[]'), math.matrix([])) }) @@ -2365,7 +2402,7 @@ describe('parse', function () { try { mathClone.evaluate('f(x)=1;config({clone:f})') - } catch (err) {} + } catch (err) { } assert.strictEqual(mathClone.evaluate('2'), 2) })