Added the option trackSpaces to attach spacesBefore and spacesAfter properties to AST nodes.

This commit is contained in:
Martin Carlberg committed 2013-01-08 22:23:34 +01:00
1 parent 79d2ac0566
commit 957b34d169
1 file changed
+52 -10
+52 -10
View File
@@ -73,6 +73,13 @@ if (!exports.acorn) {
// after and before it), but never twice in the before (or after)
// array of different nodes.
trackComments: false,
// When `trackSpaces` is turned on, the parser will attach
// `spacesBefore` and `spacesAfter` properties to AST nodes
// holding arrays of strings. The same spaces may appear in both
// a `spacesBefore` and `spacesAfter` array (of the nodes
// after and before it), but never twice in the before (or after)
// array of different nodes.
trackSpaces: false,
// When `locations` is on, `loc` properties holding objects with
// `start` and `end` properties in `{line, column}` form (with
// line being 1-based and column 0-based) will be attached to the
@@ -151,6 +158,11 @@ if (!exports.acorn) {
var tokCommentsBefore, tokCommentsAfter;
// These are used to hold arrays of spaces when
// `options.trackSpaces` is true.
var tokSpacesBefore, tokSpacesAfter;
// Interal state for the tokenizer. To distinguish between division
// operators and regular expressions, it remembers whether the last
// token was one that is allowed to be followed by an expression.
@@ -158,7 +170,7 @@ if (!exports.acorn) {
// division operator. See the `parseStatement` function for a
// caveat.)
var tokRegexpAllowed, tokComments;
var tokRegexpAllowed, tokComments, tokSpaces;
// When `options.locations` is true, these are used to keep
// track of the current line, and know when a new line has been
@@ -478,11 +490,12 @@ if (!exports.acorn) {
tokLineStartNext = nextLineStart();
tokRegexpAllowed = true;
tokComments = null;
tokSpaces = null;
skipSpace();
}
// Called at the end of every token. Sets `tokEnd`, `tokVal`,
// `tokCommentsAfter`, and `tokRegexpAllowed`, and skips the space
// `tokCommentsAfter`, `tokSpacesAfter`, and `tokRegexpAllowed`, and skips the space
// after the token, so that the next one's `tokStart` will point at
// the right position.
@@ -493,12 +506,14 @@ if (!exports.acorn) {
skipSpace();
tokVal = val;
tokCommentsAfter = tokComments;
tokSpacesAfter = tokSpaces;
tokRegexpAllowed = type.beforeExpr;
tokAfterImport = type.afterImport;
}
function skipBlockComment() {
var end = input.indexOf("*/", tokPos += 2);
tokSpaces = null;
if (end === -1) raise(tokPos - 2, "Unterminated comment");
if (options.trackComments)
(tokComments || (tokComments = [])).push(input.slice(tokPos, end));
@@ -508,6 +523,7 @@ if (!exports.acorn) {
function skipLineComment(skipCharacters) {
var start = tokPos;
var ch = input.charCodeAt(tokPos+=skipCharacters);
tokSpaces = null;
while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8329) {
++tokPos;
ch = input.charCodeAt(tokPos);
@@ -516,12 +532,24 @@ if (!exports.acorn) {
(tokComments || (tokComments = [])).push(input.slice(start, tokPos));
}
function skipWhiteSpaces() {
var start = tokPos;
var ch = input.charCodeAt(++tokPos);
while ((ch < 14 && ch > 8) || ch === 32 || ch === 160 || (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch)))) // 9 - 13, ' ', '\xa0' ....
ch = input.charCodeAt(++tokPos);
if (options.trackSpaces)
(tokSpaces || (tokSpaces = [])).push(input.slice(start, tokPos));
}
// Called at the start of the parse and after every token. Skips
// whitespace and comments, and, if `options.trackComments` is on,
// will store all skipped comments in `tokComments`.
// will store all skipped comments in `tokComments`. If
// `options.trackSpaces` is on, will store the last skipped spaces in
// `tokSpaces`.
function skipSpace() {
tokComments = null;
tokSpaces = null;
while (tokPos < inputLen) {
var ch = input.charCodeAt(tokPos);
if (ch === 47) { // '/'
@@ -531,12 +559,8 @@ if (!exports.acorn) {
} else if (next === 47) { // '/'
skipLineComment(2);
} else break;
} else if (ch < 14 && ch > 8) {
++tokPos;
} else if (ch === 32 || ch === 160) { // ' ', '\xa0'
++tokPos;
} else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
++tokPos;
} else if ((ch < 14 && ch > 8) || ch === 32 || ch === 160 || (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch)))) { // 9 - 13, ' ', '\xa0' ....
skipWhiteSpaces();
} else {
break;
}
@@ -724,6 +748,7 @@ if (!exports.acorn) {
tokStart = tokPos;
if (options.locations) tokStartLoc = curLineLoc();
tokCommentsBefore = tokComments;
tokSpacesBefore = tokSpaces;
if (forceRegexp) return readRegexp();
if (tokPos >= inputLen) return finishToken(_eof);
@@ -1010,6 +1035,10 @@ if (!exports.acorn) {
node.commentsBefore = tokCommentsBefore;
tokCommentsBefore = null;
}
if (options.trackSpaces && tokSpacesBefore) {
node.spacesBefore = tokSpacesBefore;
tokSpacesBefore = null;
}
if (options.locations)
node.loc = new node_loc_t();
if (options.ranges)
@@ -1045,7 +1074,8 @@ if (!exports.acorn) {
// We keep track of the last node that we finished, in order
// 'bubble' `commentsAfter` properties up to the biggest node. I.e.
// in '`1 + 1 // foo', the comment should be attached to the binary
// operator node, not the second literal node.
// operator node, not the second literal node. The same is done on
// `spacesAfter`
var lastFinishedNode;
@@ -1061,6 +1091,18 @@ if (!exports.acorn) {
node.commentsAfter = lastFinishedNode.commentsAfter;
lastFinishedNode.commentsAfter = null;
}
if (!options.trackSpaces)
lastFinishedNode = node;
}
if (options.trackSpaces) {
if (tokSpacesAfter) {
node.spacesAfter = tokSpacesAfter;
tokSpacesAfter = null;
} else if (lastFinishedNode && lastFinishedNode.end === lastEnd &&
lastFinishedNode.spacesAfter) {
node.spacesAfter = lastFinishedNode.spacesAfter;
lastFinishedNode.spacesAfter = null;
}
lastFinishedNode = node;
}
if (options.locations)