import { CommandNode } from "../../../../Tokenization/Nodes/CommandNode" ; import { IBudgieNode } from "../../../../Tokenization/Nodes/IBudgieNode" ; import { TextNode } from "../../../../Tokenization/Nodes/TextNode" ; import { KeywordParameter } from "./KeywordParameter" ; import { IParameter } from "./Parameter" ; /**
 * Some number of repeating parameters.
 */ export class RepeatingParameters implements IParameter { /**
     * A plain-text description of this parameter.
     */ public description : string ; /**
     * Parameters contained inside.
     */ public parameters : IParameter [ ] ; param descriptor param parameters public constructor ( description , parameters ) { this . description = description ; this . parameters = parameters ; } returns public isRequired ( ) { return false ; } param node param inputPosition param requirements param requirementPosition returns public validate ( node , inputPosition , requirements , requirementPosition ) { const endIndex = this . getEndingIndex ( node , inputPosition , requirements , requirementPosition ) ; const repeatedCount = endIndex - inputPosition ; if ( repeatedCount % this . parameters . length !== 0 ) { throw new Error ( `${ node . command }: Expected a multiple of ${ this . parameters . length } repeating parameters but got ${ repeatedCount }.` ) ; } return endIndex ; } param node param inputPosition param requirements param requirementPosition returns private doesNextCommandMatchKeywordParameter ( node , inputPosition , requirements , requirementPosition ) { const nextRequirement = requirements [ requirementPosition + 1 ] ; if ( nextRequirement instanceof KeywordParameter ) { for ( let i = inputPosition ; i < node . args . length ; i += 1 ) { const arg = node . args [ i ] ; if ( arg instanceof TextNode && nextRequirement . literals . has ( arg . text ) ) { return i ; } } } return - 1 ; } param node param inputPosition param requirements param requirementPosition returns private getEndingIndex ( node , inputPosition , requirements , requirementPosition ) { if ( requirementPosition === requirements . length - 1 ) { return node . args . length ; } const keywordMatchIndex = this . doesNextCommandMatchKeywordParameter ( node , inputPosition , requirements , requirementPosition ) ; if ( keywordMatchIndex !== - 1 ) { return keywordMatchIndex ; } return node . args . length - this . getRemainingRequiredParameters ( requirements , requirementPosition ) ; } param requirements param requirementPosition returns private getRemainingRequiredParameters ( requirements , requirementPosition ) { let remainingRequiredParameters = 0 ; for ( let i = requirementPosition ; i < requirements . length ; i += 1 ) { const requirement = requirements [ i ] ; if ( requirement . isRequired ( ) ) { remainingRequiredParameters += 1 ; } } return remainingRequiredParameters ; } }