@weborigami/language 0.0.64 → 0.0.65-beta.2

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/index.ts CHANGED
@@ -3,13 +3,16 @@ import { Packed } from "@weborigami/async-tree";
3
3
  export * from "./main.js";
4
4
 
5
5
  /**
6
- * A chunk of compiled Origami code. This is just an Array with an additional
7
- * `source` property.
6
+ * A chunk of compiled Origami code. This is just an array with an additional
7
+ * `location` property.
8
8
  */
9
- interface ArrayWithSource extends Array<any> {
10
- source?: Source;
11
- }
12
- export type Code = ArrayWithSource;
9
+ export type Code = Array<any> & {
10
+ location: {
11
+ source: Source;
12
+ start: Position;
13
+ end: Position;
14
+ };
15
+ };
13
16
 
14
17
  /**
15
18
  * A class constructor is an object with a `new` method that returns an
@@ -26,6 +29,14 @@ export type ExtensionHandler = {
26
29
  unpack?: UnpackFunction;
27
30
  }
28
31
 
32
+ export type ParseResult = Code | string | number;
33
+
34
+ export type Position = {
35
+ column: number;
36
+ line: number;
37
+ offset: number;
38
+ }
39
+
29
40
  /**
30
41
  * A mixin is a function that takes an existing class and returns a new class.
31
42
  *
@@ -40,11 +51,11 @@ export type Mixin<MixinMembers> = <T>(
40
51
 
41
52
  /**
42
53
  * Source code representation used by the parser.
43
- */
54
+ */
44
55
  export type Source = {
45
- name: string;
56
+ name?: string;
46
57
  text: string;
47
- url: URL;
58
+ url?: URL;
48
59
  }
49
60
 
50
61
  /**
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@weborigami/language",
3
- "version": "0.0.64",
3
+ "version": "0.0.65-beta.2",
4
4
  "description": "Web Origami expression language compiler and runtime",
5
5
  "type": "module",
6
6
  "main": "./main.js",
7
7
  "types": "./index.ts",
8
8
  "devDependencies": {
9
- "@types/node": "20.14.9",
9
+ "@types/node": "22.5.4",
10
10
  "peggy": "4.0.3",
11
- "typescript": "5.5.3"
11
+ "typescript": "5.5.4"
12
12
  },
13
13
  "dependencies": {
14
- "@weborigami/async-tree": "0.0.64",
15
- "@weborigami/types": "0.0.64",
14
+ "@weborigami/async-tree": "0.0.65-beta.2",
15
+ "@weborigami/types": "0.0.65-beta.2",
16
16
  "watcher": "2.3.1"
17
17
  },
18
18
  "scripts": {
@@ -8,11 +8,11 @@ function compile(source, startRule) {
8
8
  // Trim whitespace from template blocks before we begin lexing, as our
9
9
  // heuristics are non-local and hard to implement in our parser.
10
10
  const preprocessed = trimTemplateWhitespace(source.text);
11
- const code = parse(preprocessed, {
11
+ const parseResult = parse(preprocessed, {
12
12
  grammarSource: source,
13
13
  startRule,
14
14
  });
15
- const fn = createExpressionFunction(code);
15
+ const fn = createExpressionFunction(parseResult);
16
16
  return fn;
17
17
  }
18
18
 
@@ -7,16 +7,14 @@
7
7
  //
8
8
 
9
9
  import * as ops from "../runtime/ops.js";
10
- import { makeArray, makeFunctionCall, makeObject, makePipeline, makeTemplate } from "./parserHelpers.js";
11
-
12
- // If a parse result is an object that will be evaluated at runtime, attach the
13
- // location of the source code that produced it for debugging and error messages.
14
- function annotate(parseResult, location) {
15
- if (typeof parseResult === "object" && parseResult !== null) {
16
- parseResult.location = location;
17
- }
18
- return parseResult;
19
- }
10
+ import {
11
+ annotate,
12
+ makeArray,
13
+ makeFunctionCall,
14
+ makeObject,
15
+ makePipeline,
16
+ makeTemplate
17
+ } from "./parserHelpers.js";
20
18
 
21
19
  }}
22
20
 
@@ -45,7 +43,9 @@ array "array"
45
43
 
46
44
  // A separated list of array entries
47
45
  arrayEntries
48
- = @arrayEntry|1.., separator| separator?
46
+ = entries:arrayEntry|1.., separator| separator? {
47
+ return annotate(entries, location());
48
+ }
49
49
 
50
50
  arrayEntry
51
51
  = spread
@@ -68,15 +68,15 @@ callTarget "function call"
68
68
  closingBrace
69
69
  = "}"
70
70
  / .? {
71
- error("Expected right curly brace");
72
- }
71
+ error("Expected right curly brace");
72
+ }
73
73
 
74
74
  // Required closing bracket
75
75
  closingBracket
76
76
  = "]"
77
77
  / .? {
78
- error("Expected right bracket");
79
- }
78
+ error("Expected right bracket");
79
+ }
80
80
 
81
81
  // Required closing parenthesis. We use this for the `group` term: it's the last
82
82
  // term in the `step` parser that starts with a parenthesis, so if that parser
@@ -84,8 +84,8 @@ closingBracket
84
84
  closingParen
85
85
  = ")"
86
86
  / .? {
87
- error("Expected right parenthesis");
88
- }
87
+ error("Expected right parenthesis");
88
+ }
89
89
 
90
90
  // A single line comment
91
91
  comment "comment"
@@ -106,7 +106,14 @@ doubleQuoteStringChar
106
106
  ellipsis = "..." / "…" // Unicode ellipsis
107
107
 
108
108
  escapedChar "backslash-escaped character"
109
- = "\\" @.
109
+ = "\\0" { return "\0"; }
110
+ / "\\b" { return "\b"; }
111
+ / "\\f" { return "\f"; }
112
+ / "\\n" { return "\n"; }
113
+ / "\\r" { return "\r"; }
114
+ / "\\t" { return "\t"; }
115
+ / "\\v" { return "\v"; }
116
+ / "\\" @.
110
117
 
111
118
  // An Origami expression, no leading/trailing whitespace
112
119
  expr
@@ -126,15 +133,17 @@ float "floating-point number"
126
133
  // of function calls, like `fn(arg1)(arg2)(arg3)`.
127
134
  functionComposition "function composition"
128
135
  = target:callTarget chain:args* end:implicitParensArgs? {
129
- if (end) {
130
- chain.push(end);
136
+ if (end) {
137
+ chain.push(end);
138
+ }
139
+ return annotate(makeFunctionCall(target, chain), location());
131
140
  }
132
- return annotate(makeFunctionCall(target, chain), location());
133
- }
134
141
 
135
142
  // An expression in parentheses: `(foo)`
136
143
  group "parenthetical group"
137
- = "(" __ @expr __ closingParen
144
+ = "(" __ expr:expr __ closingParen {
145
+ return annotate(expr, location());
146
+ }
138
147
 
139
148
  guillemetString "guillemet string"
140
149
  = '«' chars:guillemetStringChar* '»' { return chars.join(""); }
@@ -157,7 +166,9 @@ identifierChar
157
166
  / escapedChar
158
167
 
159
168
  identifierList
160
- = @identifier|1.., separator| separator?
169
+ = list:identifier|1.., separator| separator? {
170
+ return annotate(list, location());
171
+ }
161
172
 
162
173
  identifierOrString
163
174
  = identifier
@@ -166,7 +177,10 @@ identifierOrString
166
177
  implicitParensArgs "arguments with implicit parentheses"
167
178
  // Implicit parens args are a separate list of `step`, not `expr`, because
168
179
  // they can't contain a pipeline.
169
- = inlineSpace+ @step|1.., separator| separator?
180
+ = inlineSpace+ args:step|1.., separator| separator? {
181
+ /* Stuff */
182
+ return annotate(args, location());
183
+ }
170
184
 
171
185
  inlineSpace
172
186
  = [ \t]
@@ -184,12 +198,18 @@ lambda "lambda function"
184
198
 
185
199
  // A path that begins with a slash: `/foo/bar`
186
200
  leadingSlashPath "path with a leading slash"
187
- = "/" @path
188
- / "/" { return annotate([""], location()); }
201
+ = "/" path:path {
202
+ return annotate(path, location());
203
+ }
204
+ / "/" {
205
+ return annotate([""], location());
206
+ }
189
207
 
190
208
  // A separated list of expressions
191
209
  list "list"
192
- = @expr|1.., separator| separator?
210
+ = list:expr|1.., separator| separator? {
211
+ return annotate(list, location());
212
+ }
193
213
 
194
214
  multiLineComment
195
215
  = "/*" (!"*/" .)* "*/" { return null; }
@@ -212,7 +232,9 @@ object "object literal"
212
232
 
213
233
  // A separated list of object entries
214
234
  objectEntries
215
- = @objectEntry|1.., separator| separator?
235
+ = entries:objectEntry|1.., separator| separator? {
236
+ return annotate(entries, location());
237
+ }
216
238
 
217
239
  objectEntry
218
240
  = spread
@@ -223,8 +245,8 @@ objectEntry
223
245
  // A getter definition inside an object literal: `foo = 1`
224
246
  objectGetter "object getter"
225
247
  = key:objectKey __ "=" __ value:expr {
226
- return annotate([key, [ops.getter, value]], location());
227
- }
248
+ return annotate([key, [ops.getter, value]], location());
249
+ }
228
250
 
229
251
  // A standalone reference inside an object literal: `foo`
230
252
  objectIdentifier "object identifier"
@@ -238,17 +260,19 @@ objectKey "object key"
238
260
 
239
261
  // A property definition in an object literal: `x: 1`
240
262
  objectProperty "object property"
241
- = @objectKey __ ":" __ @expr
263
+ = key:objectKey __ ":" __ value:expr {
264
+ return annotate([key, value], location());
265
+ }
242
266
 
243
267
  parameterizedLambda
244
268
  = "(" __ parameters:identifierList? __ ")" __ doubleArrow __ expr:expr {
245
- return annotate([ops.lambda, parameters ?? [], expr], location());
246
- }
269
+ return annotate([ops.lambda, parameters ?? [], expr], location());
270
+ }
247
271
 
248
272
  // Function arguments in parentheses
249
273
  parensArgs "function arguments in parentheses"
250
274
  = "(" __ list:list? __ ")" {
251
- return list ?? annotate([undefined], location());
275
+ return annotate(list ?? [undefined], location());
252
276
  }
253
277
 
254
278
  pipeline
@@ -258,7 +282,9 @@ pipeline
258
282
 
259
283
  // A slash-separated path of keys
260
284
  path "slash-separated path"
261
- = pathKey|1.., "/"|
285
+ = path:pathKey|1.., "/"| {
286
+ return annotate(path, location());
287
+ }
262
288
 
263
289
  // A single key in a slash-separated path
264
290
  pathKey "path element"
@@ -318,7 +344,9 @@ singleQuoteStringChar
318
344
  = !("'" / newLine) @textChar
319
345
 
320
346
  spread
321
- = ellipsis expr:expr { return [ops.spread, expr]; }
347
+ = ellipsis expr:expr {
348
+ return annotate([ops.spread, expr], location());
349
+ }
322
350
 
323
351
  // A single step in a pipeline, or a top-level expression
324
352
  step
@@ -372,7 +400,9 @@ templateDocumentText "template text"
372
400
 
373
401
  // A backtick-quoted template literal
374
402
  templateLiteral "template literal"
375
- = "`" @templateLiteralContents "`"
403
+ = "`" contents:templateLiteralContents "`" {
404
+ return annotate(contents, location());
405
+ }
376
406
 
377
407
  templateLiteralChar
378
408
  = !("`" / "${") @textChar
@@ -389,10 +419,13 @@ templateLiteralText
389
419
 
390
420
  // A substitution in a template literal: `${x}`
391
421
  templateSubstitution "template substitution"
392
- = "${" __ @expr __ "}"
422
+ = "${" __ expr:expr __ "}" {
423
+ return annotate(expr, location());
424
+ }
393
425
 
394
426
  textChar
395
- = escapedChar / .
427
+ = escapedChar
428
+ / .
396
429
 
397
430
  whitespaceWithNewLine
398
431
  = inlineSpace* comment? newLine __
@@ -1,3 +1,3 @@
1
- import { Code } from "../../index.ts";
1
+ import { ParseResult } from "../../index.ts";
2
2
 
3
- export function parse(input: string, options: any): Code;
3
+ export function parse(input: string, options: any): ParseResult;