@teasel/parser
Every export of the package, as its declarations say.
Options
export interface Options {
/** @default 'script' */
sourceType?: 'script' | 'module';
/**
* Parse TypeScript. `'erase'` parses it and emits JavaScript: annotations, type-only
* declarations and imports go, assertions give way to their expression, and what erasure
* cannot express (enums, namespaces with values, parameter properties, `export =`, `import =`)
* stays in the tree and is listed as `typescript` on the answer, as are the proposals
* JavaScript itself has: decorators and accessor fields (`AccessorProperty`).
*/
typescript?: boolean | 'erase';
/** Attach `leadingComments`, `trailingComments` and `innerComments` to nodes, and list every comment read as `comments` on the answer. */
comments?: boolean;
/**
* Scope analysis: the answer lists `scopes`, `bindings` and `references`, and `scopeOf` and
* `referenceOf` answer for a node. The tree itself carries nothing, and a copy of a node
* carries no facts. TypeScript type positions bind nothing.
*/
scopes?: boolean;
/**
* Add `loc` with line and column to every node. `'js'` adds it to the JavaScript nodes and
* comments only: a host's own nodes, a stylesheet's included, keep `start` and `end`.
* @default false
*/
locations?: boolean | 'js';
/** Mark a node the source wraps in parens with `parenthesized: true`, absent otherwise. */
parenthesized?: boolean;
allowReturnOutsideFunction?: boolean;
allowAwaitOutsideFunction?: boolean;
allowSuperOutsideMethod?: boolean;
allowUndeclaredExports?: boolean;
/**
* List syntax errors on the answer as `errors` instead of throwing the first: a missing
* operand, name or pattern is an `Identifier` named `''` of no width where it was expected,
* and a statement or entry that cannot be read is skipped to the next stop token or
* unmatched closing bracket, an empty identifier standing for it. Placeholders are neither
* bindings nor references.
*/
errorRecovery?: boolean;
}parentOf
The node node is a child of; undefined for the root of an answer and for a comment listed in comments. A literal's regex and a template element's value are not nodes and have none.
export declare function parentOf(node: Node | HostNode | Comment | null | undefined): Node | HostNode | undefined;scopeOf
With scopes: the scope node opens, when it opens one.
export declare function scopeOf(node: Node | HostNode | null | undefined): Scope | undefined;referenceOf
With scopes: the reference an identifier makes, the binding itself for the identifier that declares it; a global's too, which no binding lists. Undefined when the identifier names no value, a property key say.
export declare function referenceOf(node: Node | null | undefined): Reference | undefined;Piece
One piece of JavaScript read at a position of the source, as far as it goes; until ends it
where the host's own tokens follow. A piece is built once and read at any position of any
source. T is what its parse answers with.
export declare class Piece<T> {
#private;
private constructor();
/**
* The same piece, ended where one of the host's own tokens, words or punctuators, follows.
* One read outside every bracket the parse opened, where the expression could end, ends it:
* `,` ends an expression before a sequence would, and `/>` is never a division. A `then`
* after `.` is a property name. A TypeScript `as` is the host's unless another `as` follows
* the assertion, so `xs as T[] as item` ends after the type.
*/
until(...tokens: string[]): Piece<T>;
}js
JavaScript: a parse of it reads the whole source, or the program inside [start, end]. Its members read one piece.
export declare const js: Language<Program> & {
readonly expression: Piece<Expression>;
/** An assignment target: an identifier or a destructuring pattern. */
readonly pattern: Piece<Pattern>;
/** A parenthesized parameter list, as an arrow function's is read. */
readonly params: Piece<Pattern[]>;
readonly statement: Piece<Statement>;
/** A `TSTypeParameterDeclaration`; TypeScript only, `not_typescript` otherwise. */
readonly typeParameters: Piece<Node>;
/** The fields TypeScript may add to a node of any type, holding nodes: annotations, type parameters and arguments, what a class implements, decorators. */
readonly extras: readonly string[];
};css
CSS: a parse of it reads the whole source as a stylesheet, a StyleSheet of rules and at-rules with its comments listed.
export declare const css: Language<HostNode>;Source
A source kept with its options; a parse keeps nothing of it in the engine. Offsets are UTF-16;
positions stay those of the whole source. A lone surrogate in the text reaches the parser as
U+FFFD, the way TextEncoder encodes it, so string values, template cooked and raw text and
regex patterns carry U+FFFD there while spans and loc are right.
export declare class Source {
#private;
constructor(source: string, options?: Options);
/**
* What `what` answers with: `js` by default, the whole source as a program. A piece of
* JavaScript is read at `at`, a UTF-16 offset, or at `[start, end]` as if the source ended at
* `end`; `js` takes the same for the program inside a range. `css` reads the whole source as a
* stylesheet. A grammar from
* `@teasel/parser/grammar` reads the whole source as a document of its host language: the
* host's own nodes around the JavaScript ones, in one tree, in TypeScript when the grammar
* says so of a script tag. The engine read the grammar when it was made.
*/
parse(): Parsed<Program>;
parse<T>(piece: Piece<T>, at?: number | [start: number, end: number]): Parsed<T>;
parse(language: typeof js, at?: number | [start: number, end: number]): Parsed<Program>;
parse<T>(what: Piece<T> | typeof js, at?: number | [start: number, end: number]): Parsed<T | Program>;
parse<T>(language: Language<T>): Parsed<T>;
}Scope
A scope, as one of scopes on the answer.
export interface Scope {
kind: 'module' | 'script' | 'function' | 'function-name' | 'class' | 'block' | 'catch' | 'for' | 'switch' | 'static-block' | 'with' | 'namespace' | 'enum' | 'fragment';
/** The node that opens it; null for a function-name scope and for the scope around a parameter list parsed on its own. */
node: Node | HostNode | null;
parent: Scope | null;
/** An `await` or `for await` runs directly in it, no function around; only a program or fragment scope can say so. */
topLevelAwait: boolean;
}Binding
A binding, as one of bindings on the answer: one an identifier declares, or the arguments a function reads.
export type Binding = Declared | Arguments;Declared
A binding an identifier declares. It is the reference that identifier makes, the first of its own: referenceOf answers with it, and its binding is itself.
export interface Declared extends Reference {
name: string;
/**
* What declared it. `function-name` and `class-name` are the name a function expression or a class
* expression has inside itself, `const f = function g() {}` declaring `g`. `pattern` is a name that
* a `js.pattern` piece declares, parsed on its own; a `js.params` piece declares `param`s.
*/
kind: 'var' | 'let' | 'const' | 'using' | 'await using' | 'function' | 'class' | 'param' | 'catch' | 'import' | 'function-name' | 'class-name' | 'enum' | 'enum-member' | 'namespace' | 'pattern';
/** The identifier that declares it. */
node: Identifier;
/** The scope it is declared in. */
scope: Scope;
/** What declares it: the declarator, function, class, import specifier, catch clause or enum, as eslint-scope's definition node; null for a pattern or parameter list parsed on its own. */
declaration: Node | null;
binding: Declared;
declares: true;
/** The declaration binds a value: an initializer, a parameter, a function, a class, an import; not a bare `let x;`. */
write: boolean;
read: false;
mutate: false;
/** The initializer of a declarator, `1` in `let x = 1`; null otherwise, the iterated expression of a `for-of` and a parameter's default being on the tree. */
writeExpr: Expression | null;
}Arguments
The arguments of a function that reads it: bound by the call, declared by no identifier.
export interface Arguments {
name: 'arguments';
kind: 'arguments';
scope: Scope;
node: null;
declaration: null;
binding: Arguments;
declares: true;
write: true;
read: false;
mutate: false;
writeExpr: null;
}Root
A piece of JavaScript a host read on its own, as one of roots on a document's answer, with what the tables hold for it.
export interface Root {
node: Node;
/** The scope the piece sits in. */
scope: Scope;
/** The scopes opened inside it, the bindings declared and the references made there. */
scopes: Scope[];
bindings: Binding[];
references: Reference[];
}Reference
A reference, as one of references on the answer: an identifier using a name, or declaring it again. A binding is one too, the reference its declaring identifier makes.
export interface Reference {
node: Identifier;
/** The scope the reference is made from. */
scope: Scope;
/** Null for a global. */
binding: Binding | null;
/** The identifier is assigned to, updated or bound by a destructuring assignment. */
write: boolean;
/** A member of the identifier's value is assigned to, updated or deleted. */
mutate: boolean;
/** The identifier's value is read: every reference but a declaration, a plain assignment's target or a destructuring one's; a compound assignment or an update reads and writes. */
read: boolean;
/** What a write assigns: the right side of the assignment, the iterated expression of a `for-in` or `for-of`, or what a declaration is initialized with, as eslint-scope's `writeExpr`; null for an update. */
writeExpr: Expression | null;
/** The identifier declares its binding: the binding itself for the first declaration, and a reference of its own for a name declared again, `var x` twice, which writes when a value is bound there. */
declares: boolean;
}Span
A range of the source, with loc when locations is on.
export interface Span {
start: number;
end: number;
loc?: SourceLocation;
}Comment
export interface Comment extends Span {
type: 'Line' | 'Block';
value: string;
}Kept
A node erasure left in place, by type.
export interface Kept extends Span {
type: string;
}Recovered
A syntax error, as errors lists it. A parse that cannot answer throws the first as a
SyntaxError with these fields, its message the code then each argument in quotes,
expected '}'.
export interface Recovered {
/** What went wrong, for a host to branch on; what each code means is at Error codes. */
code: Code;
/** What the error is about, a name or a token, when the code takes any. */
args: readonly string[];
/** The start of the token the parser could not accept; for `unexpected_eof`, the end of what was parsed. */
pos: number;
/** The end of that token, or `pos` when the cause is elsewhere, an earlier declaration say. */
end: number;
/** 1-based line and 0-based column of `pos`; a thrown `invalid_request` for a bad offset and a thrown `nesting_depth` for a tree too deep for the stack have neither. */
line: number;
column: number;
}Language
What a parse reads as a whole and up to the end it is given: JavaScript, or a host language by its grammar. T is what its parse answers with.
export interface Language<T> {
/** For every type of node a parse of the language answers with, the fields that hold a node or a list of nodes: what a walk follows. A grammar's names the JavaScript types beside the host's. */
readonly children: Readonly<Record<string, readonly string[]>>;
}Parsed
What a parse returns: the node, or the patterns of a parameter list, and what the options add; a key is there exactly when its option is on.
export interface Parsed<T> {
node: T;
/** The offset after everything the parse consumed: the node, its closing parens and the comments after it; a program's is the end it was given. */
end: number;
/** Every comment read, in source order; with `comments`. */
comments?: Comment[];
/** What erasure left in place; with `typescript: 'erase'`. */
typescript?: Kept[];
/** The errors recovered from, in source order; with `errorRecovery`. */
errors?: Recovered[];
/** With `scopes`. */
scopes?: Scope[];
bindings?: Binding[];
references?: Reference[];
/** With `scopes`, for a document read by a host grammar: its pieces of JavaScript in source order. */
roots?: Root[];
}HostNode
A node of a host language, as its grammar names the type and the fields; the JavaScript under it is ESTree. The node a grammar wraps children in has no span.
export interface HostNode extends Partial<Span> {
type: string;
[field: string]: unknown;
}Code
What a parse error names in code; what each means is at Error codes.
export type Code = (typeof CODES)[number];