UNPKG

langium

Version:

A language engineering tool for the Language Server Protocol

234 lines 9.79 kB
/****************************************************************************** * Copyright 2021 TypeFox GmbH * This program and the accompanying materials are made available under the * terms of the MIT License, which is available in the project root. ******************************************************************************/ import type { DSLMethodOpts, ILexingError, IOrAlt, IParserErrorMessageProvider, IRecognitionException, IToken, TokenType, TokenVocabulary } from 'chevrotain'; import type { AbstractElement, Action, ParserRule } from '../languages/generated/ast.js'; import type { LangiumCoreServices } from '../services.js'; import type { AstNode } from '../syntax-tree.js'; import type { Lexer } from './lexer.js'; import type { IParserConfig } from './parser-config.js'; import { EmbeddedActionsParser } from 'chevrotain'; import type { LexingReport } from './token-builder.js'; export type ParseResult<T = AstNode> = { value: T; parserErrors: IRecognitionException[]; lexerErrors: ILexingError[]; lexerReport?: LexingReport; }; export declare const DatatypeSymbol: unique symbol; type RuleResult = (args: Args) => any; type Args = Record<string, boolean>; type RuleImpl = (args: Args) => any; /** * Base interface for all parsers. Mainly used by the `parser-builder-base.ts` to perform work on different kinds of parsers. * The main use cases are: * * AST parser: Based on a string, create an AST for the current grammar * * Completion parser: Based on a partial string, identify the current position of the input within the grammar */ export interface BaseParser { /** * Adds a new parser rule to the parser */ rule(rule: ParserRule, impl: RuleImpl): RuleResult; /** * Returns the executable rule function for the specified rule name */ getRule(name: string): RuleResult | undefined; /** * Performs alternatives parsing (the `|` operation in EBNF/Langium) */ alternatives(idx: number, choices: Array<IOrAlt<any>>): void; /** * Parses the callback as optional (the `?` operation in EBNF/Langium) */ optional(idx: number, callback: DSLMethodOpts<unknown>): void; /** * Parses the callback 0 or more times (the `*` operation in EBNF/Langium) */ many(idx: number, callback: DSLMethodOpts<unknown>): void; /** * Parses the callback 1 or more times (the `+` operation in EBNF/Langium) */ atLeastOne(idx: number, callback: DSLMethodOpts<unknown>): void; /** * Consumes a specific token type from the token input stream. * Requires a unique index within the rule for a specific token type. */ consume(idx: number, tokenType: TokenType, feature: AbstractElement): void; /** * Invokes the executable function for a given parser rule. * Requires a unique index within the rule for a specific sub rule. * Arguments can be supplied to the rule invocation for semantic predicates */ subrule(idx: number, rule: RuleResult, fragment: boolean, feature: AbstractElement, args: Args): void; /** * Executes a grammar action that modifies the currently active AST node */ action($type: string, action: Action): void; /** * Finishes construction of the current AST node. Only used by the AST parser. */ construct(): unknown; /** * Whether the parser is currently actually in use or in "recording mode". * Recording mode is activated once when the parser is analyzing itself. * During this phase, no input exists and therefore no AST should be constructed */ isRecording(): boolean; /** * Current state of the unordered groups */ get unorderedGroups(): Map<string, boolean[]>; /** * The rule stack indicates the indices of rules that are currently invoked, * in order of their invocation. */ getRuleStack(): number[]; } export declare abstract class AbstractLangiumParser implements BaseParser { protected readonly lexer: Lexer; protected readonly wrapper: ChevrotainWrapper; protected _unorderedGroups: Map<string, boolean[]>; protected allRules: Map<string, RuleResult>; protected mainRule: RuleResult; constructor(services: LangiumCoreServices); alternatives(idx: number, choices: Array<IOrAlt<any>>): void; optional(idx: number, callback: DSLMethodOpts<unknown>): void; many(idx: number, callback: DSLMethodOpts<unknown>): void; atLeastOne(idx: number, callback: DSLMethodOpts<unknown>): void; abstract rule(rule: ParserRule, impl: RuleImpl): RuleResult; abstract consume(idx: number, tokenType: TokenType, feature: AbstractElement): void; abstract subrule(idx: number, rule: RuleResult, fragment: boolean, feature: AbstractElement, args: Args): void; abstract action($type: string, action: Action): void; abstract construct(): unknown; getRule(name: string): RuleResult | undefined; isRecording(): boolean; get unorderedGroups(): Map<string, boolean[]>; getRuleStack(): number[]; finalize(): void; } export interface ParserOptions { rule?: string; } export declare class LangiumParser extends AbstractLangiumParser { private readonly linker; private readonly converter; private readonly astReflection; private readonly nodeBuilder; private lexerResult?; private stack; private assignmentMap; private get current(); constructor(services: LangiumCoreServices); rule(rule: ParserRule, impl: RuleImpl): RuleResult; private computeRuleType; parse<T extends AstNode = AstNode>(input: string, options?: ParserOptions): ParseResult<T>; private startImplementation; private extractHiddenTokens; consume(idx: number, tokenType: TokenType, feature: AbstractElement): void; /** * Most consumed parser tokens are valid. However there are two cases in which they are not valid: * * 1. They were inserted during error recovery by the parser. These tokens don't really exist and should not be further processed * 2. They contain invalid token ranges. This might include the special EOF token, or other tokens produced by invalid token builders. */ private isValidToken; subrule(idx: number, rule: RuleResult, fragment: boolean, feature: AbstractElement, args: Args): void; private performSubruleAssignment; action($type: string, action: Action): void; construct(): unknown; private getAssignment; private assign; private assignWithoutOverride; get definitionErrors(): IParserDefinitionError[]; } export interface IParserDefinitionError { message: string; type: number; ruleName?: string; } export declare abstract class AbstractParserErrorMessageProvider implements IParserErrorMessageProvider { buildMismatchTokenMessage(options: { expected: TokenType; actual: IToken; previous: IToken; ruleName: string; }): string; buildNotAllInputParsedMessage(options: { firstRedundant: IToken; ruleName: string; }): string; buildNoViableAltMessage(options: { expectedPathsPerAlt: TokenType[][][]; actual: IToken[]; previous: IToken; customUserDescription: string; ruleName: string; }): string; buildEarlyExitMessage(options: { expectedIterationPaths: TokenType[][]; actual: IToken[]; previous: IToken; customUserDescription: string; ruleName: string; }): string; } export declare class LangiumParserErrorMessageProvider extends AbstractParserErrorMessageProvider { buildMismatchTokenMessage({ expected, actual }: { expected: TokenType; actual: IToken; previous: IToken; ruleName: string; }): string; buildNotAllInputParsedMessage({ firstRedundant }: { firstRedundant: IToken; ruleName: string; }): string; } export interface CompletionParserResult { tokens: IToken[]; elementStack: AbstractElement[]; tokenIndex: number; } export declare class LangiumCompletionParser extends AbstractLangiumParser { private tokens; private elementStack; private lastElementStack; private nextTokenIndex; private stackSize; action(): void; construct(): unknown; parse(input: string): CompletionParserResult; rule(rule: ParserRule, impl: RuleImpl): RuleResult; private resetState; private startImplementation; private removeUnexpectedElements; keepStackSize(): number; resetStackSize(size: number): void; consume(idx: number, tokenType: TokenType, feature: AbstractElement): void; subrule(idx: number, rule: RuleResult, fragment: boolean, feature: AbstractElement, args: Args): void; before(element: AbstractElement): void; after(element: AbstractElement): void; get currIdx(): number; } /** * This class wraps the embedded actions parser of chevrotain and exposes protected methods. * This way, we can build the `LangiumParser` as a composition. */ declare class ChevrotainWrapper extends EmbeddedActionsParser { definitionErrors: IParserDefinitionError[]; constructor(tokens: TokenVocabulary, config: IParserConfig); get IS_RECORDING(): boolean; DEFINE_RULE(name: string, impl: RuleImpl): RuleResult; wrapSelfAnalysis(): void; wrapConsume(idx: number, tokenType: TokenType): IToken; wrapSubrule(idx: number, rule: RuleResult, args: Args): unknown; wrapOr(idx: number, choices: Array<IOrAlt<any>>): void; wrapOption(idx: number, callback: DSLMethodOpts<unknown>): void; wrapMany(idx: number, callback: DSLMethodOpts<unknown>): void; wrapAtLeastOne(idx: number, callback: DSLMethodOpts<unknown>): void; } export {}; //# sourceMappingURL=langium-parser.d.ts.map