ohm-js 17.2.1 → 17.3.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.
Files changed (50) hide show
  1. package/dist/ohm-extras.cjs +517 -471
  2. package/dist/ohm-extras.js +517 -471
  3. package/dist/ohm.cjs +510 -464
  4. package/dist/ohm.cjs.map +1 -1
  5. package/dist/ohm.js +511 -465
  6. package/dist/ohm.min.js +1 -1
  7. package/extras/VisitorFamily.js +9 -9
  8. package/extras/index.d.ts +1 -1
  9. package/extras/semantics-toAST.js +1 -1
  10. package/index.d.ts +24 -4
  11. package/package.json +4 -4
  12. package/src/Builder.js +8 -8
  13. package/src/CaseInsensitiveTerminal.js +3 -3
  14. package/src/Grammar.js +69 -70
  15. package/src/GrammarDecl.js +5 -5
  16. package/src/IndentationSensitive.js +6 -6
  17. package/src/InputStream.js +3 -0
  18. package/src/Interval.js +19 -7
  19. package/src/MatchResult.js +14 -16
  20. package/src/MatchState.js +17 -17
  21. package/src/PosInfo.js +7 -7
  22. package/src/Semantics.js +43 -43
  23. package/src/Trace.js +19 -19
  24. package/src/buildGrammar.js +4 -4
  25. package/src/common.js +9 -9
  26. package/src/errors.js +36 -36
  27. package/src/main.js +3 -3
  28. package/src/nodes.js +4 -4
  29. package/src/ohm-cmd.js +5 -5
  30. package/src/pexprs-allowsSkippingPrecedingSpace.js +2 -2
  31. package/src/pexprs-assertAllApplicationsAreValid.js +11 -11
  32. package/src/pexprs-assertChoicesHaveUniformArity.js +9 -9
  33. package/src/pexprs-assertIteratedExprsAreNotNullable.js +7 -7
  34. package/src/pexprs-eval.js +39 -36
  35. package/src/pexprs-getArity.js +6 -6
  36. package/src/pexprs-introduceParams.js +5 -5
  37. package/src/pexprs-isNullable.js +9 -9
  38. package/src/pexprs-main.js +12 -4
  39. package/src/pexprs-outputRecipe.js +15 -15
  40. package/src/pexprs-substituteParams.js +6 -6
  41. package/src/pexprs-toArgumentNameList.js +20 -20
  42. package/src/pexprs-toDisplayString.js +5 -5
  43. package/src/pexprs-toFailure.js +12 -12
  44. package/src/pexprs-toString.js +20 -20
  45. package/src/semanticsDeferredInit.js +8 -8
  46. package/src/unicode.js +54 -0
  47. package/src/util.js +3 -3
  48. package/src/version.js +1 -1
  49. package/dist/ohm-grammar.js.new +0 -0
  50. package/src/UnicodeCategories.js +0 -30
@@ -20,7 +20,7 @@ pexprs.any.allowsSkippingPrecedingSpace =
20
20
  pexprs.Terminal.prototype.allowsSkippingPrecedingSpace =
21
21
  pexprs.Range.prototype.allowsSkippingPrecedingSpace =
22
22
  pexprs.UnicodeChar.prototype.allowsSkippingPrecedingSpace =
23
- function() {
23
+ function () {
24
24
  return true;
25
25
  };
26
26
 
@@ -34,6 +34,6 @@ pexprs.Alt.prototype.allowsSkippingPrecedingSpace =
34
34
  pexprs.Not.prototype.allowsSkippingPrecedingSpace =
35
35
  pexprs.Param.prototype.allowsSkippingPrecedingSpace =
36
36
  pexprs.Seq.prototype.allowsSkippingPrecedingSpace =
37
- function() {
37
+ function () {
38
38
  return false;
39
39
  };
@@ -15,13 +15,13 @@ util.awaitBuiltInRules(g => {
15
15
 
16
16
  let lexifyCount;
17
17
 
18
- pexprs.PExpr.prototype.assertAllApplicationsAreValid = function(ruleName, grammar) {
18
+ pexprs.PExpr.prototype.assertAllApplicationsAreValid = function (ruleName, grammar) {
19
19
  lexifyCount = 0;
20
20
  this._assertAllApplicationsAreValid(ruleName, grammar);
21
21
  };
22
22
 
23
23
  pexprs.PExpr.prototype._assertAllApplicationsAreValid = abstract(
24
- '_assertAllApplicationsAreValid',
24
+ '_assertAllApplicationsAreValid'
25
25
  );
26
26
 
27
27
  pexprs.any._assertAllApplicationsAreValid =
@@ -30,23 +30,23 @@ pexprs.any._assertAllApplicationsAreValid =
30
30
  pexprs.Range.prototype._assertAllApplicationsAreValid =
31
31
  pexprs.Param.prototype._assertAllApplicationsAreValid =
32
32
  pexprs.UnicodeChar.prototype._assertAllApplicationsAreValid =
33
- function(ruleName, grammar) {
33
+ function (ruleName, grammar) {
34
34
  // no-op
35
35
  };
36
36
 
37
- pexprs.Lex.prototype._assertAllApplicationsAreValid = function(ruleName, grammar) {
37
+ pexprs.Lex.prototype._assertAllApplicationsAreValid = function (ruleName, grammar) {
38
38
  lexifyCount++;
39
39
  this.expr._assertAllApplicationsAreValid(ruleName, grammar);
40
40
  lexifyCount--;
41
41
  };
42
42
 
43
- pexprs.Alt.prototype._assertAllApplicationsAreValid = function(ruleName, grammar) {
43
+ pexprs.Alt.prototype._assertAllApplicationsAreValid = function (ruleName, grammar) {
44
44
  for (let idx = 0; idx < this.terms.length; idx++) {
45
45
  this.terms[idx]._assertAllApplicationsAreValid(ruleName, grammar);
46
46
  }
47
47
  };
48
48
 
49
- pexprs.Seq.prototype._assertAllApplicationsAreValid = function(ruleName, grammar) {
49
+ pexprs.Seq.prototype._assertAllApplicationsAreValid = function (ruleName, grammar) {
50
50
  for (let idx = 0; idx < this.factors.length; idx++) {
51
51
  this.factors[idx]._assertAllApplicationsAreValid(ruleName, grammar);
52
52
  }
@@ -55,14 +55,14 @@ pexprs.Seq.prototype._assertAllApplicationsAreValid = function(ruleName, grammar
55
55
  pexprs.Iter.prototype._assertAllApplicationsAreValid =
56
56
  pexprs.Not.prototype._assertAllApplicationsAreValid =
57
57
  pexprs.Lookahead.prototype._assertAllApplicationsAreValid =
58
- function(ruleName, grammar) {
58
+ function (ruleName, grammar) {
59
59
  this.expr._assertAllApplicationsAreValid(ruleName, grammar);
60
60
  };
61
61
 
62
- pexprs.Apply.prototype._assertAllApplicationsAreValid = function(
63
- ruleName,
64
- grammar,
65
- skipSyntacticCheck = false,
62
+ pexprs.Apply.prototype._assertAllApplicationsAreValid = function (
63
+ ruleName,
64
+ grammar,
65
+ skipSyntacticCheck = false
66
66
  ) {
67
67
  const ruleInfo = grammar.rules[this.ruleName];
68
68
  const isContextSyntactic = isSyntactic(ruleName) && lexifyCount === 0;
@@ -7,7 +7,7 @@ import * as pexprs from './pexprs-main.js';
7
7
  // --------------------------------------------------------------------
8
8
 
9
9
  pexprs.PExpr.prototype.assertChoicesHaveUniformArity = abstract(
10
- 'assertChoicesHaveUniformArity',
10
+ 'assertChoicesHaveUniformArity'
11
11
  );
12
12
 
13
13
  pexprs.any.assertChoicesHaveUniformArity =
@@ -17,11 +17,11 @@ pexprs.any.assertChoicesHaveUniformArity =
17
17
  pexprs.Param.prototype.assertChoicesHaveUniformArity =
18
18
  pexprs.Lex.prototype.assertChoicesHaveUniformArity =
19
19
  pexprs.UnicodeChar.prototype.assertChoicesHaveUniformArity =
20
- function(ruleName) {
20
+ function (ruleName) {
21
21
  // no-op
22
22
  };
23
23
 
24
- pexprs.Alt.prototype.assertChoicesHaveUniformArity = function(ruleName) {
24
+ pexprs.Alt.prototype.assertChoicesHaveUniformArity = function (ruleName) {
25
25
  if (this.terms.length === 0) {
26
26
  return;
27
27
  }
@@ -36,7 +36,7 @@ pexprs.Alt.prototype.assertChoicesHaveUniformArity = function(ruleName) {
36
36
  }
37
37
  };
38
38
 
39
- pexprs.Extend.prototype.assertChoicesHaveUniformArity = function(ruleName) {
39
+ pexprs.Extend.prototype.assertChoicesHaveUniformArity = function (ruleName) {
40
40
  // Extend is a special case of Alt that's guaranteed to have exactly two
41
41
  // cases: [extensions, origBody].
42
42
  const actualArity = this.terms[0].getArity();
@@ -46,25 +46,25 @@ pexprs.Extend.prototype.assertChoicesHaveUniformArity = function(ruleName) {
46
46
  }
47
47
  };
48
48
 
49
- pexprs.Seq.prototype.assertChoicesHaveUniformArity = function(ruleName) {
49
+ pexprs.Seq.prototype.assertChoicesHaveUniformArity = function (ruleName) {
50
50
  for (let idx = 0; idx < this.factors.length; idx++) {
51
51
  this.factors[idx].assertChoicesHaveUniformArity(ruleName);
52
52
  }
53
53
  };
54
54
 
55
- pexprs.Iter.prototype.assertChoicesHaveUniformArity = function(ruleName) {
55
+ pexprs.Iter.prototype.assertChoicesHaveUniformArity = function (ruleName) {
56
56
  this.expr.assertChoicesHaveUniformArity(ruleName);
57
57
  };
58
58
 
59
- pexprs.Not.prototype.assertChoicesHaveUniformArity = function(ruleName) {
59
+ pexprs.Not.prototype.assertChoicesHaveUniformArity = function (ruleName) {
60
60
  // no-op (not required b/c the nested expr doesn't show up in the CST)
61
61
  };
62
62
 
63
- pexprs.Lookahead.prototype.assertChoicesHaveUniformArity = function(ruleName) {
63
+ pexprs.Lookahead.prototype.assertChoicesHaveUniformArity = function (ruleName) {
64
64
  this.expr.assertChoicesHaveUniformArity(ruleName);
65
65
  };
66
66
 
67
- pexprs.Apply.prototype.assertChoicesHaveUniformArity = function(ruleName) {
67
+ pexprs.Apply.prototype.assertChoicesHaveUniformArity = function (ruleName) {
68
68
  // The arities of the parameter expressions is required to be 1 by
69
69
  // `assertAllApplicationsAreValid()`.
70
70
  };
@@ -7,7 +7,7 @@ import * as pexprs from './pexprs-main.js';
7
7
  // --------------------------------------------------------------------
8
8
 
9
9
  pexprs.PExpr.prototype.assertIteratedExprsAreNotNullable = abstract(
10
- 'assertIteratedExprsAreNotNullable',
10
+ 'assertIteratedExprsAreNotNullable'
11
11
  );
12
12
 
13
13
  pexprs.any.assertIteratedExprsAreNotNullable =
@@ -16,23 +16,23 @@ pexprs.any.assertIteratedExprsAreNotNullable =
16
16
  pexprs.Range.prototype.assertIteratedExprsAreNotNullable =
17
17
  pexprs.Param.prototype.assertIteratedExprsAreNotNullable =
18
18
  pexprs.UnicodeChar.prototype.assertIteratedExprsAreNotNullable =
19
- function(grammar) {
19
+ function (grammar) {
20
20
  // no-op
21
21
  };
22
22
 
23
- pexprs.Alt.prototype.assertIteratedExprsAreNotNullable = function(grammar) {
23
+ pexprs.Alt.prototype.assertIteratedExprsAreNotNullable = function (grammar) {
24
24
  for (let idx = 0; idx < this.terms.length; idx++) {
25
25
  this.terms[idx].assertIteratedExprsAreNotNullable(grammar);
26
26
  }
27
27
  };
28
28
 
29
- pexprs.Seq.prototype.assertIteratedExprsAreNotNullable = function(grammar) {
29
+ pexprs.Seq.prototype.assertIteratedExprsAreNotNullable = function (grammar) {
30
30
  for (let idx = 0; idx < this.factors.length; idx++) {
31
31
  this.factors[idx].assertIteratedExprsAreNotNullable(grammar);
32
32
  }
33
33
  };
34
34
 
35
- pexprs.Iter.prototype.assertIteratedExprsAreNotNullable = function(grammar) {
35
+ pexprs.Iter.prototype.assertIteratedExprsAreNotNullable = function (grammar) {
36
36
  // Note: this is the implementation of this method for `Star` and `Plus` expressions.
37
37
  // It is overridden for `Opt` below.
38
38
  this.expr.assertIteratedExprsAreNotNullable(grammar);
@@ -45,11 +45,11 @@ pexprs.Opt.prototype.assertIteratedExprsAreNotNullable =
45
45
  pexprs.Not.prototype.assertIteratedExprsAreNotNullable =
46
46
  pexprs.Lookahead.prototype.assertIteratedExprsAreNotNullable =
47
47
  pexprs.Lex.prototype.assertIteratedExprsAreNotNullable =
48
- function(grammar) {
48
+ function (grammar) {
49
49
  this.expr.assertIteratedExprsAreNotNullable(grammar);
50
50
  };
51
51
 
52
- pexprs.Apply.prototype.assertIteratedExprsAreNotNullable = function(grammar) {
52
+ pexprs.Apply.prototype.assertIteratedExprsAreNotNullable = function (grammar) {
53
53
  this.args.forEach(arg => {
54
54
  arg.assertIteratedExprsAreNotNullable(grammar);
55
55
  });
@@ -3,6 +3,7 @@ import * as common from './common.js';
3
3
  import * as errors from './errors.js';
4
4
  import {IterationNode, NonterminalNode, TerminalNode} from './nodes.js';
5
5
  import * as pexprs from './pexprs-main.js';
6
+ import {MAX_CODE_POINT} from './InputStream.js';
6
7
 
7
8
  // --------------------------------------------------------------------
8
9
  // Operations
@@ -26,7 +27,7 @@ import * as pexprs from './pexprs-main.js';
26
27
  */
27
28
  pexprs.PExpr.prototype.eval = common.abstract('eval'); // function(state) { ... }
28
29
 
29
- pexprs.any.eval = function(state) {
30
+ pexprs.any.eval = function (state) {
30
31
  const {inputStream} = state;
31
32
  const origPos = inputStream.pos;
32
33
  const cp = inputStream.nextCodePoint();
@@ -39,7 +40,7 @@ pexprs.any.eval = function(state) {
39
40
  }
40
41
  };
41
42
 
42
- pexprs.end.eval = function(state) {
43
+ pexprs.end.eval = function (state) {
43
44
  const {inputStream} = state;
44
45
  const origPos = inputStream.pos;
45
46
  if (inputStream.atEnd()) {
@@ -51,7 +52,7 @@ pexprs.end.eval = function(state) {
51
52
  }
52
53
  };
53
54
 
54
- pexprs.Terminal.prototype.eval = function(state) {
55
+ pexprs.Terminal.prototype.eval = function (state) {
55
56
  const {inputStream} = state;
56
57
  const origPos = inputStream.pos;
57
58
  if (!inputStream.matchString(this.obj)) {
@@ -63,7 +64,7 @@ pexprs.Terminal.prototype.eval = function(state) {
63
64
  }
64
65
  };
65
66
 
66
- pexprs.Range.prototype.eval = function(state) {
67
+ pexprs.Range.prototype.eval = function (state) {
67
68
  const {inputStream} = state;
68
69
  const origPos = inputStream.pos;
69
70
 
@@ -82,18 +83,18 @@ pexprs.Range.prototype.eval = function(state) {
82
83
  }
83
84
  };
84
85
 
85
- pexprs.Param.prototype.eval = function(state) {
86
+ pexprs.Param.prototype.eval = function (state) {
86
87
  return state.eval(state.currentApplication().args[this.index]);
87
88
  };
88
89
 
89
- pexprs.Lex.prototype.eval = function(state) {
90
+ pexprs.Lex.prototype.eval = function (state) {
90
91
  state.enterLexifiedContext();
91
92
  const ans = state.eval(this.expr);
92
93
  state.exitLexifiedContext();
93
94
  return ans;
94
95
  };
95
96
 
96
- pexprs.Alt.prototype.eval = function(state) {
97
+ pexprs.Alt.prototype.eval = function (state) {
97
98
  for (let idx = 0; idx < this.terms.length; idx++) {
98
99
  if (state.eval(this.terms[idx])) {
99
100
  return true;
@@ -102,7 +103,7 @@ pexprs.Alt.prototype.eval = function(state) {
102
103
  return false;
103
104
  };
104
105
 
105
- pexprs.Seq.prototype.eval = function(state) {
106
+ pexprs.Seq.prototype.eval = function (state) {
106
107
  for (let idx = 0; idx < this.factors.length; idx++) {
107
108
  const factor = this.factors[idx];
108
109
  if (!state.eval(factor)) {
@@ -112,7 +113,7 @@ pexprs.Seq.prototype.eval = function(state) {
112
113
  return true;
113
114
  };
114
115
 
115
- pexprs.Iter.prototype.eval = function(state) {
116
+ pexprs.Iter.prototype.eval = function (state) {
116
117
  const {inputStream} = state;
117
118
  const origPos = inputStream.pos;
118
119
  const arity = this.getArity();
@@ -134,8 +135,8 @@ pexprs.Iter.prototype.eval = function(state) {
134
135
  numMatches++;
135
136
  const row = state._bindings.splice(state._bindings.length - arity, arity);
136
137
  const rowOffsets = state._bindingOffsets.splice(
137
- state._bindingOffsets.length - arity,
138
- arity,
138
+ state._bindingOffsets.length - arity,
139
+ arity
139
140
  );
140
141
  for (idx = 0; idx < row.length; idx++) {
141
142
  cols[idx].push(row[idx]);
@@ -159,14 +160,14 @@ pexprs.Iter.prototype.eval = function(state) {
159
160
  const isOptional = this instanceof pexprs.Opt;
160
161
  for (idx = 0; idx < cols.length; idx++) {
161
162
  state._bindings.push(
162
- new IterationNode(cols[idx], colOffsets[idx], matchLength, isOptional),
163
+ new IterationNode(cols[idx], colOffsets[idx], matchLength, isOptional)
163
164
  );
164
165
  state._bindingOffsets.push(offset);
165
166
  }
166
167
  return true;
167
168
  };
168
169
 
169
- pexprs.Not.prototype.eval = function(state) {
170
+ pexprs.Not.prototype.eval = function (state) {
170
171
  /*
171
172
  TODO:
172
173
  - Right now we're just throwing away all of the failures that happen inside a `not`, and
@@ -192,7 +193,7 @@ pexprs.Not.prototype.eval = function(state) {
192
193
  return true;
193
194
  };
194
195
 
195
- pexprs.Lookahead.prototype.eval = function(state) {
196
+ pexprs.Lookahead.prototype.eval = function (state) {
196
197
  const {inputStream} = state;
197
198
  const origPos = inputStream.pos;
198
199
  if (state.eval(this.expr)) {
@@ -203,7 +204,7 @@ pexprs.Lookahead.prototype.eval = function(state) {
203
204
  }
204
205
  };
205
206
 
206
- pexprs.Apply.prototype.eval = function(state) {
207
+ pexprs.Apply.prototype.eval = function (state) {
207
208
  const caller = state.currentApplication();
208
209
  const actuals = caller ? caller.args : [];
209
210
  const app = this.substituteParams(actuals);
@@ -226,7 +227,7 @@ pexprs.Apply.prototype.eval = function(state) {
226
227
  return app.reallyEval(state);
227
228
  };
228
229
 
229
- pexprs.Apply.prototype.handleCycle = function(state) {
230
+ pexprs.Apply.prototype.handleCycle = function (state) {
230
231
  const posInfo = state.getCurrentPosInfo();
231
232
  const {currentLeftRecursion} = posInfo;
232
233
  const memoKey = this.toMemoKey();
@@ -249,7 +250,7 @@ pexprs.Apply.prototype.handleCycle = function(state) {
249
250
  return state.useMemoizedResult(state.inputStream.pos, memoRec);
250
251
  };
251
252
 
252
- pexprs.Apply.prototype.reallyEval = function(state) {
253
+ pexprs.Apply.prototype.reallyEval = function (state) {
253
254
  const {inputStream} = state;
254
255
  const origPos = inputStream.pos;
255
256
  const origPosInfo = state.getCurrentPosInfo();
@@ -319,8 +320,8 @@ pexprs.Apply.prototype.reallyEval = function(state) {
319
320
  // Fix the input stream's examinedLength -- it should be the maximum examined length
320
321
  // across all applications, not just this one.
321
322
  inputStream.examinedLength = Math.max(
322
- inputStream.examinedLength,
323
- origInputStreamExaminedLength,
323
+ inputStream.examinedLength,
324
+ origInputStreamExaminedLength
324
325
  );
325
326
 
326
327
  state.exitApplication(origPosInfo, value);
@@ -328,7 +329,7 @@ pexprs.Apply.prototype.reallyEval = function(state) {
328
329
  return succeeded;
329
330
  };
330
331
 
331
- pexprs.Apply.prototype.evalOnce = function(expr, state) {
332
+ pexprs.Apply.prototype.evalOnce = function (expr, state) {
332
333
  const {inputStream} = state;
333
334
  const origPos = inputStream.pos;
334
335
 
@@ -343,7 +344,7 @@ pexprs.Apply.prototype.evalOnce = function(expr, state) {
343
344
  }
344
345
  };
345
346
 
346
- pexprs.Apply.prototype.growSeedResult = function(body, state, origPos, lrMemoRec, newValue) {
347
+ pexprs.Apply.prototype.growSeedResult = function (body, state, origPos, lrMemoRec, newValue) {
347
348
  if (!newValue) {
348
349
  return false;
349
350
  }
@@ -361,13 +362,13 @@ pexprs.Apply.prototype.growSeedResult = function(body, state, origPos, lrMemoRec
361
362
  // element in `state.trace`.
362
363
  const seedTrace = state.trace[state.trace.length - 1];
363
364
  lrMemoRec.traceEntry = new Trace(
364
- state.input,
365
- origPos,
366
- inputStream.pos,
367
- this,
368
- true,
369
- [newValue],
370
- [seedTrace.clone()],
365
+ state.input,
366
+ origPos,
367
+ inputStream.pos,
368
+ this,
369
+ true,
370
+ [newValue],
371
+ [seedTrace.clone()]
371
372
  );
372
373
  }
373
374
  inputStream.pos = origPos;
@@ -387,15 +388,17 @@ pexprs.Apply.prototype.growSeedResult = function(body, state, origPos, lrMemoRec
387
388
  return lrMemoRec.value;
388
389
  };
389
390
 
390
- pexprs.UnicodeChar.prototype.eval = function(state) {
391
+ pexprs.UnicodeChar.prototype.eval = function (state) {
391
392
  const {inputStream} = state;
392
393
  const origPos = inputStream.pos;
393
- const ch = inputStream.next();
394
- if (ch && this.pattern.test(ch)) {
395
- state.pushBinding(new TerminalNode(ch.length), origPos);
396
- return true;
397
- } else {
398
- state.processFailure(origPos, this);
399
- return false;
394
+ const cp = inputStream.nextCodePoint();
395
+ if (cp !== undefined && cp <= MAX_CODE_POINT) {
396
+ const ch = String.fromCodePoint(cp);
397
+ if (this.pattern.test(ch)) {
398
+ state.pushBinding(new TerminalNode(ch.length), origPos);
399
+ return true;
400
+ }
400
401
  }
402
+ state.processFailure(origPos, this);
403
+ return false;
401
404
  };
@@ -14,17 +14,17 @@ pexprs.any.getArity =
14
14
  pexprs.Param.prototype.getArity =
15
15
  pexprs.Apply.prototype.getArity =
16
16
  pexprs.UnicodeChar.prototype.getArity =
17
- function() {
17
+ function () {
18
18
  return 1;
19
19
  };
20
20
 
21
- pexprs.Alt.prototype.getArity = function() {
21
+ pexprs.Alt.prototype.getArity = function () {
22
22
  // This is ok b/c all terms must have the same arity -- this property is
23
23
  // checked by the Grammar constructor.
24
24
  return this.terms.length === 0 ? 0 : this.terms[0].getArity();
25
25
  };
26
26
 
27
- pexprs.Seq.prototype.getArity = function() {
27
+ pexprs.Seq.prototype.getArity = function () {
28
28
  let arity = 0;
29
29
  for (let idx = 0; idx < this.factors.length; idx++) {
30
30
  arity += this.factors[idx].getArity();
@@ -32,14 +32,14 @@ pexprs.Seq.prototype.getArity = function() {
32
32
  return arity;
33
33
  };
34
34
 
35
- pexprs.Iter.prototype.getArity = function() {
35
+ pexprs.Iter.prototype.getArity = function () {
36
36
  return this.expr.getArity();
37
37
  };
38
38
 
39
- pexprs.Not.prototype.getArity = function() {
39
+ pexprs.Not.prototype.getArity = function () {
40
40
  return 0;
41
41
  };
42
42
 
43
- pexprs.Lookahead.prototype.getArity = pexprs.Lex.prototype.getArity = function() {
43
+ pexprs.Lookahead.prototype.getArity = pexprs.Lex.prototype.getArity = function () {
44
44
  return this.expr.getArity();
45
45
  };
@@ -18,18 +18,18 @@ pexprs.any.introduceParams =
18
18
  pexprs.Range.prototype.introduceParams =
19
19
  pexprs.Param.prototype.introduceParams =
20
20
  pexprs.UnicodeChar.prototype.introduceParams =
21
- function(formals) {
21
+ function (formals) {
22
22
  return this;
23
23
  };
24
24
 
25
- pexprs.Alt.prototype.introduceParams = function(formals) {
25
+ pexprs.Alt.prototype.introduceParams = function (formals) {
26
26
  this.terms.forEach((term, idx, terms) => {
27
27
  terms[idx] = term.introduceParams(formals);
28
28
  });
29
29
  return this;
30
30
  };
31
31
 
32
- pexprs.Seq.prototype.introduceParams = function(formals) {
32
+ pexprs.Seq.prototype.introduceParams = function (formals) {
33
33
  this.factors.forEach((factor, idx, factors) => {
34
34
  factors[idx] = factor.introduceParams(formals);
35
35
  });
@@ -40,12 +40,12 @@ pexprs.Iter.prototype.introduceParams =
40
40
  pexprs.Not.prototype.introduceParams =
41
41
  pexprs.Lookahead.prototype.introduceParams =
42
42
  pexprs.Lex.prototype.introduceParams =
43
- function(formals) {
43
+ function (formals) {
44
44
  this.expr = this.expr.introduceParams(formals);
45
45
  return this;
46
46
  };
47
47
 
48
- pexprs.Apply.prototype.introduceParams = function(formals) {
48
+ pexprs.Apply.prototype.introduceParams = function (formals) {
49
49
  const index = formals.indexOf(this.ruleName);
50
50
  if (index >= 0) {
51
51
  if (this.args.length > 0) {
@@ -6,7 +6,7 @@ import * as pexprs from './pexprs-main.js';
6
6
  // --------------------------------------------------------------------
7
7
 
8
8
  // Returns `true` if this parsing expression may accept without consuming any input.
9
- pexprs.PExpr.prototype.isNullable = function(grammar) {
9
+ pexprs.PExpr.prototype.isNullable = function (grammar) {
10
10
  return this._isNullable(grammar, Object.create(null));
11
11
  };
12
12
 
@@ -17,15 +17,15 @@ pexprs.any._isNullable =
17
17
  pexprs.Param.prototype._isNullable =
18
18
  pexprs.Plus.prototype._isNullable =
19
19
  pexprs.UnicodeChar.prototype._isNullable =
20
- function(grammar, memo) {
20
+ function (grammar, memo) {
21
21
  return false;
22
22
  };
23
23
 
24
- pexprs.end._isNullable = function(grammar, memo) {
24
+ pexprs.end._isNullable = function (grammar, memo) {
25
25
  return true;
26
26
  };
27
27
 
28
- pexprs.Terminal.prototype._isNullable = function(grammar, memo) {
28
+ pexprs.Terminal.prototype._isNullable = function (grammar, memo) {
29
29
  if (typeof this.obj === 'string') {
30
30
  // This is an over-simplification: it's only correct if the input is a string. If it's an array
31
31
  // or an object, then the empty string parsing expression is not nullable.
@@ -35,11 +35,11 @@ pexprs.Terminal.prototype._isNullable = function(grammar, memo) {
35
35
  }
36
36
  };
37
37
 
38
- pexprs.Alt.prototype._isNullable = function(grammar, memo) {
38
+ pexprs.Alt.prototype._isNullable = function (grammar, memo) {
39
39
  return this.terms.length === 0 || this.terms.some(term => term._isNullable(grammar, memo));
40
40
  };
41
41
 
42
- pexprs.Seq.prototype._isNullable = function(grammar, memo) {
42
+ pexprs.Seq.prototype._isNullable = function (grammar, memo) {
43
43
  return this.factors.every(factor => factor._isNullable(grammar, memo));
44
44
  };
45
45
 
@@ -47,15 +47,15 @@ pexprs.Star.prototype._isNullable =
47
47
  pexprs.Opt.prototype._isNullable =
48
48
  pexprs.Not.prototype._isNullable =
49
49
  pexprs.Lookahead.prototype._isNullable =
50
- function(grammar, memo) {
50
+ function (grammar, memo) {
51
51
  return true;
52
52
  };
53
53
 
54
- pexprs.Lex.prototype._isNullable = function(grammar, memo) {
54
+ pexprs.Lex.prototype._isNullable = function (grammar, memo) {
55
55
  return this.expr._isNullable(grammar, memo);
56
56
  };
57
57
 
58
- pexprs.Apply.prototype._isNullable = function(grammar, memo) {
58
+ pexprs.Apply.prototype._isNullable = function (grammar, memo) {
59
59
  const key = this.toMemoKey();
60
60
  if (!Object.prototype.hasOwnProperty.call(memo, key)) {
61
61
  const {body} = grammar.rules[this.ruleName];
@@ -1,4 +1,4 @@
1
- import {UnicodeCategories} from './UnicodeCategories.js';
1
+ import {UnicodeBinaryProperties, UnicodeCategories} from './unicode.js';
2
2
  import * as common from './common.js';
3
3
 
4
4
  // --------------------------------------------------------------------
@@ -180,9 +180,17 @@ export class Apply extends PExpr {
180
180
  // Unicode character
181
181
 
182
182
  export class UnicodeChar extends PExpr {
183
- constructor(category) {
183
+ constructor(categoryOrProp) {
184
184
  super();
185
- this.category = category;
186
- this.pattern = UnicodeCategories[category];
185
+ this.categoryOrProp = categoryOrProp;
186
+ if (categoryOrProp in UnicodeCategories) {
187
+ this.pattern = UnicodeCategories[categoryOrProp];
188
+ } else if (categoryOrProp in UnicodeBinaryProperties) {
189
+ this.pattern = UnicodeBinaryProperties[categoryOrProp];
190
+ } else {
191
+ throw new Error(
192
+ `Invalid Unicode category or property name: ${JSON.stringify(categoryOrProp)}`
193
+ );
194
+ }
187
195
  }
188
196
  }
@@ -20,38 +20,38 @@ function getMetaInfo(expr, grammarInterval) {
20
20
 
21
21
  pexprs.PExpr.prototype.outputRecipe = abstract('outputRecipe');
22
22
 
23
- pexprs.any.outputRecipe = function(formals, grammarInterval) {
23
+ pexprs.any.outputRecipe = function (formals, grammarInterval) {
24
24
  return ['any', getMetaInfo(this, grammarInterval)];
25
25
  };
26
26
 
27
- pexprs.end.outputRecipe = function(formals, grammarInterval) {
27
+ pexprs.end.outputRecipe = function (formals, grammarInterval) {
28
28
  return ['end', getMetaInfo(this, grammarInterval)];
29
29
  };
30
30
 
31
- pexprs.Terminal.prototype.outputRecipe = function(formals, grammarInterval) {
31
+ pexprs.Terminal.prototype.outputRecipe = function (formals, grammarInterval) {
32
32
  return ['terminal', getMetaInfo(this, grammarInterval), this.obj];
33
33
  };
34
34
 
35
- pexprs.Range.prototype.outputRecipe = function(formals, grammarInterval) {
35
+ pexprs.Range.prototype.outputRecipe = function (formals, grammarInterval) {
36
36
  return ['range', getMetaInfo(this, grammarInterval), this.from, this.to];
37
37
  };
38
38
 
39
- pexprs.Param.prototype.outputRecipe = function(formals, grammarInterval) {
39
+ pexprs.Param.prototype.outputRecipe = function (formals, grammarInterval) {
40
40
  return ['param', getMetaInfo(this, grammarInterval), this.index];
41
41
  };
42
42
 
43
- pexprs.Alt.prototype.outputRecipe = function(formals, grammarInterval) {
43
+ pexprs.Alt.prototype.outputRecipe = function (formals, grammarInterval) {
44
44
  return ['alt', getMetaInfo(this, grammarInterval)].concat(
45
- this.terms.map(term => term.outputRecipe(formals, grammarInterval)),
45
+ this.terms.map(term => term.outputRecipe(formals, grammarInterval))
46
46
  );
47
47
  };
48
48
 
49
- pexprs.Extend.prototype.outputRecipe = function(formals, grammarInterval) {
49
+ pexprs.Extend.prototype.outputRecipe = function (formals, grammarInterval) {
50
50
  const extension = this.terms[0]; // [extension, original]
51
51
  return extension.outputRecipe(formals, grammarInterval);
52
52
  };
53
53
 
54
- pexprs.Splice.prototype.outputRecipe = function(formals, grammarInterval) {
54
+ pexprs.Splice.prototype.outputRecipe = function (formals, grammarInterval) {
55
55
  const beforeTerms = this.terms.slice(0, this.expansionPos);
56
56
  const afterTerms = this.terms.slice(this.expansionPos + 1);
57
57
  return [
@@ -62,9 +62,9 @@ pexprs.Splice.prototype.outputRecipe = function(formals, grammarInterval) {
62
62
  ];
63
63
  };
64
64
 
65
- pexprs.Seq.prototype.outputRecipe = function(formals, grammarInterval) {
65
+ pexprs.Seq.prototype.outputRecipe = function (formals, grammarInterval) {
66
66
  return ['seq', getMetaInfo(this, grammarInterval)].concat(
67
- this.factors.map(factor => factor.outputRecipe(formals, grammarInterval)),
67
+ this.factors.map(factor => factor.outputRecipe(formals, grammarInterval))
68
68
  );
69
69
  };
70
70
 
@@ -74,7 +74,7 @@ pexprs.Star.prototype.outputRecipe =
74
74
  pexprs.Not.prototype.outputRecipe =
75
75
  pexprs.Lookahead.prototype.outputRecipe =
76
76
  pexprs.Lex.prototype.outputRecipe =
77
- function(formals, grammarInterval) {
77
+ function (formals, grammarInterval) {
78
78
  return [
79
79
  this.constructor.name.toLowerCase(),
80
80
  getMetaInfo(this, grammarInterval),
@@ -82,7 +82,7 @@ pexprs.Star.prototype.outputRecipe =
82
82
  ];
83
83
  };
84
84
 
85
- pexprs.Apply.prototype.outputRecipe = function(formals, grammarInterval) {
85
+ pexprs.Apply.prototype.outputRecipe = function (formals, grammarInterval) {
86
86
  return [
87
87
  'app',
88
88
  getMetaInfo(this, grammarInterval),
@@ -91,6 +91,6 @@ pexprs.Apply.prototype.outputRecipe = function(formals, grammarInterval) {
91
91
  ];
92
92
  };
93
93
 
94
- pexprs.UnicodeChar.prototype.outputRecipe = function(formals, grammarInterval) {
95
- return ['unicodeChar', getMetaInfo(this, grammarInterval), this.category];
94
+ pexprs.UnicodeChar.prototype.outputRecipe = function (formals, grammarInterval) {
95
+ return ['unicodeChar', getMetaInfo(this, grammarInterval), this.categoryOrProp];
96
96
  };