agency-lang 0.0.20 → 0.0.22

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.
Files changed (82) hide show
  1. package/dist/lib/backends/agencyGenerator.d.ts +10 -2
  2. package/dist/lib/backends/agencyGenerator.js +86 -19
  3. package/dist/lib/backends/agencyGenerator.test.js +0 -48
  4. package/dist/lib/backends/baseGenerator.d.ts +11 -4
  5. package/dist/lib/backends/baseGenerator.js +35 -11
  6. package/dist/lib/backends/graphGenerator.js +19 -186
  7. package/dist/lib/backends/typescriptGenerator/builtins.js +6 -0
  8. package/dist/lib/backends/typescriptGenerator.d.ts +11 -3
  9. package/dist/lib/backends/typescriptGenerator.js +98 -26
  10. package/dist/lib/backends/utils.d.ts +1 -1
  11. package/dist/lib/parser.js +5 -5
  12. package/dist/lib/parser.test.js +15 -38
  13. package/dist/lib/parsers/access.test.js +14 -3
  14. package/dist/lib/parsers/assignment.test.js +159 -4
  15. package/dist/lib/parsers/await.d.ts +3 -0
  16. package/dist/lib/parsers/await.js +18 -0
  17. package/dist/lib/parsers/body.test.js +10 -1
  18. package/dist/lib/parsers/dataStructures.js +2 -2
  19. package/dist/lib/parsers/dataStructures.test.js +11 -11
  20. package/dist/lib/parsers/function.d.ts +8 -3
  21. package/dist/lib/parsers/function.js +64 -12
  22. package/dist/lib/parsers/function.test.js +284 -52
  23. package/dist/lib/parsers/functionCall.test.js +6 -6
  24. package/dist/lib/parsers/ifElse.test.d.ts +1 -0
  25. package/dist/lib/parsers/ifElse.test.js +376 -0
  26. package/dist/lib/parsers/importStatement.js +2 -2
  27. package/dist/lib/parsers/literals.d.ts +1 -0
  28. package/dist/lib/parsers/literals.js +6 -2
  29. package/dist/lib/parsers/literals.test.js +110 -21
  30. package/dist/lib/parsers/matchBlock.js +7 -4
  31. package/dist/lib/parsers/matchBlock.test.js +16 -16
  32. package/dist/lib/parsers/newline.d.ts +3 -0
  33. package/dist/lib/parsers/newline.js +2 -0
  34. package/dist/lib/parsers/parserUtils.d.ts +3 -1
  35. package/dist/lib/parsers/parserUtils.js +4 -1
  36. package/dist/lib/parsers/returnStatement.js +2 -1
  37. package/dist/lib/parsers/returnStatement.test.js +2 -2
  38. package/dist/lib/parsers/specialVar.test.js +7 -7
  39. package/dist/lib/parsers/typeHints.d.ts +1 -1
  40. package/dist/lib/parsers/typeHints.js +6 -6
  41. package/dist/lib/parsers/typeHints.test.js +0 -8
  42. package/dist/lib/parsers/utils.d.ts +1 -0
  43. package/dist/lib/parsers/utils.js +2 -1
  44. package/dist/lib/parsers/whileLoop.test.js +46 -1
  45. package/dist/lib/templates/backends/graphGenerator/goToNode.d.ts +2 -1
  46. package/dist/lib/templates/backends/graphGenerator/goToNode.js +11 -1
  47. package/dist/lib/templates/backends/graphGenerator/graphNode.d.ts +2 -2
  48. package/dist/lib/templates/backends/graphGenerator/graphNode.js +2 -1
  49. package/dist/lib/templates/backends/graphGenerator/imports.d.ts +1 -1
  50. package/dist/lib/templates/backends/graphGenerator/imports.js +14 -1
  51. package/dist/lib/templates/backends/typescriptGenerator/builtinFunctions/sleep.d.ts +4 -0
  52. package/dist/lib/templates/backends/typescriptGenerator/builtinFunctions/sleep.js +13 -0
  53. package/dist/lib/templates/backends/typescriptGenerator/builtinFunctions/time.d.ts +7 -0
  54. package/dist/lib/templates/backends/typescriptGenerator/builtinFunctions/time.js +12 -0
  55. package/dist/lib/templates/backends/typescriptGenerator/functionDefinition.d.ts +1 -1
  56. package/dist/lib/templates/backends/typescriptGenerator/functionDefinition.js +1 -0
  57. package/dist/lib/templates/backends/typescriptGenerator/promptFunction.d.ts +1 -1
  58. package/dist/lib/templates/backends/typescriptGenerator/promptFunction.js +3 -2
  59. package/dist/lib/templates/backends/typescriptGenerator/tool.d.ts +1 -1
  60. package/dist/lib/templates/backends/typescriptGenerator/tool.js +1 -1
  61. package/dist/lib/templates/backends/typescriptGenerator/toolCall.d.ts +1 -1
  62. package/dist/lib/templates/backends/typescriptGenerator/toolCall.js +2 -2
  63. package/dist/lib/types/await.d.ts +7 -0
  64. package/dist/lib/types/await.js +1 -0
  65. package/dist/lib/types/graphNode.d.ts +2 -1
  66. package/dist/lib/types/ifElse.d.ts +7 -0
  67. package/dist/lib/types/ifElse.js +1 -0
  68. package/dist/lib/types/literals.d.ts +1 -1
  69. package/dist/lib/types/returnStatement.d.ts +2 -1
  70. package/dist/lib/types/timeBlock.d.ts +5 -0
  71. package/dist/lib/types/timeBlock.js +1 -0
  72. package/dist/lib/types.d.ts +16 -8
  73. package/dist/lib/types.js +1 -0
  74. package/dist/lib/utils.d.ts +1 -0
  75. package/dist/lib/utils.js +3 -0
  76. package/package.json +3 -2
  77. package/dist/lib/parsers/assignment.d.ts +0 -3
  78. package/dist/lib/parsers/assignment.js +0 -8
  79. package/dist/lib/templates/backends/graphGenerator/node.d.ts +0 -7
  80. package/dist/lib/templates/backends/graphGenerator/node.js +0 -18
  81. package/dist/lib/templates/backends/graphGenerator/promptNode.d.ts +0 -8
  82. package/dist/lib/templates/backends/graphGenerator/promptNode.js +0 -16
@@ -0,0 +1,376 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { ifParser } from "./function.js";
3
+ describe("ifParser", () => {
4
+ const testCases = [
5
+ // Happy path - simple if statements with literals as conditions
6
+ {
7
+ input: "if (true) {\n x = 1\n}",
8
+ expected: {
9
+ success: true,
10
+ result: {
11
+ type: "ifElse",
12
+ condition: { type: "variableName", value: "true" },
13
+ thenBody: [
14
+ {
15
+ type: "assignment",
16
+ variableName: "x",
17
+ value: { type: "number", value: "1" },
18
+ },
19
+ {
20
+ type: "newLine",
21
+ },
22
+ ],
23
+ elseBody: undefined,
24
+ },
25
+ },
26
+ },
27
+ {
28
+ input: "if (false) {\n y = 2\n}",
29
+ expected: {
30
+ success: true,
31
+ result: {
32
+ type: "ifElse",
33
+ condition: { type: "variableName", value: "false" },
34
+ thenBody: [
35
+ {
36
+ type: "assignment",
37
+ variableName: "y",
38
+ value: { type: "number", value: "2" },
39
+ },
40
+ {
41
+ type: "newLine",
42
+ },
43
+ ],
44
+ elseBody: undefined,
45
+ },
46
+ },
47
+ },
48
+ {
49
+ input: "if (x) {\n foo = 1\n}",
50
+ expected: {
51
+ success: true,
52
+ result: {
53
+ type: "ifElse",
54
+ condition: { type: "variableName", value: "x" },
55
+ thenBody: [
56
+ {
57
+ type: "assignment",
58
+ variableName: "foo",
59
+ value: { type: "number", value: "1" },
60
+ },
61
+ {
62
+ type: "newLine",
63
+ },
64
+ ],
65
+ elseBody: undefined,
66
+ },
67
+ },
68
+ },
69
+ {
70
+ input: "if (1) {\n x = 2\n}",
71
+ expected: {
72
+ success: true,
73
+ result: {
74
+ type: "ifElse",
75
+ condition: { type: "number", value: "1" },
76
+ thenBody: [
77
+ {
78
+ type: "assignment",
79
+ variableName: "x",
80
+ value: { type: "number", value: "2" },
81
+ },
82
+ {
83
+ type: "newLine",
84
+ },
85
+ ],
86
+ elseBody: undefined,
87
+ },
88
+ },
89
+ },
90
+ {
91
+ input: 'if ("yes") {\n x = 3\n}',
92
+ expected: {
93
+ success: true,
94
+ result: {
95
+ type: "ifElse",
96
+ condition: { type: "string", segments: [{ type: "text", value: "yes" }] },
97
+ thenBody: [
98
+ {
99
+ type: "assignment",
100
+ variableName: "x",
101
+ value: { type: "number", value: "3" },
102
+ },
103
+ {
104
+ type: "newLine",
105
+ },
106
+ ],
107
+ elseBody: undefined,
108
+ },
109
+ },
110
+ },
111
+ // Function calls as conditions
112
+ {
113
+ input: "if (isValid()) {\n x = 1\n}",
114
+ expected: {
115
+ success: true,
116
+ result: {
117
+ type: "ifElse",
118
+ condition: {
119
+ type: "functionCall",
120
+ functionName: "isValid",
121
+ arguments: [],
122
+ },
123
+ thenBody: [
124
+ {
125
+ type: "assignment",
126
+ variableName: "x",
127
+ value: { type: "number", value: "1" },
128
+ },
129
+ {
130
+ type: "newLine",
131
+ },
132
+ ],
133
+ elseBody: undefined,
134
+ },
135
+ },
136
+ },
137
+ // Access expressions as conditions
138
+ {
139
+ input: "if (obj.isReady) {\n x = 1\n}",
140
+ expected: {
141
+ success: true,
142
+ result: {
143
+ type: "ifElse",
144
+ condition: {
145
+ type: "accessExpression",
146
+ expression: {
147
+ type: "dotProperty",
148
+ object: { type: "variableName", value: "obj" },
149
+ propertyName: "isReady",
150
+ },
151
+ },
152
+ thenBody: [
153
+ {
154
+ type: "assignment",
155
+ variableName: "x",
156
+ value: { type: "number", value: "1" },
157
+ },
158
+ {
159
+ type: "newLine",
160
+ },
161
+ ],
162
+ elseBody: undefined,
163
+ },
164
+ },
165
+ },
166
+ // Index access as conditions
167
+ // TODO fix
168
+ /* {
169
+ input: "if (arr[0]) {\n x = 1\n}",
170
+ expected: {
171
+ success: true,
172
+ result: {
173
+ type: "ifElse",
174
+ condition: {
175
+ type: "indexAccess",
176
+ object: { type: "variableName", value: "arr" },
177
+ index: { type: "number", value: "0" },
178
+ },
179
+ thenBody: [
180
+ {
181
+ type: "assignment",
182
+ variableName: "x",
183
+ value: { type: "number", value: "1" },
184
+ },
185
+ ],
186
+ elseBody: undefined,
187
+ },
188
+ },
189
+ },
190
+ */
191
+ // Empty bodies
192
+ {
193
+ input: "if (true) {\n}",
194
+ expected: {
195
+ success: true,
196
+ result: {
197
+ type: "ifElse",
198
+ condition: { type: "variableName", value: "true" },
199
+ thenBody: [],
200
+ elseBody: undefined,
201
+ },
202
+ },
203
+ },
204
+ // Multiple statements in bodies
205
+ {
206
+ input: "if (x) {\n a = 1\n b = 2\n c = 3\n}",
207
+ expected: {
208
+ success: true,
209
+ result: {
210
+ type: "ifElse",
211
+ condition: { type: "variableName", value: "x" },
212
+ thenBody: [
213
+ {
214
+ type: "assignment",
215
+ variableName: "a",
216
+ value: { type: "number", value: "1" },
217
+ },
218
+ {
219
+ type: "newLine",
220
+ },
221
+ {
222
+ type: "assignment",
223
+ variableName: "b",
224
+ value: { type: "number", value: "2" },
225
+ },
226
+ {
227
+ type: "newLine",
228
+ },
229
+ {
230
+ type: "assignment",
231
+ variableName: "c",
232
+ value: { type: "number", value: "3" },
233
+ },
234
+ {
235
+ type: "newLine",
236
+ },
237
+ ],
238
+ elseBody: undefined,
239
+ },
240
+ },
241
+ },
242
+ // Whitespace variations
243
+ {
244
+ input: "if(x){\n foo = 1\n}",
245
+ expected: {
246
+ success: true,
247
+ result: {
248
+ type: "ifElse",
249
+ condition: { type: "variableName", value: "x" },
250
+ thenBody: [
251
+ {
252
+ type: "assignment",
253
+ variableName: "foo",
254
+ value: { type: "number", value: "1" },
255
+ },
256
+ {
257
+ type: "newLine",
258
+ },
259
+ ],
260
+ elseBody: undefined,
261
+ },
262
+ },
263
+ },
264
+ {
265
+ input: "if ( x ) {\n foo = 1\n}",
266
+ expected: {
267
+ success: true,
268
+ result: {
269
+ type: "ifElse",
270
+ condition: { type: "variableName", value: "x" },
271
+ thenBody: [
272
+ {
273
+ type: "assignment",
274
+ variableName: "foo",
275
+ value: { type: "number", value: "1" },
276
+ },
277
+ {
278
+ type: "newLine",
279
+ },
280
+ ],
281
+ elseBody: undefined,
282
+ },
283
+ },
284
+ },
285
+ {
286
+ input: "if(x){\nfoo=1\n}",
287
+ expected: {
288
+ success: true,
289
+ result: {
290
+ type: "ifElse",
291
+ condition: { type: "variableName", value: "x" },
292
+ thenBody: [
293
+ {
294
+ type: "assignment",
295
+ variableName: "foo",
296
+ value: { type: "number", value: "1" },
297
+ },
298
+ {
299
+ type: "newLine",
300
+ },
301
+ ],
302
+ elseBody: undefined,
303
+ },
304
+ },
305
+ },
306
+ // Failure cases - missing parentheses
307
+ {
308
+ input: "if x {\n foo = 1\n}",
309
+ expected: { success: false },
310
+ },
311
+ {
312
+ input: "if (x {\n foo = 1\n}",
313
+ expected: { success: false },
314
+ },
315
+ {
316
+ input: "if x) {\n foo = 1\n}",
317
+ expected: { success: false },
318
+ },
319
+ // Failure cases - missing braces
320
+ {
321
+ input: "if (x) \n foo = 1\n",
322
+ expected: { success: false },
323
+ },
324
+ {
325
+ input: "if (x) {\n foo = 1",
326
+ expected: { success: false },
327
+ },
328
+ {
329
+ input: "if (x) \n foo = 1\n}",
330
+ expected: { success: false },
331
+ },
332
+ // Failure cases - missing condition
333
+ {
334
+ input: "if () {\n foo = 1\n}",
335
+ expected: { success: false },
336
+ },
337
+ // Failure cases - empty or malformed
338
+ {
339
+ input: "",
340
+ expected: { success: false },
341
+ },
342
+ {
343
+ input: "if",
344
+ expected: { success: false },
345
+ },
346
+ {
347
+ input: "if ()",
348
+ expected: { success: false },
349
+ },
350
+ {
351
+ input: "if (x)",
352
+ expected: { success: false },
353
+ },
354
+ {
355
+ input: "if (x) {}else",
356
+ expected: { success: false },
357
+ },
358
+ ];
359
+ testCases.forEach(({ input, expected }) => {
360
+ if (expected.success) {
361
+ it(`should parse "${input.replace(/\n/g, "\\n")}" successfully`, () => {
362
+ const result = ifParser(input);
363
+ expect(result.success).toBe(true);
364
+ if (result.success) {
365
+ expect(result.result).toEqual(expected.result);
366
+ }
367
+ });
368
+ }
369
+ else {
370
+ it(`should fail to parse "${input.replace(/\n/g, "\\n")}"`, () => {
371
+ const result = ifParser(input);
372
+ expect(result.success).toBe(false);
373
+ });
374
+ }
375
+ });
376
+ });
@@ -1,3 +1,3 @@
1
- import { capture, many1Till, oneOf, seqC, set, spaces, str, trace, } from "tarsec";
1
+ import { capture, many1Till, newline, oneOf, optional, seqC, set, spaces, str, trace, } from "tarsec";
2
2
  import { optionalSemicolon } from "./parserUtils.js";
3
- export const importStatmentParser = trace("importStatement", seqC(set("type", "importStatement"), str("import"), spaces, capture(many1Till(str("from")), "importedNames"), str("from"), spaces, capture(many1Till(oneOf(";\n")), "modulePath"), optionalSemicolon));
3
+ export const importStatmentParser = trace("importStatement", seqC(set("type", "importStatement"), str("import"), spaces, capture(many1Till(str("from")), "importedNames"), str("from"), spaces, capture(many1Till(oneOf(";\n")), "modulePath"), optionalSemicolon, optional(newline)));
@@ -1,6 +1,7 @@
1
1
  import { InterpolationSegment, Literal, MultiLineStringLiteral, NumberLiteral, PromptLiteral, StringLiteral, TextSegment, VariableNameLiteral } from "../types.js";
2
2
  import { Parser } from "tarsec";
3
3
  export declare const textSegmentParser: Parser<TextSegment>;
4
+ export declare const stringTextSegmentParser: Parser<TextSegment>;
4
5
  export declare const interpolationSegmentParser: Parser<InterpolationSegment>;
5
6
  export declare const promptParser: Parser<PromptLiteral>;
6
7
  export declare const numberParser: Parser<NumberLiteral>;
@@ -1,13 +1,17 @@
1
1
  import { backtick, varNameChar } from "./utils.js";
2
- import { capture, char, digit, letter, many, many1Till, many1WithJoin, manyTillOneOf, manyTillStr, manyWithJoin, map, or, seq, seqC, set, str, } from "tarsec";
2
+ import { capture, char, digit, letter, many, many1Till, many1WithJoin, manyTillStr, manyWithJoin, map, or, seq, seqC, set, str, } from "tarsec";
3
3
  export const textSegmentParser = map(many1Till(or(backtick, char("$"))), (text) => ({
4
4
  type: "text",
5
5
  value: text,
6
6
  }));
7
+ export const stringTextSegmentParser = map(many1Till(or(char('"'), char("$"))), (text) => ({
8
+ type: "text",
9
+ value: text,
10
+ }));
7
11
  export const interpolationSegmentParser = seqC(set("type", "interpolation"), char("$"), char("{"), capture(manyTillStr("}"), "variableName"), char("}"));
8
12
  export const promptParser = seqC(set("type", "prompt"), backtick, capture(many(or(textSegmentParser, interpolationSegmentParser)), "segments"), backtick);
9
13
  export const numberParser = seqC(set("type", "number"), capture(many1WithJoin(or(char("-"), char("."), digit)), "value"));
10
- export const stringParser = seqC(set("type", "string"), char('"'), capture(manyTillOneOf(['"', "\n"]), "value"), char('"'));
14
+ export const stringParser = seqC(set("type", "string"), char('"'), capture(many(or(stringTextSegmentParser, interpolationSegmentParser)), "segments"), char('"'));
11
15
  export const multiLineStringParser = seqC(set("type", "multiLineString"), str('"""'), capture(manyTillStr('"""'), "value"), str('"""'));
12
16
  export const variableNameParser = seq([
13
17
  set("type", "variableName"),
@@ -363,62 +363,143 @@ describe("literals parsers", () => {
363
363
  // Happy path
364
364
  {
365
365
  input: '"hello"',
366
- expected: { success: true, result: { type: "string", value: "hello" } },
366
+ expected: {
367
+ success: true,
368
+ result: {
369
+ type: "string",
370
+ segments: [{ type: "text", value: "hello" }],
371
+ },
372
+ },
367
373
  },
368
374
  {
369
375
  input: '"world"',
370
- expected: { success: true, result: { type: "string", value: "world" } },
376
+ expected: {
377
+ success: true,
378
+ result: {
379
+ type: "string",
380
+ segments: [{ type: "text", value: "world" }],
381
+ },
382
+ },
371
383
  },
372
384
  {
373
385
  input: '"Hello, World!"',
374
386
  expected: {
375
387
  success: true,
376
- result: { type: "string", value: "Hello, World!" },
388
+ result: {
389
+ type: "string",
390
+ segments: [{ type: "text", value: "Hello, World!" }],
391
+ },
377
392
  },
378
393
  },
379
394
  // Empty string
380
395
  {
381
396
  input: '""',
382
- expected: { success: true, result: { type: "string", value: "" } },
397
+ expected: {
398
+ success: true,
399
+ result: { type: "string", segments: [] },
400
+ },
383
401
  },
384
402
  // Strings with special characters
385
403
  {
386
404
  input: '"123"',
387
- expected: { success: true, result: { type: "string", value: "123" } },
405
+ expected: {
406
+ success: true,
407
+ result: {
408
+ type: "string",
409
+ segments: [{ type: "text", value: "123" }],
410
+ },
411
+ },
388
412
  },
389
413
  {
390
414
  input: '" spaces "',
391
415
  expected: {
392
416
  success: true,
393
- result: { type: "string", value: " spaces " },
417
+ result: {
418
+ type: "string",
419
+ segments: [{ type: "text", value: " spaces " }],
420
+ },
394
421
  },
395
422
  },
396
423
  {
397
424
  input: '"tab\there"',
398
425
  expected: {
399
426
  success: true,
400
- result: { type: "string", value: "tab\there" },
427
+ result: {
428
+ type: "string",
429
+ segments: [{ type: "text", value: "tab\there" }],
430
+ },
401
431
  },
402
432
  },
403
433
  {
404
- input: '"special!@#$%^&*()"',
434
+ input: '"special!@#%^&*()"',
405
435
  expected: {
406
436
  success: true,
407
- result: { type: "string", value: "special!@#$%^&*()" },
437
+ result: {
438
+ type: "string",
439
+ segments: [{ type: "text", value: "special!@#%^&*()" }],
440
+ },
408
441
  },
409
442
  },
410
443
  {
411
444
  input: '"single\'quote"',
412
445
  expected: {
413
446
  success: true,
414
- result: { type: "string", value: "single'quote" },
447
+ result: {
448
+ type: "string",
449
+ segments: [{ type: "text", value: "single'quote" }],
450
+ },
415
451
  },
416
452
  },
417
453
  {
418
454
  input: '"`backtick`"',
419
455
  expected: {
420
456
  success: true,
421
- result: { type: "string", value: "`backtick`" },
457
+ result: {
458
+ type: "string",
459
+ segments: [{ type: "text", value: "`backtick`" }],
460
+ },
461
+ },
462
+ },
463
+ // Strings with interpolation
464
+ {
465
+ input: '"Hello ${name}"',
466
+ expected: {
467
+ success: true,
468
+ result: {
469
+ type: "string",
470
+ segments: [
471
+ { type: "text", value: "Hello " },
472
+ { type: "interpolation", variableName: "name" },
473
+ ],
474
+ },
475
+ },
476
+ },
477
+ {
478
+ input: '"${greeting} world"',
479
+ expected: {
480
+ success: true,
481
+ result: {
482
+ type: "string",
483
+ segments: [
484
+ { type: "interpolation", variableName: "greeting" },
485
+ { type: "text", value: " world" },
486
+ ],
487
+ },
488
+ },
489
+ },
490
+ {
491
+ input: '"The value is ${x} and ${y}"',
492
+ expected: {
493
+ success: true,
494
+ result: {
495
+ type: "string",
496
+ segments: [
497
+ { type: "text", value: "The value is " },
498
+ { type: "interpolation", variableName: "x" },
499
+ { type: "text", value: " and " },
500
+ { type: "interpolation", variableName: "y" },
501
+ ],
502
+ },
422
503
  },
423
504
  },
424
505
  // Failure cases
@@ -427,13 +508,6 @@ describe("literals parsers", () => {
427
508
  { input: "'hello'", expected: { success: false } },
428
509
  { input: "", expected: { success: false } },
429
510
  { input: "hello", expected: { success: false } },
430
- /// use """ for multi-line strings
431
- {
432
- input: '"newline\nhere"',
433
- expected: {
434
- success: false,
435
- },
436
- },
437
511
  ];
438
512
  testCases.forEach(({ input, expected }) => {
439
513
  if (expected.success) {
@@ -755,11 +829,20 @@ describe("literals parsers", () => {
755
829
  // String literals
756
830
  {
757
831
  input: '"hello"',
758
- expected: { success: true, result: { type: "string", value: "hello" } },
832
+ expected: {
833
+ success: true,
834
+ result: {
835
+ type: "string",
836
+ segments: [{ type: "text", value: "hello" }],
837
+ },
838
+ },
759
839
  },
760
840
  {
761
841
  input: '""',
762
- expected: { success: true, result: { type: "string", value: "" } },
842
+ expected: {
843
+ success: true,
844
+ result: { type: "string", segments: [] },
845
+ },
763
846
  },
764
847
  // Variable name literals (lowest precedence)
765
848
  {
@@ -784,7 +867,13 @@ describe("literals parsers", () => {
784
867
  // Strings vs other types
785
868
  {
786
869
  input: '"123"',
787
- expected: { success: true, result: { type: "string", value: "123" } },
870
+ expected: {
871
+ success: true,
872
+ result: {
873
+ type: "string",
874
+ segments: [{ type: "text", value: "123" }],
875
+ },
876
+ },
788
877
  },
789
878
  // Failure cases
790
879
  { input: "", expected: { success: false } },
@@ -9,16 +9,19 @@ export type MatchBlock = {
9
9
  };
10
10
  */
11
11
  import { capture, char, newline, or, sepBy, seqC, set, str, } from "tarsec";
12
- import { optionalSpaces } from "./utils.js";
12
+ import { optionalSpaces, optionalSpacesOrNewline } from "./utils.js";
13
13
  import { literalParser } from "./literals.js";
14
- import { assignmentParser } from "./assignment.js";
15
14
  import { functionCallParser } from "./functionCall.js";
16
15
  import { accessExpressionParser, indexAccessParser } from "./access.js";
17
16
  import { optionalSemicolon } from "./parserUtils.js";
18
17
  import { agencyArrayParser, agencyObjectParser } from "./dataStructures.js";
19
18
  import { commentParser } from "./comment.js";
20
19
  import { returnStatementParser } from "./returnStatement.js";
20
+ import { assignmentParser } from "./function.js";
21
21
  export const defaultCaseParser = char("_");
22
- export const matchBlockParserCase = seqC(set("type", "matchBlockCase"), optionalSpaces, capture(or(defaultCaseParser, indexAccessParser, accessExpressionParser, literalParser), "caseValue"), optionalSpaces, str("=>"), optionalSpaces, capture(or(returnStatementParser, agencyArrayParser, agencyObjectParser, accessExpressionParser, assignmentParser, functionCallParser, literalParser), "body"));
22
+ export const matchBlockParserCase = (input) => {
23
+ const parser = seqC(set("type", "matchBlockCase"), optionalSpaces, capture(or(defaultCaseParser, indexAccessParser, accessExpressionParser, literalParser), "caseValue"), optionalSpaces, str("=>"), optionalSpaces, capture(or(returnStatementParser, agencyArrayParser, agencyObjectParser, accessExpressionParser, assignmentParser, functionCallParser, literalParser), "body"));
24
+ return parser(input);
25
+ };
23
26
  const semicolon = seqC(optionalSpaces, char(";"), optionalSpaces);
24
- export const matchBlockParser = seqC(set("type", "matchBlock"), str("match"), optionalSpaces, char("("), capture(literalParser, "expression"), char(")"), optionalSpaces, char("{"), optionalSpaces, capture(sepBy(or(semicolon, newline), or(commentParser, matchBlockParserCase)), "cases"), optionalSpaces, char("}"), optionalSemicolon);
27
+ export const matchBlockParser = seqC(set("type", "matchBlock"), str("match"), optionalSpaces, char("("), capture(literalParser, "expression"), char(")"), optionalSpaces, char("{"), optionalSpacesOrNewline, capture(sepBy(or(semicolon, newline), or(commentParser, matchBlockParserCase)), "cases"), optionalSpaces, char("}"), optionalSemicolon);