UNPKG

antlr-ng

Version:

Next generation ANTLR Tool

161 lines (160 loc) 6.08 kB
import { ATN, ATNState } from "antlr4ng"; import type { Constructor } from "../misc/Utils.js"; import { ActionAST } from "../tool/ast/ActionAST.js"; import { BlockAST } from "../tool/ast/BlockAST.js"; import { GrammarAST } from "../tool/ast/GrammarAST.js"; import { PredAST } from "../tool/ast/PredAST.js"; import { TerminalAST } from "../tool/ast/TerminalAST.js"; import { Rule } from "../tool/Rule.js"; import type { IGrammar, IParserATNFactory } from "../types.js"; import { IATNFactory, type IStatePair } from "./IATNFactory.js"; /** * ATN construction routines triggered by ATNBuilder.g. * * No side-effects. It builds an {@link ATN} object and returns it. */ export declare class ParserATNFactory implements IParserATNFactory, IATNFactory { currentRule?: Rule; currentOuterAlt: number; protected readonly g: IGrammar; protected readonly atn: ATN; private readonly preventEpsilonClosureBlocks; private readonly preventEpsilonOptionalBlocks; constructor(g: IGrammar); /** * `(BLOCK (ALT .))` or `(BLOCK (ALT 'a') (ALT .))`. */ private static blockHasWildcardAlt; createATN(): ATN; setCurrentRuleName(name: string): void; /** From label `A` build graph `o-A->o`. */ tokenRef(node: TerminalAST): IStatePair | null; /** * From set build single edge graph `o->o-set->o`. To conform to what an alt block looks like, must have extra * state on left. This also handles `~A`, converted to `~{A}` set. */ set(associatedAST: GrammarAST, terminals: GrammarAST[], invert: boolean): IStatePair; /** Not valid for non-lexers. */ range(a: GrammarAST, b: GrammarAST): IStatePair | null; /** For a non-lexer, just build a simple token reference atom. */ stringLiteral(stringLiteralAST: TerminalAST): IStatePair | null; /** `[Aa]` char sets not allowed in parser */ charSetLiteral(charSetAST: GrammarAST): IStatePair | null; /** * For reference to rule `r`, build * * ``` * o->(r) o * ``` * * where `(r)` is the start of rule `r` and the trailing `o` is not linked to from rule ref state directly (uses * {@see RuleTransition.followState}). */ ruleRef(node: GrammarAST): IStatePair | null; /** From an empty alternative build `o-e->o`. */ epsilon(node: GrammarAST): IStatePair; epsilon(a: ATNState | null, b: ATNState, prepend?: boolean): void; /** * Build what amounts to an epsilon transition with a semantic predicate action. The `pred` is a pointer * into the AST of the {@link ANTLRParser#SEMPRED} token. */ sempred(pred: PredAST): IStatePair; /** * Build what amounts to an epsilon transition with an action. * The action goes into ATN though it is ignored during prediction * if {@see ActionTransition.actionIndex actionIndex} `< 0`. */ action(astOrString: ActionAST | string): IStatePair; /** * From `A|B|..|Z` alternative block build * * ``` * o->o-A->o->o (last ATNState is BlockEndState pointed to by all alts) * | ^ * |->o-B->o--| * | | * ... | * | | * |->o-Z->o--| * ``` * * So start node points at every alternative with epsilon transition and * every alt right side points at a block end ATNState. * * Special case: only one alternative: don't make a block with alt * begin/end. * * Special case: if just a list of tokens/chars/sets, then collapse to a * single edged o-set->o graph. * * TODO: Set alt number (1..n) in the states? */ block(blkAST: BlockAST, ebnfRoot: GrammarAST | null, alts: IStatePair[]): IStatePair | undefined; alt(els: IStatePair[]): IStatePair; /** Build an atom with all possible values in its label. */ wildcard(node: GrammarAST): IStatePair; label(t: IStatePair): IStatePair; listLabel(t: IStatePair): IStatePair; lexerAltCommands(alt: IStatePair, commands: IStatePair): IStatePair; lexerCallCommand(_id: GrammarAST, arg: GrammarAST): IStatePair; lexerCommand(id: GrammarAST): IStatePair; /** start-> rule - block -> end */ protected rule(ruleAST: GrammarAST, name: string, blk: IStatePair): IStatePair; protected _ruleRef(node: GrammarAST): IStatePair | null; protected newState<T extends ATNState>(nodeType: Constructor<T>): T; protected checkEpsilonClosure(): void; protected doCreateATN(rules: Rule[]): void; private addFollowLink; private elemList; /** * From `(A)?` build either: * * ``` * o--A->o * | ^ * o---->| * ``` * * or, if `A` is a block, just add an empty alt to the end of the block. */ private optional; /** * From `(blk)+` build * * ``` * |---------| * v | * [o-blk-o]->o->o * ``` * * We add a decision for loop back node to the existing one at `blk` start. */ private plus; /** * From `(blk)*` build `( blk+ )?` with *two* decisions, one for entry and one for choosing alts of `blk`. * * ``` * |-------------| * v | * o--[o-blk-o]->o o * | ^ * -----------------| * ``` * * Note that the optional bypass must jump outside the loop as `(A|B)*` is not the same thing as `(A|B|)+`. */ private star; private addRuleFollowLinks; /** * Add an EOF transition to any rule end ATNState that points to nothing (i.e., for all those rules not invoked * by another rule). These are start symbols then. * * Return the number of grammar entry points; i.e., how many rules are not invoked by another rule (they can * only be invoked from outside). These are the start rules. */ private addEOFTransitionToStartRules; private expectNonGreedy; private makeBlock; /** Define all the rule begin/end ATNStates to solve forward reference issues. */ private createRuleStartAndStopATNStates; }