199 lines
7.3 KiB
JavaScript
199 lines
7.3 KiB
JavaScript
// Acorn is a tiny, fast JavaScript parser written in JavaScript.
|
|
//
|
|
// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and
|
|
// various contributors and released under an MIT license.
|
|
//
|
|
// Git repositories for Acorn are available at
|
|
//
|
|
// http://marijnhaverbeke.nl/git/acorn
|
|
// https://github.com/marijnh/acorn.git
|
|
//
|
|
// Please use the [github bug tracker][ghbt] to report issues.
|
|
//
|
|
// [ghbt]: https://github.com/marijnh/acorn/issues
|
|
//
|
|
// This file defines the main parser interface. The library also comes
|
|
// with a [error-tolerant parser][dammit] and an
|
|
// [abstract syntax tree walker][walk], defined in other files.
|
|
//
|
|
// [dammit]: acorn_loose.js
|
|
// [walk]: util/walk.js
|
|
|
|
import {Parser} from "./state"
|
|
import {has, isArray} from "./util"
|
|
import {SourceLocation} from "./location"
|
|
import "./parseutil"
|
|
import "./statement"
|
|
import "./lval"
|
|
import "./expression"
|
|
|
|
export {Parser} from "./state"
|
|
export {SourceLocation} from "./location"
|
|
export {getLineInfo} from "./location"
|
|
export {Node} from "./node"
|
|
export {TokenType, types as tokTypes} from "./tokentype"
|
|
export {TokContext, types as tokContexts} from "./tokencontext"
|
|
export {isIdentifierChar, isIdentifierStart} from "./identifier"
|
|
export {Token} from "./tokenize"
|
|
export {isNewLine, lineBreak} from "./whitespace"
|
|
|
|
export const version = "0.12.1"
|
|
|
|
// The main exported interface (under `self.acorn` when in the
|
|
// browser) is a `parse` function that takes a code string and
|
|
// returns an abstract syntax tree as specified by [Mozilla parser
|
|
// API][api].
|
|
//
|
|
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
|
|
|
|
export function parse(input, options) {
|
|
let p = parser(options, input)
|
|
let startPos = p.options.locations ? [p.pos, p.curPosition()] : p.pos
|
|
p.nextToken()
|
|
return p.parseTopLevel(p.options.program || p.startNodeAt(startPos))
|
|
}
|
|
|
|
// A second optional argument can be given to further configure
|
|
// the parser process. These options are recognized:
|
|
|
|
export const defaultOptions = {
|
|
// `ecmaVersion` indicates the ECMAScript version to parse. Must
|
|
// be either 3, or 5, or 6. This influences support for strict
|
|
// mode, the set of reserved words, support for getters and
|
|
// setters and other features.
|
|
ecmaVersion: 5,
|
|
// Source type ("script" or "module") for different semantics
|
|
sourceType: "script",
|
|
// `onInsertedSemicolon` can be a callback that will be called
|
|
// when a semicolon is automatically inserted. It will be passed
|
|
// th position of the comma as an offset, and if `locations` is
|
|
// enabled, it is given the location as a `{line, column}` object
|
|
// as second argument.
|
|
onInsertedSemicolon: null,
|
|
// `onTrailingComma` is similar to `onInsertedSemicolon`, but for
|
|
// trailing commas.
|
|
onTrailingComma: null,
|
|
// By default, reserved words are not enforced. Disable
|
|
// `allowReserved` to enforce them. When this option has the
|
|
// value "never", reserved words and keywords can also not be
|
|
// used as property names.
|
|
allowReserved: true,
|
|
// When enabled, a return at the top level is not considered an
|
|
// error.
|
|
allowReturnOutsideFunction: false,
|
|
// When enabled, import/export statements are not constrained to
|
|
// appearing at the top of the program.
|
|
allowImportExportEverywhere: false,
|
|
// When enabled, hashbang directive in the beginning of file
|
|
// is allowed and treated as a line comment.
|
|
allowHashBang: 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
|
|
// nodes.
|
|
locations: false,
|
|
// A function can be passed as `onToken` option, which will
|
|
// cause Acorn to call that function with object in the same
|
|
// format as tokenize() returns. Note that you are not
|
|
// allowed to call the parser from the callback—that will
|
|
// corrupt its internal state.
|
|
onToken: null,
|
|
// A function can be passed as `onComment` option, which will
|
|
// cause Acorn to call that function with `(block, text, start,
|
|
// end)` parameters whenever a comment is skipped. `block` is a
|
|
// boolean indicating whether this is a block (`/* */`) comment,
|
|
// `text` is the content of the comment, and `start` and `end` are
|
|
// character offsets that denote the start and end of the comment.
|
|
// When the `locations` option is on, two more parameters are
|
|
// passed, the full `{line, column}` locations of the start and
|
|
// end of the comments. Note that you are not allowed to call the
|
|
// parser from the callback—that will corrupt its internal state.
|
|
onComment: null,
|
|
// Nodes have their start and end characters offsets recorded in
|
|
// `start` and `end` properties (directly on the node, rather than
|
|
// the `loc` object, which holds line/column data. To also add a
|
|
// [semi-standardized][range] `range` property holding a `[start,
|
|
// end]` array with the same numbers, set the `ranges` option to
|
|
// `true`.
|
|
//
|
|
// [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
|
|
ranges: false,
|
|
// It is possible to parse multiple files into a single AST by
|
|
// passing the tree produced by parsing the first file as
|
|
// `program` option in subsequent parses. This will add the
|
|
// toplevel forms of the parsed file to the `Program` (top) node
|
|
// of an existing parse tree.
|
|
program: null,
|
|
// When `locations` is on, you can pass this to record the source
|
|
// file in every node's `loc` object.
|
|
sourceFile: null,
|
|
// This value, if given, is stored in every node, whether
|
|
// `locations` is on or off.
|
|
directSourceFile: null,
|
|
// When enabled, parenthesized expressions are represented by
|
|
// (non-standard) ParenthesizedExpression nodes
|
|
preserveParens: false,
|
|
plugins: {}
|
|
}
|
|
|
|
// Registered plugins
|
|
|
|
export const plugins = {}
|
|
|
|
// Interpret and default an options object
|
|
|
|
function getOptions(opts) {
|
|
let options = {}
|
|
for (let opt in defaultOptions)
|
|
options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]
|
|
|
|
if (isArray(options.onToken)) {
|
|
var tokens = options.onToken;
|
|
options.onToken = (token) => tokens.push(token)
|
|
}
|
|
if (isArray(options.onComment))
|
|
options.onComment = pushComment(options, options.onComment);
|
|
|
|
return options;
|
|
}
|
|
|
|
function pushComment(options, array) {
|
|
return function (block, text, start, end, startLoc, endLoc) {
|
|
let comment = {
|
|
type: block ? 'Block' : 'Line',
|
|
value: text,
|
|
start: start,
|
|
end: end
|
|
}
|
|
if (options.locations)
|
|
comment.loc = new SourceLocation(this, startLoc, endLoc)
|
|
if (options.ranges)
|
|
comment.range = [start, end]
|
|
array.push(comment)
|
|
}
|
|
}
|
|
|
|
// 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.
|
|
|
|
export function parseExpressionAt(input, pos, options) {
|
|
let p = parser(options, input, pos)
|
|
p.nextToken()
|
|
return p.parseExpression()
|
|
}
|
|
|
|
// Acorn is organized as a tokenizer and a recursive-descent parser.
|
|
// The `tokenize` export provides an interface to the tokenizer.
|
|
// Because the tokenizer is optimized for being efficiently used by
|
|
// the Acorn parser itself, this interface is somewhat crude and not
|
|
// very modular.
|
|
|
|
export function tokenizer(input, options) {
|
|
return parser(options, input)
|
|
}
|
|
|
|
function parser(options, input) {
|
|
return new Parser(getOptions(options), String(input))
|
|
}
|