chevrotain
Version:
Chevrotain is a high performance fault tolerant javascript parsing DSL for building recursive decent parsers
718 lines (621 loc) • 17.3 kB
text/typescript
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<T>(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<T>(
this: MixedInParser,
idx: number,
ruleToCall: (idx: number) => T,
options?: SubruleMethodOpts
): T {
return this.subruleInternal(ruleToCall, idx, options)
}
option<OUT>(
this: MixedInParser,
idx: number,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): OUT {
return this.optionInternal(actionORMethodDef, idx)
}
or(
this: MixedInParser,
idx: number,
altsOrOpts: IOrAlt<any>[] | OrMethodOpts<any>
): any {
return this.orInternal(altsOrOpts, idx)
}
many(
this: MixedInParser,
idx: number,
actionORMethodDef: GrammarAction<any> | DSLMethodOpts<any>
): void {
return this.manyInternal(idx, actionORMethodDef)
}
atLeastOne(
this: MixedInParser,
idx: number,
actionORMethodDef: GrammarAction<any> | DSLMethodOptsWithErr<any>
): 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<T>(
this: MixedInParser,
ruleToCall: (idx: number) => T,
options?: SubruleMethodOpts
): T {
return this.subruleInternal(ruleToCall, 0, options)
}
SUBRULE1<T>(
this: MixedInParser,
ruleToCall: (idx: number) => T,
options?: SubruleMethodOpts
): T {
return this.subruleInternal(ruleToCall, 1, options)
}
SUBRULE2<T>(
this: MixedInParser,
ruleToCall: (idx: number) => T,
options?: SubruleMethodOpts
): T {
return this.subruleInternal(ruleToCall, 2, options)
}
SUBRULE3<T>(
this: MixedInParser,
ruleToCall: (idx: number) => T,
options?: SubruleMethodOpts
): T {
return this.subruleInternal(ruleToCall, 3, options)
}
SUBRULE4<T>(
this: MixedInParser,
ruleToCall: (idx: number) => T,
options?: SubruleMethodOpts
): T {
return this.subruleInternal(ruleToCall, 4, options)
}
SUBRULE5<T>(
this: MixedInParser,
ruleToCall: (idx: number) => T,
options?: SubruleMethodOpts
): T {
return this.subruleInternal(ruleToCall, 5, options)
}
SUBRULE6<T>(
this: MixedInParser,
ruleToCall: (idx: number) => T,
options?: SubruleMethodOpts
): T {
return this.subruleInternal(ruleToCall, 6, options)
}
SUBRULE7<T>(
this: MixedInParser,
ruleToCall: (idx: number) => T,
options?: SubruleMethodOpts
): T {
return this.subruleInternal(ruleToCall, 7, options)
}
SUBRULE8<T>(
this: MixedInParser,
ruleToCall: (idx: number) => T,
options?: SubruleMethodOpts
): T {
return this.subruleInternal(ruleToCall, 8, options)
}
SUBRULE9<T>(
this: MixedInParser,
ruleToCall: (idx: number) => T,
options?: SubruleMethodOpts
): T {
return this.subruleInternal(ruleToCall, 9, options)
}
OPTION<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): OUT {
return this.optionInternal(actionORMethodDef, 0)
}
OPTION1<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): OUT {
return this.optionInternal(actionORMethodDef, 1)
}
OPTION2<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): OUT {
return this.optionInternal(actionORMethodDef, 2)
}
OPTION3<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): OUT {
return this.optionInternal(actionORMethodDef, 3)
}
OPTION4<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): OUT {
return this.optionInternal(actionORMethodDef, 4)
}
OPTION5<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): OUT {
return this.optionInternal(actionORMethodDef, 5)
}
OPTION6<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): OUT {
return this.optionInternal(actionORMethodDef, 6)
}
OPTION7<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): OUT {
return this.optionInternal(actionORMethodDef, 7)
}
OPTION8<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): OUT {
return this.optionInternal(actionORMethodDef, 8)
}
OPTION9<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): OUT {
return this.optionInternal(actionORMethodDef, 9)
}
OR<T>(
this: MixedInParser,
altsOrOpts: IOrAlt<any>[] | OrMethodOpts<unknown>
): T {
return this.orInternal(altsOrOpts, 0)
}
OR1<T>(
this: MixedInParser,
altsOrOpts: IOrAlt<any>[] | OrMethodOpts<unknown>
): T {
return this.orInternal(altsOrOpts, 1)
}
OR2<T>(
this: MixedInParser,
altsOrOpts: IOrAlt<any>[] | OrMethodOpts<unknown>
): T {
return this.orInternal(altsOrOpts, 2)
}
OR3<T>(
this: MixedInParser,
altsOrOpts: IOrAlt<any>[] | OrMethodOpts<unknown>
): T {
return this.orInternal(altsOrOpts, 3)
}
OR4<T>(
this: MixedInParser,
altsOrOpts: IOrAlt<any>[] | OrMethodOpts<unknown>
): T {
return this.orInternal(altsOrOpts, 4)
}
OR5<T>(
this: MixedInParser,
altsOrOpts: IOrAlt<any>[] | OrMethodOpts<unknown>
): T {
return this.orInternal(altsOrOpts, 5)
}
OR6<T>(
this: MixedInParser,
altsOrOpts: IOrAlt<any>[] | OrMethodOpts<unknown>
): T {
return this.orInternal(altsOrOpts, 6)
}
OR7<T>(
this: MixedInParser,
altsOrOpts: IOrAlt<any>[] | OrMethodOpts<unknown>
): T {
return this.orInternal(altsOrOpts, 7)
}
OR8<T>(
this: MixedInParser,
altsOrOpts: IOrAlt<any>[] | OrMethodOpts<unknown>
): T {
return this.orInternal(altsOrOpts, 8)
}
OR9<T>(
this: MixedInParser,
altsOrOpts: IOrAlt<any>[] | OrMethodOpts<unknown>
): T {
return this.orInternal(altsOrOpts, 9)
}
MANY<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): void {
this.manyInternal(0, actionORMethodDef)
}
MANY1<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): void {
this.manyInternal(1, actionORMethodDef)
}
MANY2<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): void {
this.manyInternal(2, actionORMethodDef)
}
MANY3<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): void {
this.manyInternal(3, actionORMethodDef)
}
MANY4<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): void {
this.manyInternal(4, actionORMethodDef)
}
MANY5<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): void {
this.manyInternal(5, actionORMethodDef)
}
MANY6<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): void {
this.manyInternal(6, actionORMethodDef)
}
MANY7<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): void {
this.manyInternal(7, actionORMethodDef)
}
MANY8<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): void {
this.manyInternal(8, actionORMethodDef)
}
MANY9<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOpts<OUT>
): void {
this.manyInternal(9, actionORMethodDef)
}
MANY_SEP<OUT>(this: MixedInParser, options: ManySepMethodOpts<OUT>): void {
this.manySepFirstInternal(0, options)
}
MANY_SEP1<OUT>(this: MixedInParser, options: ManySepMethodOpts<OUT>): void {
this.manySepFirstInternal(1, options)
}
MANY_SEP2<OUT>(this: MixedInParser, options: ManySepMethodOpts<OUT>): void {
this.manySepFirstInternal(2, options)
}
MANY_SEP3<OUT>(this: MixedInParser, options: ManySepMethodOpts<OUT>): void {
this.manySepFirstInternal(3, options)
}
MANY_SEP4<OUT>(this: MixedInParser, options: ManySepMethodOpts<OUT>): void {
this.manySepFirstInternal(4, options)
}
MANY_SEP5<OUT>(this: MixedInParser, options: ManySepMethodOpts<OUT>): void {
this.manySepFirstInternal(5, options)
}
MANY_SEP6<OUT>(this: MixedInParser, options: ManySepMethodOpts<OUT>): void {
this.manySepFirstInternal(6, options)
}
MANY_SEP7<OUT>(this: MixedInParser, options: ManySepMethodOpts<OUT>): void {
this.manySepFirstInternal(7, options)
}
MANY_SEP8<OUT>(this: MixedInParser, options: ManySepMethodOpts<OUT>): void {
this.manySepFirstInternal(8, options)
}
MANY_SEP9<OUT>(this: MixedInParser, options: ManySepMethodOpts<OUT>): void {
this.manySepFirstInternal(9, options)
}
AT_LEAST_ONE<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOptsWithErr<OUT>
): void {
this.atLeastOneInternal(0, actionORMethodDef)
}
AT_LEAST_ONE1<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOptsWithErr<OUT>
): void {
return this.atLeastOneInternal(1, actionORMethodDef)
}
AT_LEAST_ONE2<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOptsWithErr<OUT>
): void {
this.atLeastOneInternal(2, actionORMethodDef)
}
AT_LEAST_ONE3<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOptsWithErr<OUT>
): void {
this.atLeastOneInternal(3, actionORMethodDef)
}
AT_LEAST_ONE4<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOptsWithErr<OUT>
): void {
this.atLeastOneInternal(4, actionORMethodDef)
}
AT_LEAST_ONE5<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOptsWithErr<OUT>
): void {
this.atLeastOneInternal(5, actionORMethodDef)
}
AT_LEAST_ONE6<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOptsWithErr<OUT>
): void {
this.atLeastOneInternal(6, actionORMethodDef)
}
AT_LEAST_ONE7<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOptsWithErr<OUT>
): void {
this.atLeastOneInternal(7, actionORMethodDef)
}
AT_LEAST_ONE8<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOptsWithErr<OUT>
): void {
this.atLeastOneInternal(8, actionORMethodDef)
}
AT_LEAST_ONE9<OUT>(
this: MixedInParser,
actionORMethodDef: GrammarAction<OUT> | DSLMethodOptsWithErr<OUT>
): void {
this.atLeastOneInternal(9, actionORMethodDef)
}
AT_LEAST_ONE_SEP<OUT>(
this: MixedInParser,
options: AtLeastOneSepMethodOpts<OUT>
): void {
this.atLeastOneSepFirstInternal(0, options)
}
AT_LEAST_ONE_SEP1<OUT>(
this: MixedInParser,
options: AtLeastOneSepMethodOpts<OUT>
): void {
this.atLeastOneSepFirstInternal(1, options)
}
AT_LEAST_ONE_SEP2<OUT>(
this: MixedInParser,
options: AtLeastOneSepMethodOpts<OUT>
): void {
this.atLeastOneSepFirstInternal(2, options)
}
AT_LEAST_ONE_SEP3<OUT>(
this: MixedInParser,
options: AtLeastOneSepMethodOpts<OUT>
): void {
this.atLeastOneSepFirstInternal(3, options)
}
AT_LEAST_ONE_SEP4<OUT>(
this: MixedInParser,
options: AtLeastOneSepMethodOpts<OUT>
): void {
this.atLeastOneSepFirstInternal(4, options)
}
AT_LEAST_ONE_SEP5<OUT>(
this: MixedInParser,
options: AtLeastOneSepMethodOpts<OUT>
): void {
this.atLeastOneSepFirstInternal(5, options)
}
AT_LEAST_ONE_SEP6<OUT>(
this: MixedInParser,
options: AtLeastOneSepMethodOpts<OUT>
): void {
this.atLeastOneSepFirstInternal(6, options)
}
AT_LEAST_ONE_SEP7<OUT>(
this: MixedInParser,
options: AtLeastOneSepMethodOpts<OUT>
): void {
this.atLeastOneSepFirstInternal(7, options)
}
AT_LEAST_ONE_SEP8<OUT>(
this: MixedInParser,
options: AtLeastOneSepMethodOpts<OUT>
): void {
this.atLeastOneSepFirstInternal(8, options)
}
AT_LEAST_ONE_SEP9<OUT>(
this: MixedInParser,
options: AtLeastOneSepMethodOpts<OUT>
): void {
this.atLeastOneSepFirstInternal(9, options)
}
RULE<T>(
this: MixedInParser,
name: string,
implementation: (...implArgs: any[]) => T,
config: IRuleConfig<T> = 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<T>(
this: MixedInParser,
name: string,
impl: (...implArgs: any[]) => T,
config: IRuleConfig<T> = 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<T>(
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<string, Rule> {
return this.gastProductionsCache
}
public getSerializedGastProductions(this: MixedInParser): ISerializedGast[] {
return serializeGrammar(values(this.gastProductionsCache))
}
}