couple more bits of parsing

main
Mari 7 months ago
parent 1afed85dbe
commit 8f13574ee7
  1. 10
      src/grammar/grammar.ohm
  2. 114
      src/grammar/parser.ts
  3. 10
      src/model/Messages.ts

@ -167,6 +167,16 @@ FabulaDSL {
FailReason = avoid|dodge|miss|resist|fail|block|parry
FailOperation = Operands colon FailReason
allySide = caseInsensitive<"allies">|caseInsensitive<"ally">
|caseInsensitive<"friendly">|caseInsensitive<"friends">|caseInsensitive<"friend">
|caseInsensitive<"party">|caseInsensitive<"pcs">|caseInsensitive<"pc">
|caseInsensitive<"heroes">|caseInsensitive<"hero">
enemySide = caseInsensitive<"villains">|caseInsensitive<"villain">
|caseInsensitive<"enemies">|caseInsensitive<"enemy">
|caseInsensitive<"npcs">|caseInsensitive<"npc">
|caseInsensitive<"opponents">|caseInsensitive<"opponent">|caseInsensitive<"opposed">
characterSide = allySide|enemySide
printOperator = ">"
PrintOperation = printOperator textToEndOfLine
PrintOperationWithOperands = Operands colon printOperator textToEndOfLine

@ -2,48 +2,52 @@ import grammar from "./grammar.ohm-bundle";
import {
Affinity,
ElementalType,
FailReason,
MarkdownContext,
MarkdownOutput,
MeteredResource,
NumberSign,
Operands, OperandsFrom,
Operands,
OperandsFrom,
ParseContext,
Resource, Source, Target,
Resource,
Source,
Target,
UnmeteredResource,
} from "../model/Messages";
import {Iter, IterationNode, Node, NonterminalNode, TerminalNode} from "ohm-js";
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 {
element: ElementalType|null
affinity: Affinity
sign: NumberSign
numberValue: number
identifier: string
resource: Resource|null
operands: Operands
blockTargets: Operands
blockSources: Operands
silenced: boolean
currentValue: number
maxValue: number
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.
textValue: string
failReason: unknown // TODO: create an enum for this
readonly textValue: string
// TODO: create rules for these to describe clocks/timers/items/statuses/characters and implement them
nameText: string
descriptionText: string
readonly nameText: string
readonly descriptionText: string
// TODO: use for portraits, status icons, backdrops, BGM, and SFX
url: string
side: CharacterSide
privacy: CharacterPrivacy
clockMode: ClockMode
timerDirection: TimerDirection
timerDurationMs: number
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
@ -782,4 +786,64 @@ parser.addAttribute<number>("maxValue", {
_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`)
}
})

@ -48,6 +48,16 @@ export enum UnmeteredResource {
export type Resource = MeteredResource|UnmeteredResource
export enum FailReason {
Avoid = "avoid",
Dodge = "dodge",
Miss = "miss",
Resist = "resist",
Fail = "fail",
Block = "block",
Parry = "parry",
}
export const Target: unique symbol = Symbol("target");
export const Source: unique symbol = Symbol("source");

Loading…
Cancel
Save