diff --git a/HISTORY.md b/HISTORY.md index 64185188a..ecd610c1e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,8 +1,9 @@ # History -## not yet released, version 3.4.2 +## not yet released, version 3.5.0 +- Comments of expressions are are now stored in the parsed nodes. See #690. - Fixed function `print` not accepting an Object with formatting options as third parameter Thanks @ThomasBrierley. diff --git a/docs/expressions/expression_trees.md b/docs/expressions/expression_trees.md index a2efef480..ee0010918 100644 --- a/docs/expressions/expression_trees.md +++ b/docs/expressions/expression_trees.md @@ -201,6 +201,12 @@ All nodes have the following methods: Each `Node` has the following properties: +- `comment: string` + + A string holding a comment if there was any in the expression, or else the + string will be empty string. A comment can be attached to the root node of + an expression or to each of the childs nodes of a `BlockNode`. + - `isNode: true` Is defined with value `true` on Nodes. Additionally, each type of node diff --git a/lib/expression/node/Node.js b/lib/expression/node/Node.js index f23a0683d..5130e9a35 100644 --- a/lib/expression/node/Node.js +++ b/lib/expression/node/Node.js @@ -26,6 +26,8 @@ function factory (type, config, load, typed, math) { Node.prototype.isNode = true; + Node.prototype.comment = ''; + /** * Compile the node to javascript code * @return {{eval: function}} expr Returns an object with a function 'eval', diff --git a/lib/expression/parse.js b/lib/expression/parse.js index 0fb4ee74f..83939231c 100644 --- a/lib/expression/parse.js +++ b/lib/expression/parse.js @@ -145,6 +145,7 @@ function factory (type, config, load, typed) { var extra_nodes = {}; // current extra nodes var expression = ''; // current expression + var comment = ''; // last parsed comment var index = 0; // current index in expr var c = ''; // current token character in expr var token = ''; // current token @@ -202,6 +203,7 @@ function factory (type, config, load, typed) { function getToken() { token_type = TOKENTYPE.NULL; token = ''; + comment = ''; // skip over whitespaces // space, tab, and newline when inside parameters @@ -213,6 +215,7 @@ function factory (type, config, load, typed) { // skip comment if (c == '#') { while (c != '\n' && c != '') { + comment += c; next(); } } @@ -478,11 +481,14 @@ function factory (type, config, load, typed) { if (token == '') { // empty expression - return new ConstantNode('undefined', 'undefined'); + node = new ConstantNode('undefined', 'undefined'); + node.comment = comment; + return node } if (token != '\n' && token != ';') { node = parseAssignment(); + node.comment = comment; } // TODO: simplify this loop @@ -498,6 +504,7 @@ function factory (type, config, load, typed) { getToken(); if (token != '\n' && token != ';' && token != '') { node = parseAssignment(); + node.comment = comment; visible = (token != ';'); blocks.push({ diff --git a/test/expression/parse.test.js b/test/expression/parse.test.js index b8c28ff05..b70f4a453 100644 --- a/test/expression/parse.test.js +++ b/test/expression/parse.test.js @@ -203,6 +203,18 @@ describe('parse', function() { assert.deepEqual(parseAndEval('2 + 3 # - 4\n6-2'), new ResultSet([5, 4])); }); + it('should fill in the property comment of a Node', function() { + assert.equal(parse('2 + 3').comment, ''); + + assert.equal(parse('2 + 3 # hello').comment, '# hello'); + assert.equal(parse(' # hi').comment, '# hi'); + + var blockNode = parse('2 # foo\n3 # bar'); + assert.equal(blockNode.blocks.length, 2); + assert.equal(blockNode.blocks[0].node.comment, '# foo'); + assert.equal(blockNode.blocks[1].node.comment, '# bar'); + }); + }); describe('number', function () {