ohm-js 17.2.1 → 17.4.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 (52) hide show
  1. package/dist/ohm-extras.cjs +568 -471
  2. package/dist/ohm-extras.js +568 -471
  3. package/dist/ohm.cjs +511 -464
  4. package/dist/ohm.cjs.map +1 -1
  5. package/dist/ohm.js +512 -465
  6. package/dist/ohm.min.js +1 -1
  7. package/extras/VisitorFamily.js +9 -9
  8. package/extras/index.d.ts +7 -11
  9. package/extras/index.mjs +1 -0
  10. package/extras/recoverSourceOrder.js +48 -0
  11. package/extras/semantics-toAST.js +1 -1
  12. package/index.d.ts +24 -4
  13. package/package.json +4 -4
  14. package/src/Builder.js +8 -8
  15. package/src/CaseInsensitiveTerminal.js +3 -3
  16. package/src/Grammar.js +69 -70
  17. package/src/GrammarDecl.js +5 -5
  18. package/src/IndentationSensitive.js +6 -6
  19. package/src/InputStream.js +3 -0
  20. package/src/Interval.js +19 -7
  21. package/src/MatchResult.js +14 -16
  22. package/src/MatchState.js +17 -17
  23. package/src/PosInfo.js +7 -7
  24. package/src/Semantics.js +43 -43
  25. package/src/Trace.js +19 -19
  26. package/src/buildGrammar.js +4 -4
  27. package/src/common.js +9 -9
  28. package/src/errors.js +36 -36
  29. package/src/main.js +3 -3
  30. package/src/nodes.js +4 -4
  31. package/src/ohm-cmd.js +5 -5
  32. package/src/pexprs-allowsSkippingPrecedingSpace.js +2 -2
  33. package/src/pexprs-assertAllApplicationsAreValid.js +11 -11
  34. package/src/pexprs-assertChoicesHaveUniformArity.js +9 -9
  35. package/src/pexprs-assertIteratedExprsAreNotNullable.js +7 -7
  36. package/src/pexprs-eval.js +40 -36
  37. package/src/pexprs-getArity.js +6 -6
  38. package/src/pexprs-introduceParams.js +5 -5
  39. package/src/pexprs-isNullable.js +9 -9
  40. package/src/pexprs-main.js +12 -4
  41. package/src/pexprs-outputRecipe.js +15 -15
  42. package/src/pexprs-substituteParams.js +6 -6
  43. package/src/pexprs-toArgumentNameList.js +20 -20
  44. package/src/pexprs-toDisplayString.js +5 -5
  45. package/src/pexprs-toFailure.js +12 -12
  46. package/src/pexprs-toString.js +20 -20
  47. package/src/semanticsDeferredInit.js +8 -8
  48. package/src/unicode.js +54 -0
  49. package/src/util.js +3 -3
  50. package/src/version.js +1 -1
  51. package/dist/ohm-grammar.js.new +0 -0
  52. package/src/UnicodeCategories.js +0 -30
@@ -12,14 +12,14 @@
12
12
 
13
13
  function abstract(optMethodName) {
14
14
  const methodName = optMethodName || '';
15
- return function() {
15
+ return function () {
16
16
  throw new Error(
17
- 'this method ' +
17
+ 'this method ' +
18
18
  methodName +
19
19
  ' is abstract! ' +
20
20
  '(it has no implementation in class ' +
21
21
  this.constructor.name +
22
- ')',
22
+ ')'
23
23
  );
24
24
  };
25
25
  }
@@ -112,11 +112,11 @@
112
112
  this.strings = [];
113
113
  }
114
114
 
115
- StringBuffer.prototype.append = function(str) {
115
+ StringBuffer.prototype.append = function (str) {
116
116
  this.strings.push(str);
117
117
  };
118
118
 
119
- StringBuffer.prototype.contents = function() {
119
+ StringBuffer.prototype.contents = function () {
120
120
  return this.strings.join('');
121
121
  };
122
122
 
@@ -140,9 +140,9 @@
140
140
  case 'x':
141
141
  return escapeUnicode(s.slice(2, 4));
142
142
  case 'u':
143
- return s.charAt(2) === '{' ?
144
- escapeUnicode(s.slice(3, -1)) :
145
- escapeUnicode(s.slice(2, 6));
143
+ return s.charAt(2) === '{'
144
+ ? escapeUnicode(s.slice(3, -1))
145
+ : escapeUnicode(s.slice(2, 6));
146
146
  default:
147
147
  return s.charAt(1);
148
148
  }
@@ -168,7 +168,7 @@
168
168
  typeName = typeof obj;
169
169
  }
170
170
  return typeName + ': ' + JSON.stringify(String(obj));
171
- } catch (e) {
171
+ } catch {
172
172
  return baseToString;
173
173
  }
174
174
  }
@@ -334,9 +334,9 @@
334
334
  // Get the next line.
335
335
  const nextLineEndOffset = str.indexOf('\n', lineEndOffset + 1);
336
336
  nextLine =
337
- nextLineEndOffset === -1 ?
338
- str.slice(lineEndOffset) :
339
- str.slice(lineEndOffset, nextLineEndOffset);
337
+ nextLineEndOffset === -1
338
+ ? str.slice(lineEndOffset)
339
+ : str.slice(lineEndOffset, nextLineEndOffset);
340
340
  // Strip leading and trailing EOL char(s).
341
341
  nextLine = nextLine.replace(/^\r?\n/, '').replace(/\r$/, '');
342
342
  }
@@ -448,11 +448,11 @@
448
448
  this._shapes = config.shapes;
449
449
  this._getTag = config.getTag;
450
450
 
451
- this.Adapter = function(thing, family) {
451
+ this.Adapter = function (thing, family) {
452
452
  this._adaptee = thing;
453
453
  this._family = family;
454
454
  };
455
- this.Adapter.prototype.valueOf = function() {
455
+ this.Adapter.prototype.valueOf = function () {
456
456
  throw new Error('heeey!');
457
457
  };
458
458
  this.operations = {};
@@ -481,15 +481,15 @@
481
481
  assert(k in this._getChildren, "Unrecognized action name '" + k + "'");
482
482
  const action = dict[k];
483
483
  assert(
484
- typeof action === 'function',
485
- "Key '" + k + "': expected function, got " + action,
484
+ typeof action === 'function',
485
+ "Key '" + k + "': expected function, got " + action
486
486
  );
487
487
  if (k in this._arities) {
488
488
  const expected = this._arities[k];
489
489
  const actual = dict[k].length;
490
490
  assert(
491
- actual === expected,
492
- "Action '" + k + "' has the wrong arity: expected " + expected + ', got ' + actual,
491
+ actual === expected,
492
+ "Action '" + k + "' has the wrong arity: expected " + expected + ', got ' + actual
493
493
  );
494
494
  }
495
495
  });
@@ -506,7 +506,7 @@
506
506
  };
507
507
 
508
508
  const family = this;
509
- this.Adapter.prototype[name] = function(...args) {
509
+ this.Adapter.prototype[name] = function (...args) {
510
510
  const tag = family._getTag(this._adaptee);
511
511
  assert(tag in family._getChildren, "getTag returned unrecognized tag '" + tag + "'");
512
512
  assert(tag in actions, "No action for '" + tag + "' in operation '" + name + "'");
@@ -521,8 +521,8 @@
521
521
  const oldArgs = this.args;
522
522
  this.args = argsObj;
523
523
  const ans = actions[tag].apply(
524
- this,
525
- family._getChildren[tag](this._adaptee, family._wrap),
524
+ this,
525
+ family._getChildren[tag](this._adaptee, family._wrap)
526
526
  );
527
527
  this.args = oldArgs;
528
528
  return ans;
@@ -588,7 +588,7 @@
588
588
  const node = {
589
589
  type: ctorName,
590
590
  };
591
- // eslint-disable-next-line guard-for-in
591
+
592
592
  for (const prop in propMap) {
593
593
  const mappedProp = mapping[ctorName] && mapping[ctorName][prop];
594
594
  if (typeof mappedProp === 'number') {
@@ -663,36 +663,60 @@
663
663
  return g.createSemantics().addOperation('toAST(mapping)', defaultOperation);
664
664
  }
665
665
 
666
- // These are just categories that are used in ES5/ES2015.
667
- // The full list of Unicode categories is here: http://www.fileformat.info/info/unicode/category/index.htm.
668
- const UnicodeCategories = {
669
- // Letters
670
- Lu: /\p{Lu}/u,
671
- Ll: /\p{Ll}/u,
672
- Lt: /\p{Lt}/u,
673
- Lm: /\p{Lm}/u,
674
- Lo: /\p{Lo}/u,
675
-
676
- // Numbers
677
- Nl: /\p{Nl}/u,
678
- Nd: /\p{Nd}/u,
679
-
680
- // Marks
681
- Mn: /\p{Mn}/u,
682
- Mc: /\p{Mc}/u,
683
-
684
- // Punctuation, Connector
685
- Pc: /\p{Pc}/u,
686
-
687
- // Separator, Space
688
- Zs: /\p{Zs}/u,
689
-
690
- // These two are not real Unicode categories, but our useful for Ohm.
691
- // L is a combination of all the letter categories.
692
- // Ltmo is a combination of Lt, Lm, and Lo.
693
- L: /\p{Letter}/u,
694
- Ltmo: /\p{Lt}|\p{Lm}|\p{Lo}/u,
695
- };
666
+ // The full list of categories from:
667
+ // https://www.unicode.org/Public/UCD/latest/ucd/extracted/DerivedGeneralCategory.txt.
668
+
669
+ const toRegExp = val => new RegExp(String.raw`\p{${val}}`, 'u');
670
+
671
+ /*
672
+ grep -v '^#' DerivedGeneralCategory.txt \
673
+ | cut -d';' -f2 \
674
+ | awk 'NF{print $1}' \
675
+ | sort -u \
676
+ | awk '{printf "\x27%s\x27,\n",$1}'
677
+ */
678
+
679
+ const UnicodeCategories = Object.fromEntries(
680
+ [
681
+ 'Cc',
682
+ 'Cf',
683
+ 'Cn',
684
+ 'Co',
685
+ 'Cs',
686
+ 'Ll',
687
+ 'Lm',
688
+ 'Lo',
689
+ 'Lt',
690
+ 'Lu',
691
+ 'Mc',
692
+ 'Me',
693
+ 'Mn',
694
+ 'Nd',
695
+ 'Nl',
696
+ 'No',
697
+ 'Pc',
698
+ 'Pd',
699
+ 'Pe',
700
+ 'Pf',
701
+ 'Pi',
702
+ 'Po',
703
+ 'Ps',
704
+ 'Sc',
705
+ 'Sk',
706
+ 'Sm',
707
+ 'So',
708
+ 'Zl',
709
+ 'Zp',
710
+ 'Zs',
711
+ ].map(cat => [cat, toRegExp(cat)])
712
+ );
713
+ UnicodeCategories['Ltmo'] = /\p{Lt}|\p{Lm}|\p{Lo}/u;
714
+
715
+ // We only support a few of these for now, but could add more later.
716
+ // See https://www.unicode.org/Public/UCD/latest/ucd/PropertyAliases.txt
717
+ const UnicodeBinaryProperties = Object.fromEntries(
718
+ ['XID_Start', 'XID_Continue', 'White_Space'].map(prop => [prop, toRegExp(prop)])
719
+ );
696
720
 
697
721
  // --------------------------------------------------------------------
698
722
  // Private stuff
@@ -873,10 +897,18 @@
873
897
  // Unicode character
874
898
 
875
899
  class UnicodeChar extends PExpr {
876
- constructor(category) {
900
+ constructor(categoryOrProp) {
877
901
  super();
878
- this.category = category;
879
- this.pattern = UnicodeCategories[category];
902
+ this.categoryOrProp = categoryOrProp;
903
+ if (categoryOrProp in UnicodeCategories) {
904
+ this.pattern = UnicodeCategories[categoryOrProp];
905
+ } else if (categoryOrProp in UnicodeBinaryProperties) {
906
+ this.pattern = UnicodeBinaryProperties[categoryOrProp];
907
+ } else {
908
+ throw new Error(
909
+ `Invalid Unicode category or property name: ${JSON.stringify(categoryOrProp)}`
910
+ );
911
+ }
880
912
  }
881
913
  }
882
914
 
@@ -927,9 +959,9 @@
927
959
  // Undeclared grammar
928
960
 
929
961
  function undeclaredGrammar(grammarName, namespace, interval) {
930
- const message = namespace ?
931
- `Grammar ${grammarName} is not declared in namespace '${namespace}'` :
932
- 'Undeclared grammar ' + grammarName;
962
+ const message = namespace
963
+ ? `Grammar ${grammarName} is not declared in namespace '${namespace}'`
964
+ : 'Undeclared grammar ' + grammarName;
933
965
  return createError(message, interval);
934
966
  }
935
967
 
@@ -949,8 +981,8 @@
949
981
 
950
982
  function undeclaredRule(ruleName, grammarName, optInterval) {
951
983
  return createError(
952
- 'Rule ' + ruleName + ' is not declared in grammar ' + grammarName,
953
- optInterval,
984
+ 'Rule ' + ruleName + ' is not declared in grammar ' + grammarName,
985
+ optInterval
954
986
  );
955
987
  }
956
988
 
@@ -958,8 +990,8 @@
958
990
 
959
991
  function cannotOverrideUndeclaredRule(ruleName, grammarName, optSource) {
960
992
  return createError(
961
- 'Cannot override rule ' + ruleName + ' because it is not declared in ' + grammarName,
962
- optSource,
993
+ 'Cannot override rule ' + ruleName + ' because it is not declared in ' + grammarName,
994
+ optSource
963
995
  );
964
996
  }
965
997
 
@@ -967,8 +999,8 @@
967
999
 
968
1000
  function cannotExtendUndeclaredRule(ruleName, grammarName, optSource) {
969
1001
  return createError(
970
- 'Cannot extend rule ' + ruleName + ' because it is not declared in ' + grammarName,
971
- optSource,
1002
+ 'Cannot extend rule ' + ruleName + ' because it is not declared in ' + grammarName,
1003
+ optSource
972
1004
  );
973
1005
  }
974
1006
 
@@ -987,14 +1019,14 @@
987
1019
 
988
1020
  function wrongNumberOfParameters(ruleName, expected, actual, source) {
989
1021
  return createError(
990
- 'Wrong number of parameters for rule ' +
1022
+ 'Wrong number of parameters for rule ' +
991
1023
  ruleName +
992
1024
  ' (expected ' +
993
1025
  expected +
994
1026
  ', got ' +
995
1027
  actual +
996
1028
  ')',
997
- source,
1029
+ source
998
1030
  );
999
1031
  }
1000
1032
 
@@ -1002,14 +1034,14 @@
1002
1034
 
1003
1035
  function wrongNumberOfArguments(ruleName, expected, actual, expr) {
1004
1036
  return createError(
1005
- 'Wrong number of arguments for rule ' +
1037
+ 'Wrong number of arguments for rule ' +
1006
1038
  ruleName +
1007
1039
  ' (expected ' +
1008
1040
  expected +
1009
1041
  ', got ' +
1010
1042
  actual +
1011
1043
  ')',
1012
- expr,
1044
+ expr
1013
1045
  );
1014
1046
  }
1015
1047
 
@@ -1017,8 +1049,8 @@
1017
1049
 
1018
1050
  function duplicateParameterNames(ruleName, duplicates, source) {
1019
1051
  return createError(
1020
- 'Duplicate parameter names in rule ' + ruleName + ': ' + duplicates.join(', '),
1021
- source,
1052
+ 'Duplicate parameter names in rule ' + ruleName + ': ' + duplicates.join(', '),
1053
+ source
1022
1054
  );
1023
1055
  }
1024
1056
 
@@ -1026,14 +1058,14 @@
1026
1058
 
1027
1059
  function invalidParameter(ruleName, expr) {
1028
1060
  return createError(
1029
- 'Invalid parameter to rule ' +
1061
+ 'Invalid parameter to rule ' +
1030
1062
  ruleName +
1031
1063
  ': ' +
1032
1064
  expr +
1033
1065
  ' has arity ' +
1034
1066
  expr.getArity() +
1035
1067
  ', but parameter expressions must have arity 1',
1036
- expr.source,
1068
+ expr.source
1037
1069
  );
1038
1070
  }
1039
1071
 
@@ -1045,8 +1077,8 @@
1045
1077
 
1046
1078
  function applicationOfSyntacticRuleFromLexicalContext(ruleName, applyExpr) {
1047
1079
  return createError(
1048
- 'Cannot apply syntactic rule ' + ruleName + ' from here (inside a lexical context)',
1049
- applyExpr.source,
1080
+ 'Cannot apply syntactic rule ' + ruleName + ' from here (inside a lexical context)',
1081
+ applyExpr.source
1050
1082
  );
1051
1083
  }
1052
1084
 
@@ -1055,9 +1087,9 @@
1055
1087
  function applySyntacticWithLexicalRuleApplication(applyExpr) {
1056
1088
  const {ruleName} = applyExpr;
1057
1089
  return createError(
1058
- `applySyntactic is for syntactic rules, but '${ruleName}' is a lexical rule. ` +
1090
+ `applySyntactic is for syntactic rules, but '${ruleName}' is a lexical rule. ` +
1059
1091
  syntacticVsLexicalNote,
1060
- applyExpr.source,
1092
+ applyExpr.source
1061
1093
  );
1062
1094
  }
1063
1095
 
@@ -1065,8 +1097,8 @@
1065
1097
 
1066
1098
  function unnecessaryExperimentalApplySyntactic(applyExpr) {
1067
1099
  return createError(
1068
- 'applySyntactic is not required here (in a syntactic context)',
1069
- applyExpr.source,
1100
+ 'applySyntactic is not required here (in a syntactic context)',
1101
+ applyExpr.source
1070
1102
  );
1071
1103
  }
1072
1104
 
@@ -1092,8 +1124,8 @@
1092
1124
  const digitIntervals = applyWrapper.children.slice(1, -1).map(d => d.source);
1093
1125
  const fullInterval = digitIntervals[0].coverageWith(...digitIntervals.slice(1));
1094
1126
  return createError(
1095
- `U+${fullInterval.contents} is not a valid Unicode code point`,
1096
- fullInterval,
1127
+ `U+${fullInterval.contents} is not a valid Unicode code point`,
1128
+ fullInterval
1097
1129
  );
1098
1130
  }
1099
1131
 
@@ -1111,8 +1143,8 @@
1111
1143
  "' (possible infinite loop)";
1112
1144
  if (applicationStack.length > 0) {
1113
1145
  const stackTrace = applicationStack
1114
- .map(app => new Apply(app.ruleName, app.args))
1115
- .join('\n');
1146
+ .map(app => new Apply(app.ruleName, app.args))
1147
+ .join('\n');
1116
1148
  message += '\nApplication stack (most recent application last):\n' + stackTrace;
1117
1149
  }
1118
1150
  return createError(message, kleeneExpr.expr.source);
@@ -1122,7 +1154,7 @@
1122
1154
 
1123
1155
  function inconsistentArity(ruleName, expected, actual, expr) {
1124
1156
  return createError(
1125
- 'Rule ' +
1157
+ 'Rule ' +
1126
1158
  ruleName +
1127
1159
  ' involves an alternation which has inconsistent arity ' +
1128
1160
  '(expected ' +
@@ -1130,7 +1162,7 @@
1130
1162
  ', got ' +
1131
1163
  actual +
1132
1164
  ')',
1133
- expr.source,
1165
+ expr.source
1134
1166
  );
1135
1167
  }
1136
1168
 
@@ -1145,12 +1177,12 @@
1145
1177
 
1146
1178
  function missingSemanticAction(ctorName, name, type, stack) {
1147
1179
  let stackTrace = stack
1148
- .slice(0, -1)
1149
- .map(info => {
1150
- const ans = ' ' + info[0].name + ' > ' + info[1];
1151
- return info.length === 3 ? ans + " for '" + info[2] + "'" : ans;
1152
- })
1153
- .join('\n');
1180
+ .slice(0, -1)
1181
+ .map(info => {
1182
+ const ans = ' ' + info[0].name + ' > ' + info[1];
1183
+ return info.length === 3 ? ans + " for '" + info[2] + "'" : ans;
1184
+ })
1185
+ .join('\n');
1154
1186
  stackTrace += '\n ' + name + ' > ' + ctorName;
1155
1187
 
1156
1188
  let moreInfo = '';
@@ -1187,11 +1219,23 @@
1187
1219
 
1188
1220
  class Interval {
1189
1221
  constructor(sourceString, startIdx, endIdx) {
1190
- this.sourceString = sourceString;
1222
+ // Store the full source in a non-enumerable property, so that when
1223
+ // grammars and other objects are printed in the REPL, it's not
1224
+ // cluttered with multiple copies of the same long string.
1225
+ Object.defineProperty(this, '_sourceString', {
1226
+ value: sourceString,
1227
+ configurable: false,
1228
+ enumerable: false,
1229
+ writable: false,
1230
+ });
1191
1231
  this.startIdx = startIdx;
1192
1232
  this.endIdx = endIdx;
1193
1233
  }
1194
1234
 
1235
+ get sourceString() {
1236
+ return this._sourceString;
1237
+ }
1238
+
1195
1239
  get contents() {
1196
1240
  if (this._contents === undefined) {
1197
1241
  this._contents = this.sourceString.slice(this.startIdx, this.endIdx);
@@ -1257,13 +1301,13 @@
1257
1301
  throw intervalSourcesDontMatch();
1258
1302
  }
1259
1303
  assert(
1260
- this.startIdx >= that.startIdx && this.endIdx <= that.endIdx,
1261
- 'other interval does not cover this one',
1304
+ this.startIdx >= that.startIdx && this.endIdx <= that.endIdx,
1305
+ 'other interval does not cover this one'
1262
1306
  );
1263
1307
  return new Interval(
1264
- this.sourceString,
1265
- this.startIdx - that.startIdx,
1266
- this.endIdx - that.startIdx,
1308
+ this.sourceString,
1309
+ this.startIdx - that.startIdx,
1310
+ this.endIdx - that.startIdx
1267
1311
  );
1268
1312
  }
1269
1313
 
@@ -1282,7 +1326,7 @@
1282
1326
  }
1283
1327
  }
1284
1328
 
1285
- Interval.coverage = function(firstInterval, ...intervals) {
1329
+ Interval.coverage = function (firstInterval, ...intervals) {
1286
1330
  let {startIdx, endIdx} = firstInterval;
1287
1331
  for (const interval of intervals) {
1288
1332
  if (interval.sourceString !== firstInterval.sourceString) {
@@ -1296,6 +1340,7 @@
1296
1340
  };
1297
1341
 
1298
1342
  const MAX_CHAR_CODE = 0xffff;
1343
+ const MAX_CODE_POINT = 0x10ffff;
1299
1344
 
1300
1345
  class InputStream {
1301
1346
  constructor(source) {
@@ -1341,6 +1386,8 @@
1341
1386
 
1342
1387
  This is intended to be a locale-invariant comparison, which means it may not obey
1343
1388
  locale-specific expectations (e.g. "i" => "İ").
1389
+
1390
+ See also https://unicode.org/faq/casemap_charprop.html#casemap
1344
1391
  */
1345
1392
  for (idx = 0; idx < s.length; idx++) {
1346
1393
  const actual = this.next();
@@ -1375,13 +1422,13 @@
1375
1422
 
1376
1423
  class MatchResult {
1377
1424
  constructor(
1378
- matcher,
1379
- input,
1380
- startExpr,
1381
- cst,
1382
- cstOffset,
1383
- rightmostFailurePosition,
1384
- optRecordedFailures,
1425
+ matcher,
1426
+ input,
1427
+ startExpr,
1428
+ cst,
1429
+ cstOffset,
1430
+ rightmostFailurePosition,
1431
+ optRecordedFailures
1385
1432
  ) {
1386
1433
  this.matcher = matcher;
1387
1434
  this.input = input;
@@ -1392,22 +1439,20 @@
1392
1439
  this._rightmostFailures = optRecordedFailures;
1393
1440
 
1394
1441
  if (this.failed()) {
1395
- /* eslint-disable no-invalid-this */
1396
- defineLazyProperty(this, 'message', function() {
1442
+ defineLazyProperty(this, 'message', function () {
1397
1443
  const detail = 'Expected ' + this.getExpectedText();
1398
1444
  return (
1399
1445
  getLineAndColumnMessage(this.input, this.getRightmostFailurePosition()) + detail
1400
1446
  );
1401
1447
  });
1402
- defineLazyProperty(this, 'shortMessage', function() {
1448
+ defineLazyProperty(this, 'shortMessage', function () {
1403
1449
  const detail = 'expected ' + this.getExpectedText();
1404
1450
  const errorInfo = getLineAndColumn(
1405
- this.input,
1406
- this.getRightmostFailurePosition(),
1451
+ this.input,
1452
+ this.getRightmostFailurePosition()
1407
1453
  );
1408
1454
  return 'Line ' + errorInfo.lineNum + ', col ' + errorInfo.colNum + ': ' + detail;
1409
1455
  });
1410
- /* eslint-enable no-invalid-this */
1411
1456
  }
1412
1457
  }
1413
1458
 
@@ -1436,9 +1481,9 @@
1436
1481
  }
1437
1482
 
1438
1483
  toString() {
1439
- return this.succeeded() ?
1440
- '[match succeeded]' :
1441
- '[match failed at position ' + this.getRightmostFailurePosition() + ']';
1484
+ return this.succeeded()
1485
+ ? '[match succeeded]'
1486
+ : '[match failed at position ' + this.getRightmostFailurePosition() + ']';
1442
1487
  }
1443
1488
 
1444
1489
  // Return a string summarizing the expected contents of the input stream when
@@ -1504,14 +1549,14 @@
1504
1549
  const indexOfFirstInvolvedRule =
1505
1550
  applicationMemoKeyStack.indexOf(headApplication.toMemoKey()) + 1;
1506
1551
  const involvedApplicationMemoKeys = applicationMemoKeyStack.slice(
1507
- indexOfFirstInvolvedRule,
1552
+ indexOfFirstInvolvedRule
1508
1553
  );
1509
1554
 
1510
- memoRec.isInvolved = function(applicationMemoKey) {
1555
+ memoRec.isInvolved = function (applicationMemoKey) {
1511
1556
  return involvedApplicationMemoKeys.indexOf(applicationMemoKey) >= 0;
1512
1557
  };
1513
1558
 
1514
- memoRec.updateInvolvedApplicationMemoKeys = function() {
1559
+ memoRec.updateInvolvedApplicationMemoKeys = function () {
1515
1560
  for (let idx = indexOfFirstInvolvedRule; idx < applicationMemoKeyStack.length; idx++) {
1516
1561
  const applicationMemoKey = applicationMemoKeyStack[idx];
1517
1562
  if (!this.isInvolved(applicationMemoKey)) {
@@ -1545,8 +1590,8 @@
1545
1590
  this.memo[memoKey] = memoRec;
1546
1591
  this.maxExaminedLength = Math.max(this.maxExaminedLength, memoRec.examinedLength);
1547
1592
  this.maxRightmostFailureOffset = Math.max(
1548
- this.maxRightmostFailureOffset,
1549
- memoRec.rightmostFailureOffset,
1593
+ this.maxRightmostFailureOffset,
1594
+ memoRec.rightmostFailureOffset
1550
1595
  );
1551
1596
  return memoRec;
1552
1597
  }
@@ -1568,8 +1613,8 @@
1568
1613
  } else {
1569
1614
  this.maxExaminedLength = Math.max(this.maxExaminedLength, memoRec.examinedLength);
1570
1615
  this.maxRightmostFailureOffset = Math.max(
1571
- this.maxRightmostFailureOffset,
1572
- memoRec.rightmostFailureOffset,
1616
+ this.maxRightmostFailureOffset,
1617
+ memoRec.rightmostFailureOffset
1573
1618
  );
1574
1619
  }
1575
1620
  });
@@ -1618,10 +1663,10 @@
1618
1663
  if (typeof obj === 'string') {
1619
1664
  // Replace non-printable characters with visible symbols.
1620
1665
  return obj
1621
- .replace(/ /g, DOT_OPERATOR)
1622
- .replace(/\t/g, SYMBOL_FOR_HORIZONTAL_TABULATION)
1623
- .replace(/\n/g, SYMBOL_FOR_LINE_FEED)
1624
- .replace(/\r/g, SYMBOL_FOR_CARRIAGE_RETURN);
1666
+ .replace(/ /g, DOT_OPERATOR)
1667
+ .replace(/\t/g, SYMBOL_FOR_HORIZONTAL_TABULATION)
1668
+ .replace(/\n/g, SYMBOL_FOR_LINE_FEED)
1669
+ .replace(/\r/g, SYMBOL_FOR_CARRIAGE_RETURN);
1625
1670
  }
1626
1671
  return String(obj);
1627
1672
  }
@@ -1652,13 +1697,13 @@
1652
1697
 
1653
1698
  cloneWithExpr(expr) {
1654
1699
  const ans = new Trace(
1655
- this.input,
1656
- this.pos,
1657
- this.pos2,
1658
- expr,
1659
- this.succeeded,
1660
- this.bindings,
1661
- this.children,
1700
+ this.input,
1701
+ this.pos,
1702
+ this.pos2,
1703
+ expr,
1704
+ this.succeeded,
1705
+ this.bindings,
1706
+ this.children
1662
1707
  );
1663
1708
 
1664
1709
  ans.isHeadOfLeftRecursion = this.isHeadOfLeftRecursion;
@@ -1673,13 +1718,13 @@
1673
1718
  // Record the trace information for the terminating condition of the LR loop.
1674
1719
  recordLRTermination(ruleBodyTrace, value) {
1675
1720
  this.terminatingLREntry = new Trace(
1676
- this.input,
1677
- this.pos,
1678
- this.pos2,
1679
- this.expr,
1680
- false,
1681
- [value],
1682
- [ruleBodyTrace],
1721
+ this.input,
1722
+ this.pos,
1723
+ this.pos2,
1724
+ this.expr,
1725
+ false,
1726
+ [value],
1727
+ [ruleBodyTrace]
1683
1728
  );
1684
1729
  this.terminatingLREntry.terminatesLR = true;
1685
1730
  }
@@ -1739,7 +1784,7 @@
1739
1784
  const ctorName = node.expr.constructor.name;
1740
1785
  // Don't print anything for Alt nodes.
1741
1786
  if (ctorName === 'Alt') {
1742
- return; // eslint-disable-line consistent-return
1787
+ return;
1743
1788
  }
1744
1789
  sb.append(getInputExcerpt(node.input, node.pos, 10) + spaces(depth * 2 + 1));
1745
1790
  sb.append((node.succeeded ? CHECK_MARK : BALLOT_X) + ' ' + node.displayString);
@@ -1797,7 +1842,7 @@
1797
1842
  Terminal.prototype.allowsSkippingPrecedingSpace =
1798
1843
  Range.prototype.allowsSkippingPrecedingSpace =
1799
1844
  UnicodeChar.prototype.allowsSkippingPrecedingSpace =
1800
- function() {
1845
+ function () {
1801
1846
  return true;
1802
1847
  };
1803
1848
 
@@ -1811,7 +1856,7 @@
1811
1856
  Not.prototype.allowsSkippingPrecedingSpace =
1812
1857
  Param.prototype.allowsSkippingPrecedingSpace =
1813
1858
  Seq.prototype.allowsSkippingPrecedingSpace =
1814
- function() {
1859
+ function () {
1815
1860
  return false;
1816
1861
  };
1817
1862
 
@@ -1827,13 +1872,13 @@
1827
1872
 
1828
1873
  let lexifyCount;
1829
1874
 
1830
- PExpr.prototype.assertAllApplicationsAreValid = function(ruleName, grammar) {
1875
+ PExpr.prototype.assertAllApplicationsAreValid = function (ruleName, grammar) {
1831
1876
  lexifyCount = 0;
1832
1877
  this._assertAllApplicationsAreValid(ruleName, grammar);
1833
1878
  };
1834
1879
 
1835
1880
  PExpr.prototype._assertAllApplicationsAreValid = abstract(
1836
- '_assertAllApplicationsAreValid',
1881
+ '_assertAllApplicationsAreValid'
1837
1882
  );
1838
1883
 
1839
1884
  any._assertAllApplicationsAreValid =
@@ -1842,23 +1887,23 @@
1842
1887
  Range.prototype._assertAllApplicationsAreValid =
1843
1888
  Param.prototype._assertAllApplicationsAreValid =
1844
1889
  UnicodeChar.prototype._assertAllApplicationsAreValid =
1845
- function(ruleName, grammar) {
1890
+ function (ruleName, grammar) {
1846
1891
  // no-op
1847
1892
  };
1848
1893
 
1849
- Lex.prototype._assertAllApplicationsAreValid = function(ruleName, grammar) {
1894
+ Lex.prototype._assertAllApplicationsAreValid = function (ruleName, grammar) {
1850
1895
  lexifyCount++;
1851
1896
  this.expr._assertAllApplicationsAreValid(ruleName, grammar);
1852
1897
  lexifyCount--;
1853
1898
  };
1854
1899
 
1855
- Alt.prototype._assertAllApplicationsAreValid = function(ruleName, grammar) {
1900
+ Alt.prototype._assertAllApplicationsAreValid = function (ruleName, grammar) {
1856
1901
  for (let idx = 0; idx < this.terms.length; idx++) {
1857
1902
  this.terms[idx]._assertAllApplicationsAreValid(ruleName, grammar);
1858
1903
  }
1859
1904
  };
1860
1905
 
1861
- Seq.prototype._assertAllApplicationsAreValid = function(ruleName, grammar) {
1906
+ Seq.prototype._assertAllApplicationsAreValid = function (ruleName, grammar) {
1862
1907
  for (let idx = 0; idx < this.factors.length; idx++) {
1863
1908
  this.factors[idx]._assertAllApplicationsAreValid(ruleName, grammar);
1864
1909
  }
@@ -1867,14 +1912,14 @@
1867
1912
  Iter.prototype._assertAllApplicationsAreValid =
1868
1913
  Not.prototype._assertAllApplicationsAreValid =
1869
1914
  Lookahead.prototype._assertAllApplicationsAreValid =
1870
- function(ruleName, grammar) {
1915
+ function (ruleName, grammar) {
1871
1916
  this.expr._assertAllApplicationsAreValid(ruleName, grammar);
1872
1917
  };
1873
1918
 
1874
- Apply.prototype._assertAllApplicationsAreValid = function(
1875
- ruleName,
1876
- grammar,
1877
- skipSyntacticCheck = false,
1919
+ Apply.prototype._assertAllApplicationsAreValid = function (
1920
+ ruleName,
1921
+ grammar,
1922
+ skipSyntacticCheck = false
1878
1923
  ) {
1879
1924
  const ruleInfo = grammar.rules[this.ruleName];
1880
1925
  const isContextSyntactic = isSyntactic(ruleName) && lexifyCount === 0;
@@ -1937,7 +1982,7 @@
1937
1982
  // --------------------------------------------------------------------
1938
1983
 
1939
1984
  PExpr.prototype.assertChoicesHaveUniformArity = abstract(
1940
- 'assertChoicesHaveUniformArity',
1985
+ 'assertChoicesHaveUniformArity'
1941
1986
  );
1942
1987
 
1943
1988
  any.assertChoicesHaveUniformArity =
@@ -1947,11 +1992,11 @@
1947
1992
  Param.prototype.assertChoicesHaveUniformArity =
1948
1993
  Lex.prototype.assertChoicesHaveUniformArity =
1949
1994
  UnicodeChar.prototype.assertChoicesHaveUniformArity =
1950
- function(ruleName) {
1995
+ function (ruleName) {
1951
1996
  // no-op
1952
1997
  };
1953
1998
 
1954
- Alt.prototype.assertChoicesHaveUniformArity = function(ruleName) {
1999
+ Alt.prototype.assertChoicesHaveUniformArity = function (ruleName) {
1955
2000
  if (this.terms.length === 0) {
1956
2001
  return;
1957
2002
  }
@@ -1966,7 +2011,7 @@
1966
2011
  }
1967
2012
  };
1968
2013
 
1969
- Extend.prototype.assertChoicesHaveUniformArity = function(ruleName) {
2014
+ Extend.prototype.assertChoicesHaveUniformArity = function (ruleName) {
1970
2015
  // Extend is a special case of Alt that's guaranteed to have exactly two
1971
2016
  // cases: [extensions, origBody].
1972
2017
  const actualArity = this.terms[0].getArity();
@@ -1976,25 +2021,25 @@
1976
2021
  }
1977
2022
  };
1978
2023
 
1979
- Seq.prototype.assertChoicesHaveUniformArity = function(ruleName) {
2024
+ Seq.prototype.assertChoicesHaveUniformArity = function (ruleName) {
1980
2025
  for (let idx = 0; idx < this.factors.length; idx++) {
1981
2026
  this.factors[idx].assertChoicesHaveUniformArity(ruleName);
1982
2027
  }
1983
2028
  };
1984
2029
 
1985
- Iter.prototype.assertChoicesHaveUniformArity = function(ruleName) {
2030
+ Iter.prototype.assertChoicesHaveUniformArity = function (ruleName) {
1986
2031
  this.expr.assertChoicesHaveUniformArity(ruleName);
1987
2032
  };
1988
2033
 
1989
- Not.prototype.assertChoicesHaveUniformArity = function(ruleName) {
2034
+ Not.prototype.assertChoicesHaveUniformArity = function (ruleName) {
1990
2035
  // no-op (not required b/c the nested expr doesn't show up in the CST)
1991
2036
  };
1992
2037
 
1993
- Lookahead.prototype.assertChoicesHaveUniformArity = function(ruleName) {
2038
+ Lookahead.prototype.assertChoicesHaveUniformArity = function (ruleName) {
1994
2039
  this.expr.assertChoicesHaveUniformArity(ruleName);
1995
2040
  };
1996
2041
 
1997
- Apply.prototype.assertChoicesHaveUniformArity = function(ruleName) {
2042
+ Apply.prototype.assertChoicesHaveUniformArity = function (ruleName) {
1998
2043
  // The arities of the parameter expressions is required to be 1 by
1999
2044
  // `assertAllApplicationsAreValid()`.
2000
2045
  };
@@ -2004,7 +2049,7 @@
2004
2049
  // --------------------------------------------------------------------
2005
2050
 
2006
2051
  PExpr.prototype.assertIteratedExprsAreNotNullable = abstract(
2007
- 'assertIteratedExprsAreNotNullable',
2052
+ 'assertIteratedExprsAreNotNullable'
2008
2053
  );
2009
2054
 
2010
2055
  any.assertIteratedExprsAreNotNullable =
@@ -2013,23 +2058,23 @@
2013
2058
  Range.prototype.assertIteratedExprsAreNotNullable =
2014
2059
  Param.prototype.assertIteratedExprsAreNotNullable =
2015
2060
  UnicodeChar.prototype.assertIteratedExprsAreNotNullable =
2016
- function(grammar) {
2061
+ function (grammar) {
2017
2062
  // no-op
2018
2063
  };
2019
2064
 
2020
- Alt.prototype.assertIteratedExprsAreNotNullable = function(grammar) {
2065
+ Alt.prototype.assertIteratedExprsAreNotNullable = function (grammar) {
2021
2066
  for (let idx = 0; idx < this.terms.length; idx++) {
2022
2067
  this.terms[idx].assertIteratedExprsAreNotNullable(grammar);
2023
2068
  }
2024
2069
  };
2025
2070
 
2026
- Seq.prototype.assertIteratedExprsAreNotNullable = function(grammar) {
2071
+ Seq.prototype.assertIteratedExprsAreNotNullable = function (grammar) {
2027
2072
  for (let idx = 0; idx < this.factors.length; idx++) {
2028
2073
  this.factors[idx].assertIteratedExprsAreNotNullable(grammar);
2029
2074
  }
2030
2075
  };
2031
2076
 
2032
- Iter.prototype.assertIteratedExprsAreNotNullable = function(grammar) {
2077
+ Iter.prototype.assertIteratedExprsAreNotNullable = function (grammar) {
2033
2078
  // Note: this is the implementation of this method for `Star` and `Plus` expressions.
2034
2079
  // It is overridden for `Opt` below.
2035
2080
  this.expr.assertIteratedExprsAreNotNullable(grammar);
@@ -2042,11 +2087,11 @@
2042
2087
  Not.prototype.assertIteratedExprsAreNotNullable =
2043
2088
  Lookahead.prototype.assertIteratedExprsAreNotNullable =
2044
2089
  Lex.prototype.assertIteratedExprsAreNotNullable =
2045
- function(grammar) {
2090
+ function (grammar) {
2046
2091
  this.expr.assertIteratedExprsAreNotNullable(grammar);
2047
2092
  };
2048
2093
 
2049
- Apply.prototype.assertIteratedExprsAreNotNullable = function(grammar) {
2094
+ Apply.prototype.assertIteratedExprsAreNotNullable = function (grammar) {
2050
2095
  this.args.forEach(arg => {
2051
2096
  arg.assertIteratedExprsAreNotNullable(grammar);
2052
2097
  });
@@ -2090,11 +2135,11 @@
2090
2135
  onlyChild() {
2091
2136
  if (this.numChildren() !== 1) {
2092
2137
  throw new Error(
2093
- 'cannot get only child of a node of type ' +
2138
+ 'cannot get only child of a node of type ' +
2094
2139
  this.ctorName +
2095
2140
  ' (it has ' +
2096
2141
  this.numChildren() +
2097
- ' children)',
2142
+ ' children)'
2098
2143
  );
2099
2144
  } else {
2100
2145
  return this.firstChild();
@@ -2104,7 +2149,7 @@
2104
2149
  firstChild() {
2105
2150
  if (this.hasNoChildren()) {
2106
2151
  throw new Error(
2107
- 'cannot get first child of a ' + this.ctorName + ' node, which has no children',
2152
+ 'cannot get first child of a ' + this.ctorName + ' node, which has no children'
2108
2153
  );
2109
2154
  } else {
2110
2155
  return this.childAt(0);
@@ -2114,7 +2159,7 @@
2114
2159
  lastChild() {
2115
2160
  if (this.hasNoChildren()) {
2116
2161
  throw new Error(
2117
- 'cannot get last child of a ' + this.ctorName + ' node, which has no children',
2162
+ 'cannot get last child of a ' + this.ctorName + ' node, which has no children'
2118
2163
  );
2119
2164
  } else {
2120
2165
  return this.childAt(this.numChildren() - 1);
@@ -2248,7 +2293,7 @@
2248
2293
  */
2249
2294
  PExpr.prototype.eval = abstract('eval'); // function(state) { ... }
2250
2295
 
2251
- any.eval = function(state) {
2296
+ any.eval = function (state) {
2252
2297
  const {inputStream} = state;
2253
2298
  const origPos = inputStream.pos;
2254
2299
  const cp = inputStream.nextCodePoint();
@@ -2261,7 +2306,7 @@
2261
2306
  }
2262
2307
  };
2263
2308
 
2264
- end.eval = function(state) {
2309
+ end.eval = function (state) {
2265
2310
  const {inputStream} = state;
2266
2311
  const origPos = inputStream.pos;
2267
2312
  if (inputStream.atEnd()) {
@@ -2273,7 +2318,7 @@
2273
2318
  }
2274
2319
  };
2275
2320
 
2276
- Terminal.prototype.eval = function(state) {
2321
+ Terminal.prototype.eval = function (state) {
2277
2322
  const {inputStream} = state;
2278
2323
  const origPos = inputStream.pos;
2279
2324
  if (!inputStream.matchString(this.obj)) {
@@ -2285,7 +2330,7 @@
2285
2330
  }
2286
2331
  };
2287
2332
 
2288
- Range.prototype.eval = function(state) {
2333
+ Range.prototype.eval = function (state) {
2289
2334
  const {inputStream} = state;
2290
2335
  const origPos = inputStream.pos;
2291
2336
 
@@ -2304,18 +2349,18 @@
2304
2349
  }
2305
2350
  };
2306
2351
 
2307
- Param.prototype.eval = function(state) {
2352
+ Param.prototype.eval = function (state) {
2308
2353
  return state.eval(state.currentApplication().args[this.index]);
2309
2354
  };
2310
2355
 
2311
- Lex.prototype.eval = function(state) {
2356
+ Lex.prototype.eval = function (state) {
2312
2357
  state.enterLexifiedContext();
2313
2358
  const ans = state.eval(this.expr);
2314
2359
  state.exitLexifiedContext();
2315
2360
  return ans;
2316
2361
  };
2317
2362
 
2318
- Alt.prototype.eval = function(state) {
2363
+ Alt.prototype.eval = function (state) {
2319
2364
  for (let idx = 0; idx < this.terms.length; idx++) {
2320
2365
  if (state.eval(this.terms[idx])) {
2321
2366
  return true;
@@ -2324,7 +2369,7 @@
2324
2369
  return false;
2325
2370
  };
2326
2371
 
2327
- Seq.prototype.eval = function(state) {
2372
+ Seq.prototype.eval = function (state) {
2328
2373
  for (let idx = 0; idx < this.factors.length; idx++) {
2329
2374
  const factor = this.factors[idx];
2330
2375
  if (!state.eval(factor)) {
@@ -2334,7 +2379,7 @@
2334
2379
  return true;
2335
2380
  };
2336
2381
 
2337
- Iter.prototype.eval = function(state) {
2382
+ Iter.prototype.eval = function (state) {
2338
2383
  const {inputStream} = state;
2339
2384
  const origPos = inputStream.pos;
2340
2385
  const arity = this.getArity();
@@ -2356,8 +2401,8 @@
2356
2401
  numMatches++;
2357
2402
  const row = state._bindings.splice(state._bindings.length - arity, arity);
2358
2403
  const rowOffsets = state._bindingOffsets.splice(
2359
- state._bindingOffsets.length - arity,
2360
- arity,
2404
+ state._bindingOffsets.length - arity,
2405
+ arity
2361
2406
  );
2362
2407
  for (idx = 0; idx < row.length; idx++) {
2363
2408
  cols[idx].push(row[idx]);
@@ -2381,14 +2426,14 @@
2381
2426
  const isOptional = this instanceof Opt;
2382
2427
  for (idx = 0; idx < cols.length; idx++) {
2383
2428
  state._bindings.push(
2384
- new IterationNode(cols[idx], colOffsets[idx], matchLength, isOptional),
2429
+ new IterationNode(cols[idx], colOffsets[idx], matchLength, isOptional)
2385
2430
  );
2386
2431
  state._bindingOffsets.push(offset);
2387
2432
  }
2388
2433
  return true;
2389
2434
  };
2390
2435
 
2391
- Not.prototype.eval = function(state) {
2436
+ Not.prototype.eval = function (state) {
2392
2437
  /*
2393
2438
  TODO:
2394
2439
  - Right now we're just throwing away all of the failures that happen inside a `not`, and
@@ -2414,7 +2459,7 @@
2414
2459
  return true;
2415
2460
  };
2416
2461
 
2417
- Lookahead.prototype.eval = function(state) {
2462
+ Lookahead.prototype.eval = function (state) {
2418
2463
  const {inputStream} = state;
2419
2464
  const origPos = inputStream.pos;
2420
2465
  if (state.eval(this.expr)) {
@@ -2425,7 +2470,7 @@
2425
2470
  }
2426
2471
  };
2427
2472
 
2428
- Apply.prototype.eval = function(state) {
2473
+ Apply.prototype.eval = function (state) {
2429
2474
  const caller = state.currentApplication();
2430
2475
  const actuals = caller ? caller.args : [];
2431
2476
  const app = this.substituteParams(actuals);
@@ -2448,7 +2493,7 @@
2448
2493
  return app.reallyEval(state);
2449
2494
  };
2450
2495
 
2451
- Apply.prototype.handleCycle = function(state) {
2496
+ Apply.prototype.handleCycle = function (state) {
2452
2497
  const posInfo = state.getCurrentPosInfo();
2453
2498
  const {currentLeftRecursion} = posInfo;
2454
2499
  const memoKey = this.toMemoKey();
@@ -2471,7 +2516,7 @@
2471
2516
  return state.useMemoizedResult(state.inputStream.pos, memoRec);
2472
2517
  };
2473
2518
 
2474
- Apply.prototype.reallyEval = function(state) {
2519
+ Apply.prototype.reallyEval = function (state) {
2475
2520
  const {inputStream} = state;
2476
2521
  const origPos = inputStream.pos;
2477
2522
  const origPosInfo = state.getCurrentPosInfo();
@@ -2524,6 +2569,7 @@
2524
2569
  }
2525
2570
  if (memoRec) {
2526
2571
  memoRec.failuresAtRightmostPosition = state.cloneRecordedFailures();
2572
+ memoRec.rightmostFailureOffset = state._getRightmostFailureOffset();
2527
2573
  }
2528
2574
  }
2529
2575
 
@@ -2541,8 +2587,8 @@
2541
2587
  // Fix the input stream's examinedLength -- it should be the maximum examined length
2542
2588
  // across all applications, not just this one.
2543
2589
  inputStream.examinedLength = Math.max(
2544
- inputStream.examinedLength,
2545
- origInputStreamExaminedLength,
2590
+ inputStream.examinedLength,
2591
+ origInputStreamExaminedLength
2546
2592
  );
2547
2593
 
2548
2594
  state.exitApplication(origPosInfo, value);
@@ -2550,7 +2596,7 @@
2550
2596
  return succeeded;
2551
2597
  };
2552
2598
 
2553
- Apply.prototype.evalOnce = function(expr, state) {
2599
+ Apply.prototype.evalOnce = function (expr, state) {
2554
2600
  const {inputStream} = state;
2555
2601
  const origPos = inputStream.pos;
2556
2602
 
@@ -2565,7 +2611,7 @@
2565
2611
  }
2566
2612
  };
2567
2613
 
2568
- Apply.prototype.growSeedResult = function(body, state, origPos, lrMemoRec, newValue) {
2614
+ Apply.prototype.growSeedResult = function (body, state, origPos, lrMemoRec, newValue) {
2569
2615
  if (!newValue) {
2570
2616
  return false;
2571
2617
  }
@@ -2583,13 +2629,13 @@
2583
2629
  // element in `state.trace`.
2584
2630
  const seedTrace = state.trace[state.trace.length - 1];
2585
2631
  lrMemoRec.traceEntry = new Trace(
2586
- state.input,
2587
- origPos,
2588
- inputStream.pos,
2589
- this,
2590
- true,
2591
- [newValue],
2592
- [seedTrace.clone()],
2632
+ state.input,
2633
+ origPos,
2634
+ inputStream.pos,
2635
+ this,
2636
+ true,
2637
+ [newValue],
2638
+ [seedTrace.clone()]
2593
2639
  );
2594
2640
  }
2595
2641
  inputStream.pos = origPos;
@@ -2609,17 +2655,19 @@
2609
2655
  return lrMemoRec.value;
2610
2656
  };
2611
2657
 
2612
- UnicodeChar.prototype.eval = function(state) {
2658
+ UnicodeChar.prototype.eval = function (state) {
2613
2659
  const {inputStream} = state;
2614
2660
  const origPos = inputStream.pos;
2615
- const ch = inputStream.next();
2616
- if (ch && this.pattern.test(ch)) {
2617
- state.pushBinding(new TerminalNode(ch.length), origPos);
2618
- return true;
2619
- } else {
2620
- state.processFailure(origPos, this);
2621
- return false;
2661
+ const cp = inputStream.nextCodePoint();
2662
+ if (cp !== undefined && cp <= MAX_CODE_POINT) {
2663
+ const ch = String.fromCodePoint(cp);
2664
+ if (this.pattern.test(ch)) {
2665
+ state.pushBinding(new TerminalNode(ch.length), origPos);
2666
+ return true;
2667
+ }
2622
2668
  }
2669
+ state.processFailure(origPos, this);
2670
+ return false;
2623
2671
  };
2624
2672
 
2625
2673
  // --------------------------------------------------------------------
@@ -2635,17 +2683,17 @@
2635
2683
  Param.prototype.getArity =
2636
2684
  Apply.prototype.getArity =
2637
2685
  UnicodeChar.prototype.getArity =
2638
- function() {
2686
+ function () {
2639
2687
  return 1;
2640
2688
  };
2641
2689
 
2642
- Alt.prototype.getArity = function() {
2690
+ Alt.prototype.getArity = function () {
2643
2691
  // This is ok b/c all terms must have the same arity -- this property is
2644
2692
  // checked by the Grammar constructor.
2645
2693
  return this.terms.length === 0 ? 0 : this.terms[0].getArity();
2646
2694
  };
2647
2695
 
2648
- Seq.prototype.getArity = function() {
2696
+ Seq.prototype.getArity = function () {
2649
2697
  let arity = 0;
2650
2698
  for (let idx = 0; idx < this.factors.length; idx++) {
2651
2699
  arity += this.factors[idx].getArity();
@@ -2653,15 +2701,15 @@
2653
2701
  return arity;
2654
2702
  };
2655
2703
 
2656
- Iter.prototype.getArity = function() {
2704
+ Iter.prototype.getArity = function () {
2657
2705
  return this.expr.getArity();
2658
2706
  };
2659
2707
 
2660
- Not.prototype.getArity = function() {
2708
+ Not.prototype.getArity = function () {
2661
2709
  return 0;
2662
2710
  };
2663
2711
 
2664
- Lookahead.prototype.getArity = Lex.prototype.getArity = function() {
2712
+ Lookahead.prototype.getArity = Lex.prototype.getArity = function () {
2665
2713
  return this.expr.getArity();
2666
2714
  };
2667
2715
 
@@ -2684,38 +2732,38 @@
2684
2732
 
2685
2733
  PExpr.prototype.outputRecipe = abstract('outputRecipe');
2686
2734
 
2687
- any.outputRecipe = function(formals, grammarInterval) {
2735
+ any.outputRecipe = function (formals, grammarInterval) {
2688
2736
  return ['any', getMetaInfo(this, grammarInterval)];
2689
2737
  };
2690
2738
 
2691
- end.outputRecipe = function(formals, grammarInterval) {
2739
+ end.outputRecipe = function (formals, grammarInterval) {
2692
2740
  return ['end', getMetaInfo(this, grammarInterval)];
2693
2741
  };
2694
2742
 
2695
- Terminal.prototype.outputRecipe = function(formals, grammarInterval) {
2743
+ Terminal.prototype.outputRecipe = function (formals, grammarInterval) {
2696
2744
  return ['terminal', getMetaInfo(this, grammarInterval), this.obj];
2697
2745
  };
2698
2746
 
2699
- Range.prototype.outputRecipe = function(formals, grammarInterval) {
2747
+ Range.prototype.outputRecipe = function (formals, grammarInterval) {
2700
2748
  return ['range', getMetaInfo(this, grammarInterval), this.from, this.to];
2701
2749
  };
2702
2750
 
2703
- Param.prototype.outputRecipe = function(formals, grammarInterval) {
2751
+ Param.prototype.outputRecipe = function (formals, grammarInterval) {
2704
2752
  return ['param', getMetaInfo(this, grammarInterval), this.index];
2705
2753
  };
2706
2754
 
2707
- Alt.prototype.outputRecipe = function(formals, grammarInterval) {
2755
+ Alt.prototype.outputRecipe = function (formals, grammarInterval) {
2708
2756
  return ['alt', getMetaInfo(this, grammarInterval)].concat(
2709
- this.terms.map(term => term.outputRecipe(formals, grammarInterval)),
2757
+ this.terms.map(term => term.outputRecipe(formals, grammarInterval))
2710
2758
  );
2711
2759
  };
2712
2760
 
2713
- Extend.prototype.outputRecipe = function(formals, grammarInterval) {
2761
+ Extend.prototype.outputRecipe = function (formals, grammarInterval) {
2714
2762
  const extension = this.terms[0]; // [extension, original]
2715
2763
  return extension.outputRecipe(formals, grammarInterval);
2716
2764
  };
2717
2765
 
2718
- Splice.prototype.outputRecipe = function(formals, grammarInterval) {
2766
+ Splice.prototype.outputRecipe = function (formals, grammarInterval) {
2719
2767
  const beforeTerms = this.terms.slice(0, this.expansionPos);
2720
2768
  const afterTerms = this.terms.slice(this.expansionPos + 1);
2721
2769
  return [
@@ -2726,9 +2774,9 @@
2726
2774
  ];
2727
2775
  };
2728
2776
 
2729
- Seq.prototype.outputRecipe = function(formals, grammarInterval) {
2777
+ Seq.prototype.outputRecipe = function (formals, grammarInterval) {
2730
2778
  return ['seq', getMetaInfo(this, grammarInterval)].concat(
2731
- this.factors.map(factor => factor.outputRecipe(formals, grammarInterval)),
2779
+ this.factors.map(factor => factor.outputRecipe(formals, grammarInterval))
2732
2780
  );
2733
2781
  };
2734
2782
 
@@ -2738,7 +2786,7 @@
2738
2786
  Not.prototype.outputRecipe =
2739
2787
  Lookahead.prototype.outputRecipe =
2740
2788
  Lex.prototype.outputRecipe =
2741
- function(formals, grammarInterval) {
2789
+ function (formals, grammarInterval) {
2742
2790
  return [
2743
2791
  this.constructor.name.toLowerCase(),
2744
2792
  getMetaInfo(this, grammarInterval),
@@ -2746,7 +2794,7 @@
2746
2794
  ];
2747
2795
  };
2748
2796
 
2749
- Apply.prototype.outputRecipe = function(formals, grammarInterval) {
2797
+ Apply.prototype.outputRecipe = function (formals, grammarInterval) {
2750
2798
  return [
2751
2799
  'app',
2752
2800
  getMetaInfo(this, grammarInterval),
@@ -2755,8 +2803,8 @@
2755
2803
  ];
2756
2804
  };
2757
2805
 
2758
- UnicodeChar.prototype.outputRecipe = function(formals, grammarInterval) {
2759
- return ['unicodeChar', getMetaInfo(this, grammarInterval), this.category];
2806
+ UnicodeChar.prototype.outputRecipe = function (formals, grammarInterval) {
2807
+ return ['unicodeChar', getMetaInfo(this, grammarInterval), this.categoryOrProp];
2760
2808
  };
2761
2809
 
2762
2810
  // --------------------------------------------------------------------
@@ -2776,18 +2824,18 @@
2776
2824
  Range.prototype.introduceParams =
2777
2825
  Param.prototype.introduceParams =
2778
2826
  UnicodeChar.prototype.introduceParams =
2779
- function(formals) {
2827
+ function (formals) {
2780
2828
  return this;
2781
2829
  };
2782
2830
 
2783
- Alt.prototype.introduceParams = function(formals) {
2831
+ Alt.prototype.introduceParams = function (formals) {
2784
2832
  this.terms.forEach((term, idx, terms) => {
2785
2833
  terms[idx] = term.introduceParams(formals);
2786
2834
  });
2787
2835
  return this;
2788
2836
  };
2789
2837
 
2790
- Seq.prototype.introduceParams = function(formals) {
2838
+ Seq.prototype.introduceParams = function (formals) {
2791
2839
  this.factors.forEach((factor, idx, factors) => {
2792
2840
  factors[idx] = factor.introduceParams(formals);
2793
2841
  });
@@ -2798,12 +2846,12 @@
2798
2846
  Not.prototype.introduceParams =
2799
2847
  Lookahead.prototype.introduceParams =
2800
2848
  Lex.prototype.introduceParams =
2801
- function(formals) {
2849
+ function (formals) {
2802
2850
  this.expr = this.expr.introduceParams(formals);
2803
2851
  return this;
2804
2852
  };
2805
2853
 
2806
- Apply.prototype.introduceParams = function(formals) {
2854
+ Apply.prototype.introduceParams = function (formals) {
2807
2855
  const index = formals.indexOf(this.ruleName);
2808
2856
  if (index >= 0) {
2809
2857
  if (this.args.length > 0) {
@@ -2824,7 +2872,7 @@
2824
2872
  // --------------------------------------------------------------------
2825
2873
 
2826
2874
  // Returns `true` if this parsing expression may accept without consuming any input.
2827
- PExpr.prototype.isNullable = function(grammar) {
2875
+ PExpr.prototype.isNullable = function (grammar) {
2828
2876
  return this._isNullable(grammar, Object.create(null));
2829
2877
  };
2830
2878
 
@@ -2835,15 +2883,15 @@
2835
2883
  Param.prototype._isNullable =
2836
2884
  Plus.prototype._isNullable =
2837
2885
  UnicodeChar.prototype._isNullable =
2838
- function(grammar, memo) {
2886
+ function (grammar, memo) {
2839
2887
  return false;
2840
2888
  };
2841
2889
 
2842
- end._isNullable = function(grammar, memo) {
2890
+ end._isNullable = function (grammar, memo) {
2843
2891
  return true;
2844
2892
  };
2845
2893
 
2846
- Terminal.prototype._isNullable = function(grammar, memo) {
2894
+ Terminal.prototype._isNullable = function (grammar, memo) {
2847
2895
  if (typeof this.obj === 'string') {
2848
2896
  // This is an over-simplification: it's only correct if the input is a string. If it's an array
2849
2897
  // or an object, then the empty string parsing expression is not nullable.
@@ -2853,11 +2901,11 @@
2853
2901
  }
2854
2902
  };
2855
2903
 
2856
- Alt.prototype._isNullable = function(grammar, memo) {
2904
+ Alt.prototype._isNullable = function (grammar, memo) {
2857
2905
  return this.terms.length === 0 || this.terms.some(term => term._isNullable(grammar, memo));
2858
2906
  };
2859
2907
 
2860
- Seq.prototype._isNullable = function(grammar, memo) {
2908
+ Seq.prototype._isNullable = function (grammar, memo) {
2861
2909
  return this.factors.every(factor => factor._isNullable(grammar, memo));
2862
2910
  };
2863
2911
 
@@ -2865,15 +2913,15 @@
2865
2913
  Opt.prototype._isNullable =
2866
2914
  Not.prototype._isNullable =
2867
2915
  Lookahead.prototype._isNullable =
2868
- function(grammar, memo) {
2916
+ function (grammar, memo) {
2869
2917
  return true;
2870
2918
  };
2871
2919
 
2872
- Lex.prototype._isNullable = function(grammar, memo) {
2920
+ Lex.prototype._isNullable = function (grammar, memo) {
2873
2921
  return this.expr._isNullable(grammar, memo);
2874
2922
  };
2875
2923
 
2876
- Apply.prototype._isNullable = function(grammar, memo) {
2924
+ Apply.prototype._isNullable = function (grammar, memo) {
2877
2925
  const key = this.toMemoKey();
2878
2926
  if (!Object.prototype.hasOwnProperty.call(memo, key)) {
2879
2927
  const {body} = grammar.rules[this.ruleName];
@@ -2902,19 +2950,19 @@
2902
2950
  Terminal.prototype.substituteParams =
2903
2951
  Range.prototype.substituteParams =
2904
2952
  UnicodeChar.prototype.substituteParams =
2905
- function(actuals) {
2953
+ function (actuals) {
2906
2954
  return this;
2907
2955
  };
2908
2956
 
2909
- Param.prototype.substituteParams = function(actuals) {
2957
+ Param.prototype.substituteParams = function (actuals) {
2910
2958
  return checkNotNull(actuals[this.index]);
2911
2959
  };
2912
2960
 
2913
- Alt.prototype.substituteParams = function(actuals) {
2961
+ Alt.prototype.substituteParams = function (actuals) {
2914
2962
  return new Alt(this.terms.map(term => term.substituteParams(actuals)));
2915
2963
  };
2916
2964
 
2917
- Seq.prototype.substituteParams = function(actuals) {
2965
+ Seq.prototype.substituteParams = function (actuals) {
2918
2966
  return new Seq(this.factors.map(factor => factor.substituteParams(actuals)));
2919
2967
  };
2920
2968
 
@@ -2922,11 +2970,11 @@
2922
2970
  Not.prototype.substituteParams =
2923
2971
  Lookahead.prototype.substituteParams =
2924
2972
  Lex.prototype.substituteParams =
2925
- function(actuals) {
2973
+ function (actuals) {
2926
2974
  return new this.constructor(this.expr.substituteParams(actuals));
2927
2975
  };
2928
2976
 
2929
- Apply.prototype.substituteParams = function(actuals) {
2977
+ Apply.prototype.substituteParams = function (actuals) {
2930
2978
  if (this.args.length === 0) {
2931
2979
  // Avoid making a copy of this application, as an optimization
2932
2980
  return this;
@@ -3000,15 +3048,15 @@
3000
3048
  // function(firstArgIndex, noDupCheck) { ... }
3001
3049
  PExpr.prototype.toArgumentNameList = abstract('toArgumentNameList');
3002
3050
 
3003
- any.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3051
+ any.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3004
3052
  return ['any'];
3005
3053
  };
3006
3054
 
3007
- end.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3055
+ end.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3008
3056
  return ['end'];
3009
3057
  };
3010
3058
 
3011
- Terminal.prototype.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3059
+ Terminal.prototype.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3012
3060
  if (typeof this.obj === 'string' && /^[_a-zA-Z0-9]+$/.test(this.obj)) {
3013
3061
  // If this terminal is a valid suffix for a JS identifier, just prepend it with '_'
3014
3062
  return ['_' + this.obj];
@@ -3018,7 +3066,7 @@
3018
3066
  }
3019
3067
  };
3020
3068
 
3021
- Range.prototype.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3069
+ Range.prototype.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3022
3070
  let argName = this.from + '_to_' + this.to;
3023
3071
  // If the `argName` is not valid then try to prepend a `_`.
3024
3072
  if (!isRestrictedJSIdentifier(argName)) {
@@ -3031,11 +3079,11 @@
3031
3079
  return [argName];
3032
3080
  };
3033
3081
 
3034
- Alt.prototype.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3082
+ Alt.prototype.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3035
3083
  // `termArgNameLists` is an array of arrays where each row is the
3036
3084
  // argument name list that corresponds to a term in this alternation.
3037
3085
  const termArgNameLists = this.terms.map(term =>
3038
- term.toArgumentNameList(firstArgIndex, true),
3086
+ term.toArgumentNameList(firstArgIndex, true)
3039
3087
  );
3040
3088
 
3041
3089
  const argumentNameList = [];
@@ -3055,7 +3103,7 @@
3055
3103
  return argumentNameList;
3056
3104
  };
3057
3105
 
3058
- Seq.prototype.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3106
+ Seq.prototype.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3059
3107
  // Generate the argument name list, without worrying about duplicates.
3060
3108
  let argumentNameList = [];
3061
3109
  this.factors.forEach(factor => {
@@ -3071,44 +3119,44 @@
3071
3119
  return argumentNameList;
3072
3120
  };
3073
3121
 
3074
- Iter.prototype.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3122
+ Iter.prototype.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3075
3123
  const argumentNameList = this.expr
3076
- .toArgumentNameList(firstArgIndex, noDupCheck)
3077
- .map(exprArgumentString =>
3078
- exprArgumentString[exprArgumentString.length - 1] === 's' ?
3079
- exprArgumentString + 'es' :
3080
- exprArgumentString + 's',
3081
- );
3124
+ .toArgumentNameList(firstArgIndex, noDupCheck)
3125
+ .map(exprArgumentString =>
3126
+ exprArgumentString[exprArgumentString.length - 1] === 's'
3127
+ ? exprArgumentString + 'es'
3128
+ : exprArgumentString + 's'
3129
+ );
3082
3130
  if (!noDupCheck) {
3083
3131
  resolveDuplicatedNames(argumentNameList);
3084
3132
  }
3085
3133
  return argumentNameList;
3086
3134
  };
3087
3135
 
3088
- Opt.prototype.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3136
+ Opt.prototype.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3089
3137
  return this.expr.toArgumentNameList(firstArgIndex, noDupCheck).map(argName => {
3090
3138
  return 'opt' + argName[0].toUpperCase() + argName.slice(1);
3091
3139
  });
3092
3140
  };
3093
3141
 
3094
- Not.prototype.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3142
+ Not.prototype.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3095
3143
  return [];
3096
3144
  };
3097
3145
 
3098
3146
  Lookahead.prototype.toArgumentNameList = Lex.prototype.toArgumentNameList =
3099
- function(firstArgIndex, noDupCheck) {
3147
+ function (firstArgIndex, noDupCheck) {
3100
3148
  return this.expr.toArgumentNameList(firstArgIndex, noDupCheck);
3101
3149
  };
3102
3150
 
3103
- Apply.prototype.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3151
+ Apply.prototype.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3104
3152
  return [this.ruleName];
3105
3153
  };
3106
3154
 
3107
- UnicodeChar.prototype.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3155
+ UnicodeChar.prototype.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3108
3156
  return ['$' + firstArgIndex];
3109
3157
  };
3110
3158
 
3111
- Param.prototype.toArgumentNameList = function(firstArgIndex, noDupCheck) {
3159
+ Param.prototype.toArgumentNameList = function (firstArgIndex, noDupCheck) {
3112
3160
  return ['param' + this.index];
3113
3161
  };
3114
3162
 
@@ -3121,7 +3169,7 @@
3121
3169
  // Returns a string representing the PExpr, for use as a UI label, etc.
3122
3170
  PExpr.prototype.toDisplayString = abstract('toDisplayString');
3123
3171
 
3124
- Alt.prototype.toDisplayString = Seq.prototype.toDisplayString = function() {
3172
+ Alt.prototype.toDisplayString = Seq.prototype.toDisplayString = function () {
3125
3173
  if (this.source) {
3126
3174
  return this.source.trimmed().contents;
3127
3175
  }
@@ -3137,11 +3185,11 @@
3137
3185
  Terminal.prototype.toDisplayString =
3138
3186
  Range.prototype.toDisplayString =
3139
3187
  Param.prototype.toDisplayString =
3140
- function() {
3188
+ function () {
3141
3189
  return this.toString();
3142
3190
  };
3143
3191
 
3144
- Apply.prototype.toDisplayString = function() {
3192
+ Apply.prototype.toDisplayString = function () {
3145
3193
  if (this.args.length > 0) {
3146
3194
  const ps = this.args.map(arg => arg.toDisplayString());
3147
3195
  return this.ruleName + '<' + ps.join(',') + '>';
@@ -3150,8 +3198,8 @@
3150
3198
  }
3151
3199
  };
3152
3200
 
3153
- UnicodeChar.prototype.toDisplayString = function() {
3154
- return 'Unicode [' + this.category + '] character';
3201
+ UnicodeChar.prototype.toDisplayString = function () {
3202
+ return 'Unicode [' + this.categoryOrProp + '] character';
3155
3203
  };
3156
3204
 
3157
3205
  // --------------------------------------------------------------------
@@ -3254,34 +3302,34 @@
3254
3302
 
3255
3303
  PExpr.prototype.toFailure = abstract('toFailure');
3256
3304
 
3257
- any.toFailure = function(grammar) {
3305
+ any.toFailure = function (grammar) {
3258
3306
  return new Failure(this, 'any object', 'description');
3259
3307
  };
3260
3308
 
3261
- end.toFailure = function(grammar) {
3309
+ end.toFailure = function (grammar) {
3262
3310
  return new Failure(this, 'end of input', 'description');
3263
3311
  };
3264
3312
 
3265
- Terminal.prototype.toFailure = function(grammar) {
3313
+ Terminal.prototype.toFailure = function (grammar) {
3266
3314
  return new Failure(this, this.obj, 'string');
3267
3315
  };
3268
3316
 
3269
- Range.prototype.toFailure = function(grammar) {
3317
+ Range.prototype.toFailure = function (grammar) {
3270
3318
  // TODO: come up with something better
3271
3319
  return new Failure(this, JSON.stringify(this.from) + '..' + JSON.stringify(this.to), 'code');
3272
3320
  };
3273
3321
 
3274
- Not.prototype.toFailure = function(grammar) {
3322
+ Not.prototype.toFailure = function (grammar) {
3275
3323
  const description =
3276
3324
  this.expr === any ? 'nothing' : 'not ' + this.expr.toFailure(grammar);
3277
3325
  return new Failure(this, description, 'description');
3278
3326
  };
3279
3327
 
3280
- Lookahead.prototype.toFailure = function(grammar) {
3328
+ Lookahead.prototype.toFailure = function (grammar) {
3281
3329
  return this.expr.toFailure(grammar);
3282
3330
  };
3283
3331
 
3284
- Apply.prototype.toFailure = function(grammar) {
3332
+ Apply.prototype.toFailure = function (grammar) {
3285
3333
  let {description} = grammar.rules[this.ruleName];
3286
3334
  if (!description) {
3287
3335
  const article = /^[aeiouAEIOU]/.test(this.ruleName) ? 'an' : 'a';
@@ -3290,23 +3338,23 @@
3290
3338
  return new Failure(this, description, 'description');
3291
3339
  };
3292
3340
 
3293
- UnicodeChar.prototype.toFailure = function(grammar) {
3294
- return new Failure(this, 'a Unicode [' + this.category + '] character', 'description');
3341
+ UnicodeChar.prototype.toFailure = function (grammar) {
3342
+ return new Failure(this, 'a Unicode [' + this.categoryOrProp + '] character', 'description');
3295
3343
  };
3296
3344
 
3297
- Alt.prototype.toFailure = function(grammar) {
3345
+ Alt.prototype.toFailure = function (grammar) {
3298
3346
  const fs = this.terms.map(t => t.toFailure(grammar));
3299
3347
  const description = '(' + fs.join(' or ') + ')';
3300
3348
  return new Failure(this, description, 'description');
3301
3349
  };
3302
3350
 
3303
- Seq.prototype.toFailure = function(grammar) {
3351
+ Seq.prototype.toFailure = function (grammar) {
3304
3352
  const fs = this.factors.map(f => f.toFailure(grammar));
3305
3353
  const description = '(' + fs.join(' ') + ')';
3306
3354
  return new Failure(this, description, 'description');
3307
3355
  };
3308
3356
 
3309
- Iter.prototype.toFailure = function(grammar) {
3357
+ Iter.prototype.toFailure = function (grammar) {
3310
3358
  const description = '(' + this.expr.toFailure(grammar) + this.operator + ')';
3311
3359
  return new Failure(this, description, 'description');
3312
3360
  };
@@ -3324,55 +3372,55 @@
3324
3372
  */
3325
3373
  PExpr.prototype.toString = abstract('toString');
3326
3374
 
3327
- any.toString = function() {
3375
+ any.toString = function () {
3328
3376
  return 'any';
3329
3377
  };
3330
3378
 
3331
- end.toString = function() {
3379
+ end.toString = function () {
3332
3380
  return 'end';
3333
3381
  };
3334
3382
 
3335
- Terminal.prototype.toString = function() {
3383
+ Terminal.prototype.toString = function () {
3336
3384
  return JSON.stringify(this.obj);
3337
3385
  };
3338
3386
 
3339
- Range.prototype.toString = function() {
3387
+ Range.prototype.toString = function () {
3340
3388
  return JSON.stringify(this.from) + '..' + JSON.stringify(this.to);
3341
3389
  };
3342
3390
 
3343
- Param.prototype.toString = function() {
3391
+ Param.prototype.toString = function () {
3344
3392
  return '$' + this.index;
3345
3393
  };
3346
3394
 
3347
- Lex.prototype.toString = function() {
3395
+ Lex.prototype.toString = function () {
3348
3396
  return '#(' + this.expr.toString() + ')';
3349
3397
  };
3350
3398
 
3351
- Alt.prototype.toString = function() {
3352
- return this.terms.length === 1 ?
3353
- this.terms[0].toString() :
3354
- '(' + this.terms.map(term => term.toString()).join(' | ') + ')';
3399
+ Alt.prototype.toString = function () {
3400
+ return this.terms.length === 1
3401
+ ? this.terms[0].toString()
3402
+ : '(' + this.terms.map(term => term.toString()).join(' | ') + ')';
3355
3403
  };
3356
3404
 
3357
- Seq.prototype.toString = function() {
3358
- return this.factors.length === 1 ?
3359
- this.factors[0].toString() :
3360
- '(' + this.factors.map(factor => factor.toString()).join(' ') + ')';
3405
+ Seq.prototype.toString = function () {
3406
+ return this.factors.length === 1
3407
+ ? this.factors[0].toString()
3408
+ : '(' + this.factors.map(factor => factor.toString()).join(' ') + ')';
3361
3409
  };
3362
3410
 
3363
- Iter.prototype.toString = function() {
3411
+ Iter.prototype.toString = function () {
3364
3412
  return this.expr + this.operator;
3365
3413
  };
3366
3414
 
3367
- Not.prototype.toString = function() {
3415
+ Not.prototype.toString = function () {
3368
3416
  return '~' + this.expr;
3369
3417
  };
3370
3418
 
3371
- Lookahead.prototype.toString = function() {
3419
+ Lookahead.prototype.toString = function () {
3372
3420
  return '&' + this.expr;
3373
3421
  };
3374
3422
 
3375
- Apply.prototype.toString = function() {
3423
+ Apply.prototype.toString = function () {
3376
3424
  if (this.args.length > 0) {
3377
3425
  const ps = this.args.map(arg => arg.toString());
3378
3426
  return this.ruleName + '<' + ps.join(',') + '>';
@@ -3381,8 +3429,8 @@
3381
3429
  }
3382
3430
  };
3383
3431
 
3384
- UnicodeChar.prototype.toString = function() {
3385
- return '\\p{' + this.category + '}';
3432
+ UnicodeChar.prototype.toString = function () {
3433
+ return '\\p{' + this.categoryOrProp + '}';
3386
3434
  };
3387
3435
 
3388
3436
  class CaseInsensitiveTerminal extends PExpr {
@@ -3430,9 +3478,9 @@
3430
3478
 
3431
3479
  toFailure(grammar) {
3432
3480
  return new Failure(
3433
- this,
3434
- this.obj.toFailure(grammar) + ' (case-insensitive)',
3435
- 'description',
3481
+ this,
3482
+ this.obj.toFailure(grammar) + ' (case-insensitive)',
3483
+ 'description'
3436
3484
  );
3437
3485
  }
3438
3486
 
@@ -3502,8 +3550,8 @@
3502
3550
  posInfo.exit();
3503
3551
 
3504
3552
  this.rightmostFailurePosition = Math.max(
3505
- this.rightmostFailurePosition,
3506
- this._rightmostFailurePositionStack.pop(),
3553
+ this.rightmostFailurePosition,
3554
+ this._rightmostFailurePositionStack.pop()
3507
3555
  );
3508
3556
 
3509
3557
  if (optNode) {
@@ -3639,9 +3687,9 @@
3639
3687
  }
3640
3688
 
3641
3689
  _getRightmostFailureOffset() {
3642
- return this.rightmostFailurePosition >= 0 ?
3643
- this.posToOffset(this.rightmostFailurePosition) :
3644
- -1;
3690
+ return this.rightmostFailurePosition >= 0
3691
+ ? this.posToOffset(this.rightmostFailurePosition)
3692
+ : -1;
3645
3693
  }
3646
3694
 
3647
3695
  // Returns the memoized trace entry for `expr` at `pos`, if one exists, `null` otherwise.
@@ -3698,8 +3746,8 @@
3698
3746
  const memoRecRightmostFailurePosition =
3699
3747
  this.inputStream.pos + memoRec.rightmostFailureOffset;
3700
3748
  this.rightmostFailurePosition = Math.max(
3701
- this.rightmostFailurePosition,
3702
- memoRecRightmostFailurePosition,
3749
+ this.rightmostFailurePosition,
3750
+ memoRecRightmostFailurePosition
3703
3751
  );
3704
3752
  if (
3705
3753
  this.recordedFailures &&
@@ -3710,8 +3758,8 @@
3710
3758
  }
3711
3759
 
3712
3760
  this.inputStream.examinedLength = Math.max(
3713
- this.inputStream.examinedLength,
3714
- memoRec.examinedLength + origPos,
3761
+ this.inputStream.examinedLength,
3762
+ memoRec.examinedLength + origPos
3715
3763
  );
3716
3764
 
3717
3765
  if (memoRec.value) {
@@ -3789,7 +3837,7 @@
3789
3837
  let rightmostFailures;
3790
3838
  if (this.recordedFailures) {
3791
3839
  rightmostFailures = Object.keys(this.recordedFailures).map(
3792
- key => this.recordedFailures[key],
3840
+ key => this.recordedFailures[key]
3793
3841
  );
3794
3842
  }
3795
3843
  const cst = this._bindings[0];
@@ -3797,13 +3845,13 @@
3797
3845
  cst.grammar = this.grammar;
3798
3846
  }
3799
3847
  return new MatchResult(
3800
- this.matcher,
3801
- this.input,
3802
- this.startExpr,
3803
- cst,
3804
- this._bindingOffsets[0],
3805
- this.rightmostFailurePosition,
3806
- rightmostFailures,
3848
+ this.matcher,
3849
+ this.input,
3850
+ this.startExpr,
3851
+ cst,
3852
+ this._bindingOffsets[0],
3853
+ this.rightmostFailurePosition,
3854
+ rightmostFailures
3807
3855
  );
3808
3856
  }
3809
3857
 
@@ -4116,11 +4164,11 @@
4116
4164
  if (superSemantics) {
4117
4165
  if (!(grammar.equals(this.super.grammar) || grammar._inheritsFrom(this.super.grammar))) {
4118
4166
  throw new Error(
4119
- "Cannot extend a semantics for grammar '" +
4167
+ "Cannot extend a semantics for grammar '" +
4120
4168
  this.super.grammar.name +
4121
4169
  "' for use with grammar '" +
4122
4170
  grammar.name +
4123
- "' (not a sub-grammar)",
4171
+ "' (not a sub-grammar)"
4124
4172
  );
4125
4173
  }
4126
4174
  this.operations = Object.create(this.super.operations);
@@ -4129,7 +4177,7 @@
4129
4177
 
4130
4178
  // Assign unique symbols for each of the attributes inherited from the super-semantics so that
4131
4179
  // they are memoized independently.
4132
- // eslint-disable-next-line guard-for-in
4180
+
4133
4181
  for (const attributeName in this.attributes) {
4134
4182
  Object.defineProperty(this.attributeKeys, attributeName, {
4135
4183
  value: uniqueId(attributeName),
@@ -4158,11 +4206,11 @@
4158
4206
  // Throws an exception if one or more of them doesn't.
4159
4207
  checkActionDicts() {
4160
4208
  let name;
4161
- // eslint-disable-next-line guard-for-in
4209
+
4162
4210
  for (name in this.operations) {
4163
4211
  this.operations[name].checkActionDict(this.grammar);
4164
4212
  }
4165
- // eslint-disable-next-line guard-for-in
4213
+
4166
4214
  for (name in this.attributes) {
4167
4215
  this.attributes[name].checkActionDict(this.grammar);
4168
4216
  }
@@ -4262,9 +4310,9 @@
4262
4310
  });
4263
4311
 
4264
4312
  const entry =
4265
- type === 'operation' ?
4266
- new Operation(name, formals, realActionDict, builtInDefault) :
4267
- new Attribute(name, realActionDict, builtInDefault);
4313
+ type === 'operation'
4314
+ ? new Operation(name, formals, realActionDict, builtInDefault)
4315
+ : new Attribute(name, realActionDict, builtInDefault);
4268
4316
 
4269
4317
  // The following check is not strictly necessary (it will happen later anyway) but it's better
4270
4318
  // to catch errors early.
@@ -4280,7 +4328,7 @@
4280
4328
  // Check that the caller passed the correct number of arguments.
4281
4329
  if (arguments.length !== thisThing.formals.length) {
4282
4330
  throw new Error(
4283
- 'Invalid number of arguments passed to ' +
4331
+ 'Invalid number of arguments passed to ' +
4284
4332
  name +
4285
4333
  ' ' +
4286
4334
  type +
@@ -4288,7 +4336,7 @@
4288
4336
  thisThing.formals.length +
4289
4337
  ', got ' +
4290
4338
  arguments.length +
4291
- ')',
4339
+ ')'
4292
4340
  );
4293
4341
  }
4294
4342
 
@@ -4309,7 +4357,7 @@
4309
4357
 
4310
4358
  if (type === 'operation') {
4311
4359
  this.Wrapper.prototype[name] = doIt;
4312
- this.Wrapper.prototype[name].toString = function() {
4360
+ this.Wrapper.prototype[name].toString = function () {
4313
4361
  return '[' + name + ' operation]';
4314
4362
  };
4315
4363
  } else {
@@ -4331,13 +4379,13 @@
4331
4379
 
4332
4380
  if (!(this.super && name in this.super[typePlural])) {
4333
4381
  throw new Error(
4334
- 'Cannot extend ' +
4382
+ 'Cannot extend ' +
4335
4383
  type +
4336
4384
  " '" +
4337
4385
  name +
4338
4386
  "': did not inherit an " +
4339
4387
  type +
4340
- ' with that name',
4388
+ ' with that name'
4341
4389
  );
4342
4390
  }
4343
4391
  if (hasOwnProperty(this[typePlural], name)) {
@@ -4354,9 +4402,9 @@
4354
4402
  });
4355
4403
 
4356
4404
  this[typePlural][name] =
4357
- type === 'operation' ?
4358
- new Operation(name, inheritedFormals, newActionDict) :
4359
- new Attribute(name, newActionDict);
4405
+ type === 'operation'
4406
+ ? new Operation(name, inheritedFormals, newActionDict)
4407
+ : new Attribute(name, newActionDict);
4360
4408
 
4361
4409
  // The following check is not strictly necessary (it will happen later anyway) but it's better
4362
4410
  // to catch errors early.
@@ -4369,12 +4417,12 @@
4369
4417
  }
4370
4418
  if (name in this.operations) {
4371
4419
  throw new Error(
4372
- 'Cannot add ' + type + " '" + name + "': an operation with that name already exists",
4420
+ 'Cannot add ' + type + " '" + name + "': an operation with that name already exists"
4373
4421
  );
4374
4422
  }
4375
4423
  if (name in this.attributes) {
4376
4424
  throw new Error(
4377
- 'Cannot add ' + type + " '" + name + "': an attribute with that name already exists",
4425
+ 'Cannot add ' + type + " '" + name + "': an attribute with that name already exists"
4378
4426
  );
4379
4427
  }
4380
4428
  }
@@ -4400,8 +4448,8 @@
4400
4448
  }
4401
4449
 
4402
4450
  const r = Semantics.prototypeGrammar.match(
4403
- signature,
4404
- type === 'operation' ? 'OperationSignature' : 'AttributeSignature',
4451
+ signature,
4452
+ type === 'operation' ? 'OperationSignature' : 'AttributeSignature'
4405
4453
  );
4406
4454
  if (r.failed()) {
4407
4455
  throw new Error(r.message);
@@ -4411,7 +4459,7 @@
4411
4459
  }
4412
4460
 
4413
4461
  function newDefaultAction(type, name, doIt) {
4414
- return function(...children) {
4462
+ return function (...children) {
4415
4463
  const thisThing = this._semantics.operations[name] || this._semantics.attributes[name];
4416
4464
  const args = thisThing.formals.map(formal => this.args[formal]);
4417
4465
 
@@ -4435,12 +4483,12 @@
4435
4483
  // Semantics instance. When that function is invoked with a CST node as an argument, it returns
4436
4484
  // a wrapper for that node which gives access to the operations and attributes provided by this
4437
4485
  // semantics.
4438
- Semantics.createSemantics = function(grammar, optSuperSemantics) {
4486
+ Semantics.createSemantics = function (grammar, optSuperSemantics) {
4439
4487
  const s = new Semantics(
4440
- grammar,
4441
- optSuperSemantics !== undefined ?
4442
- optSuperSemantics :
4443
- Semantics.BuiltInSemantics._getSemantics(),
4488
+ grammar,
4489
+ optSuperSemantics !== undefined
4490
+ ? optSuperSemantics
4491
+ : Semantics.BuiltInSemantics._getSemantics()
4444
4492
  );
4445
4493
 
4446
4494
  // To enable clients to invoke a semantics like a function, return a function that acts as a proxy
@@ -4448,8 +4496,8 @@
4448
4496
  const proxy = function ASemantics(matchResult) {
4449
4497
  if (!(matchResult instanceof MatchResult)) {
4450
4498
  throw new TypeError(
4451
- 'Semantics expected a MatchResult, but got ' +
4452
- unexpectedObjToString(matchResult),
4499
+ 'Semantics expected a MatchResult, but got ' +
4500
+ unexpectedObjToString(matchResult)
4453
4501
  );
4454
4502
  }
4455
4503
  if (matchResult.failed()) {
@@ -4459,11 +4507,11 @@
4459
4507
  const cst = matchResult._cst;
4460
4508
  if (cst.grammar !== grammar) {
4461
4509
  throw new Error(
4462
- "Cannot use a MatchResult from grammar '" +
4510
+ "Cannot use a MatchResult from grammar '" +
4463
4511
  cst.grammar.name +
4464
4512
  "' with a semantics for '" +
4465
4513
  grammar.name +
4466
- "'",
4514
+ "'"
4467
4515
  );
4468
4516
  }
4469
4517
  const inputStream = new InputStream(matchResult.input);
@@ -4471,38 +4519,38 @@
4471
4519
  };
4472
4520
 
4473
4521
  // Forward public methods from the proxy to the semantics instance.
4474
- proxy.addOperation = function(signature, actionDict) {
4522
+ proxy.addOperation = function (signature, actionDict) {
4475
4523
  s.addOperationOrAttribute('operation', signature, actionDict);
4476
4524
  return proxy;
4477
4525
  };
4478
- proxy.extendOperation = function(name, actionDict) {
4526
+ proxy.extendOperation = function (name, actionDict) {
4479
4527
  s.extendOperationOrAttribute('operation', name, actionDict);
4480
4528
  return proxy;
4481
4529
  };
4482
- proxy.addAttribute = function(name, actionDict) {
4530
+ proxy.addAttribute = function (name, actionDict) {
4483
4531
  s.addOperationOrAttribute('attribute', name, actionDict);
4484
4532
  return proxy;
4485
4533
  };
4486
- proxy.extendAttribute = function(name, actionDict) {
4534
+ proxy.extendAttribute = function (name, actionDict) {
4487
4535
  s.extendOperationOrAttribute('attribute', name, actionDict);
4488
4536
  return proxy;
4489
4537
  };
4490
- proxy._getActionDict = function(operationOrAttributeName) {
4538
+ proxy._getActionDict = function (operationOrAttributeName) {
4491
4539
  const action =
4492
4540
  s.operations[operationOrAttributeName] || s.attributes[operationOrAttributeName];
4493
4541
  if (!action) {
4494
4542
  throw new Error(
4495
- '"' +
4543
+ '"' +
4496
4544
  operationOrAttributeName +
4497
4545
  '" is not a valid operation or attribute ' +
4498
4546
  'name in this semantics for "' +
4499
4547
  grammar.name +
4500
- '"',
4548
+ '"'
4501
4549
  );
4502
4550
  }
4503
4551
  return action.actionDict;
4504
4552
  };
4505
- proxy._remove = function(operationOrAttributeName) {
4553
+ proxy._remove = function (operationOrAttributeName) {
4506
4554
  let semantic;
4507
4555
  if (operationOrAttributeName in s.operations) {
4508
4556
  semantic = s.operations[operationOrAttributeName];
@@ -4514,16 +4562,16 @@
4514
4562
  delete s.Wrapper.prototype[operationOrAttributeName];
4515
4563
  return semantic;
4516
4564
  };
4517
- proxy.getOperationNames = function() {
4565
+ proxy.getOperationNames = function () {
4518
4566
  return Object.keys(s.operations);
4519
4567
  };
4520
- proxy.getAttributeNames = function() {
4568
+ proxy.getAttributeNames = function () {
4521
4569
  return Object.keys(s.attributes);
4522
4570
  };
4523
- proxy.getGrammar = function() {
4571
+ proxy.getGrammar = function () {
4524
4572
  return s.grammar;
4525
4573
  };
4526
- proxy.toRecipe = function(semanticsOnly) {
4574
+ proxy.toRecipe = function (semanticsOnly) {
4527
4575
  return s.toRecipe(semanticsOnly);
4528
4576
  };
4529
4577
 
@@ -4531,7 +4579,7 @@
4531
4579
  proxy.toString = s.toString.bind(s);
4532
4580
 
4533
4581
  // Returns the semantics for the proxy.
4534
- proxy._getSemantics = function() {
4582
+ proxy._getSemantics = function () {
4535
4583
  return s;
4536
4584
  };
4537
4585
 
@@ -4623,8 +4671,8 @@
4623
4671
 
4624
4672
  function getSortedRuleValues(grammar) {
4625
4673
  return Object.keys(grammar.rules)
4626
- .sort()
4627
- .map(name => grammar.rules[name]);
4674
+ .sort()
4675
+ .map(name => grammar.rules[name]);
4628
4676
  }
4629
4677
 
4630
4678
  // Until ES2019, JSON was not a valid subset of JavaScript because U+2028 (line separator)
@@ -4645,11 +4693,11 @@
4645
4693
  if (optDefaultStartRule) {
4646
4694
  if (!(optDefaultStartRule in rules)) {
4647
4695
  throw new Error(
4648
- "Invalid start rule: '" +
4696
+ "Invalid start rule: '" +
4649
4697
  optDefaultStartRule +
4650
4698
  "' is not a rule in grammar '" +
4651
4699
  name +
4652
- "'",
4700
+ "'"
4653
4701
  );
4654
4702
  }
4655
4703
  this.defaultStartRule = optDefaultStartRule;
@@ -4720,7 +4768,6 @@
4720
4768
  _checkTopDownActionDict(what, name, actionDict) {
4721
4769
  const problems = [];
4722
4770
 
4723
- // eslint-disable-next-line guard-for-in
4724
4771
  for (const k in actionDict) {
4725
4772
  const v = actionDict[k];
4726
4773
  const isSpecialAction = SPECIAL_ACTION_NAMES.includes(k);
@@ -4750,10 +4797,10 @@
4750
4797
  if (problems.length > 0) {
4751
4798
  const prettyProblems = problems.map(problem => '- ' + problem);
4752
4799
  const error = new Error(
4753
- [
4754
- `Found errors in the action dictionary of the '${name}' ${what}:`,
4755
- ...prettyProblems,
4756
- ].join('\n'),
4800
+ [
4801
+ `Found errors in the action dictionary of the '${name}' ${what}:`,
4802
+ ...prettyProblems,
4803
+ ].join('\n')
4757
4804
  );
4758
4805
  error.problems = problems;
4759
4806
  throw error;
@@ -4766,9 +4813,9 @@
4766
4813
  // All special actions have an expected arity of 0, though all but _terminal
4767
4814
  // are expected to use the rest parameter syntax (e.g. `_iter(...children)`).
4768
4815
  // This is considered to have arity 0, i.e. `((...args) => {}).length` is 0.
4769
- return SPECIAL_ACTION_NAMES.includes(actionName) ?
4770
- 0 :
4771
- this.rules[actionName].body.getArity();
4816
+ return SPECIAL_ACTION_NAMES.includes(actionName)
4817
+ ? 0
4818
+ : this.rules[actionName].body.getArity();
4772
4819
  }
4773
4820
 
4774
4821
  _inheritsFrom(grammar) {
@@ -4859,7 +4906,7 @@
4859
4906
  sb.append('{');
4860
4907
 
4861
4908
  let first = true;
4862
- // eslint-disable-next-line guard-for-in
4909
+
4863
4910
  for (const ruleName in this.rules) {
4864
4911
  const {body} = this.rules[ruleName];
4865
4912
  if (first) {
@@ -4906,10 +4953,10 @@
4906
4953
  if (formals.length !== app.args.length) {
4907
4954
  const {source} = this.rules[app.ruleName];
4908
4955
  throw wrongNumberOfParameters(
4909
- app.ruleName,
4910
- formals.length,
4911
- app.args.length,
4912
- source,
4956
+ app.ruleName,
4957
+ formals.length,
4958
+ app.args.length,
4959
+ source
4913
4960
  );
4914
4961
  }
4915
4962
  return app;
@@ -4928,63 +4975,63 @@
4928
4975
  // `digit`, and is implicitly the super-grammar of any grammar whose super-grammar
4929
4976
  // isn't specified.
4930
4977
  Grammar.ProtoBuiltInRules = new Grammar(
4931
- 'ProtoBuiltInRules', // name
4932
- undefined, // supergrammar
4933
- {
4934
- any: {
4935
- body: any,
4936
- formals: [],
4937
- description: 'any character',
4938
- primitive: true,
4939
- },
4940
- end: {
4941
- body: end,
4942
- formals: [],
4943
- description: 'end of input',
4944
- primitive: true,
4945
- },
4946
-
4947
- caseInsensitive: {
4948
- body: new CaseInsensitiveTerminal(new Param(0)),
4949
- formals: ['str'],
4950
- primitive: true,
4951
- },
4952
- lower: {
4953
- body: new UnicodeChar('Ll'),
4954
- formals: [],
4955
- description: 'a lowercase letter',
4956
- primitive: true,
4957
- },
4958
- upper: {
4959
- body: new UnicodeChar('Lu'),
4960
- formals: [],
4961
- description: 'an uppercase letter',
4962
- primitive: true,
4963
- },
4964
- // Union of Lt (titlecase), Lm (modifier), and Lo (other), i.e. any letter not in Ll or Lu.
4965
- unicodeLtmo: {
4966
- body: new UnicodeChar('Ltmo'),
4967
- formals: [],
4968
- description: 'a Unicode character in Lt, Lm, or Lo',
4969
- primitive: true,
4970
- },
4971
-
4972
- // These rules are not truly primitive (they could be written in userland) but are defined
4973
- // here for bootstrapping purposes.
4974
- spaces: {
4975
- body: new Star(new Apply('space')),
4976
- formals: [],
4977
- },
4978
- space: {
4979
- body: new Range('\x00', ' '),
4980
- formals: [],
4981
- description: 'a space',
4982
- },
4978
+ 'ProtoBuiltInRules', // name
4979
+ undefined, // supergrammar
4980
+ {
4981
+ any: {
4982
+ body: any,
4983
+ formals: [],
4984
+ description: 'any character',
4985
+ primitive: true,
4986
+ },
4987
+ end: {
4988
+ body: end,
4989
+ formals: [],
4990
+ description: 'end of input',
4991
+ primitive: true,
4992
+ },
4993
+
4994
+ caseInsensitive: {
4995
+ body: new CaseInsensitiveTerminal(new Param(0)),
4996
+ formals: ['str'],
4997
+ primitive: true,
4998
+ },
4999
+ lower: {
5000
+ body: new UnicodeChar('Ll'),
5001
+ formals: [],
5002
+ description: 'a lowercase letter',
5003
+ primitive: true,
5004
+ },
5005
+ upper: {
5006
+ body: new UnicodeChar('Lu'),
5007
+ formals: [],
5008
+ description: 'an uppercase letter',
5009
+ primitive: true,
5010
+ },
5011
+ // Union of Lt (titlecase), Lm (modifier), and Lo (other), i.e. any letter not in Ll or Lu.
5012
+ unicodeLtmo: {
5013
+ body: new UnicodeChar('Ltmo'),
5014
+ formals: [],
5015
+ description: 'a Unicode character in Lt, Lm, or Lo',
5016
+ primitive: true,
4983
5017
  },
5018
+
5019
+ // These rules are not truly primitive (they could be written in userland) but are defined
5020
+ // here for bootstrapping purposes.
5021
+ spaces: {
5022
+ body: new Star(new Apply('space')),
5023
+ formals: [],
5024
+ },
5025
+ space: {
5026
+ body: new Range('\x00', ' '),
5027
+ formals: [],
5028
+ description: 'a space',
5029
+ },
5030
+ }
4984
5031
  );
4985
5032
 
4986
5033
  // This method is called from main.js once Ohm has loaded.
4987
- Grammar.initApplicationParser = function(grammar, builderFn) {
5034
+ Grammar.initApplicationParser = function (grammar, builderFn) {
4988
5035
  ohmGrammar$1 = grammar;
4989
5036
  buildGrammar$1 = builderFn;
4990
5037
  };
@@ -5012,7 +5059,7 @@
5012
5059
  // TODO: The conditional expression below is an ugly hack. It's kind of ok because
5013
5060
  // I doubt anyone will ever try to declare a grammar called `BuiltInRules`. Still,
5014
5061
  // we should try to find a better way to do this.
5015
- this.name === 'BuiltInRules' ? Grammar.ProtoBuiltInRules : Grammar.BuiltInRules,
5062
+ this.name === 'BuiltInRules' ? Grammar.ProtoBuiltInRules : Grammar.BuiltInRules
5016
5063
  );
5017
5064
  }
5018
5065
  return this.superGrammar;
@@ -5080,10 +5127,10 @@
5080
5127
  // Creates a Grammar instance, and if it passes the sanity checks, returns it.
5081
5128
  build() {
5082
5129
  const grammar = new Grammar(
5083
- this.name,
5084
- this.ensureSuperGrammar(),
5085
- this.rules,
5086
- this.defaultStartRule,
5130
+ this.name,
5131
+ this.ensureSuperGrammar(),
5132
+ this.rules,
5133
+ this.defaultStartRule
5087
5134
  );
5088
5135
  // Initialize internal props that are inherited from the super grammar.
5089
5136
  grammar._matchStateInitializer = grammar.superGrammar._matchStateInitializer;
@@ -5184,7 +5231,7 @@
5184
5231
  if (superGrammar) {
5185
5232
  // `superGrammar` may be a recipe (i.e. an Array), or an actual grammar instance.
5186
5233
  gDecl.withSuperGrammar(
5187
- superGrammar instanceof Grammar ? superGrammar : this.fromRecipe(superGrammar),
5234
+ superGrammar instanceof Grammar ? superGrammar : this.fromRecipe(superGrammar)
5188
5235
  );
5189
5236
  }
5190
5237
  if (defaultStartRule) {
@@ -5208,8 +5255,8 @@
5208
5255
  let source;
5209
5256
  if (gDecl.source && metaInfo && metaInfo.sourceInterval) {
5210
5257
  source = gDecl.source.subInterval(
5211
- metaInfo.sourceInterval[0],
5212
- metaInfo.sourceInterval[1] - metaInfo.sourceInterval[0],
5258
+ metaInfo.sourceInterval[0],
5259
+ metaInfo.sourceInterval[1] - metaInfo.sourceInterval[0]
5213
5260
  );
5214
5261
  }
5215
5262
  gDecl[action](ruleName, formals, body, description, source);
@@ -5304,7 +5351,7 @@
5304
5351
 
5305
5352
  app(ruleName, optParams) {
5306
5353
  if (optParams && optParams.length > 0) {
5307
- optParams = optParams.map(function(param) {
5354
+ optParams = optParams.map(function (param) {
5308
5355
  return param instanceof PExpr ? param : this.fromRecipe(param);
5309
5356
  }, this);
5310
5357
  }
@@ -5316,10 +5363,10 @@
5316
5363
  // `this.currentDecl` and `this.currentRuleName` being set.
5317
5364
  splice(beforeTerms, afterTerms) {
5318
5365
  return new Splice(
5319
- this.currentDecl.superGrammar,
5320
- this.currentRuleName,
5321
- beforeTerms.map(term => this.fromRecipe(term)),
5322
- afterTerms.map(term => this.fromRecipe(term)),
5366
+ this.currentDecl.superGrammar,
5367
+ this.currentRuleName,
5368
+ beforeTerms.map(term => this.fromRecipe(term)),
5369
+ afterTerms.map(term => this.fromRecipe(term))
5323
5370
  );
5324
5371
  }
5325
5372
 
@@ -5460,10 +5507,10 @@
5460
5507
  });
5461
5508
 
5462
5509
  return new Splice(
5463
- decl.superGrammar,
5464
- currentRuleName,
5465
- beforeTerms,
5466
- afterTerms,
5510
+ decl.superGrammar,
5511
+ currentRuleName,
5512
+ beforeTerms,
5513
+ afterTerms
5467
5514
  ).withSource(this.source);
5468
5515
  } else {
5469
5516
  return builder.alt(...args).withSource(this.source);
@@ -5608,14 +5655,14 @@
5608
5655
  };
5609
5656
 
5610
5657
  Semantics.BuiltInSemantics = Semantics.createSemantics(builtInRules, null).addOperation(
5611
- 'asIteration',
5612
- {
5613
- emptyListOf: actions.empty,
5614
- nonemptyListOf: actions.nonEmpty,
5615
- EmptyListOf: actions.empty,
5616
- NonemptyListOf: actions.nonEmpty,
5617
- _iter: actions.self,
5618
- },
5658
+ 'asIteration',
5659
+ {
5660
+ emptyListOf: actions.empty,
5661
+ nonemptyListOf: actions.nonEmpty,
5662
+ EmptyListOf: actions.empty,
5663
+ NonemptyListOf: actions.nonEmpty,
5664
+ _iter: actions.self,
5665
+ }
5619
5666
  );
5620
5667
  }
5621
5668
 
@@ -5804,12 +5851,12 @@
5804
5851
  const newAnyBody = new Splice(BuiltInRules, 'any', [applyIndent, applyDedent], []);
5805
5852
 
5806
5853
  const IndentationSensitive = new Builder()
5807
- .newGrammar('IndentationSensitive')
5808
- .withSuperGrammar(BuiltInRules)
5809
- .define('indent', [], new Indentation(true), INDENT_DESCRIPTION, undefined, true)
5810
- .define('dedent', [], new Indentation(false), DEDENT_DESCRIPTION, undefined, true)
5811
- .extend('any', [], newAnyBody, 'any character', undefined)
5812
- .build();
5854
+ .newGrammar('IndentationSensitive')
5855
+ .withSuperGrammar(BuiltInRules)
5856
+ .define('indent', [], new Indentation(true), INDENT_DESCRIPTION, undefined, true)
5857
+ .define('dedent', [], new Indentation(false), DEDENT_DESCRIPTION, undefined, true)
5858
+ .extend('any', [], newAnyBody, 'any character', undefined)
5859
+ .build();
5813
5860
 
5814
5861
  Object.assign(IndentationSensitive, {
5815
5862
  _matchStateInitializer(state) {
@@ -5842,7 +5889,7 @@
5842
5889
  source = source.toString();
5843
5890
  } else {
5844
5891
  throw new TypeError(
5845
- 'Expected string as first argument, got ' + unexpectedObjToString(source),
5892
+ 'Expected string as first argument, got ' + unexpectedObjToString(source)
5846
5893
  );
5847
5894
  }
5848
5895
  }
@@ -5998,10 +6045,60 @@
5998
6045
  return semantics(matchResult).examples();
5999
6046
  }
6000
6047
 
6048
+ /*
6049
+ To find iter nodes that are derived from the same repetition expression, we
6050
+ look for adjacent iter nodes that have the same source interval and the same
6051
+ number of children.
6052
+
6053
+ A few things to note:
6054
+ - The children of `*` and `+` nodes can't be nullable, so the associated iter
6055
+ nodes always consume some input, and therefore consecutive nodes that have
6056
+ the same interval must come from the same repetition expression.
6057
+ - We *could* mistake `a? b?` for (a b)?`, if neither of them comsume any input.
6058
+ However, for the purposes of this module, those two cases are equivalent
6059
+ anyways, since we only care about finding the correct order of the non-iter
6060
+ nodes, and both interpretations yield the same order.
6061
+ */
6062
+ const isIterSibling = (refNode, n) => {
6063
+ return (
6064
+ n.isIteration() &&
6065
+ n.source.startIdx === refNode.source.startIdx &&
6066
+ n.source.endIdx === refNode.source.endIdx &&
6067
+ n.children.length === refNode.children.length
6068
+ );
6069
+ };
6070
+
6071
+ function recoverSourceOrder(nodes, depth = 0) {
6072
+ const ans = [];
6073
+ for (let i = 0; i < nodes.length; i++) {
6074
+ const n = nodes[i];
6075
+ if (!n.isIteration()) {
6076
+ ans.push(n);
6077
+ continue;
6078
+ }
6079
+
6080
+ // We found an iter node, now find its siblings.
6081
+ const siblings = [n];
6082
+ // Find the first node that's *not* part of the current list.
6083
+ for (let j = i + 1; j < nodes.length && isIterSibling(n, nodes[j]); j++) {
6084
+ siblings.push(nodes[j]);
6085
+ i = j;
6086
+ }
6087
+ const cousins = [];
6088
+ const numRows = siblings[0].children.length;
6089
+ for (let row = 0; row < numRows; row++) {
6090
+ cousins.push(...siblings.map(sib => sib.children[row]));
6091
+ }
6092
+ ans.push(...recoverSourceOrder(cousins, depth + 1));
6093
+ }
6094
+ return ans;
6095
+ }
6096
+
6001
6097
  exports.VisitorFamily = VisitorFamily;
6002
6098
  exports.extractExamples = extractExamples;
6003
6099
  exports.getLineAndColumn = getLineAndColumn;
6004
6100
  exports.getLineAndColumnMessage = getLineAndColumnMessage;
6101
+ exports.recoverSourceOrder = recoverSourceOrder;
6005
6102
  exports.semanticsForToAST = semanticsForToAST;
6006
6103
  exports.toAST = toAST;
6007
6104