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