@teasel/parser/grammar
Every export of the grammar builders, as their declarations say. A grammar crosses to the engine as JSON.stringify({ name, definition }), which is also what the Rust crate's parse_document and the command line's --host read.
Site
Where a source may be read: a form, a block's body, a directive's attribute value, the document, an element, a this attribute, a text or comment node, the fragment node, a directive's name, a literal.
export type Site = 'form' | 'body' | 'value' | 'document' | 'element' | 'this' | 'text' | 'fragment' | 'directive' | 'literal';Source
What fills a field: T is what a parse puts there, S where it may be read.
export interface Source<T = unknown, S extends Site = Site, M extends Mods = Plain> {
readonly from: string;
readonly read: string;
readonly optional: M['optional'];
readonly bind: M['bind'];
readonly orArg: M['orArg'];
readonly [out]?: {
readonly t: T;
readonly m: M;
readonly s: (site: S) => void;
};
}Children
A node's children: the grammar's fragment node when it has one, else the list.
export interface Children {
readonly [children]: true;
}js
JavaScript read at a position of a form.
export declare const js: {
expression: Source<Expression, "form", Plain>;
pattern: Source<Pattern, "form", Plain>;
params: Source<Pattern[], "form", Plain>;
identifier: Source<Identifier, "form", Plain>;
identifiers: Source<Identifier[], "form", Plain>;
statement: Source<Statement, "form", Plain>;
const: Source<VariableDeclaration, "form", Plain>;
/** An expression, or its statements as a program when it is not one. */
code: Source<Program | Expression, "form", Plain>;
/** The type parameters' text, without the angle brackets. */
typeParameters: Source<string, "form", Plain>;
/** The text up to the tag's end word, unread. */
text: Source<string, "form", Plain>;
};value
A directive's attribute value.
export declare const value: {
expression: Source<Expression, "value", Plain>;
pattern: Source<Pattern, "value", Plain>;
/** The value as written: text and expressions. */
raw: Source<Written, "value", Plain>;
};doc
What the document holds.
export declare const doc: {
script: Source<Script, "document", With<Plain, "missing", true>>;
module: Source<Script, "document", With<Plain, "missing", true>>;
style: Source<HostNode, "document", With<Plain, "missing", true>>;
comments: Source<Comment[], "document", Plain>;
};text
A text or comment node's text: as read, and as written.
export declare const text: {
data: Source<string, "text", Plain>;
raw: Source<string, "text", Plain>;
};content
Where the host's content goes: a block's body, an element's children, the document's.
export declare const content: Source<Children, "body" | "document" | "element", Plain>;nodes
The fragment node's own list.
export declare const nodes: Source<Nodes, "fragment", Plain>;literal
A value the site always writes.
export declare const literal: <const T extends boolean | null | readonly []>(v: T) => Source<T, 'literal'>;optional
The field is left out when nothing was read into it. The only way a field is absent.
export declare const optional: <T, S extends Exclude<Site, 'value'>, M extends Mods>(s: Source<T, S, M>) => Source<T, S, With<M, 'optional', true>>;bind
What the field reads declares names in the scope its site opens.
export declare const bind: (<T extends Bindable, S extends 'form' | 'value', M extends Mods>(s: Source<T, S, M>) => Source<T, S, With<M, 'bind', 'inside'>>) & {
/** In the scope around the block instead: a snippet's name. */
outside: <T extends Bindable, M extends Mods>(s: Source<T, 'form', M>) => Source<T, 'form', With<M, 'bind', 'outside'>>;
};orArg
Without a value, the directive's argument is the value: bind:value.
export declare const orArg: <T, M extends Mods>(s: Source<T, 'value', M>) => Source<T, 'value', With<M, 'orArg', true>>;Fields
Fields a form reads, each named once, where its source is.
export type Fields<F = Source<any, any, any>> = {
readonly [field: string]: F;
} & {
readonly [K in Reserved]?: never;
};Item
One step of a form: a host word or punctuator, fields, or a group.
export type Item = string | Fields | Opt<readonly Item[]> | OneOf<readonly (readonly Item[])[]> | Scope<readonly Item[]>;Opt
export interface Opt<I extends readonly unknown[]> {
readonly opt: I;
}OneOf
export interface OneOf<A extends readonly (readonly unknown[])[]> {
readonly oneOf: A;
}Scope
The document's or fragment's fields whose names the fields inside see.
export interface Scope<I extends readonly unknown[]> {
readonly scope: I;
}Form
A form whose fields read what F allows.
export type Form<F> = readonly (string | Fields<F> | Opt<Form<F>> | OneOf<readonly Form<F>[]>)[];seq
A sequence kept for reuse in several forms.
export declare const seq: <const I extends readonly Item[]>(...items: I) => I;opt
[ … ]: read when its first word or reader is there.
export declare const opt: <const I extends readonly [Item, ...Item[]]>(...items: I) => Opt<I>;oneOf
{ a | b }: exactly one, chosen by how it starts; wrap in opt for at most one.
export declare const oneOf: <const A extends readonly [readonly [Item, ...Item[]], ...(readonly [Item, ...Item[]])[]]>(...alternatives: A) => OneOf<A>;scope
export declare const scope: <const I extends readonly Item[]>(...items: I) => Scope<I>;Node
A node type and the form its fields come from.
export interface Node<T extends string = string, I extends readonly Item[] = readonly Item[]> {
readonly node: T;
readonly form?: I;
}Place
Where a construct may stand: in content, in an attribute value, among an element's attributes, in the text of an rcdata element.
export type Place = 'content' | 'value' | 'attributes' | 'rcdata';Piece
A marker and what its form reads after it: a construct's open, a branch, or its close.
export interface Piece<I extends BlockForm = BlockForm> {
/**
* Parts that whitespace and comments may stand between; a part is matched as written. A marker
* that stops partway is another word, `{.5}` no `{...}`, unless it stops after a part's leading
* punctuation or a whole part: `{#eac` is an error.
*/
readonly marker: readonly [string, ...string[]];
/** Whitespace must follow the marker. */
readonly space?: boolean;
readonly form: I;
}Branch
export interface Branch<I extends BlockForm = BlockForm> extends Piece<I> {
/** The branch opens the construct again inside this field, with this flag true on the one it opens. */
readonly reopen?: readonly [field: string, flag: string];
}Tag
A construct without a close: it reads no content and opens no scope.
export interface Tag {
/** Content when left out. */
readonly in?: readonly Place[];
readonly open: Piece<TagForm>;
readonly branches?: undefined;
readonly close?: undefined;
}Block
A construct with a close: its open, and every branch, ends in content.
export interface Block {
/** Content when left out. */
readonly in?: readonly Place[];
readonly open: Piece;
readonly branches?: readonly Branch[];
/** Words only: what ends the block. */
readonly close: Piece<readonly string[]>;
}Construct
A tag or a block; the type of the node it makes is the key it is written under.
export type Construct = Tag | Block;Directive
export interface Directive<T extends string = string> extends Node<T, DirectiveForm> {
readonly unique?: 'kind' | 'attributes';
}directive
What a directive's attribute name holds.
export declare const directive: {
kind: Source<string, "directive", Plain>;
/** The argument; an expression when the directive syntax brackets a dynamic one. */
arg: Source<string | Expression | null, "directive", Plain>;
modifiers: Source<string[], "directive", Plain>;
raw: Source<string, "directive", Plain>;
};Element
export interface Element<T extends string = string> extends Node<T, Form<Field<'this'>>> {
readonly root?: true;
readonly once?: true;
/** Only inside the element this names. */
readonly inside?: string;
readonly outside?: string;
readonly content?: 'raw' | 'rcdata';
}element
What an element's tag holds.
export declare const element: {
tag: Source<string, "element", Plain>;
attributes: Source<Attributes, "element", Plain>;
/** The expression of a `this` attribute, which leaves the attributes. */
this: Source<Expression, "this", Plain>;
/** The same, a text value read as a string literal. */
thisOrText: Source<Expression, "this", Plain>;
};Definition
A host language: its document, its content, and the JavaScript inside them.
export interface Definition {
readonly document: Node<string, Scoped<Field<'document'> | Source<null | readonly [], 'literal', any>>>;
readonly text: Node<string, Scoped<Always<'text'>>>;
readonly comment: Node<string, Scoped<Always<'text'>>>;
readonly fragment?: Node<string, Scoped<Always<'fragment'>>>;
/** `{name}` among the attributes is `name={name}`: the marker and the word around the name. */
readonly attributes?: {
readonly shorthand?: readonly [open: string, close: string];
};
readonly autoclose?: true;
readonly trim?: true;
readonly void?: readonly string[];
readonly verbatim?: string;
readonly elements: {
readonly fields: Fields<Always<'element'>>;
readonly rules?: {
readonly [name: string]: Element;
};
readonly component?: Element;
readonly other?: Element;
};
readonly script?: {
readonly element: string;
readonly module?: readonly Marker[];
readonly typescript?: readonly Marker[];
};
readonly style?: string;
readonly directives?: {
readonly prefix?: string;
readonly arg?: string;
readonly modifier?: string;
readonly dynamic?: readonly [open: string, close: string];
readonly unique?: 'raw';
readonly fields: Fields<Always<'directive'>>;
readonly shorthands?: {
readonly [token: string]: readonly [name: string, ...modifiers: string[]];
};
readonly rules?: {
readonly [name: string]: Directive;
};
readonly other?: Directive;
};
/** By the type of the node each makes. */
readonly constructs?: {
readonly [type: string]: Construct;
};
}Grammar
export interface Grammar<D extends Definition = Definition> extends Language<NodeOf<D['document'], D>> {
readonly host: string;
readonly definition: D;
}grammar
export declare const grammar: <const D extends Definition>(host: string, definition: D) => Grammar<D>;Content
What a host's content can hold; an rcdata element's, what stands in rcdata.
export type Content<G extends Definition> = ElementNode<Values<G['elements']['rules']> | G['elements']['component'] | G['elements']['other'], G> | NodeOf<G['text'], G> | NodeOf<G['comment'], G> | Constructs<G, 'content'> | Constructs<G, 'rcdata'>;Attribute
What an element's attributes can hold.
export type Attribute<G extends Definition> = AttributeNode<G> | DirectiveNode<Values<NonNullable<G['directives']>['rules']> | NonNullable<G['directives']>['other'], G> | Constructs<G, 'attributes'>;Infer
The tree a grammar's parse answers with.
export type Infer<Gr extends Grammar> = Gr extends Grammar<infer G> ? NodeOf<G['document'], G> : never;NodeType
A node type of the grammar, by name.
export type NodeType<Gr extends Grammar, T extends string> = Gr extends Grammar<infer G> ? Extract<Content<G> | Attribute<G> | Constructs<G, 'value'> | FragmentNode<G> | ScriptNode<G>, {
type: T;
}> : never;