import { AtLeastOneSepMethodOpts, ConsumeMethodOpts, DSLMethodOpts, DSLMethodOptsWithErr, GrammarAction, IOrAlt, IRuleConfig, ISerializedGast, IToken, ManySepMethodOpts, OrMethodOpts, SubruleMethodOpts, TokenType, } from "@chevrotain/types"; import { includes, values } from "lodash-es"; import { isRecognitionException } from "../../exceptions_public.js"; import { DEFAULT_RULE_CONFIG, ParserDefinitionErrorType } from "../parser.js"; import { defaultGrammarValidatorErrorProvider } from "../../errors_public.js"; import { validateRuleIsOverridden } from "../../grammar/checks.js"; import { MixedInParser } from "./parser_traits.js"; import { Rule, serializeGrammar } from "@chevrotain/gast"; import { IParserDefinitionError } from "../../grammar/types.js"; import { ParserMethodInternal } from "../types.js"; /** * This trait is responsible for implementing the public API * for defining Chevrotain parsers, i.e: * - CONSUME * - RULE * - OPTION * - ... */ export class RecognizerApi { ACTION(this: MixedInParser, impl: () => T): T { return impl.call(this); } consume( this: MixedInParser, idx: number, tokType: TokenType, options?: ConsumeMethodOpts, ): IToken { return this.consumeInternal(tokType, idx, options); } subrule( this: MixedInParser, idx: number, ruleToCall: ParserMethodInternal, options?: SubruleMethodOpts, ): R { return this.subruleInternal(ruleToCall, idx, options); } option( this: MixedInParser, idx: number, actionORMethodDef: GrammarAction | DSLMethodOpts, ): OUT | undefined { return this.optionInternal(actionORMethodDef, idx); } or( this: MixedInParser, idx: number, altsOrOpts: IOrAlt[] | OrMethodOpts, ): any { return this.orInternal(altsOrOpts, idx); } many( this: MixedInParser, idx: number, actionORMethodDef: GrammarAction | DSLMethodOpts, ): void { return this.manyInternal(idx, actionORMethodDef); } atLeastOne( this: MixedInParser, idx: number, actionORMethodDef: GrammarAction | DSLMethodOptsWithErr, ): void { return this.atLeastOneInternal(idx, actionORMethodDef); } CONSUME( this: MixedInParser, tokType: TokenType, options?: ConsumeMethodOpts, ): IToken { return this.consumeInternal(tokType, 0, options); } CONSUME1( this: MixedInParser, tokType: TokenType, options?: ConsumeMethodOpts, ): IToken { return this.consumeInternal(tokType, 1, options); } CONSUME2( this: MixedInParser, tokType: TokenType, options?: ConsumeMethodOpts, ): IToken { return this.consumeInternal(tokType, 2, options); } CONSUME3( this: MixedInParser, tokType: TokenType, options?: ConsumeMethodOpts, ): IToken { return this.consumeInternal(tokType, 3, options); } CONSUME4( this: MixedInParser, tokType: TokenType, options?: ConsumeMethodOpts, ): IToken { return this.consumeInternal(tokType, 4, options); } CONSUME5( this: MixedInParser, tokType: TokenType, options?: ConsumeMethodOpts, ): IToken { return this.consumeInternal(tokType, 5, options); } CONSUME6( this: MixedInParser, tokType: TokenType, options?: ConsumeMethodOpts, ): IToken { return this.consumeInternal(tokType, 6, options); } CONSUME7( this: MixedInParser, tokType: TokenType, options?: ConsumeMethodOpts, ): IToken { return this.consumeInternal(tokType, 7, options); } CONSUME8( this: MixedInParser, tokType: TokenType, options?: ConsumeMethodOpts, ): IToken { return this.consumeInternal(tokType, 8, options); } CONSUME9( this: MixedInParser, tokType: TokenType, options?: ConsumeMethodOpts, ): IToken { return this.consumeInternal(tokType, 9, options); } SUBRULE( this: MixedInParser, ruleToCall: ParserMethodInternal, options?: SubruleMethodOpts, ): R { return this.subruleInternal(ruleToCall, 0, options); } SUBRULE1( this: MixedInParser, ruleToCall: ParserMethodInternal, options?: SubruleMethodOpts, ): R { return this.subruleInternal(ruleToCall, 1, options); } SUBRULE2( this: MixedInParser, ruleToCall: ParserMethodInternal, options?: SubruleMethodOpts, ): R { return this.subruleInternal(ruleToCall, 2, options); } SUBRULE3( this: MixedInParser, ruleToCall: ParserMethodInternal, options?: SubruleMethodOpts, ): R { return this.subruleInternal(ruleToCall, 3, options); } SUBRULE4( this: MixedInParser, ruleToCall: ParserMethodInternal, options?: SubruleMethodOpts, ): R { return this.subruleInternal(ruleToCall, 4, options); } SUBRULE5( this: MixedInParser, ruleToCall: ParserMethodInternal, options?: SubruleMethodOpts, ): R { return this.subruleInternal(ruleToCall, 5, options); } SUBRULE6( this: MixedInParser, ruleToCall: ParserMethodInternal, options?: SubruleMethodOpts, ): R { return this.subruleInternal(ruleToCall, 6, options); } SUBRULE7( this: MixedInParser, ruleToCall: ParserMethodInternal, options?: SubruleMethodOpts, ): R { return this.subruleInternal(ruleToCall, 7, options); } SUBRULE8( this: MixedInParser, ruleToCall: ParserMethodInternal, options?: SubruleMethodOpts, ): R { return this.subruleInternal(ruleToCall, 8, options); } SUBRULE9( this: MixedInParser, ruleToCall: ParserMethodInternal, options?: SubruleMethodOpts, ): R { return this.subruleInternal(ruleToCall, 9, options); } OPTION( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): OUT | undefined { return this.optionInternal(actionORMethodDef, 0); } OPTION1( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): OUT | undefined { return this.optionInternal(actionORMethodDef, 1); } OPTION2( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): OUT | undefined { return this.optionInternal(actionORMethodDef, 2); } OPTION3( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): OUT | undefined { return this.optionInternal(actionORMethodDef, 3); } OPTION4( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): OUT | undefined { return this.optionInternal(actionORMethodDef, 4); } OPTION5( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): OUT | undefined { return this.optionInternal(actionORMethodDef, 5); } OPTION6( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): OUT | undefined { return this.optionInternal(actionORMethodDef, 6); } OPTION7( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): OUT | undefined { return this.optionInternal(actionORMethodDef, 7); } OPTION8( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): OUT | undefined { return this.optionInternal(actionORMethodDef, 8); } OPTION9( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): OUT | undefined { return this.optionInternal(actionORMethodDef, 9); } OR( this: MixedInParser, altsOrOpts: IOrAlt[] | OrMethodOpts, ): T { return this.orInternal(altsOrOpts, 0); } OR1( this: MixedInParser, altsOrOpts: IOrAlt[] | OrMethodOpts, ): T { return this.orInternal(altsOrOpts, 1); } OR2( this: MixedInParser, altsOrOpts: IOrAlt[] | OrMethodOpts, ): T { return this.orInternal(altsOrOpts, 2); } OR3( this: MixedInParser, altsOrOpts: IOrAlt[] | OrMethodOpts, ): T { return this.orInternal(altsOrOpts, 3); } OR4( this: MixedInParser, altsOrOpts: IOrAlt[] | OrMethodOpts, ): T { return this.orInternal(altsOrOpts, 4); } OR5( this: MixedInParser, altsOrOpts: IOrAlt[] | OrMethodOpts, ): T { return this.orInternal(altsOrOpts, 5); } OR6( this: MixedInParser, altsOrOpts: IOrAlt[] | OrMethodOpts, ): T { return this.orInternal(altsOrOpts, 6); } OR7( this: MixedInParser, altsOrOpts: IOrAlt[] | OrMethodOpts, ): T { return this.orInternal(altsOrOpts, 7); } OR8( this: MixedInParser, altsOrOpts: IOrAlt[] | OrMethodOpts, ): T { return this.orInternal(altsOrOpts, 8); } OR9( this: MixedInParser, altsOrOpts: IOrAlt[] | OrMethodOpts, ): T { return this.orInternal(altsOrOpts, 9); } MANY( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): void { this.manyInternal(0, actionORMethodDef); } MANY1( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): void { this.manyInternal(1, actionORMethodDef); } MANY2( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): void { this.manyInternal(2, actionORMethodDef); } MANY3( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): void { this.manyInternal(3, actionORMethodDef); } MANY4( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): void { this.manyInternal(4, actionORMethodDef); } MANY5( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): void { this.manyInternal(5, actionORMethodDef); } MANY6( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): void { this.manyInternal(6, actionORMethodDef); } MANY7( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): void { this.manyInternal(7, actionORMethodDef); } MANY8( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): void { this.manyInternal(8, actionORMethodDef); } MANY9( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts, ): void { this.manyInternal(9, actionORMethodDef); } MANY_SEP(this: MixedInParser, options: ManySepMethodOpts): void { this.manySepFirstInternal(0, options); } MANY_SEP1(this: MixedInParser, options: ManySepMethodOpts): void { this.manySepFirstInternal(1, options); } MANY_SEP2(this: MixedInParser, options: ManySepMethodOpts): void { this.manySepFirstInternal(2, options); } MANY_SEP3(this: MixedInParser, options: ManySepMethodOpts): void { this.manySepFirstInternal(3, options); } MANY_SEP4(this: MixedInParser, options: ManySepMethodOpts): void { this.manySepFirstInternal(4, options); } MANY_SEP5(this: MixedInParser, options: ManySepMethodOpts): void { this.manySepFirstInternal(5, options); } MANY_SEP6(this: MixedInParser, options: ManySepMethodOpts): void { this.manySepFirstInternal(6, options); } MANY_SEP7(this: MixedInParser, options: ManySepMethodOpts): void { this.manySepFirstInternal(7, options); } MANY_SEP8(this: MixedInParser, options: ManySepMethodOpts): void { this.manySepFirstInternal(8, options); } MANY_SEP9(this: MixedInParser, options: ManySepMethodOpts): void { this.manySepFirstInternal(9, options); } AT_LEAST_ONE( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOptsWithErr, ): void { this.atLeastOneInternal(0, actionORMethodDef); } AT_LEAST_ONE1( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOptsWithErr, ): void { return this.atLeastOneInternal(1, actionORMethodDef); } AT_LEAST_ONE2( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOptsWithErr, ): void { this.atLeastOneInternal(2, actionORMethodDef); } AT_LEAST_ONE3( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOptsWithErr, ): void { this.atLeastOneInternal(3, actionORMethodDef); } AT_LEAST_ONE4( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOptsWithErr, ): void { this.atLeastOneInternal(4, actionORMethodDef); } AT_LEAST_ONE5( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOptsWithErr, ): void { this.atLeastOneInternal(5, actionORMethodDef); } AT_LEAST_ONE6( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOptsWithErr, ): void { this.atLeastOneInternal(6, actionORMethodDef); } AT_LEAST_ONE7( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOptsWithErr, ): void { this.atLeastOneInternal(7, actionORMethodDef); } AT_LEAST_ONE8( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOptsWithErr, ): void { this.atLeastOneInternal(8, actionORMethodDef); } AT_LEAST_ONE9( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOptsWithErr, ): void { this.atLeastOneInternal(9, actionORMethodDef); } AT_LEAST_ONE_SEP( this: MixedInParser, options: AtLeastOneSepMethodOpts, ): void { this.atLeastOneSepFirstInternal(0, options); } AT_LEAST_ONE_SEP1( this: MixedInParser, options: AtLeastOneSepMethodOpts, ): void { this.atLeastOneSepFirstInternal(1, options); } AT_LEAST_ONE_SEP2( this: MixedInParser, options: AtLeastOneSepMethodOpts, ): void { this.atLeastOneSepFirstInternal(2, options); } AT_LEAST_ONE_SEP3( this: MixedInParser, options: AtLeastOneSepMethodOpts, ): void { this.atLeastOneSepFirstInternal(3, options); } AT_LEAST_ONE_SEP4( this: MixedInParser, options: AtLeastOneSepMethodOpts, ): void { this.atLeastOneSepFirstInternal(4, options); } AT_LEAST_ONE_SEP5( this: MixedInParser, options: AtLeastOneSepMethodOpts, ): void { this.atLeastOneSepFirstInternal(5, options); } AT_LEAST_ONE_SEP6( this: MixedInParser, options: AtLeastOneSepMethodOpts, ): void { this.atLeastOneSepFirstInternal(6, options); } AT_LEAST_ONE_SEP7( this: MixedInParser, options: AtLeastOneSepMethodOpts, ): void { this.atLeastOneSepFirstInternal(7, options); } AT_LEAST_ONE_SEP8( this: MixedInParser, options: AtLeastOneSepMethodOpts, ): void { this.atLeastOneSepFirstInternal(8, options); } AT_LEAST_ONE_SEP9( this: MixedInParser, options: AtLeastOneSepMethodOpts, ): void { this.atLeastOneSepFirstInternal(9, options); } RULE( this: MixedInParser, name: string, implementation: (...implArgs: any[]) => T, config: IRuleConfig = DEFAULT_RULE_CONFIG, ): (idxInCallingRule?: number, ...args: any[]) => T | any { if (includes(this.definedRulesNames, name)) { const errMsg = defaultGrammarValidatorErrorProvider.buildDuplicateRuleNameError({ topLevelRule: name, grammarName: this.className, }); const error = { message: errMsg, type: ParserDefinitionErrorType.DUPLICATE_RULE_NAME, ruleName: name, }; this.definitionErrors.push(error); } this.definedRulesNames.push(name); const ruleImplementation = this.defineRule(name, implementation, config); (this as any)[name] = ruleImplementation; return ruleImplementation; } OVERRIDE_RULE( this: MixedInParser, name: string, impl: (...implArgs: any[]) => T, config: IRuleConfig = DEFAULT_RULE_CONFIG, ): (idxInCallingRule?: number, ...args: any[]) => T { const ruleErrors: IParserDefinitionError[] = validateRuleIsOverridden( name, this.definedRulesNames, this.className, ); this.definitionErrors = this.definitionErrors.concat(ruleErrors); const ruleImplementation = this.defineRule(name, impl, config); (this as any)[name] = ruleImplementation; return ruleImplementation; } BACKTRACK( this: MixedInParser, grammarRule: (...args: any[]) => T, args?: any[], ): () => boolean { return function () { // save org state this.isBackTrackingStack.push(1); const orgState = this.saveRecogState(); try { grammarRule.apply(this, args); // if no exception was thrown we have succeed parsing the rule. return true; } catch (e) { if (isRecognitionException(e)) { return false; } else { throw e; } } finally { this.reloadRecogState(orgState); this.isBackTrackingStack.pop(); } }; } // GAST export APIs public getGAstProductions(this: MixedInParser): Record { return this.gastProductionsCache; } public getSerializedGastProductions(this: MixedInParser): ISerializedGast[] { return serializeGrammar(values(this.gastProductionsCache)); } }