import grammar from "./grammar.ohm-bundle"; import { Affinity, ElementalType, FailReason, MarkdownContext, MarkdownOutput, MeteredResource, NumberSign, Operands, OperandsFrom, ParseContext, Resource, Source, Target, UnmeteredResource, } from "../model/Messages"; import {IterationNode, Node, NonterminalNode, TerminalNode} from "ohm-js"; import {CharacterPrivacy, CharacterSide} from "../model/Character"; import {ClockMode, TimerDirection} from "../model/GameState"; export const parser = grammar.createSemantics() export interface ParserNode extends Node { readonly element: ElementalType|null readonly affinity: Affinity readonly sign: NumberSign readonly numberValue: number readonly identifier: string readonly resource: Resource|null readonly operands: Operands readonly blockTargets: Operands readonly blockSources: Operands readonly silenced: boolean readonly currentValue: number readonly maxValue: number readonly failReason: FailReason readonly side: CharacterSide // TODO: Implement all of the things listed below. readonly textValue: string // TODO: create rules for these to describe clocks/timers/items/statuses/characters and implement them readonly nameText: string readonly descriptionText: string // TODO: use for portraits, status icons, backdrops, BGM, and SFX readonly url: string readonly privacy: CharacterPrivacy readonly clockMode: ClockMode readonly timerDirection: TimerDirection readonly timerDurationMs: number // TODO: add backdrop and music change and sfx commands // TODO: make sure that FP and UP spent gets saved in the appropriate counters evaluate(ctx: ParseContext): ParseContext renderMarkdown(ctx: MarkdownContext): MarkdownOutput } parser.addAttribute("element", { fireElement(): ElementalType.Fire { return ElementalType.Fire }, waterElement(): ElementalType.Water { return ElementalType.Water }, lightningElement(): ElementalType.Lightning { return ElementalType.Lightning }, iceElement(): ElementalType.Ice { return ElementalType.Ice }, earthElement(): ElementalType.Earth { return ElementalType.Earth }, windElement(): ElementalType.Wind { return ElementalType.Wind }, lightElement(): ElementalType.Light { return ElementalType.Light }, darkElement(): ElementalType.Dark { return ElementalType.Dark }, physicalElement(): ElementalType.Physical { return ElementalType.Physical }, nonElement(): ElementalType.Nonelemental { return ElementalType.Nonelemental }, healingElement(): ElementalType.Healing { return ElementalType.Healing }, elementalType(elementNode: NonterminalNode): ElementalType { const element = (elementNode as ParserNode).element if (element === null) { throw Error("Unexpectedly null element when an element was specified") } return element }, DeltaOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): ElementalType | null { return (elementalType as ParserNode).element }, DeltaOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, resource: IterationNode, elementalType: IterationNode): ElementalType | null { return (elementalType as ParserNode).element }, DeltaOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): ElementalType | null { return (elementalType as ParserNode).element }, _iter(...children: readonly Node[]): ElementalType|null { if (this.isOptional() && children.length === 0) { return null } else if (this.isOptional() && children.length === 1) { return (children[0] as ParserNode).element } else { throw Error(`No idea what to say ${this.ctorName} iteration node's element is when there are multiple children`) } }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's element is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's element is`) } }) parser.addAttribute("affinity", { absorbAffinity(): Affinity.Absorbs { return Affinity.Absorbs }, immuneAffinity(): Affinity.Immune { return Affinity.Immune }, resistAffinity(): Affinity.Resistant { return Affinity.Resistant }, vulnerableAffinity(): Affinity.Vulnerable { return Affinity.Vulnerable }, normalAffinity(): Affinity.Normal { return Affinity.Normal }, affinity(affinityNode: NonterminalNode): Affinity { return (affinityNode as ParserNode).affinity }, DeltaOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): Affinity { return (affinity as ParserNode).affinity }, DeltaOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, resource: IterationNode, elementalType: IterationNode): Affinity { return (affinity as ParserNode).affinity }, DeltaOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): Affinity { return (affinity as ParserNode).affinity }, _iter(...children: readonly Node[]): Affinity { if (this.isOptional() && children.length === 0) { return Affinity.Normal } else if (this.isOptional() && children.length === 1) { return (children[0] as ParserNode).affinity } else { throw Error(`No idea what to say ${this.ctorName} iteration node's affinity is when there are multiple children`) } }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's affinity is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's affinity is`) } }) parser.addAttribute("sign", { deltaOperator(oper: NonterminalNode): NumberSign { return (oper as ParserNode).sign }, plus(): NumberSign.Positive { return NumberSign.Positive }, minus(): NumberSign.Negative { return NumberSign.Negative }, StatusOrItemDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, deltaOperator: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): NumberSign { return (deltaOperator as ParserNode).sign }, StatusOrItemCounterDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, identifier: NonterminalNode, delta: NonterminalNode): NumberSign { return (delta as ParserNode).sign }, _iter(): never { throw Error(`No idea what to say ${this.ctorName} iteration node's number sign is`) }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's number sign is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's number sign is`) } }) parser.addAttribute("numberValue", { integer(digits: IterationNode): number { return parseInt(digits.sourceString) }, Delta(sign: NonterminalNode, integer: NonterminalNode): number { const number = (integer as ParserNode).numberValue switch ((sign as ParserNode).sign) { case NumberSign.Negative: return -number case NumberSign.Positive: return number } }, DeltaOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): number { return (delta as ParserNode).numberValue }, DeltaOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, resource: IterationNode, elementalType: IterationNode): number { return (delta as ParserNode).numberValue }, DeltaOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): number { return (delta as ParserNode).numberValue }, MaxValue(separator: NonterminalNode, integer: NonterminalNode): number { return (integer as ParserNode).numberValue; }, SetValueOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, integer: NonterminalNode): number { return (integer as ParserNode).numberValue; }, SetValueOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, integer: NonterminalNode, resource: NonterminalNode): number { return (integer as ParserNode).numberValue; }, SetValueOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, integer: NonterminalNode): number { return (integer as ParserNode).numberValue; }, SetMaxOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, maxvalue: NonterminalNode): number { return (maxvalue as ParserNode).numberValue; }, SetMaxOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, maxvalue: NonterminalNode, resource: NonterminalNode): number { return (maxvalue as ParserNode).numberValue; }, SetMaxOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, maxvalue: NonterminalNode): number { return (maxvalue as ParserNode).numberValue; }, StatusOrItemCounterUnwrapped(x: IterationNode, integer: NonterminalNode): number { return (integer as ParserNode).numberValue }, StatusOrItemCounterWrapped(lParen: TerminalNode, counter: NonterminalNode, rParen: TerminalNode): number { return (counter as ParserNode).numberValue }, StatusOrItemDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, deltaOperator: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): number { return (counter as ParserNode).numberValue }, StatusOrItemCounterDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, identifier: NonterminalNode, delta: NonterminalNode): number { return (delta as ParserNode).numberValue }, StatusOrItemCounterSetOperation(operands: NonterminalNode, colon: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): number { return (counter as ParserNode).numberValue }, _iter(): never { throw Error(`No idea what to say ${this.ctorName} iteration node's number value is`) }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's number value is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's number value is`) } }) parser.addAttribute("identifier", { identifier(): string { return this.sourceString }, StatusOrItemDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, deltaOperator: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): string { return (identifier as ParserNode).identifier }, StatusOrItemCounterDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, identifier: NonterminalNode, delta: NonterminalNode): string { return (identifier as ParserNode).identifier }, StatusOrItemCounterSetOperation(operands: NonterminalNode, colon: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): string { return (identifier as ParserNode).identifier }, _iter(): never { throw Error(`No idea what to say ${this.ctorName} iteration node's identifier value is`) }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's identifier value is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's identifier value is`) } }) parser.addAttribute("resource", { BpResource(): MeteredResource.Blood { return MeteredResource.Blood }, FabulaResource(): UnmeteredResource.Fabula { return UnmeteredResource.Fabula; }, HpResource(): MeteredResource.Health { return MeteredResource.Health; }, IpResource(): MeteredResource.Items { return MeteredResource.Items; }, LevelResource(): UnmeteredResource.Level { return UnmeteredResource.Level; }, MaterialsResource(): UnmeteredResource.Materials { return UnmeteredResource.Materials; }, MeteredResource(res: NonterminalNode): MeteredResource { const r = (res as ParserNode).resource; switch (r) { case MeteredResource.Health: case MeteredResource.Magic: case MeteredResource.Items: case MeteredResource.Experience: case MeteredResource.Zero: case MeteredResource.Turns: case MeteredResource.Segments: case MeteredResource.Blood: return r default: throw Error("unexpected unmetered resource in metered resource node") } }, MoneyResource(): UnmeteredResource.Zenit { return UnmeteredResource.Zenit; }, MpResource(): MeteredResource.Magic { return MeteredResource.Magic; }, Resource(res: NonterminalNode): Resource { const r = (res as ParserNode).resource; if (r === null) { throw Error("unexpected null resource in resource node") } return r }, SpResource(type: NonterminalNode): UnmeteredResource.Special|UnmeteredResource.Fabula|UnmeteredResource.Ultima { const r = (type as ParserNode).resource; switch (r) { case UnmeteredResource.Special: case UnmeteredResource.Fabula: case UnmeteredResource.Ultima: return r default: throw Error("unexpected non-SP resources in an SP node") } }, SpecialResource(): UnmeteredResource.Special { return UnmeteredResource.Special; }, TpResource(): MeteredResource.Turns { return MeteredResource.Turns; }, UltimaResource(): Resource { return UnmeteredResource.Ultima; }, UnmeteredResource(res: NonterminalNode): UnmeteredResource { const r = (res as ParserNode).resource; switch (r) { case UnmeteredResource.Fabula: case UnmeteredResource.Ultima: case UnmeteredResource.Zenit: case UnmeteredResource.Materials: case UnmeteredResource.Special: case UnmeteredResource.Level: return r default: throw Error("unexpected metered resource in unmetered resource node") } }, XpResource(): MeteredResource.Experience { return MeteredResource.Experience; }, ZpResource(): MeteredResource.Zero { return MeteredResource.Zero; }, DeltaOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): Resource { const r = (resource as ParserNode).resource if (r === null) { throw Error("unexpected null resource in required resource node") } return r }, DeltaOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, resource: IterationNode, elementalType: IterationNode): Resource|null { return (resource as ParserNode).resource }, DeltaOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, elementalType: IterationNode): Resource { const r = (resource as ParserNode).resource if (r === null) { throw Error("unexpected null resource in required resource node") } return r }, SetValueOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, integer: NonterminalNode): Resource { const r = (resource as ParserNode).resource if (r === null) { throw Error("unexpected null resource in required resource node") } return r }, SetValueOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, integer: NonterminalNode, resource: NonterminalNode): Resource { const r = (resource as ParserNode).resource if (r === null) { throw Error("unexpected null resource in required resource node") } return r }, SetValueOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, integer: NonterminalNode): Resource { const r = (resource as ParserNode).resource if (r === null) { throw Error("unexpected null resource in required resource node") } return r }, SetMaxOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, maxvalue: NonterminalNode): MeteredResource { const r = (resource as ParserNode).resource; switch (r) { case MeteredResource.Health: case MeteredResource.Magic: case MeteredResource.Items: case MeteredResource.Experience: case MeteredResource.Zero: case MeteredResource.Turns: case MeteredResource.Segments: case MeteredResource.Blood: return r default: throw Error("unexpected unmetered resource in metered resource node") } }, SetMaxOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, maxvalue: NonterminalNode, resource: NonterminalNode): MeteredResource { const r = (resource as ParserNode).resource; switch (r) { case MeteredResource.Health: case MeteredResource.Magic: case MeteredResource.Items: case MeteredResource.Experience: case MeteredResource.Zero: case MeteredResource.Turns: case MeteredResource.Segments: case MeteredResource.Blood: return r default: throw Error("unexpected unmetered resource in metered resource node") } }, SetMaxOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, maxvalue: NonterminalNode): MeteredResource { const r = (resource as ParserNode).resource; switch (r) { case MeteredResource.Health: case MeteredResource.Magic: case MeteredResource.Items: case MeteredResource.Experience: case MeteredResource.Zero: case MeteredResource.Turns: case MeteredResource.Segments: case MeteredResource.Blood: return r default: throw Error("unexpected unmetered resource in metered resource node") } }, _iter(...children: readonly Node[]): Resource|null { if (this.isOptional() && children.length === 0) { return null } else if (this.isOptional() && children.length === 1) { return (children[0] as ParserNode).resource } else { throw Error(`No idea what to say ${this.ctorName} iteration node's resource is when there are multiple children`) } }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's resource value is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's resource value is`) }, SetMeteredOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, value: NonterminalNode): MeteredResource { const r = (resource as ParserNode).resource; switch (r) { case MeteredResource.Health: case MeteredResource.Magic: case MeteredResource.Items: case MeteredResource.Experience: case MeteredResource.Zero: case MeteredResource.Turns: case MeteredResource.Segments: case MeteredResource.Blood: return r default: throw Error("unexpected unmetered resource in metered resource node") } }, SetMeteredOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, value: NonterminalNode, resource: NonterminalNode): MeteredResource { const r = (resource as ParserNode).resource; switch (r) { case MeteredResource.Health: case MeteredResource.Magic: case MeteredResource.Items: case MeteredResource.Experience: case MeteredResource.Zero: case MeteredResource.Turns: case MeteredResource.Segments: case MeteredResource.Blood: return r default: throw Error("unexpected unmetered resource in metered resource node") } }, SetMeteredOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, value: NonterminalNode): MeteredResource { const r = (resource as ParserNode).resource; switch (r) { case MeteredResource.Health: case MeteredResource.Magic: case MeteredResource.Items: case MeteredResource.Experience: case MeteredResource.Zero: case MeteredResource.Turns: case MeteredResource.Segments: case MeteredResource.Blood: return r default: throw Error("unexpected unmetered resource in metered resource node") } }, ClearOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, nul: NonterminalNode): Resource { const r = (resource as ParserNode).resource if (r === null) { throw Error("unexpected null resource in required resource node") } return r }, ClearOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, nul: NonterminalNode, resource: NonterminalNode): Resource { const r = (resource as ParserNode).resource if (r === null) { throw Error("unexpected null resource in required resource node") } return r }, ClearOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, nul: NonterminalNode): Resource { const r = (resource as ParserNode).resource if (r === null) { throw Error("unexpected null resource in required resource node") } return r }, }) parser.addAttribute("operands", { CompleteOperation(silence: IterationNode, operation: NonterminalNode, terminator: NonterminalNode): Operands { return (operation as ParserNode).operands }, Operation(operation: NonterminalNode): Operands { return (operation as ParserNode).operands }, ClearOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, nul: NonterminalNode): Operands { return (operands as ParserNode).operands }, ClearOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, nul: NonterminalNode, resource: NonterminalNode): Operands { return (operands as ParserNode).operands }, ClearOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, nul: NonterminalNode): Operands { return (operands as ParserNode).operands; }, DeltaOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, element: IterationNode): Operands { return (operands as ParserNode).operands; }, DeltaOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, resource: IterationNode, element: IterationNode): Operands { return (operands as ParserNode).operands; }, DeltaOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, delta: NonterminalNode, affinity: IterationNode, element: IterationNode): Operands { return (operands as ParserNode).operands; }, FailOperation(operands: NonterminalNode, colon: NonterminalNode, fail: NonterminalNode): Operands { return (operands as ParserNode).operands; }, PrintOperation(): Set { return Operands() }, SetMaxOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, max: NonterminalNode): Operands { return (operands as ParserNode).operands }, SetMaxOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, max: NonterminalNode, resource: NonterminalNode): Operands { return (operands as ParserNode).operands }, SetMaxOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, max: NonterminalNode): Operands { return (operands as ParserNode).operands }, SetMeteredOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, meter: NonterminalNode): Operands { return (operands as ParserNode).operands }, SetMeteredOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, meter: NonterminalNode, resource: NonterminalNode): Operands { return (operands as ParserNode).operands }, SetMeteredOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, meter: NonterminalNode): Operands { return (operands as ParserNode).operands }, SetSourceOperation(source: NonterminalNode, operands: NonterminalNode): Operands { return (operands as ParserNode).operands }, SetTargetOperation(target: NonterminalNode, operands: NonterminalNode): Operands { return (operands as ParserNode).operands }, SetValueOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, value: NonterminalNode): Operands { return (operands as ParserNode).operands }, SetValueOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, value: NonterminalNode, resource: NonterminalNode): Operands { return (operands as ParserNode).operands }, SetValueOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, value: NonterminalNode): Operands { return (operands as ParserNode).operands }, StatusOrItemCounterDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, statusOrItem: NonterminalNode, delta: NonterminalNode): Operands { return (operands as ParserNode).operands }, StatusOrItemCounterSetOperation(operands: NonterminalNode, colon: NonterminalNode, statusOrItem: NonterminalNode, value: NonterminalNode): Operands { return (operands as ParserNode).operands }, StatusOrItemDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, delta: NonterminalNode, statusOrItem: NonterminalNode, counter: IterationNode): Operands { return (operands as ParserNode).operands }, Operands(arg0: NonterminalNode): Operands { return (arg0.asIteration() as ParserNode).operands }, _iter(...children: readonly Node[]): Operands { return OperandsFrom(children.map((child) => (child as ParserNode).operands)) }, operand(oper: NonterminalNode): Operands { return (oper as ParserNode).operands }, identifier(): Set { return Operands((this as ParserNode).identifier) }, target(): Set { return Operands(Target) }, source(): Set { return Operands(Source); }, ["null"](): Set { return Operands() }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's operands value is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's operands value is`) }, }) parser.addAttribute("blockTargets", { Block(start: NonterminalNode, terminator: NonterminalNode, code: NonterminalNode, end: NonterminalNode, terminator2: NonterminalNode): Operands { return (start as ParserNode).blockTargets }, BlockStart(silenced: IterationNode, begin: NonterminalNode, source: IterationNode, target: IterationNode, colon: NonterminalNode, text: NonterminalNode): Operands { return (target as ParserNode).operands }, _iter(): Operands { throw Error(`No idea what to say ${this.ctorName} iteration node's block targets value is`) }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's block targets value is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's block targets value is`) }, }) parser.addAttribute("blockSources", { Block(start: NonterminalNode, terminator: NonterminalNode, code: NonterminalNode, end: NonterminalNode, terminator2: NonterminalNode): Operands { return (start as ParserNode).blockSources }, BlockStart(silenced: IterationNode, begin: NonterminalNode, source: IterationNode, target: IterationNode, colon: NonterminalNode, text: NonterminalNode): Operands { return (source as ParserNode).operands }, _iter(): Operands { throw Error(`No idea what to say ${this.ctorName} iteration node's block sources value is`) }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's block sources value is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's block sources value is`) }, }) parser.addAttribute("silenced", { Block(start: NonterminalNode, terminator: NonterminalNode, code: NonterminalNode, end: NonterminalNode, terminator2: NonterminalNode): boolean { return (start as ParserNode).silenced }, BlockStart(silenced: IterationNode, begin: NonterminalNode, source: IterationNode, target: IterationNode, colon: NonterminalNode, text: NonterminalNode): boolean { return (target as ParserNode).silenced }, CompleteOperation(silenced: IterationNode, operation: NonterminalNode, terminator: NonterminalNode): boolean { return (silenced as ParserNode).silenced }, silentOperator(): boolean { return true }, _iter(): boolean { if (this.isOptional() && this.children.length === 0) { return false } else if (this.isOptional() && this.children.length === 1) { return (this.children[0] as ParserNode).silenced } else { throw Error(`No idea what to say ${this.ctorName} iteration node's element is when there are multiple children`) } }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's silenced status is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's silenced status is`) } }) parser.addAttribute("currentValue", { SetValueOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, integer: NonterminalNode): number { return (integer as ParserNode).numberValue; }, SetValueOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, integer: NonterminalNode, resource: NonterminalNode): number { return (integer as ParserNode).numberValue; }, SetValueOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, integer: NonterminalNode): number { return (integer as ParserNode).numberValue; }, MeteredValue(current: NonterminalNode, max: NonterminalNode): number { return (current as ParserNode).numberValue }, SetMeteredOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, value: NonterminalNode): number { return (value as ParserNode).currentValue; }, SetMeteredOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, value: NonterminalNode, resource: NonterminalNode): number { return (value as ParserNode).currentValue; }, SetMeteredOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, value: NonterminalNode): number { return (value as ParserNode).currentValue; }, StatusOrItemDeltaOperation(operands: NonterminalNode, colon: NonterminalNode, deltaOperator: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): number { return (counter as ParserNode).numberValue }, StatusOrItemCounterSetOperation(operands: NonterminalNode, colon: NonterminalNode, identifier: NonterminalNode, counter: NonterminalNode): number { return (counter as ParserNode).numberValue }, _iter(): never { throw Error(`No idea what to say ${this.ctorName} iteration node's current value is`) }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's current value is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's current value is`) } }) parser.addAttribute("maxValue", { SetMaxOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, maxvalue: NonterminalNode): number { return (maxvalue as ParserNode).numberValue; }, SetMaxOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, maxvalue: NonterminalNode, resource: NonterminalNode): number { return (maxvalue as ParserNode).numberValue; }, SetMaxOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, maxvalue: NonterminalNode): number { return (maxvalue as ParserNode).numberValue; }, MeteredValue(current: NonterminalNode, max: NonterminalNode): number { return (max as ParserNode).numberValue }, SetMeteredOperation(operands: NonterminalNode, space: NonterminalNode, resource: NonterminalNode, colon: NonterminalNode, value: NonterminalNode): number { return (value as ParserNode).maxValue; }, SetMeteredOperationAlternate(operands: NonterminalNode, colon: NonterminalNode, value: NonterminalNode, resource: NonterminalNode): number { return (value as ParserNode).maxValue; }, SetMeteredOperationAlternate2(operands: NonterminalNode, colon: NonterminalNode, resource: NonterminalNode, value: NonterminalNode): number { return (value as ParserNode).maxValue; }, _iter(): never { throw Error(`No idea what to say ${this.ctorName} iteration node's max value is`) }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's max value is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's max value is`) } }) parser.addAttribute("failReason", { avoid(): FailReason.Avoid { return FailReason.Avoid }, dodge(): FailReason.Dodge { return FailReason.Dodge }, miss(): FailReason.Miss { return FailReason.Miss }, resist(): FailReason.Resist { return FailReason.Resist }, fail(): FailReason.Fail { return FailReason.Fail }, block(): FailReason.Block { return FailReason.Block }, parry(): FailReason.Parry { return FailReason.Parry }, FailReason(reason: NonterminalNode): FailReason { return (reason as ParserNode).failReason }, FailOperation(operands: NonterminalNode, colon: NonterminalNode, reason: NonterminalNode): FailReason { return (reason as ParserNode).failReason }, _iter(): never { throw Error(`No idea what to say ${this.ctorName} iteration node's fail reason is`) }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's fail reason is`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's fail reason is`) } }) parser.addAttribute("side", { characterSide(side: NonterminalNode): CharacterSide { return (side as ParserNode).side }, enemySide(): CharacterSide.Enemy { return CharacterSide.Enemy }, allySide(): CharacterSide.Ally { return CharacterSide.Ally }, _iter(): never { throw Error(`No idea what to say ${this.ctorName} iteration node's loyalties are`) }, _nonterminal(): never { throw Error(`No idea what to say ${this.ctorName} nonterminal node's loyalties are`) }, _terminal(): never { throw Error(`No idea what to say ${this.ctorName} terminal node's loyalties are`) } })