Browse files

Add (optional) input source information to the syntax node.

As suggested by Daniel Dotsenko, we shall support `source` property in
the `loc` object of the syntax node.

This is also a good chance to start using the delegate for each syntax
node processing.

The tests were created by Yusuke Suzuki.

http://code.google.com/p/esprima/issues/detail?id=355
http://code.google.com/p/esprima/issues/detail?id=386
  • Loading branch information...
1 parent 2499612 commit c3b17ce3723902228fd96c3593d9f9610eadc2ec @ariya ariya committed Jan 5, 2013
Showing with 208 additions and 2 deletions.
  1. +37 −0 esprima.js
  2. +1 −1 package.json
  3. +6 −1 test/runner.js
  4. +164 −0 test/test.js
View
37 esprima.js
@@ -1082,6 +1082,10 @@ parseStatement: true, parseSourceElement: true */
name: 'SyntaxTree',
+ postProcess: function (node) {
+ return node;
+ },
+
createArrayExpression: function (elements) {
return {
type: Syntax.ArrayExpression,
@@ -3383,6 +3387,7 @@ parseStatement: true, parseSourceElement: true */
column: this.loc.end.column
}
};
+ node = delegate.postProcess(node);
}
};
@@ -3401,6 +3406,7 @@ parseStatement: true, parseSourceElement: true */
column: this.loc.end.column
}
};
+ node = delegate.postProcess(node);
}
};
@@ -3534,11 +3540,13 @@ parseStatement: true, parseSourceElement: true */
start: start,
end: end
};
+ node = delegate.postProcess(node);
} else if (typeof node.loc === 'undefined') {
node.loc = {
start: node.left.loc.start,
end: node.right.loc.end
};
+ node = delegate.postProcess(node);
}
}
}
@@ -3694,6 +3702,26 @@ parseStatement: true, parseSourceElement: true */
}
}
+ // This is used to modify the delegate.
+
+ function extend(object, properties) {
+ var entry, result = {};
+
+ for (entry in object) {
+ if (object.hasOwnProperty(entry)) {
+ result[entry] = object[entry];
+ }
+ }
+
+ for (entry in properties) {
+ if (properties.hasOwnProperty(entry)) {
+ result[entry] = properties[entry];
+ }
+ }
+
+ return result;
+ }
+
function parse(code, options) {
var program, toString;
@@ -3722,6 +3750,15 @@ parseStatement: true, parseSourceElement: true */
extra.range = (typeof options.range === 'boolean') && options.range;
extra.loc = (typeof options.loc === 'boolean') && options.loc;
+ if (extra.loc && options.source !== null && options.source !== undefined) {
+ delegate = extend(delegate, {
+ 'postProcess': function (node) {
+ node.loc.source = toString(options.source);
+ return node;
+ }
+ });
+ }
+
if (typeof options.tokens === 'boolean' && options.tokens) {
extra.tokens = [];
}
View
2 package.json
@@ -34,7 +34,7 @@
"lint": "node_modules/jslint/bin/jslint.js esprima.js",
"coverage": "npm run-script analyze-coverage && npm run-script check-coverage",
"analyze-coverage": "node node_modules/istanbul/lib/cli.js cover test/runner.js",
- "check-coverage": "node node_modules/istanbul/lib/cli.js check-coverage --statement -5 --branch -17 --function 100",
+ "check-coverage": "node node_modules/istanbul/lib/cli.js check-coverage --statement -5 --branch -19 --function 100",
"complexity": "npm run-script analyze-complexity && npm run-script check-complexity",
"analyze-complexity": "node tools/list-complexity.js",
View
7 test/runner.js
@@ -84,7 +84,8 @@ function testParse(esprima, code, syntax) {
loc: true,
tokens: (typeof syntax.tokens !== 'undefined'),
raw: true,
- tolerant: (typeof syntax.errors !== 'undefined')
+ tolerant: (typeof syntax.errors !== 'undefined'),
+ source: null
};
if (typeof syntax.tokens !== 'undefined') {
@@ -101,6 +102,10 @@ function testParse(esprima, code, syntax) {
}
}
+ if (options.loc) {
+ options.source = syntax.loc.source;
+ }
+
expected = JSON.stringify(syntax, null, 4);
try {
tree = esprima.parse(code, options);
View
164 test/test.js
@@ -16360,6 +16360,170 @@ var testFixture = {
}
},
+ 'Source option': {
+ 'x + y - z': {
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'BinaryExpression',
+ operator: '-',
+ left: {
+ type: 'BinaryExpression',
+ operator: '+',
+ left: {
+ type: 'Identifier',
+ name: 'x',
+ range: [0, 1],
+ loc: {
+ start: { line: 1, column: 0 },
+ end: { line: 1, column: 1 },
+ source: '42.js'
+ }
+ },
+ right: {
+ type: 'Identifier',
+ name: 'y',
+ range: [4, 5],
+ loc: {
+ start: { line: 1, column: 4 },
+ end: { line: 1, column: 5 },
+ source: '42.js'
+ }
+ },
+ range: [0, 5],
+ loc: {
+ start: { line: 1, column: 0 },
+ end: { line: 1, column: 5 },
+ source: '42.js'
+ }
+ },
+ right: {
+ type: 'Identifier',
+ name: 'z',
+ range: [8, 9],
+ loc: {
+ start: { line: 1, column: 8 },
+ end: { line: 1, column: 9 },
+ source: '42.js'
+ }
+ },
+ range: [0, 9],
+ loc: {
+ start: { line: 1, column: 0 },
+ end: { line: 1, column: 9 },
+ source: '42.js'
+ }
+ },
+ range: [0, 9],
+ loc: {
+ start: { line: 1, column: 0 },
+ end: { line: 1, column: 9 },
+ source: '42.js'
+ }
+ },
+
+ 'a + (b < (c * d)) + e': {
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'BinaryExpression',
+ operator: '+',
+ left: {
+ type: 'BinaryExpression',
+ operator: '+',
+ left: {
+ type: 'Identifier',
+ name: 'a',
+ range: [0, 1],
+ loc: {
+ start: { line: 1, column: 0 },
+ end: { line: 1, column: 1 },
+ source: '42.js'
+ }
+ },
+ right: {
+ type: 'BinaryExpression',
+ operator: '<',
+ left: {
+ type: 'Identifier',
+ name: 'b',
+ range: [5, 6],
+ loc: {
+ start: { line: 1, column: 5 },
+ end: { line: 1, column: 6 },
+ source: '42.js'
+ }
+ },
+ right: {
+ type: 'BinaryExpression',
+ operator: '*',
+ left: {
+ type: 'Identifier',
+ name: 'c',
+ range: [10, 11],
+ loc: {
+ start: { line: 1, column: 10 },
+ end: { line: 1, column: 11 },
+ source: '42.js'
+ }
+ },
+ right: {
+ type: 'Identifier',
+ name: 'd',
+ range: [14, 15],
+ loc: {
+ start: { line: 1, column: 14 },
+ end: { line: 1, column: 15 },
+ source: '42.js'
+ }
+ },
+ range: [10, 15],
+ loc: {
+ start: { line: 1, column: 10 },
+ end: { line: 1, column: 15 },
+ source: '42.js'
+ }
+ },
+ range: [5, 16],
+ loc: {
+ start: { line: 1, column: 5 },
+ end: { line: 1, column: 16 },
+ source: '42.js'
+ }
+ },
+ range: [0, 17],
+ loc: {
+ start: { line: 1, column: 0 },
+ end: { line: 1, column: 17 },
+ source: '42.js'
+ }
+ },
+ right: {
+ type: 'Identifier',
+ name: 'e',
+ range: [20, 21],
+ loc: {
+ start: { line: 1, column: 20 },
+ end: { line: 1, column: 21 },
+ source: '42.js'
+ }
+ },
+ range: [0, 21],
+ loc: {
+ start: { line: 1, column: 0 },
+ end: { line: 1, column: 21 },
+ source: '42.js'
+ }
+ },
+ range: [0, 21],
+ loc: {
+ start: { line: 1, column: 0 },
+ end: { line: 1, column: 21 },
+ source: '42.js'
+ }
+ }
+
+ },
+
+
'Invalid syntax': {
'{': {

0 comments on commit c3b17ce

Please sign in to comment.