You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
849 lines
38 KiB
849 lines
38 KiB
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<ElementalType|null>("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>("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<NumberSign>("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<number>("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<string>("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|null>("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>("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<never> {
|
|
return Operands<never>()
|
|
},
|
|
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<string> {
|
|
return Operands((this as ParserNode).identifier)
|
|
},
|
|
target(): Set<typeof Target> {
|
|
return Operands(Target)
|
|
},
|
|
source(): Set<typeof Source> {
|
|
return Operands(Source);
|
|
},
|
|
["null"](): Set<never> {
|
|
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<Operands>("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<Operands>("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<boolean>("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<number>("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<number>("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>("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<CharacterSide>("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`)
|
|
}
|
|
}) |