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.
536 lines
23 KiB
536 lines
23 KiB
import grammar from "./grammar.ohm-bundle";
|
|
import {
|
|
Affinity,
|
|
ElementalType,
|
|
MarkdownContext,
|
|
MarkdownOutput,
|
|
MeteredResource,
|
|
NumberSign,
|
|
Operands,
|
|
ParseContext,
|
|
Resource,
|
|
UnmeteredResource,
|
|
} from "../model/Messages";
|
|
import {IterationNode, Node, NonterminalNode, TerminalNode} from "ohm-js";
|
|
import {CharacterPrivacy, CharacterSide} from "../model/Character";
|
|
import {ClockMode} from "../model/GameState";
|
|
|
|
export const parser = grammar.createSemantics()
|
|
|
|
export interface ParserNode extends Node {
|
|
element: ElementalType|null
|
|
affinity: Affinity
|
|
sign: NumberSign
|
|
numberValue: number
|
|
identifier: string
|
|
resource: Resource|null
|
|
|
|
// TODO: Implement all of the things listed below.
|
|
operands: Operands
|
|
blockTargets: Operands
|
|
blockSources: Operands
|
|
currentValue: number|null
|
|
maxValue: number|null
|
|
textValue: string
|
|
silenced: boolean
|
|
failReason: unknown // TODO: create an enum for this
|
|
// TODO: create rules for these to describe clocks/timers/items/statuses/characters and implement them
|
|
nameText: string
|
|
descriptionText: string
|
|
side: CharacterSide
|
|
privacy: CharacterPrivacy
|
|
clockMode: ClockMode
|
|
timerDirection: unknown // TODO: create an enum for this
|
|
timerDurationMs: number
|
|
|
|
// 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: 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: 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: 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`)
|
|
}
|
|
},
|
|
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
|
|
},
|
|
}) |