The main Acorn parser provides fast, standards-compliant ECMAScript parsing with full support for ES2025 features and an extensible plugin architecture. It generates ESTree-compatible Abstract Syntax Trees (ASTs) from JavaScript source code.
import { parse, parseExpressionAt, tokenizer, Parser, defaultOptions } from "acorn";For CommonJS:
const { parse, parseExpressionAt, tokenizer, Parser, defaultOptions } = require("acorn");Parses a complete JavaScript program or module into an AST.
/**
* Parses JavaScript source code into an ESTree-compatible AST
* @param input - JavaScript source code string
* @param options - Parser configuration options
* @returns Program node representing the parsed code
*/
function parse(input: string, options: Options): Program;Usage Example:
import { parse } from "acorn";
const code = `
function greet(name) {
console.log("Hello, " + name + "!");
}
greet("World");
`;
const ast = parse(code, {
ecmaVersion: 2020,
sourceType: "script"
});
console.log(ast.type); // "Program"
console.log(ast.body.length); // 2 (function declaration + expression statement)Parses a single expression at a specific position in the source code.
/**
* Parses a single expression at the given position
* @param input - JavaScript source code string
* @param pos - Character offset to start parsing from
* @param options - Parser configuration options
* @returns Expression node
*/
function parseExpressionAt(input: string, pos: number, options: Options): Expression;Usage Example:
import { parseExpressionAt } from "acorn";
const code = "let x = 42 + 8;";
const expr = parseExpressionAt(code, 8, { ecmaVersion: 2020 }); // Parse "42 + 8"
console.log(expr.type); // "BinaryExpression"
console.log(expr.operator); // "+"Creates a tokenizer that can iterate through all tokens in the source code.
/**
* Creates a tokenizer for the given input
* @param input - JavaScript source code string
* @param options - Parser configuration options
* @returns Tokenizer object with getToken() method and iterator support
*/
function tokenizer(input: string, options: Options): {
getToken(): Token;
[Symbol.iterator](): Iterator<Token>;
};Usage Example:
import { tokenizer } from "acorn";
const code = "let x = 42;";
const tokens = tokenizer(code, { ecmaVersion: 2020 });
// Using iterator
for (const token of tokens) {
console.log(`${token.type.label}: ${token.start}-${token.end}`);
}
// Using getToken() method
const tokenizer2 = tokenizer(code, { ecmaVersion: 2020 });
let token;
while ((token = tokenizer2.getToken()).type !== tokTypes.eof) {
console.log(token);
}The main Parser class with static methods and plugin support.
/**
* Main Parser class with static parsing methods and plugin extension support
*/
class Parser {
options: Options;
input: string;
protected constructor(options: Options, input: string, startPos?: number);
/**
* Parse a complete program
*/
parse(): Program;
/**
* Static method to parse input with options
*/
static parse(input: string, options: Options): Program;
/**
* Static method to parse expression at position
*/
static parseExpressionAt(input: string, pos: number, options: Options): Expression;
/**
* Static method to create tokenizer
*/
static tokenizer(input: string, options: Options): {
getToken(): Token;
[Symbol.iterator](): Iterator<Token>;
};
/**
* Extend parser with plugins
*/
static extend(...plugins: ((BaseParser: typeof Parser) => typeof Parser)[]): typeof Parser;
}Plugin Usage Example:
import { Parser } from "acorn";
// Example plugin for JSX-like syntax
function jsxPlugin(BaseParser) {
return class extends BaseParser {
parseExprAtom() {
if (this.type === tt.lt && this.input.charCodeAt(this.pos) !== 47) {
return this.parseJSXElement();
}
return super.parseExprAtom();
}
parseJSXElement() {
// Custom JSX parsing logic
const node = this.startNode();
// ... implementation
return this.finishNode(node, "JSXElement");
}
};
}
const JSXParser = Parser.extend(jsxPlugin);
const ast = JSXParser.parse("<div>Hello</div>", { ecmaVersion: 2020 });Comprehensive configuration options for controlling parser behavior.
interface Options {
/**
* ECMAScript version to parse. Can be a number (3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
* or year (2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025)
* or "latest" for the latest supported version
*/
ecmaVersion: ecmaVersion;
/**
* Source type: "script" or "module"
* Affects global strict mode and import/export parsing
*/
sourceType?: "script" | "module";
/**
* Callback for automatic semicolon insertion events
*/
onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void;
/**
* Callback for trailing comma events
*/
onTrailingComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void;
/**
* Control reserved word enforcement
* true/false or "never" to disallow as property names too
*/
allowReserved?: boolean | "never";
/**
* Allow return statements at top level
*/
allowReturnOutsideFunction?: boolean;
/**
* Allow import/export anywhere in the program
*/
allowImportExportEverywhere?: boolean;
/**
* Allow await identifiers at top level
*/
allowAwaitOutsideFunction?: boolean;
/**
* Allow super identifiers outside methods
*/
allowSuperOutsideMethod?: boolean;
/**
* Allow hashbang directive (#!) at start of file
*/
allowHashBang?: boolean;
/**
* Validate private field usage
*/
checkPrivateFields?: boolean;
/**
* Include location information in nodes
*/
locations?: boolean;
/**
* Token callback or array to collect tokens
*/
onToken?: ((token: Token) => void) | Token[];
/**
* Comment callback or array to collect comments
*/
onComment?: ((
isBlock: boolean, text: string, start: number, end: number,
startLoc?: Position, endLoc?: Position
) => void) | Comment[];
/**
* Include range information as [start, end] arrays
*/
ranges?: boolean;
/**
* Existing program node to extend (for parsing multiple files)
*/
program?: Node;
/**
* Source file name for location info
*/
sourceFile?: string;
/**
* Direct source file for all nodes
*/
directSourceFile?: string;
/**
* Preserve parenthesized expressions as ParenthesizedExpression nodes
*/
preserveParens?: boolean;
}
type ecmaVersion = 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16
| 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025
| "latest";Pre-configured default options for the parser.
/**
* Default parser options
*/
const defaultOptions: Options;Helper functions for working with parsed code.
/**
* Get line/column information for a character offset
* @param input - Source code string
* @param offset - Character offset
* @returns Position with line and column numbers
*/
function getLineInfo(input: string, offset: number): Position;
interface Position {
/** 1-based line number */
line: number;
/** 0-based column number */
column: number;
}
interface SourceLocation {
source?: string | null;
start: Position;
end: Position;
}Token types and token objects returned by the tokenizer.
/**
* Token type definitions
*/
class TokenType {
label: string;
keyword: string | undefined;
}
/**
* All available token types
*/
const tokTypes: {
// Literals and identifiers
num: TokenType;
regexp: TokenType;
string: TokenType;
name: TokenType;
privateId: TokenType;
eof: TokenType;
// Punctuation
bracketL: TokenType; // [
bracketR: TokenType; // ]
braceL: TokenType; // {
braceR: TokenType; // }
parenL: TokenType; // (
parenR: TokenType; // )
comma: TokenType; // ,
semi: TokenType; // ;
colon: TokenType; // :
dot: TokenType; // .
question: TokenType; // ?
questionDot: TokenType; // ?.
arrow: TokenType; // =>
ellipsis: TokenType; // ...
backQuote: TokenType; // `
dollarBraceL: TokenType; // ${
// Operators
eq: TokenType; // ==, ===, !=, !==
assign: TokenType; // =, +=, -=, etc.
incDec: TokenType; // ++, --
prefix: TokenType; // !, ~, -, +
logicalOR: TokenType; // ||
logicalAND: TokenType; // &&
bitwiseOR: TokenType; // |
bitwiseXOR: TokenType; // ^
bitwiseAND: TokenType; // &
equality: TokenType; // ==, !=, ===, !==
relational: TokenType; // <, >, <=, >=, in, instanceof
bitShift: TokenType; // <<, >>, >>>
plusMin: TokenType; // +, -
modulo: TokenType; // %
star: TokenType; // *
slash: TokenType; // /
starstar: TokenType; // **
coalesce: TokenType; // ??
// Keywords
_break: TokenType;
_case: TokenType;
_catch: TokenType;
_continue: TokenType;
_debugger: TokenType;
_default: TokenType;
_do: TokenType;
_else: TokenType;
_finally: TokenType;
_for: TokenType;
_function: TokenType;
_if: TokenType;
_return: TokenType;
_switch: TokenType;
_throw: TokenType;
_try: TokenType;
_var: TokenType;
_const: TokenType;
_while: TokenType;
_with: TokenType;
_new: TokenType;
_this: TokenType;
_super: TokenType;
_class: TokenType;
_extends: TokenType;
_export: TokenType;
_import: TokenType;
_null: TokenType;
_true: TokenType;
_false: TokenType;
_in: TokenType;
_instanceof: TokenType;
_typeof: TokenType;
_void: TokenType;
_delete: TokenType;
};
/**
* Token object returned by tokenizer
*/
class Token {
type: TokenType;
start: number;
end: number;
loc?: SourceLocation;
range?: [number, number];
}
/**
* Comment object when using onComment option
*/
interface Comment {
type: "Line" | "Block";
value: string;
start: number;
end: number;
loc?: SourceLocation;
range?: [number, number];
}Complete type definitions for all ESTree-compatible AST nodes.
// Base node interface
interface Node {
start: number;
end: number;
type: string;
range?: [number, number];
loc?: SourceLocation | null;
}
// Program node (root)
interface Program extends Node {
type: "Program";
body: Array<Statement | ModuleDeclaration>;
sourceType: "script" | "module";
}
// Statements
type Statement =
| ExpressionStatement
| BlockStatement
| EmptyStatement
| DebuggerStatement
| WithStatement
| ReturnStatement
| LabeledStatement
| BreakStatement
| ContinueStatement
| IfStatement
| SwitchStatement
| ThrowStatement
| TryStatement
| WhileStatement
| DoWhileStatement
| ForStatement
| ForInStatement
| ForOfStatement
| Declaration;
// Expressions
type Expression =
| Identifier
| Literal
| ThisExpression
| ArrayExpression
| ObjectExpression
| FunctionExpression
| UnaryExpression
| UpdateExpression
| BinaryExpression
| AssignmentExpression
| LogicalExpression
| MemberExpression
| ConditionalExpression
| CallExpression
| NewExpression
| SequenceExpression
| ArrowFunctionExpression
| YieldExpression
| TemplateLiteral
| TaggedTemplateExpression
| ClassExpression
| MetaProperty
| AwaitExpression
| ChainExpression
| ImportExpression
| ParenthesizedExpression;
// Declarations
type Declaration =
| FunctionDeclaration
| VariableDeclaration
| ClassDeclaration;
// Module declarations
type ModuleDeclaration =
| ImportDeclaration
| ExportNamedDeclaration
| ExportDefaultDeclaration
| ExportAllDeclaration;
// Patterns
type Pattern =
| Identifier
| MemberExpression
| ObjectPattern
| ArrayPattern
| RestElement
| AssignmentPattern;import { parse } from "acorn";
const options = {
ecmaVersion: 2022,
sourceType: "module",
locations: true,
ranges: true
};
const ast = parse(`
import { helper } from './utils.js';
export default function main() {
const data = await helper();
return data?.results ?? [];
}
`, options);
console.log(ast.sourceType); // "module"
console.log(ast.body[0].type); // "ImportDeclaration"import { parse } from "acorn";
const tokens = [];
const ast = parse(`let x = 42;`, {
ecmaVersion: 2020,
onToken: token => tokens.push(token)
});
tokens.forEach(token => {
console.log(`${token.type.label}: "${token.start}-${token.end}"`);
});import { parse } from "acorn";
const comments = [];
const ast = parse(`
// This is a line comment
function example() {
/* Block comment */
return true;
}
`, {
ecmaVersion: 2020,
onComment: comments
});
comments.forEach(comment => {
console.log(`${comment.type}: ${comment.value}`);
});import { parse } from "acorn";
try {
const ast = parse("let x = ;", { ecmaVersion: 2020 });
} catch (error) {
console.log(`Parse error at position ${error.pos}: ${error.message}`);
// For error recovery, use acorn-loose instead
}