import { AtLeastOneSepMethodOpts, ConsumeMethodOpts, DSLMethodOpts, DSLMethodOptsWithErr, GrammarAction, IOrAlt, IRuleConfig, ISerializedGast, IToken, ManySepMethodOpts, OrMethodOpts, SubruleMethodOpts, TokenType } from "../../../../api" import { contains, values } from "../../../utils/utils" import { isRecognitionException } from "../../exceptions_public" import { DEFAULT_RULE_CONFIG, ParserDefinitionErrorType } from "../parser" import { defaultGrammarValidatorErrorProvider } from "../../errors_public" import { validateRuleIsOverridden } from "../../grammar/checks" import { MixedInParser } from "./parser_traits" import { Rule, serializeGrammar } from "../../grammar/gast/gast_public" /** * 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: (idx: number) => T, options?: SubruleMethodOpts ): T { return this.subruleInternal(ruleToCall, idx, options) } option( this: MixedInParser, idx: number, actionORMethodDef: GrammarAction | DSLMethodOpts ): OUT { 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: (idx: number) => T, options?: SubruleMethodOpts ): T { return this.subruleInternal(ruleToCall, 0, options) } SUBRULE1( this: MixedInParser, ruleToCall: (idx: number) => T, options?: SubruleMethodOpts ): T { return this.subruleInternal(ruleToCall, 1, options) } SUBRULE2( this: MixedInParser, ruleToCall: (idx: number) => T, options?: SubruleMethodOpts ): T { return this.subruleInternal(ruleToCall, 2, options) } SUBRULE3( this: MixedInParser, ruleToCall: (idx: number) => T, options?: SubruleMethodOpts ): T { return this.subruleInternal(ruleToCall, 3, options) } SUBRULE4( this: MixedInParser, ruleToCall: (idx: number) => T, options?: SubruleMethodOpts ): T { return this.subruleInternal(ruleToCall, 4, options) } SUBRULE5( this: MixedInParser, ruleToCall: (idx: number) => T, options?: SubruleMethodOpts ): T { return this.subruleInternal(ruleToCall, 5, options) } SUBRULE6( this: MixedInParser, ruleToCall: (idx: number) => T, options?: SubruleMethodOpts ): T { return this.subruleInternal(ruleToCall, 6, options) } SUBRULE7( this: MixedInParser, ruleToCall: (idx: number) => T, options?: SubruleMethodOpts ): T { return this.subruleInternal(ruleToCall, 7, options) } SUBRULE8( this: MixedInParser, ruleToCall: (idx: number) => T, options?: SubruleMethodOpts ): T { return this.subruleInternal(ruleToCall, 8, options) } SUBRULE9( this: MixedInParser, ruleToCall: (idx: number) => T, options?: SubruleMethodOpts ): T { return this.subruleInternal(ruleToCall, 9, options) } OPTION( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts ): OUT { return this.optionInternal(actionORMethodDef, 0) } OPTION1( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts ): OUT { return this.optionInternal(actionORMethodDef, 1) } OPTION2( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts ): OUT { return this.optionInternal(actionORMethodDef, 2) } OPTION3( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts ): OUT { return this.optionInternal(actionORMethodDef, 3) } OPTION4( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts ): OUT { return this.optionInternal(actionORMethodDef, 4) } OPTION5( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts ): OUT { return this.optionInternal(actionORMethodDef, 5) } OPTION6( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts ): OUT { return this.optionInternal(actionORMethodDef, 6) } OPTION7( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts ): OUT { return this.optionInternal(actionORMethodDef, 7) } OPTION8( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts ): OUT { return this.optionInternal(actionORMethodDef, 8) } OPTION9( this: MixedInParser, actionORMethodDef: GrammarAction | DSLMethodOpts ): OUT { 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 (contains(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) let ruleImplementation = this.defineRule(name, implementation, config) this[name] = ruleImplementation return ruleImplementation } OVERRIDE_RULE( this: MixedInParser, name: string, impl: (...implArgs: any[]) => T, config: IRuleConfig = DEFAULT_RULE_CONFIG ): (idxInCallingRule?: number, ...args: any[]) => T { let ruleErrors = [] ruleErrors = ruleErrors.concat( validateRuleIsOverridden(name, this.definedRulesNames, this.className) ) this.definitionErrors.push.apply(this.definitionErrors, ruleErrors) // mutability for the win let ruleImplementation = this.defineRule(name, impl, config) this[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)) } }