@weborigami/language 0.2.0 → 0.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/language",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Web Origami expression language compiler and runtime",
5
5
  "type": "module",
6
6
  "main": "./main.js",
@@ -12,8 +12,8 @@
12
12
  "yaml": "2.5.1"
13
13
  },
14
14
  "dependencies": {
15
- "@weborigami/async-tree": "0.2.0",
16
- "@weborigami/types": "0.2.0",
15
+ "@weborigami/async-tree": "0.2.1",
16
+ "@weborigami/types": "0.2.1",
17
17
  "watcher": "2.3.1"
18
18
  },
19
19
  "scripts": {
@@ -16,7 +16,7 @@ import {
16
16
  annotate,
17
17
  downgradeReference,
18
18
  makeArray,
19
- makeBinaryOperatorChain,
19
+ makeBinaryOperation,
20
20
  makeCall,
21
21
  makeDeferredArguments,
22
22
  makeObject,
@@ -24,7 +24,7 @@ import {
24
24
  makeProperty,
25
25
  makeReference,
26
26
  makeTemplate,
27
- makeUnaryOperatorCall
27
+ makeUnaryOperation
28
28
  } from "./parserHelpers.js";
29
29
 
30
30
  }}
@@ -35,6 +35,15 @@ __
35
35
  return null;
36
36
  }
37
37
 
38
+ additiveExpression
39
+ = head:multiplicativeExpression tail:(__ @additiveOperator __ @multiplicativeExpression)* {
40
+ return annotate(tail.reduce(makeBinaryOperation, head), location());
41
+ }
42
+
43
+ additiveOperator
44
+ = "+"
45
+ / "-"
46
+
38
47
  arguments "function arguments"
39
48
  = parenthesesArguments
40
49
  / pathArguments
@@ -54,20 +63,49 @@ arrayEntries
54
63
  arrayEntry
55
64
  = spread
56
65
  / pipelineExpression
66
+ // JavaScript treats a missing value as `undefined`
67
+ / __ !"]" {
68
+ return annotate([ops.literal, undefined], location());
69
+ }
57
70
 
58
71
  arrowFunction
59
72
  = "(" __ parameters:identifierList? __ ")" __ doubleArrow __ pipeline:pipelineExpression {
60
73
  return annotate([ops.lambda, parameters ?? [], pipeline], location());
61
74
  }
75
+ / identifier:identifier __ doubleArrow __ pipeline:pipelineExpression {
76
+ return annotate([ops.lambda, [identifier], pipeline], location());
77
+ }
62
78
  / conditionalExpression
63
79
 
80
+ bitwiseAndExpression
81
+ = head:equalityExpression tail:(__ @bitwiseAndOperator __ @equalityExpression)* {
82
+ return annotate(tail.reduce(makeBinaryOperation, head), location());
83
+ }
84
+
85
+ bitwiseAndOperator
86
+ = @"&" !"&"
87
+
88
+ bitwiseOrExpression
89
+ = head:bitwiseXorExpression tail:(__ @bitwiseOrOperator __ @bitwiseXorExpression)* {
90
+ return annotate(tail.reduce(makeBinaryOperation, head), location());
91
+ }
92
+
93
+ bitwiseOrOperator
94
+ = @"|" !"|"
95
+
96
+ bitwiseXorExpression
97
+ = head:bitwiseAndExpression tail:(__ @bitwiseXorOperator __ @bitwiseAndExpression)* {
98
+ return annotate(tail.reduce(makeBinaryOperation, head), location());
99
+ }
100
+
101
+ bitwiseXorOperator
102
+ = "^"
103
+
64
104
  // A function call: `fn(arg)`, possibly part of a chain of function calls, like
65
105
  // `fn(arg1)(arg2)(arg3)`.
66
106
  callExpression "function call"
67
107
  = head:protocolExpression tail:arguments* {
68
- return tail.length === 0
69
- ? head
70
- : annotate(tail.reduce(makeCall, head), location());
108
+ return annotate(tail.reduce(makeCall, head), location());
71
109
  }
72
110
 
73
111
  // Required closing curly brace. We use this for the `object` term: if the
@@ -94,6 +132,15 @@ closingParenthesis
94
132
  error("Expected right parenthesis");
95
133
  }
96
134
 
135
+ // A comma-separated list of expressions: `x, y, z`
136
+ commaExpression
137
+ // The commas are required, but the list can have a single item.
138
+ = list:pipelineExpression|1.., __ "," __ | {
139
+ return list.length === 1
140
+ ? list[0]
141
+ : annotate([ops.comma, ...list], location());
142
+ }
143
+
97
144
  // A single line comment
98
145
  comment "comment"
99
146
  = multiLineComment
@@ -129,10 +176,8 @@ doubleQuoteStringChar
129
176
  ellipsis = "..." / "…" // Unicode ellipsis
130
177
 
131
178
  equalityExpression
132
- = head:unaryExpression tail:(__ @equalityOperator __ @unaryExpression)* {
133
- return tail.length === 0
134
- ? head
135
- : annotate(makeBinaryOperatorChain(head, tail), location());
179
+ = head:relationalExpression tail:(__ @equalityOperator __ @relationalExpression)* {
180
+ return annotate(tail.reduce(makeBinaryOperation, head), location());
136
181
  }
137
182
 
138
183
  equalityOperator
@@ -151,12 +196,18 @@ escapedChar "backslash-escaped character"
151
196
  / "\\v" { return "\v"; }
152
197
  / "\\" @.
153
198
 
199
+ exponentiationExpression
200
+ = left:unaryExpression __ "**" __ right:exponentiationExpression {
201
+ return annotate([ops.exponentiation, left, right], location());
202
+ }
203
+ / unaryExpression
204
+
154
205
  // A top-level expression, possibly with leading/trailing whitespace
155
206
  expression
156
- = __ @pipelineExpression __
207
+ = __ @commaExpression __
157
208
 
158
209
  floatLiteral "floating-point number"
159
- = sign? digits? "." digits {
210
+ = digits? "." digits {
160
211
  return annotate([ops.literal, parseFloat(text())], location());
161
212
  }
162
213
 
@@ -195,7 +246,7 @@ identifier "identifier"
195
246
  = chars:identifierChar+ { return chars.join(""); }
196
247
 
197
248
  identifierChar
198
- = [^(){}\[\]<>\?!&\|\-=,/:\`"'«»\\ →⇒\t\n\r] // No unescaped whitespace or special chars
249
+ = [^(){}\[\]<>\?!\|\-=,/:\`"'«»\\→⇒… \t\n\r] // No unescaped whitespace or special chars
199
250
  / @'-' !'>' // Accept a hyphen but not in a single arrow combination
200
251
  / escapedChar
201
252
 
@@ -220,7 +271,7 @@ inlineSpace
220
271
  = [ \t]
221
272
 
222
273
  integerLiteral "integer"
223
- = sign? digits {
274
+ = digits {
224
275
  return annotate([ops.literal, parseInt(text())], location());
225
276
  }
226
277
 
@@ -235,7 +286,7 @@ literal
235
286
  / stringLiteral
236
287
 
237
288
  logicalAndExpression
238
- = head:equalityExpression tail:(__ "&&" __ @equalityExpression)* {
289
+ = head:bitwiseOrExpression tail:(__ "&&" __ @bitwiseOrExpression)* {
239
290
  return tail.length === 0
240
291
  ? head
241
292
  : annotate(
@@ -257,6 +308,16 @@ logicalOrExpression
257
308
  multiLineComment
258
309
  = "/*" (!"*/" .)* "*/" { return null; }
259
310
 
311
+ multiplicativeExpression
312
+ = head:exponentiationExpression tail:(__ @multiplicativeOperator __ @exponentiationExpression)* {
313
+ return annotate(tail.reduce(makeBinaryOperation, head), location());
314
+ }
315
+
316
+ multiplicativeOperator
317
+ = "*"
318
+ / "/"
319
+ / "%"
320
+
260
321
  // A namespace reference is a string of letters only, followed by a colon.
261
322
  // For the time being, we also allow a leading `@`, which is deprecated.
262
323
  namespace
@@ -382,7 +443,10 @@ pathSegmentChar
382
443
  // functions to it.
383
444
  pipelineExpression
384
445
  = head:shorthandFunction tail:(__ singleArrow __ @shorthandFunction)* {
385
- return tail.reduce(makePipeline, downgradeReference(head));
446
+ return annotate(
447
+ tail.reduce(makePipeline, downgradeReference(head)),
448
+ location()
449
+ );
386
450
  }
387
451
 
388
452
  primary
@@ -419,6 +483,17 @@ reference
419
483
  / namespace
420
484
  / scopeReference
421
485
 
486
+ relationalExpression
487
+ = head:shiftExpression tail:(__ @relationalOperator __ @shiftExpression)* {
488
+ return annotate(tail.reduce(makeBinaryOperation, head), location());
489
+ }
490
+
491
+ relationalOperator
492
+ = "<="
493
+ / "<"
494
+ / ">="
495
+ / ">"
496
+
422
497
  // A top-level folder below the root: `/foo`
423
498
  // or the root folder itself: `/`
424
499
  rootDirectory
@@ -449,6 +524,16 @@ slashFollows
449
524
  shebang
450
525
  = "#!" [^\n\r]* { return null; }
451
526
 
527
+ shiftExpression
528
+ = head:additiveExpression tail:(__ @shiftOperator __ @additiveExpression)* {
529
+ return annotate(tail.reduce(makeBinaryOperation, head), location());
530
+ }
531
+
532
+ shiftOperator
533
+ = "<<"
534
+ / ">>>"
535
+ / ">>"
536
+
452
537
  // A shorthand lambda expression: `=foo(_)`
453
538
  shorthandFunction "lambda function"
454
539
  // Avoid a following equal sign (for an equality)
@@ -457,9 +542,6 @@ shorthandFunction "lambda function"
457
542
  }
458
543
  / implicitParenthesesCallExpression
459
544
 
460
- sign
461
- = [+\-]
462
-
463
545
  singleArrow
464
546
  = "→"
465
547
  / "->"
@@ -539,12 +621,15 @@ textChar
539
621
  // A unary prefix operator: `!x`
540
622
  unaryExpression
541
623
  = operator:unaryOperator __ expression:unaryExpression {
542
- return annotate(makeUnaryOperatorCall(operator, expression), location());
624
+ return annotate(makeUnaryOperation(operator, expression), location());
543
625
  }
544
626
  / callExpression
545
627
 
546
628
  unaryOperator
547
629
  = "!"
630
+ / "+"
631
+ / "-"
632
+ / "~"
548
633
 
549
634
  whitespaceWithNewLine
550
635
  = inlineSpace* comment? newLine __