1 | # Acorn
|
---|
2 |
|
---|
3 | A tiny, fast JavaScript parser written in JavaScript.
|
---|
4 |
|
---|
5 | ## Community
|
---|
6 |
|
---|
7 | Acorn is open source software released under an
|
---|
8 | [MIT license](https://github.com/acornjs/acorn/blob/master/acorn/LICENSE).
|
---|
9 |
|
---|
10 | You are welcome to
|
---|
11 | [report bugs](https://github.com/acornjs/acorn/issues) or create pull
|
---|
12 | requests on [github](https://github.com/acornjs/acorn). For questions
|
---|
13 | and discussion, please use the
|
---|
14 | [Tern discussion forum](https://discuss.ternjs.net).
|
---|
15 |
|
---|
16 | ## Installation
|
---|
17 |
|
---|
18 | The easiest way to install acorn is from [`npm`](https://www.npmjs.com/):
|
---|
19 |
|
---|
20 | ```sh
|
---|
21 | npm install acorn
|
---|
22 | ```
|
---|
23 |
|
---|
24 | Alternately, you can download the source and build acorn yourself:
|
---|
25 |
|
---|
26 | ```sh
|
---|
27 | git clone https://github.com/acornjs/acorn.git
|
---|
28 | cd acorn
|
---|
29 | npm install
|
---|
30 | ```
|
---|
31 |
|
---|
32 | ## Interface
|
---|
33 |
|
---|
34 | **parse**`(input, options)` is the main interface to the library. The
|
---|
35 | `input` parameter is a string, `options` must be an object setting
|
---|
36 | some of the options listed below. The return value will be an abstract
|
---|
37 | syntax tree object as specified by the [ESTree
|
---|
38 | spec](https://github.com/estree/estree).
|
---|
39 |
|
---|
40 | ```javascript
|
---|
41 | let acorn = require("acorn");
|
---|
42 | console.log(acorn.parse("1 + 1", {ecmaVersion: 2020}));
|
---|
43 | ```
|
---|
44 |
|
---|
45 | When encountering a syntax error, the parser will raise a
|
---|
46 | `SyntaxError` object with a meaningful message. The error object will
|
---|
47 | have a `pos` property that indicates the string offset at which the
|
---|
48 | error occurred, and a `loc` object that contains a `{line, column}`
|
---|
49 | object referring to that same position.
|
---|
50 |
|
---|
51 | Options are provided by in a second argument, which should be an
|
---|
52 | object containing any of these fields (only `ecmaVersion` is
|
---|
53 | required):
|
---|
54 |
|
---|
55 | - **ecmaVersion**: Indicates the ECMAScript version to parse. Must be
|
---|
56 | either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10 (2019),
|
---|
57 | 11 (2020), 12 (2021), 13 (2022, partial support)
|
---|
58 | or `"latest"` (the latest the library supports). This influences
|
---|
59 | support for strict mode, the set of reserved words, and support
|
---|
60 | for new syntax features.
|
---|
61 |
|
---|
62 | **NOTE**: Only 'stage 4' (finalized) ECMAScript features are being
|
---|
63 | implemented by Acorn. Other proposed new features must be
|
---|
64 | implemented through plugins.
|
---|
65 |
|
---|
66 | - **sourceType**: Indicate the mode the code should be parsed in. Can be
|
---|
67 | either `"script"` or `"module"`. This influences global strict mode
|
---|
68 | and parsing of `import` and `export` declarations.
|
---|
69 |
|
---|
70 | **NOTE**: If set to `"module"`, then static `import` / `export` syntax
|
---|
71 | will be valid, even if `ecmaVersion` is less than 6.
|
---|
72 |
|
---|
73 | - **onInsertedSemicolon**: If given a callback, that callback will be
|
---|
74 | called whenever a missing semicolon is inserted by the parser. The
|
---|
75 | callback will be given the character offset of the point where the
|
---|
76 | semicolon is inserted as argument, and if `locations` is on, also a
|
---|
77 | `{line, column}` object representing this position.
|
---|
78 |
|
---|
79 | - **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing
|
---|
80 | commas.
|
---|
81 |
|
---|
82 | - **allowReserved**: If `false`, using a reserved word will generate
|
---|
83 | an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher
|
---|
84 | versions. When given the value `"never"`, reserved words and
|
---|
85 | keywords can also not be used as property names (as in Internet
|
---|
86 | Explorer's old parser).
|
---|
87 |
|
---|
88 | - **allowReturnOutsideFunction**: By default, a return statement at
|
---|
89 | the top level raises an error. Set this to `true` to accept such
|
---|
90 | code.
|
---|
91 |
|
---|
92 | - **allowImportExportEverywhere**: By default, `import` and `export`
|
---|
93 | declarations can only appear at a program's top level. Setting this
|
---|
94 | option to `true` allows them anywhere where a statement is allowed,
|
---|
95 | and also allows `import.meta` expressions to appear in scripts
|
---|
96 | (when `sourceType` is not `"module"`).
|
---|
97 |
|
---|
98 | - **allowAwaitOutsideFunction**: If `false`, `await` expressions can
|
---|
99 | only appear inside `async` functions. Defaults to `true` for
|
---|
100 | `ecmaVersion` 2022 and later, `false` for lower versions. Setting this option to
|
---|
101 | `true` allows to have top-level `await` expressions. They are
|
---|
102 | still not allowed in non-`async` functions, though.
|
---|
103 |
|
---|
104 | - **allowSuperOutsideMethod**: By default, `super` outside a method
|
---|
105 | raises an error. Set this to `true` to accept such code.
|
---|
106 |
|
---|
107 | - **allowHashBang**: When this is enabled (off by default), if the
|
---|
108 | code starts with the characters `#!` (as in a shellscript), the
|
---|
109 | first line will be treated as a comment.
|
---|
110 |
|
---|
111 | - **locations**: When `true`, each node has a `loc` object attached
|
---|
112 | with `start` and `end` subobjects, each of which contains the
|
---|
113 | one-based line and zero-based column numbers in `{line, column}`
|
---|
114 | form. Default is `false`.
|
---|
115 |
|
---|
116 | - **onToken**: If a function is passed for this option, each found
|
---|
117 | token will be passed in same format as tokens returned from
|
---|
118 | `tokenizer().getToken()`.
|
---|
119 |
|
---|
120 | If array is passed, each found token is pushed to it.
|
---|
121 |
|
---|
122 | Note that you are not allowed to call the parser from the
|
---|
123 | callback—that will corrupt its internal state.
|
---|
124 |
|
---|
125 | - **onComment**: If a function is passed for this option, whenever a
|
---|
126 | comment is encountered the function will be called with the
|
---|
127 | following parameters:
|
---|
128 |
|
---|
129 | - `block`: `true` if the comment is a block comment, false if it
|
---|
130 | is a line comment.
|
---|
131 | - `text`: The content of the comment.
|
---|
132 | - `start`: Character offset of the start of the comment.
|
---|
133 | - `end`: Character offset of the end of the comment.
|
---|
134 |
|
---|
135 | When the `locations` options is on, the `{line, column}` locations
|
---|
136 | of the comment’s start and end are passed as two additional
|
---|
137 | parameters.
|
---|
138 |
|
---|
139 | If array is passed for this option, each found comment is pushed
|
---|
140 | to it as object in Esprima format:
|
---|
141 |
|
---|
142 | ```javascript
|
---|
143 | {
|
---|
144 | "type": "Line" | "Block",
|
---|
145 | "value": "comment text",
|
---|
146 | "start": Number,
|
---|
147 | "end": Number,
|
---|
148 | // If `locations` option is on:
|
---|
149 | "loc": {
|
---|
150 | "start": {line: Number, column: Number}
|
---|
151 | "end": {line: Number, column: Number}
|
---|
152 | },
|
---|
153 | // If `ranges` option is on:
|
---|
154 | "range": [Number, Number]
|
---|
155 | }
|
---|
156 | ```
|
---|
157 |
|
---|
158 | Note that you are not allowed to call the parser from the
|
---|
159 | callback—that will corrupt its internal state.
|
---|
160 |
|
---|
161 | - **ranges**: Nodes have their start and end characters offsets
|
---|
162 | recorded in `start` and `end` properties (directly on the node,
|
---|
163 | rather than the `loc` object, which holds line/column data. To also
|
---|
164 | add a
|
---|
165 | [semi-standardized](https://bugzilla.mozilla.org/show_bug.cgi?id=745678)
|
---|
166 | `range` property holding a `[start, end]` array with the same
|
---|
167 | numbers, set the `ranges` option to `true`.
|
---|
168 |
|
---|
169 | - **program**: It is possible to parse multiple files into a single
|
---|
170 | AST by passing the tree produced by parsing the first file as the
|
---|
171 | `program` option in subsequent parses. This will add the toplevel
|
---|
172 | forms of the parsed file to the "Program" (top) node of an existing
|
---|
173 | parse tree.
|
---|
174 |
|
---|
175 | - **sourceFile**: When the `locations` option is `true`, you can pass
|
---|
176 | this option to add a `source` attribute in every node’s `loc`
|
---|
177 | object. Note that the contents of this option are not examined or
|
---|
178 | processed in any way; you are free to use whatever format you
|
---|
179 | choose.
|
---|
180 |
|
---|
181 | - **directSourceFile**: Like `sourceFile`, but a `sourceFile` property
|
---|
182 | will be added (regardless of the `location` option) directly to the
|
---|
183 | nodes, rather than the `loc` object.
|
---|
184 |
|
---|
185 | - **preserveParens**: If this option is `true`, parenthesized expressions
|
---|
186 | are represented by (non-standard) `ParenthesizedExpression` nodes
|
---|
187 | that have a single `expression` property containing the expression
|
---|
188 | inside parentheses.
|
---|
189 |
|
---|
190 | **parseExpressionAt**`(input, offset, options)` will parse a single
|
---|
191 | expression in a string, and return its AST. It will not complain if
|
---|
192 | there is more of the string left after the expression.
|
---|
193 |
|
---|
194 | **tokenizer**`(input, options)` returns an object with a `getToken`
|
---|
195 | method that can be called repeatedly to get the next token, a `{start,
|
---|
196 | end, type, value}` object (with added `loc` property when the
|
---|
197 | `locations` option is enabled and `range` property when the `ranges`
|
---|
198 | option is enabled). When the token's type is `tokTypes.eof`, you
|
---|
199 | should stop calling the method, since it will keep returning that same
|
---|
200 | token forever.
|
---|
201 |
|
---|
202 | In ES6 environment, returned result can be used as any other
|
---|
203 | protocol-compliant iterable:
|
---|
204 |
|
---|
205 | ```javascript
|
---|
206 | for (let token of acorn.tokenizer(str)) {
|
---|
207 | // iterate over the tokens
|
---|
208 | }
|
---|
209 |
|
---|
210 | // transform code to array of tokens:
|
---|
211 | var tokens = [...acorn.tokenizer(str)];
|
---|
212 | ```
|
---|
213 |
|
---|
214 | **tokTypes** holds an object mapping names to the token type objects
|
---|
215 | that end up in the `type` properties of tokens.
|
---|
216 |
|
---|
217 | **getLineInfo**`(input, offset)` can be used to get a `{line,
|
---|
218 | column}` object for a given program string and offset.
|
---|
219 |
|
---|
220 | ### The `Parser` class
|
---|
221 |
|
---|
222 | Instances of the **`Parser`** class contain all the state and logic
|
---|
223 | that drives a parse. It has static methods `parse`,
|
---|
224 | `parseExpressionAt`, and `tokenizer` that match the top-level
|
---|
225 | functions by the same name.
|
---|
226 |
|
---|
227 | When extending the parser with plugins, you need to call these methods
|
---|
228 | on the extended version of the class. To extend a parser with plugins,
|
---|
229 | you can use its static `extend` method.
|
---|
230 |
|
---|
231 | ```javascript
|
---|
232 | var acorn = require("acorn");
|
---|
233 | var jsx = require("acorn-jsx");
|
---|
234 | var JSXParser = acorn.Parser.extend(jsx());
|
---|
235 | JSXParser.parse("foo(<bar/>)", {ecmaVersion: 2020});
|
---|
236 | ```
|
---|
237 |
|
---|
238 | The `extend` method takes any number of plugin values, and returns a
|
---|
239 | new `Parser` class that includes the extra parser logic provided by
|
---|
240 | the plugins.
|
---|
241 |
|
---|
242 | ## Command line interface
|
---|
243 |
|
---|
244 | The `bin/acorn` utility can be used to parse a file from the command
|
---|
245 | line. It accepts as arguments its input file and the following
|
---|
246 | options:
|
---|
247 |
|
---|
248 | - `--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|--ecma10`: Sets the ECMAScript version
|
---|
249 | to parse. Default is version 9.
|
---|
250 |
|
---|
251 | - `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise.
|
---|
252 |
|
---|
253 | - `--locations`: Attaches a "loc" object to each node with "start" and
|
---|
254 | "end" subobjects, each of which contains the one-based line and
|
---|
255 | zero-based column numbers in `{line, column}` form.
|
---|
256 |
|
---|
257 | - `--allow-hash-bang`: If the code starts with the characters #! (as
|
---|
258 | in a shellscript), the first line will be treated as a comment.
|
---|
259 |
|
---|
260 | - `--allow-await-outside-function`: Allows top-level `await` expressions.
|
---|
261 | See the `allowAwaitOutsideFunction` option for more information.
|
---|
262 |
|
---|
263 | - `--compact`: No whitespace is used in the AST output.
|
---|
264 |
|
---|
265 | - `--silent`: Do not output the AST, just return the exit status.
|
---|
266 |
|
---|
267 | - `--help`: Print the usage information and quit.
|
---|
268 |
|
---|
269 | The utility spits out the syntax tree as JSON data.
|
---|
270 |
|
---|
271 | ## Existing plugins
|
---|
272 |
|
---|
273 | - [`acorn-jsx`](https://github.com/RReverser/acorn-jsx): Parse [Facebook JSX syntax extensions](https://github.com/facebook/jsx)
|
---|
274 |
|
---|
275 | Plugins for ECMAScript proposals:
|
---|
276 |
|
---|
277 | - [`acorn-stage3`](https://github.com/acornjs/acorn-stage3): Parse most stage 3 proposals, bundling:
|
---|
278 | - [`acorn-class-fields`](https://github.com/acornjs/acorn-class-fields): Parse [class fields proposal](https://github.com/tc39/proposal-class-fields)
|
---|
279 | - [`acorn-import-meta`](https://github.com/acornjs/acorn-import-meta): Parse [import.meta proposal](https://github.com/tc39/proposal-import-meta)
|
---|
280 | - [`acorn-private-methods`](https://github.com/acornjs/acorn-private-methods): parse [private methods, getters and setters proposal](https://github.com/tc39/proposal-private-methods)n
|
---|