-
Notifications
You must be signed in to change notification settings - Fork 0
build: prepare Stage 2 foundation #34
Description
Preparatory commit that establishes shared infrastructure for all Stage 2 features (#25). Must land before any individual Stage 2 feature work begins.
Token Allocation
Reorganize TokenType enum with all Stage 2 token IDs allocated upfront (31 total, semantically grouped). Existing tokens are renumbered for logical grouping:
| Group | Tokens |
|---|---|
| Literals | NUMBER |
| Dice operators | DICE, DICE_PERCENT, DICE_FATE |
| Arithmetic | PLUS, MINUS, MULTIPLY, DIVIDE, MODULO, POWER |
| Comparison | GREATER, GREATER_EQUAL, LESS, LESS_EQUAL, EQUAL |
| Grouping | LPAREN, RPAREN, COMMA |
| Keep/drop | KEEP_HIGH, KEEP_LOW, DROP_HIGH, DROP_LOW |
| Explode | EXPLODE, EXPLODE_COMPOUND, EXPLODE_PENETRATING |
| Reroll | REROLL, REROLL_ONCE |
| Success | FAIL |
| Functions | FUNCTION |
| Keywords | VS |
| End | EOF |
ComparePoint Type
Define canonical ComparePoint in src/types.ts:
type CompareOp = '>' | '>=' | '<' | '<=' | '=';
type ComparePoint = { operator: CompareOp; value: ASTNode };value is ASTNode (not number) to match the existing pattern where DiceNode.count and DiceNode.sides are both ASTNode. This supports computed thresholds (>=ceil(5)) and negative compare values (=-1 for Fate dice) via unary minus.
Lexer: Full-Accumulation scanIdentifier
Rewrite scanIdentifier from incremental peek-based scanning to full-accumulation: collect all consecutive alpha chars, then classify against a keyword lookup table. Resolves the d-in-round problem, d% scanning, f vs floor disambiguation, and all future identifier keywords.
Special cases after accumulation:
- Bare
dfollowed by%→DICE_PERCENT df→DICE_FATE
Operator Scanning
Add to the operator switch in nextToken():
- Comparison:
>,>=(maximal munch),<,<=(maximal munch),= - Explode:
!,!!(maximal munch),!p/!P - Comma:
,
Parser: ComparePoint Utilities
Add two methods to the Parser class for use by Stage 2 modifier parsers:
isComparePointAhead(): boolean— peeks for comparison operator tokensparseComparePoint(): ComparePoint— consumes operator + value expression
Comparison tokens get BP = -1 (terminators) so they never interfere with the main Pratt loop.
Rationale
All 8 Stage 2 features were planned in isolation and independently assigned conflicting token IDs starting at 15, used 3 different naming conventions for comparison tokens, and defined ComparePoint in 4 incompatible ways. A consilium review identified these as critical integration blockers. This issue resolves all cross-cutting conflicts in a single upfront pass.
See .claude/docs/STAGE2.md for the full design document.
Drafted with AI assistance