diff --git a/README.md b/README.md index 531f38063a..bf53c31b87 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,10 @@ object referring to that same position. [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 +**parseExpressionAt**`(input, offset, options)` will parse a single +expression in a string, and return its AST. It will not complain if +there is more of the string left after the expression. + **getLineInfo**`(input, offset)` can be used to get a `{line, column}` object for a given program string and character offset. diff --git a/acorn.js b/acorn.js index bf3a397b64..7fec92f7d0 100644 --- a/acorn.js +++ b/acorn.js @@ -43,6 +43,7 @@ input = String(inpt); inputLen = input.length; setOptions(opts); initTokenState(); + initParserState(); return parseTopLevel(options.program); }; @@ -114,6 +115,18 @@ directSourceFile: null }; + // This function tries to parse a single expression at a given + // offset in a string. Useful for parsing mixed-language formats + // that embed JavaScript expressions. + + exports.parseExpressionAt = function(inpt, pos, opts) { + input = String(inpt); inputLen = input.length; + setOptions(opts); + initTokenState(pos); + initParserState(); + return parseExpression(); + }; + var isArray = function (obj) { return Object.prototype.toString.call(obj) === "[object Array]"; }; @@ -286,6 +299,14 @@ var inTemplate; + function initParserState() { + lastStart = lastEnd = tokPos; + if (options.locations) lastEndLoc = new Position; + inFunction = inGenerator = strict = null; + labels = []; + readToken(); + } + // This function is used to raise exceptions on parse errors. It // takes an offset integer (into the current `input`) to indicate // the location of the error, attaches the position to the end @@ -554,9 +575,15 @@ // Reset the token state. Used at the start of a parse. - function initTokenState() { - tokCurLine = 1; - tokPos = tokLineStart = 0; + function initTokenState(pos) { + if (pos) { + tokPos = pos; + tokLineStart = Math.max(0, input.lastIndexOf("\n", pos)); + tokCurLine = input.slice(0, tokLineStart).split(newline).length; + } else { + tokCurLine = 1; + tokPos = tokLineStart = 0; + } tokRegexpAllowed = true; metParenL = 0; inTemplate = false; @@ -1436,12 +1463,6 @@ // to its body instead of creating a new node. function parseTopLevel(program) { - lastStart = lastEnd = tokPos; - if (options.locations) lastEndLoc = new Position; - inFunction = inGenerator = strict = null; - labels = []; - readToken(); - var node = program || startNode(), first = true; if (!program) node.body = []; while (tokType !== _eof) {