@sharpee/chord 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ir.d.ts ADDED
@@ -0,0 +1,511 @@
1
+ /**
2
+ * ir.ts — the Story IR wire types (`story language 1`).
3
+ *
4
+ * Purpose: the versioned, JSON-serializable product of Chord compilation
5
+ * (ADR-210: the IR is the product). Everything is resolved — entity
6
+ * references are canonical IDs, phrase keys are validated, event headers
7
+ * are segmented — but statements remain trees: the loader performs the
8
+ * four-phase partition (§5.4) at bind time. Nodes carry source spans for
9
+ * error reporting and IDE tooling.
10
+ *
11
+ * Public interface: StoryIR and every IR* type; IR_FORMAT.
12
+ * Owner context: @sharpee/chord owns this schema (ADR-210 Interface
13
+ * Contract 1, owner-confirmed 2026-07-10); @sharpee/ide-protocol re-exports
14
+ * it. Invariant: pure data — JSON.parse(JSON.stringify(ir)) is identity.
15
+ */
16
+ import type { Span } from './span';
17
+ /** Format stamp of this IR schema. Consumers refuse unknown formats. */
18
+ export declare const IR_FORMAT = "story language 1";
19
+ /** Root of a compiled story. */
20
+ export interface StoryIR {
21
+ format: typeof IR_FORMAT;
22
+ meta: IRMeta;
23
+ /** The story object's declared phases (ownership package D2). */
24
+ story: {
25
+ states: string[];
26
+ reversible: boolean;
27
+ };
28
+ entities: IREntity[];
29
+ conditions: IRNamedCondition[];
30
+ phrases: IRPhrases;
31
+ verbs: IRVerbDef[];
32
+ hatches: IRHatch[];
33
+ traits: IRTraitDef[];
34
+ actions: IRActionDef[];
35
+ /** Owner-attached score identities (D12) — names are owner-qualified (`pygmy-goats.fed`). */
36
+ scores: IRScoreDef[];
37
+ sequences: IRSequenceDef[];
38
+ /** True when any hatch is declared — the pure-IR profile refuses these (AC-4). */
39
+ hasHatches: boolean;
40
+ }
41
+ export interface IRMeta {
42
+ title: string;
43
+ author: string;
44
+ /** Raw header fields (id, version, blurb, ...). */
45
+ fields: Record<string, string>;
46
+ }
47
+ export interface IREntity {
48
+ /** Canonical slug (lowercased name words joined with `-`). Unique. */
49
+ id: string;
50
+ /** Display name without article. */
51
+ name: string;
52
+ /** Leading article as written (`the`), or null. */
53
+ article: string | null;
54
+ aka: string[];
55
+ /** True for the story's player entity (`create the player`). */
56
+ isPlayer: boolean;
57
+ /** Kind-noun compositions (`a room`), in declaration order. */
58
+ kinds: IRComposition[];
59
+ /** Trait-adjective compositions (`scenery`, `dark while …`). */
60
+ traits: IRComposition[];
61
+ placement: IRPlacement | null;
62
+ /** Entity IDs this entity wears at start (player wears the cloak). */
63
+ wears: string[];
64
+ exits: IRExit[];
65
+ blockedExits: IRBlockedExit[];
66
+ /**
67
+ * Ordered state names — the entity's own `states:` line first, then every
68
+ * composed trait's declared set in composition order (D8 merge; one
69
+ * namespace per entity, collisions are load errors).
70
+ */
71
+ states: string[];
72
+ /**
73
+ * The entity's OWN `states:` line permits back-transitions (D4). Trait
74
+ * sets carry their own flag on IRTraitDef — the runtime resolves a
75
+ * `change` target's declaring set for the forward-march check.
76
+ */
77
+ statesReversible: boolean;
78
+ /** Phrase key of the description in the phrase table, or null. */
79
+ descriptionKey: string | null;
80
+ /**
81
+ * Phrase key of the `first time` (first-visit) description (Z1), or null.
82
+ * Rooms only — the loader binds it to `RoomTrait.initialDescription`.
83
+ */
84
+ initialDescriptionKey: string | null;
85
+ onClauses: IROnClause[];
86
+ span: Span;
87
+ }
88
+ export interface IRComposition {
89
+ name: string;
90
+ config: IRConfigSetting[];
91
+ /** Conditional composition (`dark while …`), or null. */
92
+ condition: IRCondition | null;
93
+ span: Span;
94
+ }
95
+ export interface IRConfigSetting {
96
+ /** Setting key words joined with a space (`max items`). */
97
+ key: string;
98
+ value: string;
99
+ /** 'name' = multi-word entity-name value (`with food the handful of feed`, Phase B). */
100
+ valueKind: 'number' | 'string' | 'word' | 'name';
101
+ }
102
+ export interface IRPlacement {
103
+ relation: 'in' | 'on' | 'starts-in';
104
+ /** Entity ID of the containing place. */
105
+ place: string;
106
+ span: Span;
107
+ }
108
+ export interface IRExit {
109
+ direction: string;
110
+ /** Entity ID of the destination room. */
111
+ to: string;
112
+ span: Span;
113
+ }
114
+ export interface IRBlockedExit {
115
+ direction: string;
116
+ phraseKey: string;
117
+ /** `is blocked while <cond>` — null = always blocked (grammar log 2026-07-10). */
118
+ condition: IRCondition | null;
119
+ span: Span;
120
+ }
121
+ export interface IROnClause {
122
+ /** `on` = intercept (may refuse; primary text), `after` = react (appends; ratchet D3). */
123
+ clauseKind: 'on' | 'after';
124
+ /** `, once` clause modifier — one lifetime firing (ratchet D5). */
125
+ once: boolean;
126
+ /** Action word as written (gerund), e.g. `reading`; `every-turn` for `on every turn`. */
127
+ action: string;
128
+ /** How the clause binds: target (`it`), role (`anything as the <role>`), or every turn. */
129
+ binding: 'it' | 'role' | 'every-turn';
130
+ /** Role name for role-bound clauses (validated against the action's roles). */
131
+ role: string | null;
132
+ /** `while` qualifier (every-turn clauses). */
133
+ condition: IRCondition | null;
134
+ /** Explicit `before`/`after` ordering between traits on the same action. */
135
+ ordering: {
136
+ relation: 'before' | 'after';
137
+ trait: string;
138
+ } | null;
139
+ /**
140
+ * §5.4 compiler rule: clauses on standard-semantics actions compile to
141
+ * ActionInterceptors; clauses on dispatch verbs (`define action`) compile
142
+ * to CapabilityBehaviors. Null for every-turn clauses (daemon-shaped).
143
+ */
144
+ routing: 'interceptor' | 'capability' | null;
145
+ /**
146
+ * Narration scope (decision 10, 2026-07-11): entity/trait-owned clauses
147
+ * are presence-scoped — the loader fires their narration only when the
148
+ * player shares the owner's location (performances need an audience;
149
+ * presence, not sight). Story-owned schedule/sequence bodies broadcast.
150
+ * All on-clauses are owner-attached under the ownership package, so this
151
+ * is always 'presence' — recorded explicitly for the loader (Phase 4) and
152
+ * IDE consumers.
153
+ */
154
+ narration: 'presence' | 'broadcast';
155
+ /**
156
+ * Statement tree in source order. The phase-order rule is enforced at
157
+ * compile time; the loader partitions this into validate/execute/report.
158
+ */
159
+ body: IRStatement[];
160
+ span: Span;
161
+ }
162
+ export interface IRPhrases {
163
+ /** The story's default locale (Phase A: en-US). */
164
+ defaultLocale: string;
165
+ /** locale → phrase key → phrase. */
166
+ locales: Record<string, Record<string, IRPhrase>>;
167
+ }
168
+ export interface IRPhrase {
169
+ /** Choice strategy for multi-variant phrases, or null for a single text (Z5 adverbs, ADR-211 Decision 4). */
170
+ strategy: 'randomly' | 'cycling' | 'stopping' | 'sticky' | 'first-time' | null;
171
+ /**
172
+ * Whitespace-preserving text (`define phrase X, verbatim`, grammar log
173
+ * 2026-07-10) — the loader must exempt it from whitespace collapse.
174
+ * Present only when true (additive field; format stamp unchanged).
175
+ */
176
+ verbatim?: boolean;
177
+ /**
178
+ * Trailing `while <condition>` header gate (Z2/CP1', additive like
179
+ * `verbatim`): at a description-marker site a presence condition compiles
180
+ * to ADR-209 `mentions` and anything else registers on the ADR-211 gate
181
+ * seam keyed `(roomId, marker)`. Absent when ungated.
182
+ */
183
+ condition?: IRCondition;
184
+ variants: IRPhraseVariant[];
185
+ span: Span;
186
+ }
187
+ export interface IRPhraseVariant {
188
+ text: string;
189
+ /**
190
+ * `{…}` marker contents appearing in the text, in order. `br` is the
191
+ * built-in hard line break; prose paragraphs arrive as `\n\n` in `text`.
192
+ */
193
+ markers: string[];
194
+ }
195
+ export interface IRNamedCondition {
196
+ name: string;
197
+ /**
198
+ * True when the body references `it`/`its` — an OPEN condition, usable as
199
+ * a selection via `any <name>` (grammar log 2026-07-11). Closed conditions
200
+ * are plain truth tests.
201
+ */
202
+ open: boolean;
203
+ condition: IRCondition;
204
+ span: Span;
205
+ }
206
+ export interface IRVerbDef {
207
+ verbs: string[];
208
+ pattern: IRPatternPart[];
209
+ span: Span;
210
+ }
211
+ export type IRPatternPart = {
212
+ kind: 'word';
213
+ word: string;
214
+ } | {
215
+ kind: 'slot';
216
+ word: string;
217
+ };
218
+ export interface IRHatch {
219
+ name: string;
220
+ modulePath: string;
221
+ /** Target interface: dynamic-text producer, Action, or CapabilityBehavior. */
222
+ hatchKind: 'text' | 'action' | 'behavior';
223
+ span: Span;
224
+ }
225
+ /** `define trait` — data fields, trait-declared states, behavior clauses. */
226
+ export interface IRTraitDef {
227
+ name: string;
228
+ data: IRTraitField[];
229
+ /** Trait-declared states (ratchet D8) — every composer gets the set. */
230
+ states: string[];
231
+ statesReversible: boolean;
232
+ /** Trait-owned scores (D12); names owner-qualified (`trait.<name>.<score>`). */
233
+ scores: IRScoreDef[];
234
+ onClauses: IROnClause[];
235
+ span: Span;
236
+ }
237
+ export interface IRTraitField {
238
+ /** Field name words joined with a space (`body part`). */
239
+ name: string;
240
+ type: 'entity' | 'number' | 'name' | 'one-of';
241
+ optional: boolean;
242
+ initial: string | null;
243
+ oneOf: string[] | null;
244
+ }
245
+ /** `define action` — grammar, scope constraints, requirements, refusal ladder, body. */
246
+ export interface IRActionDef {
247
+ name: string;
248
+ patterns: IRActionPattern[];
249
+ constraints: Array<{
250
+ slot: string;
251
+ requirement: string;
252
+ }>;
253
+ /** `must` requirement lines (ratchet D6) — checked before the body. */
254
+ musts: IRMust[];
255
+ refusals: IRActionRefusal[];
256
+ /** Dispatch-miss phrase key (`otherwise refuse …`), or null. */
257
+ otherwise: string | null;
258
+ /** Action-owned scores (D12); names owner-qualified (`action.<name>.<score>`). */
259
+ scores: IRScoreDef[];
260
+ body: IRStatement[];
261
+ span: Span;
262
+ }
263
+ /** A resolved `must` requirement: refuse with the key unless the condition holds. */
264
+ export interface IRMust {
265
+ condition: IRCondition;
266
+ phraseKey: string;
267
+ span: Span;
268
+ }
269
+ export interface IRActionPattern {
270
+ parts: IRPatternPart[];
271
+ /** `→ each …` cardinality words, or null. */
272
+ cardinality: string[] | null;
273
+ }
274
+ export type IRActionRefusal = {
275
+ kind: 'without';
276
+ slot: string;
277
+ phraseKey: string;
278
+ span: Span;
279
+ } | {
280
+ kind: 'when';
281
+ condition: IRCondition;
282
+ phraseKey: string;
283
+ span: Span;
284
+ };
285
+ /** `define score <name> worth <n>` — dedup-by-identity award (ADR-129). */
286
+ export interface IRScoreDef {
287
+ name: string;
288
+ worth: number;
289
+ span: Span;
290
+ }
291
+ /** `define sequence <name>` — chained-fuse timeline. */
292
+ export interface IRSequenceDef {
293
+ /** Name words joined with a space (`closing time`). */
294
+ name: string;
295
+ /**
296
+ * Narration scope (decision 10): sequences are story-owned — their
297
+ * narration broadcasts regardless of the player's location.
298
+ */
299
+ narration: 'broadcast';
300
+ steps: IRSequenceStep[];
301
+ span: Span;
302
+ }
303
+ /** One step: wall-clock (`at turn N`/`N turns later`) or state anchor (D10). */
304
+ export interface IRSequenceStep {
305
+ timing: 'at-turn' | 'later' | 'becomes';
306
+ /** Turn count for at-turn/later; 0 for becomes. */
307
+ turns: number;
308
+ /** State anchor for `becomes` steps: owner is `story` or an entity id. */
309
+ anchor?: {
310
+ owner: string;
311
+ state: string;
312
+ } | null;
313
+ body: IRStatement[];
314
+ span: Span;
315
+ }
316
+ export type IRStatement = {
317
+ kind: 'refuse';
318
+ phraseKey: string;
319
+ params: IRParam[];
320
+ span: Span;
321
+ } | {
322
+ kind: 'phrase';
323
+ phraseKey: string;
324
+ params: IRParam[];
325
+ stmtWhen?: IRCondition | null;
326
+ span: Span;
327
+ } | {
328
+ kind: 'emit';
329
+ event: string;
330
+ stmtWhen?: IRCondition | null;
331
+ span: Span;
332
+ } | {
333
+ kind: 'set';
334
+ target: IRValue;
335
+ value: IRValue;
336
+ span: Span;
337
+ } | {
338
+ kind: 'change';
339
+ entity: IRValue;
340
+ state: string;
341
+ stmtWhen?: IRCondition | null;
342
+ span: Span;
343
+ } | {
344
+ kind: 'move';
345
+ entity: IRValue;
346
+ place: IRValue;
347
+ stmtWhen?: IRCondition | null;
348
+ span: Span;
349
+ }
350
+ /** `remove <entity>` (Z6, ADR-213 Q3) — out of play via `world.removeEntity`; observers fire. */
351
+ | {
352
+ kind: 'remove';
353
+ entity: IRValue;
354
+ stmtWhen?: IRCondition | null;
355
+ span: Span;
356
+ } | {
357
+ kind: 'award';
358
+ expression: string[];
359
+ once: boolean;
360
+ stmtWhen?: IRCondition | null;
361
+ span: Span;
362
+ } | {
363
+ kind: 'win';
364
+ phraseKey: string | null;
365
+ stmtWhen?: IRCondition | null;
366
+ span: Span;
367
+ } | {
368
+ kind: 'lose';
369
+ phraseKey: string | null;
370
+ stmtWhen?: IRCondition | null;
371
+ span: Span;
372
+ }
373
+ /** `must` requirement as a body statement (ratchet D6). */
374
+ | {
375
+ kind: 'must';
376
+ condition: IRCondition;
377
+ phraseKey: string;
378
+ span: Span;
379
+ }
380
+ /** `refuse when <cond>: <key>` as a body statement (prohibition, D6). */
381
+ | {
382
+ kind: 'refuse-when';
383
+ condition: IRCondition;
384
+ phraseKey: string;
385
+ span: Span;
386
+ } | {
387
+ kind: 'select-on';
388
+ subject: IRValue;
389
+ arms: IRSelectArm[];
390
+ span: Span;
391
+ } | {
392
+ kind: 'select-strategy';
393
+ strategy: string;
394
+ alternatives: IRStatement[][];
395
+ span: Span;
396
+ } | {
397
+ kind: 'ordinal';
398
+ ordinal: number;
399
+ body: IRStatement[];
400
+ span: Span;
401
+ }
402
+ /**
403
+ * `each <open-condition> … end each` (ratchet E3, 2026-07-12): run the
404
+ * body once per matching world entity in creation order, `the match`
405
+ * bound to that entity; empty set = no-op.
406
+ */
407
+ | {
408
+ kind: 'each';
409
+ condition: string;
410
+ body: IRStatement[];
411
+ span: Span;
412
+ };
413
+ export interface IRSelectArm {
414
+ value: string;
415
+ body: IRStatement[];
416
+ span: Span;
417
+ }
418
+ export interface IRParam {
419
+ /** Parameter name words joined with a space (`other item`). */
420
+ param: string;
421
+ value: IRValue;
422
+ span: Span;
423
+ }
424
+ export type IRValue = {
425
+ kind: 'literal';
426
+ value: string;
427
+ valueType: 'number' | 'string';
428
+ } | {
429
+ kind: 'entity';
430
+ id: string;
431
+ } | {
432
+ kind: 'player';
433
+ } | {
434
+ kind: 'it';
435
+ }
436
+ /** The story object (`change the story to after-hours`, ratchet D2). */
437
+ | {
438
+ kind: 'story';
439
+ } | {
440
+ kind: 'field';
441
+ base: IRValue;
442
+ field: string;
443
+ }
444
+ /** A grammar-slot / role context value inside an action or role clause (`the animal`, `the taker`). */
445
+ | {
446
+ kind: 'slot';
447
+ name: string;
448
+ }
449
+ /** The `each`-block binder `the match` (ratchet E3) — parallel to `it`. */
450
+ | {
451
+ kind: 'match';
452
+ } | {
453
+ kind: 'symbol';
454
+ name: string;
455
+ };
456
+ export type IRCondition = {
457
+ kind: 'and';
458
+ operands: IRCondition[];
459
+ } | {
460
+ kind: 'or';
461
+ operands: IRCondition[];
462
+ } | {
463
+ kind: 'not';
464
+ operand: IRCondition;
465
+ } | {
466
+ kind: 'chance';
467
+ n: number;
468
+ } | {
469
+ kind: 'condition';
470
+ name: string;
471
+ }
472
+ /** The story is in the named phase (`while after-hours`, ratchet D2). */
473
+ | {
474
+ kind: 'story-state';
475
+ state: string;
476
+ }
477
+ /**
478
+ * `any <open-condition>` (ratchet E1, 2026-07-12): true iff some world
479
+ * entity satisfies the named open condition; false over the empty set.
480
+ */
481
+ | {
482
+ kind: 'any-of';
483
+ condition: string;
484
+ }
485
+ /**
486
+ * `no <open-condition>` (ratchet E2, 2026-07-12): true iff no entity
487
+ * satisfies the condition; true over the empty set.
488
+ */
489
+ | {
490
+ kind: 'none-of';
491
+ condition: string;
492
+ }
493
+ /**
494
+ * `<subject> must be any <open-condition>` membership (David,
495
+ * 2026-07-12 — P3 decision, a dated addition to the proposal's §3.5
496
+ * contract): the subject satisfies the named open condition (the
497
+ * condition's `it` bound to the subject).
498
+ */
499
+ | {
500
+ kind: 'satisfies';
501
+ subject: IRValue;
502
+ condition: string;
503
+ } | {
504
+ kind: 'predicate';
505
+ /** 'can-see'/'can-reach' land with Phase B (design.md §2.7). */
506
+ pred: 'is' | 'is-a' | 'is-in' | 'is-here' | 'has' | 'holds' | 'wears' | 'can-see' | 'can-reach';
507
+ negated: boolean;
508
+ subject: IRValue;
509
+ object: IRValue;
510
+ };
511
+ //# sourceMappingURL=ir.d.ts.map
package/ir.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../../../repos/sharpee_v2/packages/chord/src/ir.ts"],"names":[],"mappings":"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"}
package/ir.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IR_FORMAT = void 0;
4
+ /** Format stamp of this IR schema. Consumers refuse unknown formats. */
5
+ exports.IR_FORMAT = 'story language 1';
6
+ //# sourceMappingURL=ir.js.map
package/ir.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ir.js","sourceRoot":"","sources":["../../../repos/sharpee_v2/packages/chord/src/ir.ts"],"names":[],"mappings":";;;AAiBA,wEAAwE;AAC3D,QAAA,SAAS,GAAG,kBAAkB,CAAC"}
package/lexer.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * lexer.ts — the Chord line lexer.
3
+ *
4
+ * Purpose: split `.story` source into logical lines, each carrying its
5
+ * indentation, its raw text (prose stays opaque to the parser — design.md
6
+ * §5.2), and a token stream for lines the parser reads as code. Block
7
+ * structure (dedent/`end` termination) is the parser's job; the lexer only
8
+ * measures indents.
9
+ *
10
+ * Public interface: lex(), Line, Token, TokenKind.
11
+ * Owner context: @sharpee/chord (language frontend; browser-safe).
12
+ *
13
+ * Invariants:
14
+ * - Every non-blank source line yields exactly one Line, in source order.
15
+ * - `Line.raw` is the untrimmed source text — prose reconstruction never
16
+ * loses characters the tokenizer didn't understand.
17
+ * - Indentation is spaces only; a tab in leading whitespace is an error
18
+ * (reported once per line) and is measured as one column.
19
+ */
20
+ import { DiagnosticBag } from './diagnostics';
21
+ import { Span } from './span';
22
+ export type TokenKind = 'word' | 'number' | 'string' | 'colon' | 'comma' | 'lparen' | 'rparen' | 'punct';
23
+ export interface Token {
24
+ kind: TokenKind;
25
+ /** Exact source text (for strings, WITHOUT the surrounding quotes). */
26
+ text: string;
27
+ span: Span;
28
+ }
29
+ /** One non-blank logical line of source. */
30
+ export interface Line {
31
+ /** 1-based source line number. */
32
+ lineNo: number;
33
+ /** Leading-space count (tabs count 1 and are reported as errors). */
34
+ indent: number;
35
+ /** Untrimmed source text. */
36
+ raw: string;
37
+ /** Token stream of the trimmed text. */
38
+ tokens: Token[];
39
+ /** True when a blank line (or start of file) immediately precedes this line. */
40
+ afterBlank: boolean;
41
+ }
42
+ /**
43
+ * Tokenize source into logical lines.
44
+ * @param source full `.story` text
45
+ * @param diagnostics receives lex errors (tabs in indentation, unterminated strings)
46
+ * @returns non-blank lines in source order
47
+ */
48
+ export declare function lex(source: string, diagnostics: DiagnosticBag): Line[];
49
+ //# sourceMappingURL=lexer.d.ts.map
package/lexer.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../../repos/sharpee_v2/packages/chord/src/lexer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAU,MAAM,QAAQ,CAAC;AAEtC,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,OAAO,CAAC;AAEZ,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,4CAA4C;AAC5C,MAAM,WAAW,IAAI;IACnB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,wCAAwC;IACxC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,gFAAgF;IAChF,UAAU,EAAE,OAAO,CAAC;CACrB;AAKD;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,GAAG,IAAI,EAAE,CAsCtE"}
package/lexer.js ADDED
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.lex = lex;
4
+ const span_1 = require("./span");
5
+ const WORD_RE = /^[A-Za-zÀ-ɏ][A-Za-z0-9À-ɏ'_-]*/;
6
+ const NUMBER_RE = /^[0-9]+(?:\.[0-9]+)*/;
7
+ /**
8
+ * Tokenize source into logical lines.
9
+ * @param source full `.story` text
10
+ * @param diagnostics receives lex errors (tabs in indentation, unterminated strings)
11
+ * @returns non-blank lines in source order
12
+ */
13
+ function lex(source, diagnostics) {
14
+ const lines = [];
15
+ const rawLines = source.split(/\r\n|\n|\r/);
16
+ let afterBlank = true; // start of file counts as a paragraph boundary
17
+ for (let i = 0; i < rawLines.length; i++) {
18
+ const raw = rawLines[i];
19
+ const lineNo = i + 1;
20
+ if (raw.trim() === '') {
21
+ afterBlank = true;
22
+ continue;
23
+ }
24
+ let indent = 0;
25
+ let col = 0;
26
+ while (col < raw.length && (raw[col] === ' ' || raw[col] === '\t')) {
27
+ if (raw[col] === '\t') {
28
+ diagnostics.error('lex.tab-indent', 'Tabs are not allowed in indentation — use spaces.', (0, span_1.spanOf)(lineNo, col + 1));
29
+ }
30
+ indent++;
31
+ col++;
32
+ }
33
+ lines.push({
34
+ lineNo,
35
+ indent,
36
+ raw,
37
+ tokens: tokenizeLine(raw, lineNo, col, diagnostics),
38
+ afterBlank,
39
+ });
40
+ afterBlank = false;
41
+ }
42
+ return lines;
43
+ }
44
+ function tokenizeLine(raw, lineNo, start, diagnostics) {
45
+ const tokens = [];
46
+ let pos = start;
47
+ while (pos < raw.length) {
48
+ const ch = raw[pos];
49
+ if (ch === ' ') {
50
+ pos++;
51
+ continue;
52
+ }
53
+ const column = pos + 1;
54
+ if (ch === '"') {
55
+ const close = raw.indexOf('"', pos + 1);
56
+ if (close === -1) {
57
+ // A lone quote is prose punctuation (multi-line dialogue in prose
58
+ // blocks, e.g. design.md §3.3 PA announcements). Positions that
59
+ // REQUIRE a string (header, hatch paths) diagnose at parse time.
60
+ tokens.push({ kind: 'punct', text: ch, span: (0, span_1.spanOf)(lineNo, column) });
61
+ pos++;
62
+ }
63
+ else {
64
+ tokens.push({ kind: 'string', text: raw.slice(pos + 1, close), span: (0, span_1.spanOf)(lineNo, column, close - pos + 1) });
65
+ pos = close + 1;
66
+ }
67
+ continue;
68
+ }
69
+ const rest = raw.slice(pos);
70
+ const word = WORD_RE.exec(rest);
71
+ if (word) {
72
+ tokens.push({ kind: 'word', text: word[0], span: (0, span_1.spanOf)(lineNo, column, word[0].length) });
73
+ pos += word[0].length;
74
+ continue;
75
+ }
76
+ const num = NUMBER_RE.exec(rest);
77
+ if (num) {
78
+ tokens.push({ kind: 'number', text: num[0], span: (0, span_1.spanOf)(lineNo, column, num[0].length) });
79
+ pos += num[0].length;
80
+ continue;
81
+ }
82
+ const single = { ':': 'colon', ',': 'comma', '(': 'lparen', ')': 'rparen' };
83
+ tokens.push({ kind: single[ch] ?? 'punct', text: ch, span: (0, span_1.spanOf)(lineNo, column) });
84
+ pos++;
85
+ }
86
+ return tokens;
87
+ }
88
+ //# sourceMappingURL=lexer.js.map