spex-parser 0.1.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.
@@ -0,0 +1,37 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Setup Node.js
19
+ uses: actions/setup-node@v4
20
+ with:
21
+ node-version: '20'
22
+ cache: 'npm'
23
+
24
+ - name: Install dependencies
25
+ run: npm ci
26
+
27
+ - name: Build
28
+ run: npm run build
29
+
30
+ - name: Type check
31
+ run: npx tsc --noEmit
32
+
33
+ - name: Run tests
34
+ run: npm test
35
+
36
+ - name: Check formatting
37
+ run: npm run format:check
@@ -0,0 +1,35 @@
1
+ name: Publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ name: Publish to npm
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout
14
+ uses: actions/checkout@v4
15
+
16
+ - name: Setup Node.js
17
+ uses: actions/setup-node@v4
18
+ with:
19
+ node-version: '20'
20
+ registry-url: 'https://registry.npmjs.org'
21
+ cache: 'npm'
22
+
23
+ - name: Install dependencies
24
+ run: npm ci
25
+
26
+ - name: Build
27
+ run: npm run build
28
+
29
+ - name: Run tests
30
+ run: npm test
31
+
32
+ - name: Publish to npm
33
+ run: npm stage publish
34
+ env:
35
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/.prettierrc ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "semi": false,
3
+ "singleQuote": true,
4
+ "trailingComma": "es5",
5
+ "printWidth": 100,
6
+ "tabWidth": 2,
7
+ "useTabs": false
8
+ }
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2026 Freelansys
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,513 @@
1
+ # Spex
2
+
3
+ Spex is a declarative language for AI-assisted software development. It addresses shortcomings of the chat interface commonly used in AI coding assistant tools.
4
+
5
+ In particular, Spex aims to solve the following problems:
6
+
7
+ - Instructions given to AI coding assistants contain valuable information, but this information is often lost among the noise produced during conversations.
8
+ - Professional software developers must adapt to a new mental model when programming through chat interfaces.
9
+ - Programs produced through chat interactions are difficult to reproduce because the exact prompts and their order are lost.
10
+ - Chat interfaces do not integrate well with existing software engineering tools such as version control systems.
11
+ - Referencing objects in the code base requires repetitive and verbose prompts.
12
+ - Because architecture and design are not persisted, AI agents must constantly read and reason about multiple files, leading to inefficient token usage.
13
+ - Reusability in chat interfaces is extremely limited and abstraction is arbitrary.
14
+
15
+ The idea behind chat interfaces in AI coding tools is that _everyone_ should be able to code. While admirable, this approach often makes the tools inadequate for professional developers.
16
+
17
+ Spex acknowledges that in serious software projects it is neither wise nor feasible to replace programmers with machines. Instead, Spex integrates with the mental model and ecosystem of professional programmers, enabling them to be significantly more efficient. For this reason, Spex is probably not suited to someone that is not familiar with programming. This is a conscious decision made to cater to the needs of professional programmers and not the general public.
18
+
19
+ For this reason, Spex syntax is intentionally close to common languages such as TypeScript and SQL. Instead of manually implementing software, developers describe *spaces of valid implementations* using familiar programming abstractions such as:
20
+
21
+ * objects
22
+ * functions
23
+ * dependencies
24
+ * constraints
25
+
26
+ The Spex runtime synthesizes concrete implementations based on these specifications.
27
+
28
+ ---
29
+
30
+ # Core Idea
31
+
32
+ In Spex:
33
+
34
+ * a type represents a space of possible implementations
35
+ * constraints refine that space
36
+ * reusable abstractions are represented as subtypes
37
+
38
+ For example:
39
+
40
+ ```spex
41
+ CREATE SecureEndpoint AS
42
+ FROM HttpRequest -> HttpResponse
43
+ SELECT {
44
+ - the user is authenticated and authorised.
45
+ - The call is rate limited.
46
+ };
47
+ ```
48
+
49
+ `SecureEndpoint` now represents the set of all endpoint implementations satisfying those constraints.
50
+
51
+ Developers can build on top of these abstractions instead of repeatedly specifying common architectural concerns.
52
+
53
+ ---
54
+
55
+ # Design Goals
56
+
57
+ Spex is designed to:
58
+
59
+ * feel familiar to software developers
60
+ * resemble SQL-style declarative programming
61
+ * support compositional software synthesis
62
+ * enable reusable architectural abstractions
63
+
64
+ ---
65
+
66
+ # Objects
67
+
68
+ Objects are analogous to types in a programming language. Objects can be translated to classes, structs, functions, etc.
69
+
70
+ ## Basic Objects
71
+
72
+ Basic objects are provided by Spex natively. These objects represent the common basic types in a programming language:
73
+
74
+ ```spex
75
+ string
76
+ number
77
+ bool
78
+ unit
79
+ ```
80
+
81
+ `unit` is a special object that represent an empty type. It is useful in defining functions that take no input or do not return anything.
82
+
83
+ ## Arrays
84
+
85
+ To represent an array:
86
+
87
+ ```spex
88
+ string[]
89
+ ```
90
+
91
+ ## Products
92
+
93
+ Product objects are created by combining other objects:
94
+
95
+ ```spex
96
+ (
97
+ id: string,
98
+ done: bool
99
+ )
100
+ ```
101
+
102
+ `unit` objects in a product are ignored. Meaning, the following products are the same:
103
+
104
+ ```spex
105
+ (
106
+ id: string,
107
+ foo: unit
108
+ )
109
+
110
+ (
111
+ id: string
112
+ )
113
+ ```
114
+
115
+ Consequently, `()` and `unit` are the same object.
116
+
117
+ ## Exponentials
118
+
119
+ Spex support function types as well which are refered to as exponential objects. An exponential is defined by its domain and codomain which have to be objects themselves:
120
+
121
+ ```spex
122
+ string -> number
123
+ (id: string) -> number
124
+ string -> unit
125
+ unit -> string
126
+ ```
127
+ `string -> unit` represents all functions that take a string as input and do not return anything. `unit -> string` on the other hand, is a function that takes nothing as input, but returns a string.
128
+
129
+ ## Subobjects
130
+
131
+ Subobjects are analogous to subsets. Subobjects refine an object by selecting memebers that satisfy some constraints. Constraints are defined through natural language:
132
+
133
+ ```spex
134
+ FROM string
135
+ SELECT {
136
+ are email addresses
137
+ }
138
+
139
+ FROM string -> number
140
+ SELECT {
141
+ return the length of the given string
142
+ }
143
+ ```
144
+
145
+ Subobjects are themselves objects so they could be subobjected as well. A good heuristic for writing constraints is to make the expression read as:
146
+
147
+ > "from `object` select those that `{constraint}`".
148
+
149
+ # Named Objects
150
+
151
+ To name an object for reuse:
152
+
153
+ ```spex
154
+ CREATE Todo AS
155
+ (
156
+ id: string,
157
+ title: string,
158
+ completed: bool,
159
+ created_at: string
160
+ );
161
+
162
+ CREATE EmailAddress AS
163
+ FROM string
164
+ SELECT {
165
+ are email addresses
166
+ };
167
+
168
+ CREATE slugify AS
169
+ FROM string -> string
170
+ SELECT {
171
+ return the slugified string
172
+ };
173
+ ```
174
+
175
+ ---
176
+
177
+ # Referencing
178
+
179
+ Spex allows referencing other objects in constraints using string interpolation as in template strings. The scope of a variable is determined using the same rules as in Typescript.
180
+
181
+ ```spex
182
+ CREATE Todo AS
183
+ (
184
+ id: string,
185
+ title: string,
186
+ completed: bool,
187
+ created_at: string
188
+ );
189
+
190
+ CREATE validate AS
191
+ FROM Todo -> bool
192
+ SELECT {
193
+ return true if @created_at is a valid date and return false otherwise
194
+ };
195
+
196
+ CREATE CreateTodo AS
197
+ FROM Todo -> Bool
198
+ SELECT {
199
+ 1. call @validate to validate the given todo
200
+ 2. throw an exception if validation failed
201
+ 3. insert the todo in the Todo table
202
+ }
203
+ ```
204
+
205
+ This forms an explicit software dependency graph between objects.
206
+
207
+ Use `.` to reference a member of a product object:
208
+
209
+ ```spex
210
+ CREATE ComplexNumber AS
211
+ (
212
+ real: number,
213
+ imag: number
214
+ );
215
+
216
+ CREATE Abs AS
217
+ FROM (z: ComplexNumber) -> number
218
+ SELECT {
219
+ return square root of @z.real^2 + @z.imag^2
220
+ }
221
+ ```
222
+
223
+ ---
224
+
225
+ # Importing and Exporting
226
+
227
+ If there is a need to reuse some object in other files, we have to export the object and then import it where it is needed.
228
+
229
+ Suppose we have a file `types.spex` with the following content:
230
+
231
+ ```spex
232
+ CREATE EmailAddress AS
233
+ FROM string
234
+ SELECT {
235
+ are email addresses
236
+ };
237
+
238
+ CREATE Password AS
239
+ FROM string
240
+ SELECT {
241
+ - have at least 8 characters
242
+ - contain at least one upper case character
243
+ - contain at least one lower case character
244
+ - contain at least one number character
245
+ - contain at least one special character
246
+ };
247
+
248
+ EXPORT EmailAddress;
249
+ EXPORT Password;
250
+ ```
251
+
252
+ Then, we can import `EmailAddress` as itself in some other file:
253
+
254
+ ```spex
255
+ IMPORT EmailAddress FROM "types.spex";
256
+ ```
257
+
258
+ Or give it a different alias:
259
+
260
+ ```spex
261
+ IMPORT EmailAddress FROM "types.spex" AS Username;
262
+ ```
263
+
264
+ Or import the whole file:
265
+
266
+ ```spex
267
+ IMPORT "types.spex" AS type;
268
+ ```
269
+
270
+ In case the whole file is imported, it's objects could be referenced by:
271
+
272
+ ```spex
273
+ IMPORT "types.spex" AS types;
274
+
275
+ CREATE SignUp AS
276
+ FROM (user: types.EmailAddress, pass: types.Password) -> string
277
+ SELECT {
278
+ 1. Check @user doesn't exists
279
+ 2. throw an error if the user exists
280
+ 3. add @user to the User table alongside the SHA-256 hash of @pass
281
+ 4. return the id of the newly created user
282
+ }
283
+ ```
284
+
285
+ ---
286
+
287
+ # Generating Code
288
+
289
+ To specify what objects in an specification has to be generated as explicit code:
290
+
291
+ ```spex
292
+ GENERATE CreateTodo
293
+ ```
294
+
295
+ Generation of some object naturally triggers generation of it's dependencies as well.
296
+
297
+ ---
298
+
299
+ # Why SQL?
300
+
301
+ Spex uses SQL-inspired syntax because developers already understand:
302
+
303
+ * schemas
304
+ * views
305
+ * refinement through selection
306
+ * declarative programming
307
+ * dependency relationships
308
+
309
+ This dramatically reduces the learning curve.
310
+
311
+ ---
312
+
313
+ # Long-Term Vision
314
+
315
+ Spex aims to provide:
316
+
317
+ * reusable semantic software abstractions
318
+ * compositional AI-assisted programming
319
+ * declarative architecture specification
320
+ * implementation synthesis guided by constraints
321
+
322
+ Instead of prompting LLMs directly, developers work with structured software semantics that can be analyzed, refined, verified, and synthesized.
323
+
324
+ # Example: Todo CLI App
325
+
326
+ This example demonstrates a simple command-line Todo application written in Spex.
327
+
328
+ The application supports:
329
+
330
+ - adding todos
331
+ - listing todos
332
+ - marking todos as completed
333
+ - persisting todos to disk
334
+ - validating input
335
+
336
+ ---
337
+
338
+ ## Domain Objects
339
+
340
+ ```spex
341
+ CREATE TodoTitle AS
342
+ FROM string
343
+ SELECT {
344
+ - are not empty
345
+ - are shorter than 120 characters
346
+ };
347
+
348
+ CREATE Todo AS
349
+ (
350
+ id: string,
351
+ title: TodoTitle,
352
+ completed: bool
353
+ );
354
+ ```
355
+
356
+ ---
357
+
358
+ ## Storage Layer
359
+
360
+ ```spex
361
+ CREATE TodoFilePath AS
362
+ FROM string
363
+ SELECT {
364
+ represent a valid path to a JSON file storing todos
365
+ };
366
+
367
+ CREATE LoadTodos AS
368
+ FROM (path: TodoFilePath) -> Todo[]
369
+ SELECT {
370
+ 1. read the JSON file at @path
371
+ 2. return an empty list if the file does not exist
372
+ 3. parse the JSON content into todos
373
+ 4. throw an exception if the JSON is invalid
374
+ };
375
+
376
+ CREATE SaveTodos AS
377
+ FROM (
378
+ path: TodoFilePath,
379
+ todos: Todo[]
380
+ ) -> unit
381
+ SELECT {
382
+ 1. serialize @todos as formatted JSON
383
+ 2. write the JSON to @path
384
+ };
385
+ ```
386
+
387
+ ---
388
+
389
+ ## Todo Creation
390
+
391
+ ```spex
392
+ CREATE CreateTodo AS
393
+ FROM (
394
+ title: TodoTitle
395
+ ) -> Todo
396
+ SELECT {
397
+ 1. generate a UUID for the todo id
398
+ 2. create a todo with completed set to false
399
+ 3. return the created todo
400
+ };
401
+ ```
402
+
403
+ ---
404
+
405
+ ## Add Todo Command
406
+
407
+ ```spex
408
+ CREATE AddTodo AS
409
+ FROM (
410
+ path: TodoFilePath,
411
+ title: TodoTitle
412
+ ) -> Todo
413
+ SELECT {
414
+ 1. call @LoadTodos using @path
415
+ 2. call @CreateTodo using @title
416
+ 3. append the new todo to the loaded todos
417
+ 4. call @SaveTodos to persist the updated todos
418
+ 5. return the created todo
419
+ };
420
+ ```
421
+
422
+ ---
423
+
424
+ ## List Todos Command
425
+
426
+ ```spex
427
+ CREATE ListTodos AS
428
+ FROM (
429
+ path: TodoFilePath
430
+ ) -> string
431
+ SELECT {
432
+ 1. load todos using @LoadTodos
433
+ 2. return a formatted string representation of all todos
434
+ 3. show completed todos with a checkmark
435
+ 4. show incomplete todos with an empty checkbox
436
+ };
437
+ ```
438
+
439
+ ---
440
+
441
+ ## Complete Todo Command
442
+
443
+ ```spex
444
+ CREATE CompleteTodo AS
445
+ FROM (
446
+ path: TodoFilePath,
447
+ id: TodoId
448
+ ) -> Todo
449
+ SELECT {
450
+ 1. load todos using @LoadTodos
451
+ 2. search for the todo matching @id
452
+ 3. throw an exception if the todo does not exist
453
+ 4. set the todo completed status to true
454
+ 5. persist the updated todo list using @SaveTodos
455
+ 6. return the updated todo
456
+ };
457
+ ```
458
+
459
+ ---
460
+
461
+ ## CLI Parsing
462
+
463
+ ```spex
464
+ CREATE CliArgs AS
465
+ (
466
+ command: string,
467
+ arguments: string[]
468
+ );
469
+
470
+ CREATE ParseCliArgs AS
471
+ FROM string[] -> CliArgs
472
+ SELECT {
473
+ 1. parse the command line arguments
474
+ 2. extract the command name
475
+ 3. extract the command arguments
476
+ };
477
+ ```
478
+
479
+ ---
480
+
481
+ ## CLI Entry Point
482
+
483
+ ```spex
484
+ CREATE Main AS
485
+ FROM string[] -> unit
486
+ SELECT {
487
+ 1. parse process arguments using @ParseCliArgs
488
+
489
+ 2. if the command is "add":
490
+ - call @AddTodo
491
+
492
+ 3. if the command is "list":
493
+ - call @ListTodos
494
+ - print the result to stdout
495
+
496
+ 4. if the command is "complete":
497
+ - call @CompleteTodo
498
+
499
+ 5. print a help message if the command is invalid
500
+
501
+ 6. print user-friendly error messages for exceptions
502
+ };
503
+ ```
504
+
505
+ ---
506
+
507
+ ## Code Generation
508
+
509
+ ```spex
510
+ GENERATE Main
511
+ ```
512
+
513
+ This triggers generation of the complete CLI application and all required dependencies.
package/dist/ast.d.ts ADDED
@@ -0,0 +1,48 @@
1
+ export type SpexFile = {
2
+ kind: 'SpexFile';
3
+ declarations: Declaration[];
4
+ };
5
+ export type Declaration = ObjectDeclaration | ImportDeclaration | ExportDeclaration | GenerateDeclaration;
6
+ export type ObjectDeclaration = {
7
+ kind: 'ObjectDeclaration';
8
+ name: string;
9
+ object: ObjectExpression;
10
+ };
11
+ export type ImportDeclaration = {
12
+ kind: 'ImportDeclaration';
13
+ name: string | null;
14
+ source: string;
15
+ alias: string | null;
16
+ };
17
+ export type ExportDeclaration = {
18
+ kind: 'ExportDeclaration';
19
+ name: string;
20
+ };
21
+ export type GenerateDeclaration = {
22
+ kind: 'GenerateDeclaration';
23
+ name: string;
24
+ };
25
+ export type ObjectExpression = NamedObject | ProductObject | ExponentialObject | SubObject | ArrayObject;
26
+ export type NamedObject = {
27
+ kind: 'NamedObject';
28
+ name: string;
29
+ };
30
+ export type ProductObject = {
31
+ kind: 'ProductObject';
32
+ fields: Record<string, ObjectExpression>;
33
+ };
34
+ export type ExponentialObject = {
35
+ kind: 'ExponentialObject';
36
+ base: ObjectExpression;
37
+ exponent: ObjectExpression;
38
+ };
39
+ export type SubObject = {
40
+ kind: 'SubObject';
41
+ base: ObjectExpression;
42
+ constraint: string;
43
+ };
44
+ export type ArrayObject = {
45
+ kind: 'ArrayObject';
46
+ base: ObjectExpression;
47
+ };
48
+ //# sourceMappingURL=ast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../src/ast.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,UAAU,CAAA;IAChB,YAAY,EAAE,WAAW,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,WAAW,GACnB,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,mBAAmB,CAAA;AAEvB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,mBAAmB,CAAA;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,gBAAgB,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,mBAAmB,CAAA;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,mBAAmB,CAAA;IACzB,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,qBAAqB,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,gBAAgB,GACxB,WAAW,GACX,aAAa,GACb,iBAAiB,GACjB,SAAS,GACT,WAAW,CAAA;AAEf,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,aAAa,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,eAAe,CAAA;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CACzC,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,mBAAmB,CAAA;IACzB,IAAI,EAAE,gBAAgB,CAAA;IACtB,QAAQ,EAAE,gBAAgB,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,WAAW,CAAA;IACjB,IAAI,EAAE,gBAAgB,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,aAAa,CAAA;IACnB,IAAI,EAAE,gBAAgB,CAAA;CACvB,CAAA"}
package/dist/ast.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.js","sourceRoot":"","sources":["../src/ast.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ export { SpexLexer } from './lexer.js';
2
+ export { SpexParser } from './parser.js';
3
+ export { SpexParserVisitor, parseToAst } from './visitor.js';
4
+ export type { SpexFile, Declaration, ObjectDeclaration, ObjectExpression, NamedObject, ProductObject, ExponentialObject, SubObject, } from './ast.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC5D,YAAY,EACV,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,SAAS,GACV,MAAM,UAAU,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { SpexLexer } from './lexer.js';
2
+ export { SpexParser } from './parser.js';
3
+ export { SpexParserVisitor, parseToAst } from './visitor.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA"}