codemirror-lang-raku 0.2.0 → 0.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.
- package/CHANGELOG.md +66 -0
- package/README.md +17 -6
- package/dist/index.cjs +332 -108
- package/dist/index.js +332 -108
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,13 +5,13 @@ import { tags, styleTags } from '@lezer/highlight';
|
|
|
5
5
|
import { Prec, EditorState } from '@codemirror/state';
|
|
6
6
|
|
|
7
7
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
8
|
-
const smiley =
|
|
9
|
-
noSmiley =
|
|
8
|
+
const smiley = 201,
|
|
9
|
+
noSmiley = 202,
|
|
10
10
|
BlockComment = 1,
|
|
11
11
|
podStart = 2,
|
|
12
|
-
podEnd =
|
|
12
|
+
podEnd = 203,
|
|
13
13
|
podEndDirective = 3,
|
|
14
|
-
podText =
|
|
14
|
+
podText = 204,
|
|
15
15
|
PodDirective = 4,
|
|
16
16
|
PodHeading = 5,
|
|
17
17
|
PodStrong = 6,
|
|
@@ -21,17 +21,18 @@ const smiley = 199,
|
|
|
21
21
|
PodFormat = 10,
|
|
22
22
|
rawHeredoc = 11,
|
|
23
23
|
interpolatingHeredoc = 12,
|
|
24
|
-
heredocStart =
|
|
24
|
+
heredocStart = 205,
|
|
25
25
|
methodDot = 13,
|
|
26
26
|
MethodName = 14,
|
|
27
|
-
declaredName =
|
|
28
|
-
declaredMethodName =
|
|
27
|
+
declaredName = 206,
|
|
28
|
+
declaredMethodName = 207,
|
|
29
|
+
declaredVariable = 208,
|
|
29
30
|
Version = 15,
|
|
30
|
-
regexStart =
|
|
31
|
-
regexBodyEnd =
|
|
32
|
-
regexLitOpen =
|
|
33
|
-
regexLitClose =
|
|
34
|
-
regexText =
|
|
31
|
+
regexStart = 209,
|
|
32
|
+
regexBodyEnd = 210,
|
|
33
|
+
regexLitOpen = 211,
|
|
34
|
+
regexLitClose = 212,
|
|
35
|
+
regexText = 213,
|
|
35
36
|
CharacterClass = 16,
|
|
36
37
|
Assertion = 17,
|
|
37
38
|
regexQuote = 18,
|
|
@@ -39,18 +40,18 @@ const smiley = 199,
|
|
|
39
40
|
regexComment = 20,
|
|
40
41
|
regexBlockComment = 21,
|
|
41
42
|
regexCapture = 22,
|
|
42
|
-
quoteContent =
|
|
43
|
-
quoteNestOpen =
|
|
44
|
-
quoteNestClose =
|
|
45
|
-
quoteEnd =
|
|
46
|
-
rawString =
|
|
47
|
-
quoteStart =
|
|
43
|
+
quoteContent = 214,
|
|
44
|
+
quoteNestOpen = 215,
|
|
45
|
+
quoteNestClose = 216,
|
|
46
|
+
quoteEnd = 217,
|
|
47
|
+
rawString = 218,
|
|
48
|
+
quoteStart = 219,
|
|
48
49
|
interpolatingWordList = 23,
|
|
49
50
|
regexLiteral = 24,
|
|
50
51
|
transliteration = 25,
|
|
51
|
-
plainName =
|
|
52
|
+
plainName = 220,
|
|
52
53
|
wordOperator = 26,
|
|
53
|
-
multiName =
|
|
54
|
+
multiName = 221,
|
|
54
55
|
operatorVariable = 27,
|
|
55
56
|
LineComment = 28,
|
|
56
57
|
DocComment = 29,
|
|
@@ -72,25 +73,26 @@ const smiley = 199,
|
|
|
72
73
|
TypeName = 80,
|
|
73
74
|
Number = 81,
|
|
74
75
|
quotedString = 82,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
76
|
+
NestedDelimiters = 83,
|
|
77
|
+
Interpolation = 84,
|
|
78
|
+
PairKey = 85,
|
|
79
|
+
multi = 96,
|
|
80
|
+
proto = 97,
|
|
81
|
+
only = 98,
|
|
82
|
+
self = 165,
|
|
83
|
+
True = 166,
|
|
84
|
+
False = 167,
|
|
85
|
+
Nil = 168,
|
|
86
|
+
Operator = 187,
|
|
87
|
+
Regex = 191,
|
|
88
|
+
Heredoc = 192,
|
|
89
|
+
StringLiteral = 193;
|
|
88
90
|
|
|
89
91
|
// Opening bracket -> closing bracket, for the delimiters of quotes and
|
|
90
92
|
// embedded comments. Raku accepts any Unicode bracket pair; this lists
|
|
91
93
|
// the ones that are likely to be typed.
|
|
92
94
|
const brackets$1 = {};
|
|
93
|
-
for (let pair of ["()", "[]", "{}", "<>", "«»", "「」", "『』", "()", "[]", "{}", "【】", "〈〉", "《》", "〔〕"])
|
|
95
|
+
for (let pair of ["()", "[]", "{}", "<>", "«»", "「」", "「」", "『』", "()", "[]", "{}", "【】", "〈〉", "《》", "〔〕"])
|
|
94
96
|
brackets$1[pair.charCodeAt(0)] = pair.charCodeAt(1);
|
|
95
97
|
function isAsciiLetter(ch) { return ch >= 97 /* Ch.a */ && ch <= 122 /* Ch.z */ || ch >= 65 /* Ch.A */ && ch <= 90 /* Ch.Z */; }
|
|
96
98
|
function isDigit(ch) { return ch >= 48 /* Ch._0 */ && ch <= 57 /* Ch._9 */; }
|
|
@@ -154,9 +156,7 @@ function word(input, from, to) {
|
|
|
154
156
|
}
|
|
155
157
|
// A quote that is being read piece by piece because it interpolates.
|
|
156
158
|
class Quote {
|
|
157
|
-
constructor(parent, open, close, count,
|
|
158
|
-
// How many nested opening delimiters are unclosed.
|
|
159
|
-
depth, interpolates,
|
|
159
|
+
constructor(parent, open, close, count, interpolates,
|
|
160
160
|
// Whether a backslash that does not start an escape still
|
|
161
161
|
// takes the delimiter after it out of play: q:c[a \] b]
|
|
162
162
|
escapes) {
|
|
@@ -164,22 +164,18 @@ class Quote {
|
|
|
164
164
|
this.open = open;
|
|
165
165
|
this.close = close;
|
|
166
166
|
this.count = count;
|
|
167
|
-
this.depth = depth;
|
|
168
167
|
this.interpolates = interpolates;
|
|
169
168
|
this.escapes = escapes;
|
|
170
169
|
let hash = parent ? parent.hash : 7;
|
|
171
|
-
for (let part of [open, count,
|
|
170
|
+
for (let part of [open, count, interpolates, escapes ? 1 : 0])
|
|
172
171
|
hash = (hash * 31 + part) | 0;
|
|
173
172
|
this.hash = hash;
|
|
174
173
|
}
|
|
175
|
-
withDepth(depth) {
|
|
176
|
-
return new Quote(this.parent, this.open, this.close, this.count, depth, this.interpolates, this.escapes);
|
|
177
|
-
}
|
|
178
174
|
}
|
|
179
175
|
const noHeredocs = [];
|
|
180
176
|
// The quote that the text of a heredoc is read as. It has no
|
|
181
177
|
// delimiters, and ends where the text does.
|
|
182
|
-
const heredocQuote = new Quote(null, -1, -1, 1,
|
|
178
|
+
const heredocQuote = new Quote(null, -1, -1, 1, 63 /* Interpolate.All */, true);
|
|
183
179
|
// The body of a regex declaration, or the inside of a regex literal,
|
|
184
180
|
// that is being read piece by piece.
|
|
185
181
|
class RegexBody {
|
|
@@ -272,11 +268,11 @@ for (let term of [VariableName, AttributeName, SpecialVariable, operatorVariable
|
|
|
272
268
|
regexText, CharacterClass, Assertion, regexQuote, regexOperator, regexComment,
|
|
273
269
|
regexBlockComment, regexCapture])
|
|
274
270
|
termModes.set(term, 1 /* Mode.AfterTerm */);
|
|
275
|
-
for (let term of [Identifier, TypeName, smiley, noSmiley, declaredName, declaredMethodName, PackageName, RoutineName,
|
|
271
|
+
for (let term of [Identifier, TypeName, smiley, noSmiley, declaredName, declaredMethodName, declaredVariable, PackageName, RoutineName,
|
|
276
272
|
methodRoutineName, multiName, multiRoutineName, RegexName, EnumName, SubsetName, ConstantName])
|
|
277
273
|
termModes.set(term, 2 /* Mode.AfterName */);
|
|
278
274
|
// The `}` of "{...}" in a string does not take a subscript.
|
|
279
|
-
for (let term of [quoteContent, Interpolation])
|
|
275
|
+
for (let term of [quoteContent, quoteNestOpen, quoteNestClose, NestedDelimiters, Interpolation])
|
|
280
276
|
termModes.set(term, 0 /* Mode.Term */);
|
|
281
277
|
for (let term of [multi, proto, only])
|
|
282
278
|
termModes.set(term, 4 /* Mode.AfterMulti */);
|
|
@@ -286,6 +282,10 @@ function modeAfterOperator(first, second, third, after) {
|
|
|
286
282
|
// A lone `*` is as often the whatever star as a multiplication.
|
|
287
283
|
if (first == 42 /* Ch.Star */ && !isOperatorChar(second))
|
|
288
284
|
return 2 /* Mode.AfterName */;
|
|
285
|
+
// A power in superscript, $x², leaves the term complete. These are
|
|
286
|
+
// the characters that the grammar's Operator token takes for one.
|
|
287
|
+
if (first == 0xb2 || first == 0xb3 || first == 0xb9 || first == 0x2070 || first >= 0x2074 && first <= 0x207b)
|
|
288
|
+
return 1 /* Mode.AfterTerm */;
|
|
289
289
|
// Postfix increment and decrement leave the term complete.
|
|
290
290
|
if ((first == 43 /* Ch.Plus */ || first == 45 /* Ch.Hyphen */) && second == first && !isOperatorChar(third) &&
|
|
291
291
|
(after == 1 /* Mode.AfterTerm */ || after == 3 /* Mode.AfterBlock */))
|
|
@@ -367,15 +367,16 @@ function hasNewline(input, from, to) {
|
|
|
367
367
|
}
|
|
368
368
|
// The heredocs that are open after a reused node, of which the input is
|
|
369
369
|
// at the start. As when tokens are shifted, a line break between tokens
|
|
370
|
-
// and the text of a heredoc close the ones before them.
|
|
371
|
-
|
|
370
|
+
// and the text of a heredoc close the ones before them. `inQuote` tells
|
|
371
|
+
// that the node is a run of pieces of a quote.
|
|
372
|
+
function heredocsAfter(node, input, before, inQuote) {
|
|
372
373
|
// Most reused nodes are single tokens.
|
|
373
374
|
if (!node.children.length && !stringTerms.has(node.type.id) && !heredocTerms.has(node.type.id))
|
|
374
375
|
return before;
|
|
375
376
|
let cursor = node.cursor(), found = [], closedAt = -1;
|
|
376
377
|
// Goes over the node at the cursor from its end, and tells whether
|
|
377
378
|
// the heredocs before some point in it are closed.
|
|
378
|
-
function scan() {
|
|
379
|
+
function scan(text = false) {
|
|
379
380
|
let type = cursor.type.id, { from, to } = cursor;
|
|
380
381
|
if (heredocTerms.has(type)) {
|
|
381
382
|
closedAt = to;
|
|
@@ -394,7 +395,7 @@ function heredocsAfter(node, input, before) {
|
|
|
394
395
|
if (!cursor.lastChild())
|
|
395
396
|
return false;
|
|
396
397
|
// Between the pieces of a string lies its text, not whitespace.
|
|
397
|
-
let gaps = !isString;
|
|
398
|
+
let gaps = !isString && !text && type != NestedDelimiters;
|
|
398
399
|
for (let gapEnd = to;;) {
|
|
399
400
|
if (gaps && hasNewline(input, cursor.to, gapEnd)) {
|
|
400
401
|
closedAt = gapEnd;
|
|
@@ -412,7 +413,8 @@ function heredocsAfter(node, input, before) {
|
|
|
412
413
|
cursor.parent();
|
|
413
414
|
return closedAt >= 0;
|
|
414
415
|
}
|
|
415
|
-
|
|
416
|
+
// A piece on its own, such as an Interpolation, is a named node.
|
|
417
|
+
scan(inQuote && node.type.isAnonymous);
|
|
416
418
|
if (!found.length && closedAt < 0)
|
|
417
419
|
return before;
|
|
418
420
|
let after = found.filter(opener => opener.pos >= closedAt).sort((a, b) => a.pos - b.pos).map(opener => opener.heredoc);
|
|
@@ -477,17 +479,9 @@ const trackContext = new ContextTracker({
|
|
|
477
479
|
let opening = wordListOpening(input, 0) || readOpening(input);
|
|
478
480
|
if (!opening)
|
|
479
481
|
return context;
|
|
480
|
-
let quote = new Quote(context.quote, opening.open, opening.close, opening.count,
|
|
482
|
+
let quote = new Quote(context.quote, opening.open, opening.close, opening.count, opening.interpolates, opening.escapes);
|
|
481
483
|
return context.withQuote(0 /* Mode.Term */, quote, withHeredocAt(context.heredocs, input, 0));
|
|
482
484
|
}
|
|
483
|
-
case quoteNestOpen:
|
|
484
|
-
case quoteNestClose: {
|
|
485
|
-
let quote = context.quote;
|
|
486
|
-
if (!quote)
|
|
487
|
-
return context;
|
|
488
|
-
let depth = quote.depth + (term == quoteNestOpen ? 1 : -1);
|
|
489
|
-
return context.withQuote(0 /* Mode.Term */, quote.withDepth(depth));
|
|
490
|
-
}
|
|
491
485
|
case quoteEnd:
|
|
492
486
|
return context.withQuote(1 /* Mode.AfterTerm */, context.quote && context.quote.parent);
|
|
493
487
|
}
|
|
@@ -511,8 +505,13 @@ const trackContext = new ContextTracker({
|
|
|
511
505
|
return term == Identifier || term == Interpolation ? context.withMode(modeAfter(term, input, 0, context.mode))
|
|
512
506
|
: context;
|
|
513
507
|
},
|
|
514
|
-
|
|
515
|
-
|
|
508
|
+
// A node that is reused leaves the quote and the regex of the context
|
|
509
|
+
// as they are: the grammar pairs the delimiters that nest in a quote
|
|
510
|
+
// (NestedDelimiters) and the braces of a block, so a node closes what
|
|
511
|
+
// it opens.
|
|
512
|
+
reuse(context, node, stack, input) {
|
|
513
|
+
let inQuote = context.quote != null && inQuoteText(stack);
|
|
514
|
+
context = context.withHeredocs(heredocsAfter(node, input, context.heredocs, inQuote));
|
|
516
515
|
// The node's positions count from its start, where the input is.
|
|
517
516
|
let last = lastToken$1(node.topNode);
|
|
518
517
|
// What comes before a trailing `++` in a reused node is a term.
|
|
@@ -540,16 +539,24 @@ const blockComment = new ExternalTokenizer(input => {
|
|
|
540
539
|
let end = embeddedCommentEnd(input, 0);
|
|
541
540
|
if (!end)
|
|
542
541
|
return;
|
|
542
|
+
// A declarator comment with brackets, #|( ... ) and #=( ... ), is
|
|
543
|
+
// still a declarator comment.
|
|
544
|
+
let term = input.peek(1) == 96 /* Ch.Backtick */ ? BlockComment : DocComment;
|
|
543
545
|
if (end < 0)
|
|
544
546
|
skipToEnd(input);
|
|
545
547
|
else
|
|
546
548
|
input.advance(end);
|
|
547
|
-
input.acceptToken(
|
|
549
|
+
input.acceptToken(term);
|
|
548
550
|
});
|
|
549
551
|
// The offset after the embedded comment that starts at offset `at`.
|
|
550
552
|
// Zero when none starts there, and -1 when it is not closed.
|
|
553
|
+
//
|
|
554
|
+
// A declarator comment with brackets that is not closed is none: it is
|
|
555
|
+
// left to be a comment of one line, so that one that is being typed
|
|
556
|
+
// does not take the declarations after it.
|
|
551
557
|
function embeddedCommentEnd(input, at) {
|
|
552
|
-
|
|
558
|
+
let mark = input.peek(at + 1);
|
|
559
|
+
if (input.peek(at) != 35 /* Ch.Hash */ || mark != 96 /* Ch.Backtick */ && mark != 124 /* Ch.Pipe */ && mark != 61 /* Ch.Equals */)
|
|
553
560
|
return 0;
|
|
554
561
|
let open = input.peek(at + 2), close = brackets$1[open];
|
|
555
562
|
if (close == null)
|
|
@@ -557,7 +564,8 @@ function embeddedCommentEnd(input, at) {
|
|
|
557
564
|
let count = 1;
|
|
558
565
|
while (input.peek(at + 2 + count) == open)
|
|
559
566
|
count++;
|
|
560
|
-
|
|
567
|
+
let end = rawEnd(input, at + 2 + count, { open, close, count, escapes: false });
|
|
568
|
+
return end < 0 && mark != 96 /* Ch.Backtick */ ? 0 : end;
|
|
561
569
|
}
|
|
562
570
|
function isBlank(ch) { return ch == 32 /* Ch.Space */ || ch == 9 /* Ch.Tab */ || ch == 13 /* Ch.Return */; }
|
|
563
571
|
// The offset of the first character at or after `pos` that is not a blank.
|
|
@@ -790,7 +798,9 @@ function quoteCharOpening(open, close, at, interpolates, escapes = true) {
|
|
|
790
798
|
// The delimiters, other than brackets, that are accepted after a quote word.
|
|
791
799
|
function isQuoteDelimiter(ch) {
|
|
792
800
|
return ch == 47 /* Ch.Slash */ || ch == 33 /* Ch.Bang */ || ch == 124 /* Ch.Pipe */ || ch == 126 /* Ch.Tilde */ || ch == 94 /* Ch.Caret */ ||
|
|
793
|
-
ch == 37 /* Ch.Percent */ || ch == 64 /* Ch.At */ || ch == 34 /* Ch.DoubleQuote */ || ch == 39 /* Ch.Apostrophe
|
|
801
|
+
ch == 37 /* Ch.Percent */ || ch == 64 /* Ch.At */ || ch == 34 /* Ch.DoubleQuote */ || ch == 39 /* Ch.Apostrophe */ || ch == 96 /* Ch.Backtick */ ||
|
|
802
|
+
// A symbol outside of ASCII: Q♥a♥
|
|
803
|
+
ch > 0xa0 && ch != 0xd7 && ch != 0xf7 && !isIdentifierStart(ch) && !isSpace(ch) && ch < 0xd800;
|
|
794
804
|
}
|
|
795
805
|
// Reads the start of a quote at offset `at`: a quote character, or a
|
|
796
806
|
// quote word (q, qq, m, s, ...) with its adverbs and its delimiter.
|
|
@@ -805,8 +815,16 @@ function readOpening(input, at = 0) {
|
|
|
805
815
|
return quoteCharOpening(next, 0x201d, at, 63 /* Interpolate.All */);
|
|
806
816
|
if (next == 0x2018 /* ‘ */)
|
|
807
817
|
return quoteCharOpening(next, 0x2019, at, 0);
|
|
818
|
+
if (next == 0x201e /* „ */)
|
|
819
|
+
return quoteCharOpening(next, 0x201d, at, 63 /* Interpolate.All */);
|
|
820
|
+
if (next == 0x201d /* ” */)
|
|
821
|
+
return quoteCharOpening(next, next, at, 63 /* Interpolate.All */);
|
|
822
|
+
if (next == 0x201a /* ‚ */)
|
|
823
|
+
return quoteCharOpening(next, 0x2019, at, 0);
|
|
808
824
|
if (next == 0x300c /* 「 */)
|
|
809
825
|
return quoteCharOpening(next, 0x300d, at, 0, false);
|
|
826
|
+
if (next == 0xff62 /* 「 */)
|
|
827
|
+
return quoteCharOpening(next, 0xff63, at, 0, false);
|
|
810
828
|
if (!isAsciiLetter(next))
|
|
811
829
|
return null;
|
|
812
830
|
let pos = at + 1;
|
|
@@ -885,14 +903,14 @@ function readOpening(input, at = 0) {
|
|
|
885
903
|
// The offset after the delimiter that closes a quote whose content
|
|
886
904
|
// starts at `pos`, or -1 when it is not closed.
|
|
887
905
|
function rawEnd(input, pos, opening) {
|
|
888
|
-
let { open, close, count } = opening;
|
|
906
|
+
let { open, close, count } = opening, other = otherClose(open);
|
|
889
907
|
for (let depth = 1;;) {
|
|
890
908
|
let ch = input.peek(pos);
|
|
891
909
|
if (ch < 0)
|
|
892
910
|
return -1;
|
|
893
911
|
if (ch == 92 /* Ch.Backslash */ && opening.escapes)
|
|
894
912
|
pos += 2;
|
|
895
|
-
else if (ch == close && repeats(input, pos, close, count)) {
|
|
913
|
+
else if (ch == close && repeats(input, pos, close, count) || ch == other) {
|
|
896
914
|
pos += count;
|
|
897
915
|
if (--depth == 0)
|
|
898
916
|
return pos;
|
|
@@ -905,26 +923,111 @@ function rawEnd(input, pos, opening) {
|
|
|
905
923
|
pos++;
|
|
906
924
|
}
|
|
907
925
|
}
|
|
926
|
+
// The character that closes a quote in a regex that opens with `ch`,
|
|
927
|
+
// or 0 when `ch` opens none: 'a', "a", ‘a’, ‚a’, “a”, „a”, 「a」
|
|
928
|
+
function quoteClose(ch) {
|
|
929
|
+
return ch == 39 /* Ch.Apostrophe */ || ch == 34 /* Ch.DoubleQuote */ ? ch : ch == 0x2018 || ch == 0x201a ? 0x2019 :
|
|
930
|
+
ch == 0x201c || ch == 0x201e ? 0x201d : ch == 0xff62 ? 0xff63 : 0;
|
|
931
|
+
}
|
|
932
|
+
// A low quote is also closed by the quote that points the other way:
|
|
933
|
+
// ‚a‘, „a“. This is that quote for the given opening one, or -1.
|
|
934
|
+
function otherClose(open) { return open == 0x201a ? 0x2018 : open == 0x201e ? 0x201c : -1; }
|
|
908
935
|
// The offset after a quoted string that starts at `pos`, or -1.
|
|
909
936
|
function quotedEnd(input, pos) {
|
|
910
|
-
let
|
|
937
|
+
let open = input.peek(pos), close = quoteClose(open), other = otherClose(open);
|
|
911
938
|
for (pos++;;) {
|
|
912
939
|
let ch = input.peek(pos);
|
|
913
940
|
if (ch < 0 || ch == 10 /* Ch.Newline */)
|
|
914
941
|
return -1;
|
|
915
|
-
|
|
942
|
+
// Nothing is escaped in 「...」.
|
|
943
|
+
if (ch == 92 /* Ch.Backslash */ && open != 0xff62)
|
|
916
944
|
pos += 2;
|
|
917
|
-
else if (ch ==
|
|
945
|
+
else if (ch == close || ch == other)
|
|
918
946
|
return pos + 1;
|
|
919
947
|
else
|
|
920
948
|
pos++;
|
|
921
949
|
}
|
|
922
950
|
}
|
|
951
|
+
// The offset after the arguments of the assertion that starts with the
|
|
952
|
+
// `<` at `pos`, or 0 when it has none on its line. The arguments are
|
|
953
|
+
// code, in which the delimiter of the regex does not end it:
|
|
954
|
+
// <name(1/2)>, <:name(/x/)>, <name: /a<b>+/ >
|
|
955
|
+
function assertionArgumentsEnd(input, pos) {
|
|
956
|
+
// An assertion can add up several names: <+:Lu +:name(/SMALL/)>
|
|
957
|
+
for (let at = pos + 1;;) {
|
|
958
|
+
while (isAssertionMark(input.peek(at)) || isBlank(input.peek(at)))
|
|
959
|
+
at++;
|
|
960
|
+
let end = nameEnd(input, at);
|
|
961
|
+
if (end < 0)
|
|
962
|
+
return 0;
|
|
963
|
+
// With parentheses, up to the one that closes them. After a colon
|
|
964
|
+
// and a space, up to the `>` that closes the assertion.
|
|
965
|
+
let open = input.peek(end);
|
|
966
|
+
if (open == 40 /* Ch.ParenOpen */)
|
|
967
|
+
return balancedEnd(input, end + 1, 40 /* Ch.ParenOpen */, 41 /* Ch.ParenClose */);
|
|
968
|
+
if (open == 58 /* Ch.Colon */ && isBlank(input.peek(end + 1)))
|
|
969
|
+
return balancedEnd(input, end + 1, 60 /* Ch.Less */, 62 /* Ch.Greater */);
|
|
970
|
+
at = end;
|
|
971
|
+
if (!isAssertionMark(input.peek(at)) && !isBlank(input.peek(at)))
|
|
972
|
+
return 0;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
// The characters that come before the name in an assertion: <.ws>, <?before>, <+alpha>
|
|
976
|
+
function isAssertionMark(ch) {
|
|
977
|
+
return ch == 46 /* Ch.Dot */ || ch == 63 /* Ch.Question */ || ch == 33 /* Ch.Bang */ || ch == 58 /* Ch.Colon */ || ch == 38 /* Ch.Amp */ || ch == 43 /* Ch.Plus */ ||
|
|
978
|
+
ch == 45 /* Ch.Hyphen */;
|
|
979
|
+
}
|
|
980
|
+
// The offset after the code that the `<` or `:` at `pos` in a regex
|
|
981
|
+
// starts, or 0 when it starts none.
|
|
982
|
+
function regexCodeEnd(input, pos) {
|
|
983
|
+
return input.peek(pos) == 60 /* Ch.Less */ ? assertionArgumentsEnd(input, pos) : regexDeclarationEnd(input, pos);
|
|
984
|
+
}
|
|
985
|
+
// The offset after the declaration that starts with the `:` at `pos`
|
|
986
|
+
// in a regex, or 0 when none does: `:my $c = $/;`. It is code up to
|
|
987
|
+
// its `;`, in which the delimiter of the regex does not end it.
|
|
988
|
+
function regexDeclarationEnd(input, pos) {
|
|
989
|
+
let end = nameEnd(input, pos + 1);
|
|
990
|
+
if (end < 0 || end - pos > 9 || !isBlank(input.peek(end)) ||
|
|
991
|
+
!/^(my|our|state|constant|temp|let)$/.test(word(input, pos + 1, end)))
|
|
992
|
+
return 0;
|
|
993
|
+
for (;;) {
|
|
994
|
+
let ch = input.peek(end);
|
|
995
|
+
if (ch < 0 || ch == 10 /* Ch.Newline */)
|
|
996
|
+
return 0;
|
|
997
|
+
if (ch == 59 /* Ch.Semicolon */)
|
|
998
|
+
return end + 1;
|
|
999
|
+
let quoted = quoteClose(ch) ? quotedEnd(input, end) : -1;
|
|
1000
|
+
end = quoted > 0 ? quoted : end + 1;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
// The offset after the `close` that matches an `open` before `pos`, or
|
|
1004
|
+
// 0 when there is none on the line. Quotes are gone over.
|
|
1005
|
+
function balancedEnd(input, pos, open, close) {
|
|
1006
|
+
for (let depth = 1;;) {
|
|
1007
|
+
let ch = input.peek(pos);
|
|
1008
|
+
if (ch < 0 || ch == 10 /* Ch.Newline */)
|
|
1009
|
+
return 0;
|
|
1010
|
+
if (ch == 92 /* Ch.Backslash */)
|
|
1011
|
+
pos += 2;
|
|
1012
|
+
else if (quoteClose(ch)) {
|
|
1013
|
+
let quoted = quotedEnd(input, pos);
|
|
1014
|
+
pos = quoted < 0 ? pos + 1 : quoted;
|
|
1015
|
+
}
|
|
1016
|
+
else {
|
|
1017
|
+
pos++;
|
|
1018
|
+
if (ch == open)
|
|
1019
|
+
depth++;
|
|
1020
|
+
else if (ch == close && --depth == 0)
|
|
1021
|
+
return pos;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
923
1025
|
// The offset of the delimiter that closes a regex whose content starts
|
|
924
1026
|
// at `pos`, or -1. Delimiters do not count inside quotes, character
|
|
925
|
-
// classes, comments and code blocks.
|
|
926
|
-
|
|
927
|
-
|
|
1027
|
+
// classes, comments and code blocks. `code` is set for the inside of a
|
|
1028
|
+
// code block, where a `<` is an operator.
|
|
1029
|
+
function regexEnd(input, { start: pos, open, close, count }, code = false) {
|
|
1030
|
+
for (let depth = 1, codeEnd;;) {
|
|
928
1031
|
let ch = input.peek(pos);
|
|
929
1032
|
if (ch < 0)
|
|
930
1033
|
return -1;
|
|
@@ -940,10 +1043,25 @@ function regexEnd(input, { start: pos, open, close, count }) {
|
|
|
940
1043
|
pos += count;
|
|
941
1044
|
depth++;
|
|
942
1045
|
}
|
|
943
|
-
else if (ch
|
|
1046
|
+
else if (quoteClose(ch)) {
|
|
944
1047
|
let end = quotedEnd(input, pos);
|
|
945
1048
|
pos = end < 0 ? pos + 1 : end;
|
|
946
1049
|
}
|
|
1050
|
+
else if (!code && ch == 60 /* Ch.Less */ && isBlank(input.peek(pos + 1))) {
|
|
1051
|
+
// A list of words, in which quotes are text: < a ' b >
|
|
1052
|
+
let end = pos + 2;
|
|
1053
|
+
while (input.peek(end) != 62 /* Ch.Greater */ && input.peek(end) != 10 /* Ch.Newline */ && input.peek(end) >= 0)
|
|
1054
|
+
end++;
|
|
1055
|
+
pos = input.peek(end) == 62 /* Ch.Greater */ ? end + 1 : pos + 1;
|
|
1056
|
+
}
|
|
1057
|
+
else if (!code && (ch == 60 /* Ch.Less */ || ch == 58 /* Ch.Colon */) && (codeEnd = regexCodeEnd(input, pos)) > 0) {
|
|
1058
|
+
pos = codeEnd;
|
|
1059
|
+
}
|
|
1060
|
+
else if (!code && (ch == 36 /* Ch.Dollar */ || ch == 64 /* Ch.At */) && input.peek(pos + 1) == 40 /* Ch.ParenOpen */) {
|
|
1061
|
+
// Code that is interpolated: $( rx/ a / )
|
|
1062
|
+
let end = balancedEnd(input, pos + 2, 40 /* Ch.ParenOpen */, 41 /* Ch.ParenClose */);
|
|
1063
|
+
pos = end > 0 ? end : pos + 1;
|
|
1064
|
+
}
|
|
947
1065
|
else if (ch == 60 /* Ch.Less */ && (input.peek(pos + 1) == 91 /* Ch.BracketOpen */ ||
|
|
948
1066
|
(input.peek(pos + 1) == 45 /* Ch.Hyphen */ || input.peek(pos + 1) == 43 /* Ch.Plus */) && input.peek(pos + 2) == 91 /* Ch.BracketOpen */)) {
|
|
949
1067
|
// <[...]>, <-[...]>, and combinations: <+[a..z]-[aeiou]>
|
|
@@ -984,7 +1102,7 @@ function regexEnd(input, { start: pos, open, close, count }) {
|
|
|
984
1102
|
pos++;
|
|
985
1103
|
}
|
|
986
1104
|
else if (ch == 123 /* Ch.BraceOpen */ && close != 125 /* Ch.BraceClose */) {
|
|
987
|
-
let end = regexEnd(input, { start: pos + 1, open: 123 /* Ch.BraceOpen */, close: 125 /* Ch.BraceClose */, count: 1 });
|
|
1105
|
+
let end = regexEnd(input, { start: pos + 1, open: 123 /* Ch.BraceOpen */, close: 125 /* Ch.BraceClose */, count: 1 }, true);
|
|
988
1106
|
pos = end < 0 ? pos + 1 : end + 1;
|
|
989
1107
|
}
|
|
990
1108
|
else {
|
|
@@ -992,6 +1110,21 @@ function regexEnd(input, { start: pos, open, close, count }) {
|
|
|
992
1110
|
}
|
|
993
1111
|
}
|
|
994
1112
|
}
|
|
1113
|
+
// The offset after the `/` that closes the replacement of s/a/b/, which
|
|
1114
|
+
// starts at `pos`, or -1. A `$/` in it does not close it, when a `/`
|
|
1115
|
+
// follows on the same line: in s/a/$/, the `$` is text.
|
|
1116
|
+
function replacementEnd(input, pos) {
|
|
1117
|
+
for (let match = false;;) {
|
|
1118
|
+
let ch = input.peek(pos);
|
|
1119
|
+
if (ch < 0 || match && ch == 10 /* Ch.Newline */)
|
|
1120
|
+
return -1;
|
|
1121
|
+
if (ch == 47 /* Ch.Slash */)
|
|
1122
|
+
return pos + 1;
|
|
1123
|
+
if (ch == 36 /* Ch.Dollar */ && input.peek(pos + 1) == 47 /* Ch.Slash */)
|
|
1124
|
+
match = true;
|
|
1125
|
+
pos += match && ch == 36 /* Ch.Dollar */ || ch == 92 /* Ch.Backslash */ ? 2 : 1;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
995
1128
|
// The offset after a regex or substitution, given its opening, or -1.
|
|
996
1129
|
function regexTokenEnd(input, opening) {
|
|
997
1130
|
let end = regexEnd(input, opening);
|
|
@@ -999,8 +1132,12 @@ function regexTokenEnd(input, opening) {
|
|
|
999
1132
|
return -1;
|
|
1000
1133
|
end += opening.count;
|
|
1001
1134
|
// s/a/b/ has a second part. s{a} = 'b' does not.
|
|
1002
|
-
if (opening.kind != "regex" && opening.open == opening.close)
|
|
1003
|
-
|
|
1135
|
+
if (opening.kind != "regex" && opening.open == opening.close) {
|
|
1136
|
+
// A `$/` in the replacement is the match variable, not a `$` before
|
|
1137
|
+
// the closing delimiter: s/(a)/[$/]/. Unless nothing closes it then.
|
|
1138
|
+
let withMatch = opening.close == 47 /* Ch.Slash */ ? replacementEnd(input, end) : -1;
|
|
1139
|
+
end = withMatch < 0 ? rawEnd(input, end, opening) : withMatch;
|
|
1140
|
+
}
|
|
1004
1141
|
return end;
|
|
1005
1142
|
}
|
|
1006
1143
|
// The opening of a bare regex: /a/
|
|
@@ -1104,6 +1241,8 @@ const declarators$1 = /^(sub|method|submethod|token|rule|regex)$/;
|
|
|
1104
1241
|
function startsDeclarator(name) {
|
|
1105
1242
|
return ["sub", "method", "submethod", "token", "rule", "regex"].some(declarator => declarator.startsWith(name));
|
|
1106
1243
|
}
|
|
1244
|
+
// What stands between the parentheses of a set operator.
|
|
1245
|
+
const setOperators = /^(<=?|>=?|<\+|>\+|==|[|&\-^+.]|elem|cont)$/;
|
|
1107
1246
|
const operatorCategory = /^(infix|prefix|postfix|circumfix|postcircumfix|term)$/;
|
|
1108
1247
|
function isWordOperator(name) {
|
|
1109
1248
|
return name == "x" || name == "xx" || name == "min" || name == "max" || name == "Z" || name == "X";
|
|
@@ -1119,6 +1258,16 @@ const termToken = new ExternalTokenizer((input, stack) => {
|
|
|
1119
1258
|
return;
|
|
1120
1259
|
}
|
|
1121
1260
|
let next = input.next, { mode } = context(stack);
|
|
1261
|
+
// The set operators that are written in parentheses: $a (<=) $b, $x (elem) $s
|
|
1262
|
+
// Not right after the term, where the parentheses hold arguments: $f(elem)
|
|
1263
|
+
if (next == 40 /* Ch.ParenOpen */ && mode == 1 /* Mode.AfterTerm */ && isSpace(input.peek(-1))) {
|
|
1264
|
+
let end = 1;
|
|
1265
|
+
while (end < 6 && input.peek(end) != 41 /* Ch.ParenClose */ && input.peek(end) >= 0)
|
|
1266
|
+
end++;
|
|
1267
|
+
if (input.peek(end) == 41 /* Ch.ParenClose */ && setOperators.test(word(input, 1, end)))
|
|
1268
|
+
input.acceptToken(wordOperator, end + 1);
|
|
1269
|
+
return;
|
|
1270
|
+
}
|
|
1122
1271
|
if (isIdentifierStart(next)) {
|
|
1123
1272
|
// The Z, X and R meta operators: Z+, X~, R-, Z=>
|
|
1124
1273
|
if (mode == 1 /* Mode.AfterTerm */ && (next == 90 /* Ch.Z */ || next == 88 /* Ch.X */ || next == 82 /* Ch.R */) &&
|
|
@@ -1161,7 +1310,25 @@ const termToken = new ExternalTokenizer((input, stack) => {
|
|
|
1161
1310
|
// space before it, it is a variable: `my Array[Int] %h`.
|
|
1162
1311
|
if (mode == 1 /* Mode.AfterTerm */ && isIdentifierStart(input.peek(1)) && !isSpace(input.peek(-1)))
|
|
1163
1312
|
return input.acceptToken(wordOperator, 1);
|
|
1164
|
-
// An operator as a routine: &
|
|
1313
|
+
// An operator as a routine: &[+], &[»+»], &[max]
|
|
1314
|
+
// After a term, the `&` is an operator: $a &[1, 2]
|
|
1315
|
+
if (next == 38 /* Ch.Amp */ && input.peek(1) == 91 /* Ch.BracketOpen */ && mode != 1 /* Mode.AfterTerm */) {
|
|
1316
|
+
// A meta operator brings brackets of its own: &[R[~~]]
|
|
1317
|
+
for (let end = 2, depth = 1; end < 14; end++) {
|
|
1318
|
+
let ch = input.peek(end);
|
|
1319
|
+
if (ch < 0 || isSpace(ch))
|
|
1320
|
+
break;
|
|
1321
|
+
if (ch == 91 /* Ch.BracketOpen */)
|
|
1322
|
+
depth++;
|
|
1323
|
+
else if (ch == 93 /* Ch.BracketClose */ && --depth == 0) {
|
|
1324
|
+
if (end > 2)
|
|
1325
|
+
input.acceptToken(operatorVariable, end + 1);
|
|
1326
|
+
break;
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
// The same by its full name: &infix:<+>
|
|
1165
1332
|
if (next == 38 /* Ch.Amp */) {
|
|
1166
1333
|
let end = nameEnd(input, 1);
|
|
1167
1334
|
if (end > 0 && operatorCategory.test(word(input, 1, end))) {
|
|
@@ -1234,17 +1401,25 @@ function hasPostfix(input, end) {
|
|
|
1234
1401
|
let methodEnd = nameEnd(input, end + 1);
|
|
1235
1402
|
return methodEnd > 0 && input.peek(methodEnd) == 40 /* Ch.ParenOpen */;
|
|
1236
1403
|
}
|
|
1404
|
+
// Whether the parser is between the pieces of a quote, as opposed to
|
|
1405
|
+
// in the code of a block in it.
|
|
1406
|
+
function inQuoteText(stack) { return stack.canShift(quoteContent); }
|
|
1407
|
+
// Whether the parser is, in a quote, right after a variable or after a
|
|
1408
|
+
// subscript or a call on one: where the grammar takes a quotePostfix.
|
|
1409
|
+
// This is asked of the parser and not of the mode, which is not known
|
|
1410
|
+
// to this precision after a reused node that ends in text of the quote.
|
|
1411
|
+
function afterQuotedVariable(stack) { return stack.canShift(rawString); }
|
|
1237
1412
|
// The pieces of a quote that interpolates.
|
|
1238
1413
|
const quoteToken = new ExternalTokenizer((input, stack) => {
|
|
1239
|
-
if (!stack
|
|
1414
|
+
if (!inQuoteText(stack))
|
|
1240
1415
|
return;
|
|
1241
|
-
let { quote
|
|
1416
|
+
let { quote } = context(stack);
|
|
1242
1417
|
if (!quote)
|
|
1243
1418
|
return;
|
|
1244
|
-
let { open, close, count, interpolates } = quote, nests = open != close;
|
|
1419
|
+
let { open, close, count, interpolates } = quote, nests = open != close, other = otherClose(open);
|
|
1245
1420
|
// After a variable, a subscript or a call continues the interpolation.
|
|
1246
1421
|
// `[` and `(` are left to the grammar's own tokens.
|
|
1247
|
-
if (
|
|
1422
|
+
if (afterQuotedVariable(stack)) {
|
|
1248
1423
|
if (input.next == 91 /* Ch.BracketOpen */ || input.next == 40 /* Ch.ParenOpen */)
|
|
1249
1424
|
return;
|
|
1250
1425
|
let end = subscriptEnd(input);
|
|
@@ -1259,12 +1434,13 @@ const quoteToken = new ExternalTokenizer((input, stack) => {
|
|
|
1259
1434
|
let next = input.next;
|
|
1260
1435
|
if (next < 0)
|
|
1261
1436
|
break;
|
|
1262
|
-
let atClose = next == close && repeats(input, 0, close, count);
|
|
1437
|
+
let atClose = next == close && repeats(input, 0, close, count) || next == other;
|
|
1263
1438
|
if (atClose || nests && next == open && repeats(input, 0, open, count)) {
|
|
1264
1439
|
if (input.pos > start)
|
|
1265
1440
|
break;
|
|
1266
1441
|
input.advance(count);
|
|
1267
|
-
|
|
1442
|
+
// Inside a nested pair, a closing delimiter closes that pair.
|
|
1443
|
+
return input.acceptToken(!atClose ? quoteNestOpen : stack.canShift(quoteNestClose) ? quoteNestClose : quoteEnd);
|
|
1268
1444
|
}
|
|
1269
1445
|
if (next == 92 /* Ch.Backslash */) {
|
|
1270
1446
|
if (interpolates & 32 /* Interpolate.Backslash */)
|
|
@@ -1364,14 +1540,21 @@ function isRegexOperator(ch) {
|
|
|
1364
1540
|
// When it is not closed on its line, this is the negated offset of the
|
|
1365
1541
|
// end of the text that was gone over to find that out.
|
|
1366
1542
|
function assertionEnd(input) {
|
|
1543
|
+
// A list of words, in which quotes and brackets are text: < a ' b >
|
|
1544
|
+
let words = isBlank(input.peek(1));
|
|
1367
1545
|
for (let pos = 1, depth = 1;;) {
|
|
1368
1546
|
let ch = input.peek(pos);
|
|
1369
1547
|
if (ch < 0 || ch == 10 /* Ch.Newline */)
|
|
1370
1548
|
return -pos;
|
|
1371
|
-
if (
|
|
1549
|
+
if (words) {
|
|
1550
|
+
pos++;
|
|
1551
|
+
if (ch == 62 /* Ch.Greater */)
|
|
1552
|
+
return pos;
|
|
1553
|
+
}
|
|
1554
|
+
else if (ch == 92 /* Ch.Backslash */) {
|
|
1372
1555
|
pos += input.peek(pos + 1) == 10 /* Ch.Newline */ || input.peek(pos + 1) < 0 ? 1 : 2;
|
|
1373
1556
|
}
|
|
1374
|
-
else if (ch
|
|
1557
|
+
else if (quoteClose(ch)) {
|
|
1375
1558
|
let end = quotedEnd(input, pos);
|
|
1376
1559
|
pos = end < 0 ? pos + 1 : end;
|
|
1377
1560
|
}
|
|
@@ -1465,7 +1648,7 @@ const regexToken = new ExternalTokenizer((input, stack) => {
|
|
|
1465
1648
|
skipLine(input);
|
|
1466
1649
|
return input.acceptToken(regexComment);
|
|
1467
1650
|
}
|
|
1468
|
-
if (next
|
|
1651
|
+
if (quoteClose(next)) {
|
|
1469
1652
|
let end = quotedEnd(input, 0);
|
|
1470
1653
|
if (end > 0 && end <= limit)
|
|
1471
1654
|
return input.acceptToken(regexQuote, end);
|
|
@@ -1531,7 +1714,7 @@ const regexToken = new ExternalTokenizer((input, stack) => {
|
|
|
1531
1714
|
input.advance();
|
|
1532
1715
|
let ch = input.next;
|
|
1533
1716
|
if (ch < 0 || input.pos == literalEnd ||
|
|
1534
|
-
ch == 10 /* Ch.Newline */ || ch == 92 /* Ch.Backslash */ || ch
|
|
1717
|
+
ch == 10 /* Ch.Newline */ || ch == 92 /* Ch.Backslash */ || quoteClose(ch) ||
|
|
1535
1718
|
ch == 60 /* Ch.Less */ || ch == 62 /* Ch.Greater */ || ch == 171 /* Ch.GuillemetOpen */ || ch == 187 /* Ch.GuillemetClose */ ||
|
|
1536
1719
|
ch == 41 /* Ch.ParenClose */ && input.peek(1) == 62 /* Ch.Greater */ ||
|
|
1537
1720
|
ch == 123 /* Ch.BraceOpen */ || ch == 125 /* Ch.BraceClose */ || ch == 35 /* Ch.Hash */ || ch == 36 /* Ch.Dollar */ ||
|
|
@@ -1553,9 +1736,8 @@ const methodDotToken = new ExternalTokenizer((input, stack) => {
|
|
|
1553
1736
|
next = input.peek(++size);
|
|
1554
1737
|
if (!isIdentifierStart(next))
|
|
1555
1738
|
return;
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
(mode != 1 /* Mode.AfterTerm */ || input.peek(nameEnd(input, size)) != 40 /* Ch.ParenOpen */))
|
|
1739
|
+
if (context(stack).quote && inQuoteText(stack) &&
|
|
1740
|
+
(!afterQuotedVariable(stack) || input.peek(nameEnd(input, size)) != 40 /* Ch.ParenOpen */))
|
|
1559
1741
|
return;
|
|
1560
1742
|
input.acceptToken(methodDot, size);
|
|
1561
1743
|
});
|
|
@@ -1580,6 +1762,26 @@ function categoryEnd(input, nameStart, pos) {
|
|
|
1580
1762
|
let close = first == 60 /* Ch.Less */ ? 62 /* Ch.Greater */ : first == 171 /* Ch.GuillemetOpen */ ? 187 /* Ch.GuillemetClose */ : -1;
|
|
1581
1763
|
if (close < 0)
|
|
1582
1764
|
return pos;
|
|
1765
|
+
// With double angles, blanks can surround the operator, which can
|
|
1766
|
+
// hold a `>` itself: infix:<< stash-eq >>, infix:<<(>=)>>
|
|
1767
|
+
// When this is not that form, the operator starts with `<`: infix:<<=>
|
|
1768
|
+
if (first == 60 /* Ch.Less */ && input.peek(open + 1) == 60 /* Ch.Less */) {
|
|
1769
|
+
let start = blanksEnd(input, open + 2);
|
|
1770
|
+
let closes = (at) => input.peek(at) == close && input.peek(at + 1) == close && input.peek(at + 2) != close;
|
|
1771
|
+
// An operator is short, and a token must not look far past its end.
|
|
1772
|
+
for (let end = start; end < start + maxGap; end++) {
|
|
1773
|
+
let ch = input.peek(end);
|
|
1774
|
+
// Not a shift in code without spaces: infix:<<=>($a){$a>>1}
|
|
1775
|
+
if (end > start && closes(end) && !continuesName(input, end + 2) && input.peek(end + 2) != 36 /* Ch.Dollar */)
|
|
1776
|
+
return end + 2;
|
|
1777
|
+
if (ch < 0 || isSpace(ch)) {
|
|
1778
|
+
let after = blanksEnd(input, end);
|
|
1779
|
+
if (end > start && closes(after))
|
|
1780
|
+
return after + 2;
|
|
1781
|
+
break;
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1583
1785
|
// The two halves of a circumfix are separated by one space.
|
|
1584
1786
|
let spaces = /circumfix$/.test(word(input, nameStart, pos)) ? 1 : 0;
|
|
1585
1787
|
for (let i = open + 1;; i++) {
|
|
@@ -1595,8 +1797,17 @@ function categoryEnd(input, nameStart, pos) {
|
|
|
1595
1797
|
// specialized identifiers, and specialization does not look at the
|
|
1596
1798
|
// parse state, so these positions get tokens of their own.
|
|
1597
1799
|
const nameToken = new ExternalTokenizer((input, stack) => {
|
|
1800
|
+
let next = input.next;
|
|
1801
|
+
// The name of a constant can have a sigil: constant $LIMIT = 3
|
|
1802
|
+
if ((next == 36 /* Ch.Dollar */ || next == 64 /* Ch.At */ || next == 37 /* Ch.Percent */ || next == 38 /* Ch.Amp */) && stack.canShift(declaredVariable)) {
|
|
1803
|
+
let end = nameEnd(input, 1);
|
|
1804
|
+
// constant &infix:<plus> = &infix:<+>
|
|
1805
|
+
if (end > 0)
|
|
1806
|
+
input.acceptToken(declaredVariable, next == 38 /* Ch.Amp */ ? categoryEnd(input, 1, end) : end);
|
|
1807
|
+
return;
|
|
1808
|
+
}
|
|
1598
1809
|
// Only a method declaration takes a mark: `method !private`, `method ^meta`.
|
|
1599
|
-
let mark =
|
|
1810
|
+
let mark = next == 33 /* Ch.Bang */ || next == 94 /* Ch.Caret */ ? 1 : 0;
|
|
1600
1811
|
let end = nameEnd(input, mark);
|
|
1601
1812
|
if (end < 0)
|
|
1602
1813
|
return;
|
|
@@ -1605,7 +1816,17 @@ const nameToken = new ExternalTokenizer((input, stack) => {
|
|
|
1605
1816
|
input.acceptToken(MethodName, end);
|
|
1606
1817
|
return;
|
|
1607
1818
|
}
|
|
1819
|
+
let named = end;
|
|
1608
1820
|
end = categoryEnd(input, mark, end);
|
|
1821
|
+
// Blanks can come before the `:sym<...>` of a declaration: token c :sym<a> { a }
|
|
1822
|
+
if (end == named) {
|
|
1823
|
+
let sym = gapEnd(input, end);
|
|
1824
|
+
if (sym > end && word(input, sym, sym + 4) == ":sym") {
|
|
1825
|
+
let symEnd = categoryEnd(input, mark, sym);
|
|
1826
|
+
if (symEnd > sym)
|
|
1827
|
+
end = symEnd;
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1609
1830
|
if (!mark && stack.canShift(declaredName))
|
|
1610
1831
|
input.acceptToken(declaredName, end);
|
|
1611
1832
|
else if (stack.canShift(declaredMethodName))
|
|
@@ -1661,27 +1882,27 @@ const versionToken = new ExternalTokenizer((input, stack) => {
|
|
|
1661
1882
|
});
|
|
1662
1883
|
|
|
1663
1884
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
1664
|
-
const spec_identifier = {__proto__:null,class:80, role:82, grammar:84, module:86, package:88, sub:102, method:106, submethod:108, token:116, rule:118, regex:120, enum:140, subset:146, constant:152, my:
|
|
1665
|
-
const spec_capIdentifier = {__proto__:null,True:
|
|
1885
|
+
const spec_identifier = {__proto__:null,class:80, role:82, grammar:84, module:86, package:88, sub:102, method:106, submethod:108, token:116, rule:118, regex:120, enum:140, subset:146, constant:152, my:172, our:174, has:176, state:178, temp:180, let:182, anon:184, augment:186, supersede:188, unit:190, multi:192, proto:194, only:196, if:198, elsif:200, else:202, unless:204, with:206, orwith:208, without:210, for:212, while:214, until:216, loop:218, repeat:220, given:222, when:224, default:226, do:228, gather:230, take:232, try:234, return:236, next:238, last:240, redo:242, proceed:244, succeed:246, react:248, whenever:250, supply:252, emit:254, start:256, use:258, need:260, import:262, require:264, no:266, is:268, does:270, of:272, returns:274, handles:276, where:278, will:280, trusts:282, hides:284, and:286, or:288, not:290, xor:292, so:294, andthen:296, orelse:298, notandthen:300, div:302, mod:304, gcd:306, lcm:308, eq:310, ne:312, lt:314, gt:316, le:318, ge:320, cmp:322, leg:324, eqv:326, but:328, self:330};
|
|
1886
|
+
const spec_capIdentifier = {__proto__:null,True:332, False:334, Nil:336, BEGIN:338, CHECK:340, INIT:342, END:344, ENTER:346, LEAVE:348, KEEP:350, UNDO:352, FIRST:354, NEXT:356, LAST:358, PRE:360, POST:362, CATCH:364, CONTROL:366, QUIT:368, CLOSE:370, DOC:372};
|
|
1666
1887
|
const parser$1 = LRParser.deserialize({
|
|
1667
1888
|
version: 14,
|
|
1668
|
-
states: "
|
|
1669
|
-
stateData: "
|
|
1670
|
-
goto: ",
|
|
1671
|
-
nodeNames: "⚠ BlockComment PodDirective PodDirective PodDirective PodHeading PodStrong PodEmphasis PodCode PodLink PodFormat Heredoc Heredoc . MethodName Version CharacterClass Assertion StringLiteral Operator LineComment BlockComment VariableName StringLiteral Regex Regex Operator VariableName LineComment DocComment Program Pod Number ) ( Parens ] [ Brackets PackageDeclaration class role grammar module package PackageName } { Block ; RoutineDeclaration sub RoutineName method submethod RoutineName RoutineName RegexDeclaration token rule regex RegexName Block Regex Escape VariableName AttributeName SpecialVariable Block EnumDeclaration enum EnumName SubsetDeclaration subset SubsetName ConstantDeclaration constant ConstantName MethodCall Identifier TypeName Number StringLiteral Interpolation PairKey my our has state temp let anon augment supersede unit multi proto only if elsif else unless with orwith without for while until loop repeat given when default do gather take try return next last redo proceed succeed react whenever supply emit start use need import require no is does of returns handles where will trusts hides and or not xor so andthen orelse notandthen div mod gcd lcm eq ne lt gt le ge cmp leg eqv but self True False Nil BEGIN CHECK INIT END ENTER LEAVE KEEP UNDO FIRST NEXT LAST PRE POST CATCH CONTROL QUIT CLOSE DOC Operator , : . Regex Heredoc StringLiteral",
|
|
1672
|
-
maxTerm:
|
|
1889
|
+
states: "/`QfQDdOOO*zO#tOOO+POWOOO+UO,UOOO+uOSO'#C{O,PQDdO'#DPO,WQDdO'#DSO,_QDdO'#D^OOQ.W'#Df'#DfO,fQDdO'#D`O5zQ8WO'#D|OOQ.W'#D}'#D}O6PQ7gO'#EOOOQ.W'#EQ'#EQO6sO!%SO'#EQOOQ.W'#HV'#HVOOQ.W'#HU'#HUOOQ.W'#Gf'#GfQfQDdOOO6zQEUO'#DTO7RQEUO'#D`O7YQEUO'#D`O@rQEUO'#DgO@|QEUO'#DsOJqQEUO'#DvO!&fQEUO'#DyOOQ.W'#H_'#H_O!0^O!!^OOO!1[O!%SOOOOOS'#Gg'#GgO!1cOSO,59gOOQ.W,59g,59gOOQ.W,59k,59kO!1mQDdO,59kOOQ.W,59n,59nO!1tQDdO,59nOOQ.W,59x,59xO!1{QDdO,59xOOQ.W'#Gh'#GhO!;eQDdO'#HXOOQ.W'#HX'#HXOOQ.W,59z,59zOOQ.W,5:h,5:hOOQ.W,5:j,5:jO!;lO!%SO'#ERO!;sQDdO'#ESOOO&j'#H['#H[O!;zO!0jO'#H[OOO&j'#Gj'#GjO!<xO!%SO,5:lOOQ.W,5:l,5:lOOQ.W-E:d-E:dOOQ.W'#DZ'#DZOOQ.W,59o,59oO,fQDdO,59oOOQ.W'#Db'#DbO,fQDdO,59zOOQ.W'#De'#DeO!=PQDdO,5:ROOQ.W'#Dk'#DkO!=WQ:[O'#DlOOQ.W,5:R,5:RO!=PQDdO,5:ROOQ.W'#Du'#DuOOQ.W,5:_,5:_OOQ.W'#Dx'#DxOOQ.W,5:b,5:bOOQ.W'#D{'#D{OOQ.W,5:e,5:eO!=`QDdO'#DrOOO#t'#HY'#HYOOO#t'#Gi'#GiO!0^O!!^OOQOOOOOO!1[O!%SOOOOOS-E:e-E:eOOQ.W1G/R1G/ROOQ.W1G/V1G/VOOQ.W1G/Y1G/YOOQ.W1G/d1G/dOOQ.W-E:f-E:fOOQ.W,5=s,5=sOOO&j,5:m,5:mO!=gO!%SO,5:mOOO&j,5:n,5:nO!=nQDdO,5:nOOO2Q'#H^'#H^OOO2Q'#Gk'#GkO!=uO!0jO,5=vOOO&j-E:h-E:hOOQ.W1G0W1G0WOOQ.W1G/Z1G/ZOOQ.W1G/f1G/fOOQ.W1G/m1G/mO!?nO!!^O'#DmOOQ.W,5:W,5:WO!?uQ7fO,5:WO!?zQDdO1G/mOOO#t,5:^,5:^O!@RQDdO,5:^OOO#t-E:g-E:gOOO&j1G0X1G0XOOO&j1G0Y1G0YOOO2Q-E:i-E:iO!@YO!!^O,5:XOOQY,5:X,5:XOOQ.W1G/r1G/rOOQ.W7+%X7+%XOOO#t1G/x1G/xOOQY1G/s1G/s",
|
|
1890
|
+
stateData: "!@m~O%wOSlOSmOSPOSZOS[OS~OQSO]YO__Og_Oh_Oi_Oj_Ok_Op_OrTOuUOxcOycOzcO{cO|cO!PVO!R`O!TdO!VeO!WeO![fO!]fO!^fO!c_O!d_O!e_O!hgO!khO!niO!s_O!w_O!xjO!yjO!zjO!{jO!|jO!}jO#OjO#PjO#QjO#RjO#SjO#TjO#UjO#VjO#WjO#XjO#YjO#ZjO#[jO#]jO#^jO#_jO#`jO#ajO#bjO#cjO#djO#ejO#fjO#gjO#hjO#ijO#jjO#kjO#ljO#mjO#njO#ojO#pjO#qjO#rjO#sjO#tjO#ujO#vjO#wjO#xjO#yjO#zjO#{jO#|jO#}jO$OjO$PjO$QjO$RjO$SjO$TjO$UjO$VjO$WjO$XjO$YjO$ZjO$[jO$]jO$^jO$_jO$`jO$ajO$bjO$cjO$djO$ejO$fjO$gjO$hjO$ijO$jjO$kjO$ljO$mjO$njO$ojO$pjO$qjO$rjO$sjO$tjO$ujO$vjO$wjO$xjO$yjO$zjO${jO$|jO$}jO%OjO%PjO%QjO%R_O%S_O%T_O%U_O%r]O%s^O%tZO%uWO%zZO%}[O&P_O~O%kkO~O%elO~O%slO~OSmOTmOUmOVmOWmOXmOYmO%dmO~ORoO%coO~P+ZOqpO~PfOtrO~PfO!OtO~PfOQSO]YO__Og_Oh_Oi_Oj_Ok_Op_OrTOuUOxcOycOzcO{cO|cO!PVO!RxO!TdO!VeO!WeO![fO!]fO!^fO!c_O!d_O!e_O!hgO!khO!niO!s_O!w_O!xjO!yjO!zjO!{jO!|jO!}jO#OjO#PjO#QjO#RjO#SjO#TjO#UjO#VjO#WjO#XjO#YjO#ZjO#[jO#]jO#^jO#_jO#`jO#ajO#bjO#cjO#djO#ejO#fjO#gjO#hjO#ijO#jjO#kjO#ljO#mjO#njO#ojO#pjO#qjO#rjO#sjO#tjO#ujO#vjO#wjO#xjO#yjO#zjO#{jO#|jO#}jO$OjO$PjO$QjO$RjO$SjO$TjO$UjO$VjO$WjO$XjO$YjO$ZjO$[jO$]jO$^jO$_jO$`jO$ajO$bjO$cjO$djO$ejO$fjO$gjO$hjO$ijO$jjO$kjO$ljO$mjO$njO$ojO$pjO$qjO$rjO$sjO$tjO$ujO$vjO$wjO$xjO$yjO$zjO${jO$|jO$}jO%OjO%PjO%QjO%R_O%S_O%T_O%U_O%r]O%s^O%tZO%uWO%zZO%}[O&P_O~O^zO~O%a{O%b{O~O!P}O!b!OO!c!PO!d!PO!e!PO%n!OO%o|O&P!PO~O%q!SO~P6XO%f!UO~P,fO%f!XO~P,fO%g!ZO~P,fOQSO]YO__Og_Oh_Oi_Oj_Ok_Op_OrTOuUOxcOycOzcO{cO|cO!P!^O!TdO!VeO!WeO![fO!]fO!^fO!c_O!d_O!e_O!hgO!khO!niO!s_O!w_O!xjO!yjO!zjO!{jO!|jO!}jO#OjO#PjO#QjO#RjO#SjO#TjO#UjO#VjO#WjO#XjO#YjO#ZjO#[jO#]jO#^jO#_jO#`jO#ajO#bjO#cjO#djO#ejO#fjO#gjO#hjO#ijO#jjO#kjO#ljO#mjO#njO#ojO#pjO#qjO#rjO#sjO#tjO#ujO#vjO#wjO#xjO#yjO#zjO#{jO#|jO#}jO$OjO$PjO$QjO$RjO$SjO$TjO$UjO$VjO$WjO$XjO$YjO$ZjO$[jO$]jO$^jO$_jO$`jO$ajO$bjO$cjO$djO$ejO$fjO$gjO$hjO$ijO$jjO$kjO$ljO$mjO$njO$ojO$pjO$qjO$rjO$sjO$tjO$ujO$vjO$wjO$xjO$yjO$zjO${jO$|jO$}jO%OjO%PjO%QjO%R_O%S_O%T_O%U_O%r]O%s^O%tZO%uWO%zZO%}[O&P_O~O!R!_O%f!]O~P7aO%f!aOQ!gX]!gX_!gXg!gXh!gXi!gXj!gXk!gXp!gXr!gXu!gXx!gXy!gXz!gX{!gX|!gX!P!gX!R!gX!T!gX!V!gX!W!gX![!gX!]!gX!^!gX!c!gX!d!gX!e!gX!h!gX!k!gX!n!gX!s!gX!w!gX!x!gX!y!gX!z!gX!{!gX!|!gX!}!gX#O!gX#P!gX#Q!gX#R!gX#S!gX#T!gX#U!gX#V!gX#W!gX#X!gX#Y!gX#Z!gX#[!gX#]!gX#^!gX#_!gX#`!gX#a!gX#b!gX#c!gX#d!gX#e!gX#f!gX#g!gX#h!gX#i!gX#j!gX#k!gX#l!gX#m!gX#n!gX#o!gX#p!gX#q!gX#r!gX#s!gX#t!gX#u!gX#v!gX#w!gX#x!gX#y!gX#z!gX#{!gX#|!gX#}!gX$O!gX$P!gX$Q!gX$R!gX$S!gX$T!gX$U!gX$V!gX$W!gX$X!gX$Y!gX$Z!gX$[!gX$]!gX$^!gX$_!gX$`!gX$a!gX$b!gX$c!gX$d!gX$e!gX$f!gX$g!gX$h!gX$i!gX$j!gX$k!gX$l!gX$m!gX$n!gX$o!gX$p!gX$q!gX$r!gX$s!gX$t!gX$u!gX$v!gX$w!gX$x!gX$y!gX$z!gX${!gX$|!gX$}!gX%O!gX%P!gX%Q!gX%R!gX%S!gX%T!gX%U!gX%`!gX%r!gX%s!gX%t!gX%u!gX%z!gX%}!gX&P!gXq!gXt!gX!O!gX~O%f!cOQ!jX]!jX_!jXg!jXh!jXi!jXj!jXk!jXp!jXr!jXu!jXx!jXy!jXz!jX{!jX|!jX!P!jX!R!jX!T!jX!V!jX!W!jX![!jX!]!jX!^!jX!c!jX!d!jX!e!jX!h!jX!k!jX!n!jX!s!jX!w!jX!x!jX!y!jX!z!jX!{!jX!|!jX!}!jX#O!jX#P!jX#Q!jX#R!jX#S!jX#T!jX#U!jX#V!jX#W!jX#X!jX#Y!jX#Z!jX#[!jX#]!jX#^!jX#_!jX#`!jX#a!jX#b!jX#c!jX#d!jX#e!jX#f!jX#g!jX#h!jX#i!jX#j!jX#k!jX#l!jX#m!jX#n!jX#o!jX#p!jX#q!jX#r!jX#s!jX#t!jX#u!jX#v!jX#w!jX#x!jX#y!jX#z!jX#{!jX#|!jX#}!jX$O!jX$P!jX$Q!jX$R!jX$S!jX$T!jX$U!jX$V!jX$W!jX$X!jX$Y!jX$Z!jX$[!jX$]!jX$^!jX$_!jX$`!jX$a!jX$b!jX$c!jX$d!jX$e!jX$f!jX$g!jX$h!jX$i!jX$j!jX$k!jX$l!jX$m!jX$n!jX$o!jX$p!jX$q!jX$r!jX$s!jX$t!jX$u!jX$v!jX$w!jX$x!jX$y!jX$z!jX${!jX$|!jX$}!jX%O!jX%P!jX%Q!jX%R!jX%S!jX%T!jX%U!jX%`!jX%r!jX%s!jX%t!jX%u!jX%z!jX%}!jX&P!jXq!jXt!jX!O!jX~O%f!eO%h!eOQ!mX]!mX_!mXg!mXh!mXi!mXj!mXk!mXp!mXr!mXu!mXx!mXy!mXz!mX{!mX|!mX!P!mX!R!mX!T!mX!V!mX!W!mX![!mX!]!mX!^!mX!c!mX!d!mX!e!mX!h!mX!k!mX!n!mX!s!mX!w!mX!x!mX!y!mX!z!mX!{!mX!|!mX!}!mX#O!mX#P!mX#Q!mX#R!mX#S!mX#T!mX#U!mX#V!mX#W!mX#X!mX#Y!mX#Z!mX#[!mX#]!mX#^!mX#_!mX#`!mX#a!mX#b!mX#c!mX#d!mX#e!mX#f!mX#g!mX#h!mX#i!mX#j!mX#k!mX#l!mX#m!mX#n!mX#o!mX#p!mX#q!mX#r!mX#s!mX#t!mX#u!mX#v!mX#w!mX#x!mX#y!mX#z!mX#{!mX#|!mX#}!mX$O!mX$P!mX$Q!mX$R!mX$S!mX$T!mX$U!mX$V!mX$W!mX$X!mX$Y!mX$Z!mX$[!mX$]!mX$^!mX$_!mX$`!mX$a!mX$b!mX$c!mX$d!mX$e!mX$f!mX$g!mX$h!mX$i!mX$j!mX$k!mX$l!mX$m!mX$n!mX$o!mX$p!mX$q!mX$r!mX$s!mX$t!mX$u!mX$v!mX$w!mX$x!mX$y!mX$z!mX${!mX$|!mX$}!mX%O!mX%P!mX%Q!mX%R!mX%S!mX%T!mX%U!mX%`!mX%r!mX%s!mX%t!mX%u!mX%z!mX%}!mX&P!mXq!mXt!mX!O!mX~O`!hOa!hOb!hOc!hOd!hOe!hOf!hO!P!gO!b!hO!c!hO!d!hO!e!hO%l!kO%m!hO~O%q!kO~P6XOR!nO%c!nO~P+ZOq!oO~PfOt!pO~PfO!O!qO~PfOQSO]YO__Og_Oh_Oi_Oj_Ok_Op_OrTOuUOxcOycOzcO{cO|cO!PVO!TdO!VeO!WeO![fO!]fO!^fO!c_O!d_O!e_O!hgO!khO!niO!s_O!w_O!xjO!yjO!zjO!{jO!|jO!}jO#OjO#PjO#QjO#RjO#SjO#TjO#UjO#VjO#WjO#XjO#YjO#ZjO#[jO#]jO#^jO#_jO#`jO#ajO#bjO#cjO#djO#ejO#fjO#gjO#hjO#ijO#jjO#kjO#ljO#mjO#njO#ojO#pjO#qjO#rjO#sjO#tjO#ujO#vjO#wjO#xjO#yjO#zjO#{jO#|jO#}jO$OjO$PjO$QjO$RjO$SjO$TjO$UjO$VjO$WjO$XjO$YjO$ZjO$[jO$]jO$^jO$_jO$`jO$ajO$bjO$cjO$djO$ejO$fjO$gjO$hjO$ijO$jjO$kjO$ljO$mjO$njO$ojO$pjO$qjO$rjO$sjO$tjO$ujO$vjO$wjO$xjO$yjO$zjO${jO$|jO$}jO%OjO%PjO%QjO%R_O%S_O%T_O%U_O%r]O%s^O%tZO%uWO%zZO%}[O&P_O~O!R!sO~P!2SO%p!tO~P6XO!O!vO~PfO]YOrTOuUO%r!xO!P&OX!b&OX!c&OX!d&OX!e&OX%n&OX%o&OX%q&OX&P&OX%p&OX~O%q!|O~P6XO!R#PO~P7aO!O#RO%i#QO~O!O#UO~PfO%p#XO~P6XO!O#YO~PfO]YOrTOuUO%r!xO!P&Oa!b&Oa!c&Oa!d&Oa!e&Oa%n&Oa%o&Oa%q&Oa&P&Oa%p&Oa~O`!hOa!hOb!hOc!hOd!hOe!hOf!hO!P!gO!b!hO!c!hO!d!hO!e!hO%m!hO~O%j#]O~P!>sO!O#^O~O!R#_O~P7aO!O#`O~PfO%j#aO~P!>sOml!d!e!cp!w%R&P%T%U~",
|
|
1891
|
+
goto: ",s&SPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP&TPPP&nPP&n&TPPPPP']PP'`P&TP'yPP'|(P&TPPP(j(m(wPPPP(z&TP)Q&TP)T&TP)W&n&T&TP&T)Z)ZPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP)c)}*T*h*r+QPPPPPPPPPPPPPPPPPPPPPPPP+W+fP,R,aP,gP,o&T!P_OTUVXbcdefqsuw}!W!Y![!`!g!w#T#V!O_OTUVXbcdefqsuw}!W!Y![!`!g!w#T#VT!x!P!zR!Wch`OTUVbqsu}!g!w#V[xXcde!W!YR!swR!YdR!Ye!PXOTUVXbcdefqsuw}!W!Y![!`!g!w#T#VR!`fQ!_fS#P![!`R#_#TR#S!^X!hk!j#Q#[R!bgR!dhR!fi]!O^l|!R!l!uQbOQqTQsUQuV[!Tbqsu!w#VQ!w}R#V!gQnSR!mn[wXcde!W!YQ![fU!rw![#TR#T!`Q!jkS#W!j#[R#[#QQ!R^Q!llQ!u|V!{!R!l!uQ!z!PR#Z!ziaOTUVbqsu}!g!w#Vh`OTUVbqsu}!g!w#VgvXcdefw!W!Y![!`#TUyXdeQ!VcQ!}!WR#O!YX!ik!j#Q#[]!Q^l|!R!l!uT!y!P!z",
|
|
1892
|
+
nodeNames: "⚠ BlockComment PodDirective PodDirective PodDirective PodHeading PodStrong PodEmphasis PodCode PodLink PodFormat Heredoc Heredoc . MethodName Version CharacterClass Assertion StringLiteral Operator LineComment BlockComment VariableName StringLiteral Regex Regex Operator VariableName LineComment DocComment Program Pod Number ) ( Parens ] [ Brackets PackageDeclaration class role grammar module package PackageName } { Block ; RoutineDeclaration sub RoutineName method submethod RoutineName RoutineName RegexDeclaration token rule regex RegexName Block Regex Escape VariableName AttributeName SpecialVariable Block EnumDeclaration enum EnumName SubsetDeclaration subset SubsetName ConstantDeclaration constant ConstantName MethodCall Identifier TypeName Number StringLiteral NestedDelimiters Interpolation PairKey my our has state temp let anon augment supersede unit multi proto only if elsif else unless with orwith without for while until loop repeat given when default do gather take try return next last redo proceed succeed react whenever supply emit start use need import require no is does of returns handles where will trusts hides and or not xor so andthen orelse notandthen div mod gcd lcm eq ne lt gt le ge cmp leg eqv but self True False Nil BEGIN CHECK INIT END ENTER LEAVE KEEP UNDO FIRST NEXT LAST PRE POST CATCH CONTROL QUIT CLOSE DOC Operator , : . Regex Heredoc StringLiteral",
|
|
1893
|
+
maxTerm: 233,
|
|
1673
1894
|
context: trackContext,
|
|
1674
1895
|
nodeProps: [
|
|
1675
1896
|
["openedBy", 33,"(",36,"[",46,"{"],
|
|
1676
1897
|
["closedBy", 34,")",37,"]",47,"}"]
|
|
1677
1898
|
],
|
|
1678
1899
|
skippedNodes: [0,1,11,12,28,29],
|
|
1679
|
-
repeatNodeCount:
|
|
1680
|
-
tokenData: "
|
|
1900
|
+
repeatNodeCount: 6,
|
|
1901
|
+
tokenData: "!'z~R!qX^&Ypq&Yqr&}st(wtu*huv6pvw:Oxy;uyz;zz{&}{|&}|}<P}!O&}!O!P<U!P!Q&}!Q!R<t!R![?T![!]Ax!]!^Go!^!_&}!_!`&}!`!a&}!a!b&}!b!cGt!c!}Ih!}#OLd#O#PLi#P#Q!$Z#Q#R&}#R#S!$`#T#o!$`#o#p!'[#p#q&}#q#r!'a#r#s&}#y#z&Y$f$g&Y$g$p&}$p$q!$`$q$r&}$r$s&}$t$x&}$x$y!'f$y$z!'f$z${&}${$|!$`$|%P&}%P%Q!'f%Q%R!$`%R%S&}%S%V?O%V%W&}%W%o!$`%o%p&}%p&a!$`&a&b&}&b#BY!$`#BY#BZ&Y#BZ$IS!$`$IS$I_&Y$Id$Il&}$It$I|&}$I|$JO&Y$JT$JU&Y$JU$KV&}$KV$KW&Y$Kh$Ki!'f$Kl$Kt!'f%!b%!r?O%#m%#n?O%#t&/x&}&/x&Et!$`&FU&FV&Y&Gh;'S!$`;'S;=`!'O?&r?Bj!$`?Hw?Ic!$`?Ii?JT!$`?J`?L{!$`~&_Y%w~X^&Ypq&Y#y#z&Y$f$g&Y#BY#BZ&Y$IS$I_&Y$I|$JO&Y$JT$JU&Y$KV$KW&Y&FU&FV&YP'Sk%RPqr&}z{&}{|&}}!O&}!P!Q&}!^!_&}!_!`&}!`!a&}!a!b&}#O#P&}#Q#R&}#p#q&}#r#s&}$g$p&}$q$r&}$r$s&}$t$x&}$z${&}$|%P&}%R%S&}%V%W&}%o%p&}&a&b&}$Id$Il&}$It$I|&}$JU$KV&}%#t&/x&}~(|Wl~OY)fZ!_)f!_!`)}!`#p)f#p#q)}#q;'S)f;'S;=`)w<%lO)f~)kSl~OY)fZ;'S)f;'S;=`)w<%lO)f~)zP;=`<%l)f~*USm~l~OY)}Z;'S)};'S;=`*b<%lO)}~*eP;=`<%l)}~*ml&P~qr,ez{0k!O!P/V!P!Q3g!Q![3l![!]3t!_!`0k!a!b0k!c!}4|#Q#R3t#R#S4|#T#o4|#r#s0k$h$i3g$p$q4|${$|4|%Q%R4|%W%o4|%p&a4|&b#BY4|#BZ$IS4|&/x&Et4|&Gh;'S4|;'S;=`6j?&r?Bj4|?Hw?Ic4|?Ii?JT4|?J`?L{4|~,ja!c~!c!}-o#R#S-o#T#o-o$p$q-o${$|-o%Q%R-o%W%o-o%p&a-o&b#BY-o#BZ$IS-o&/x&Et-o&Gh;'S-o;'S;=`0_?&r?Bj-o?Hw?Ic-o?Ii?JT-o?J`?L{-o~-te!d~wx/V}!O/V!Q![-o![!]0e!c!}-o#R#S-o#T#o-o$p$q-o${$|-o%Q%R-o%W%o-o%p&a-o&b#BY-o#BZ$IS-o&/x&Et-o&Gh;'S-o;'S;=`0_?&r?Bj-o?Hw?Ic-o?Ii?JT-o?J`?L{-o~/Ya!c!}-o#R#S-o#T#o-o$p$q-o${$|-o%Q%R-o%W%o-o%p&a-o&b#BY-o#BZ$IS-o&/x&Et-o&Gh;'S-o;'S;=`0_?&r?Bj-o?Hw?Ic-o?Ii?JT-o?J`?L{-o~0bP;=`<%l-o~0hP![!]/V~0na!c!}1s#R#S1s#T#o1s$p$q1s${$|1s%Q%R1s%W%o1s%p&a1s&b#BY1s#BZ$IS1s&/x&Et1s&Gh;'S1s;'S;=`3a?&r?Bj1s?Hw?Ic1s?Ii?JT1s?J`?L{1s~1xe!e~wx0k}!O0k!Q![1s![!]3Z!c!}1s#R#S1s#T#o1s$p$q1s${$|1s%Q%R1s%W%o1s%p&a1s&b#BY1s#BZ$IS1s&/x&Et1s&Gh;'S1s;'S;=`3a?&r?Bj1s?Hw?Ic1s?Ii?JT1s?J`?L{1s~3^P![!]0k~3dP;=`<%l1s~3lO!c~~3qP!c~!Q![3l~3wa!c!}4|#R#S4|#T#o4|$p$q4|${$|4|%Q%R4|%W%o4|%p&a4|&b#BY4|#BZ$IS4|&/x&Et4|&Gh;'S4|;'S;=`6j?&r?Bj4|?Hw?Ic4|?Ii?JT4|?J`?L{4|~5Re!c~wx3t}!O3t!Q![4|![!]6d!c!}4|#R#S4|#T#o4|$p$q4|${$|4|%Q%R4|%W%o4|%p&a4|&b#BY4|#BZ$IS4|&/x&Et4|&Gh;'S4|;'S;=`6j?&r?Bj4|?Hw?Ic4|?Ii?JT4|?J`?L{4|~6gP![!]3t~6mP;=`<%l4|~6uj%RPqr/Vuv8gz{0k!O!P/V![!]3t!_!`8t!a!b0k!c!}4|#Q#R3t#R#S4|#T#o4|#r#s0k$p$q4|${$|4|%Q%R4|%W%o4|%p&a4|&b#BY4|#BZ$IS4|&/x&Et4|&Gh;'S4|;'S;=`6j?&r?Bj4|?Hw?Ic4|?Ii?JT4|?J`?L{4|P8lP%RP!_!`8oP8tO%RP~8ya%RP!c!}1s#R#S1s#T#o1s$p$q1s${$|1s%Q%R1s%W%o1s%p&a1s&b#BY1s#BZ$IS1s&/x&Et1s&Gh;'S1s;'S;=`3a?&r?Bj1s?Hw?Ic1s?Ii?JT1s?J`?L{1s~:Tj%RPqr/Vvw8gz{0k!O!P/V![!]3t!_!`8t!a!b0k!c!}4|#Q#R3t#R#S4|#T#o4|#r#s0k$p$q4|${$|4|%Q%R4|%W%o4|%p&a4|&b#BY4|#BZ$IS4|&/x&Et4|&Gh;'S4|;'S;=`6j?&r?Bj4|?Hw?Ic4|?Ii?JT4|?J`?L{4|~;zOr~~<POq~~<UO%S~~<ZQ%U~!O!P<a!_!`8oP<fQ%RP!O!P<l#Q#R8oP<qP%RP#Q#R8o~<y^!s~!O!P=u!Q![?T!d!e?r!f!g@^!g!h>a!q!r@r!z!{AW#R#S?l#U#V?r#W#X@^#X#Y>a#]#^?O#c#d@r#l#mAW~=xP!Q![={~>QT!s~!Q![={!g!h>a#R#S=u#X#Y>a#]#^?O~>dR{|>m}!O>m!Q![>s~>pP!Q![>s~>xQ!s~!Q![>s#]#^?O~?TO!s~~?YU!s~!O!P=u!Q![?T!g!h>a#R#S?l#X#Y>a#]#^?O~?oP!Q![?T~?uR!Q!R@O!R!S@O#R#S@O~@TR!s~!Q!R@O!R!S@O#R#S@O~@aQ!Q![@g#R#S@g~@lQ!s~!Q![@g#R#S@g~@uQ!Q!Y@{#R#S@{~AQQ!s~!Q!Y@{#R#S@{~AZS!Q![Ag!c!iAg#R#SAg#T#ZAg~AlS!s~!Q![Ag!c!iAg#R#SAg#T#ZAg~A}e%T~qrC`!Q![F[![!]Gc!_!`8o!c!}Dh#R#SDh#T#oDh$p$qDh${$|Dh%Q%RDh%W%oDh%p&aDh&b#BYDh#BZ$ISDh&/x&EtDh&Gh;'SDh;'S;=`FU?&r?BjDh?Hw?IcDh?Ii?JTDh?J`?L{Dh~Cca!c!}Dh#R#SDh#T#oDh$p$qDh${$|Dh%Q%RDh%W%oDh%p&aDh&b#BYDh#BZ$ISDh&/x&EtDh&Gh;'SDh;'S;=`FU?&r?BjDh?Hw?IcDh?Ii?JTDh?J`?L{Dh~Dme!w~wxC`}!OC`!Q![Dh![!]FO!c!}Dh#R#SDh#T#oDh$p$qDh${$|Dh%Q%RDh%W%oDh%p&aDh&b#BYDh#BZ$ISDh&/x&EtDh&Gh;'SDh;'S;=`FU?&r?BjDh?Hw?IcDh?Ii?JTDh?J`?L{Dh~FRP![!]C`~FXP;=`<%lDh~F_Q!Q![F[!^!_Fe~FhT!O!PFw!Q![Fw!c!}Fw#R#SFw#T#oFw~FzU!O!PFw!Q![Fw!`!aG^!c!}Fw#R#SFw#T#oFw~GcOp~PGfP![!]GiPGlP!_!`8o~GtO!R~~Gyi&P~qr/Vz{0k!O!P/V![!]3t!_!`0k!a!b0k!c!}4|#Q#R3t#R#S4|#T#o4|#r#s0k$p$q4|${$|4|%Q%R4|%W%o4|%p&a4|&b#BY4|#BZ$IS4|&/x&Et4|&Gh;'S4|;'S;=`6j?&r?Bj4|?Hw?Ic4|?Ii?JT4|?J`?L{4|~Ime%}~wxKO}!OKO!Q![Ih![!]L^!c!}Ih#R#SIh#T#oIh$p$qIh${$|Ih%Q%RIh%W%oIh%p&aIh&b#BYIh#BZ$ISIh&/x&EtIh&Gh;'SIh;'S;=`LW?&r?BjIh?Hw?IcIh?Ii?JTIh?J`?L{Ih~KRa!c!}Ih#R#SIh#T#oIh$p$qIh${$|Ih%Q%RIh%W%oIh%p&aIh&b#BYIh#BZ$ISIh&/x&EtIh&Gh;'SIh;'S;=`LW?&r?BjIh?Hw?IcIh?Ii?JTIh?J`?L{Ih~LZP;=`<%lIh~LaP![!]KO~LiOu~RLn!U%RPOq!!Qqr!!Vrz!!Qz{!!V{|!!V|}!!Q}!O!!V!O!P!!Q!P!Q!!V!Q!^!!Q!^!_!!V!_!`!!V!`!a!!V!a!b!!V!b#O!!Q#O#P!!V#P#Q!!Q#Q#R!!V#R#p!!Q#p#q!!V#q#r!!Q#r#s!!V#s$g!!Q$g$p!!V$p$q!!Q$q$r!!V$r$s!!V$s$t!!Q$t$x!!V$x$z!!Q$z${!!V${$|!!Q$|%P!!V%P%R!!Q%R%S!!V%S%V!!Q%V%W!!V%W%o!!Q%o%p!!V%p&a!!Q&a&b!!V&b$Id!!Q$Id$Il!!V$Il$It!!Q$It$I|!!V$I|$JU!!Q$JU$KV!!V$KV%#t!!Q%#t&/x!!V&/x;'S!!Q;'S;=`!$R;=`O!!QQ!!VO!bQR!!^k!bQ%RPqr&}z{&}{|&}}!O&}!P!Q&}!^!_&}!_!`&}!`!a&}!a!b&}#O#P&}#Q#R&}#p#q&}#r#s&}$g$p&}$q$r&}$r$s&}$t$x&}$z${&}$|%P&}%R%S&}%V%W&}%o%p&}&a&b&}$Id$Il&}$It$I|&}$JU$KV&}%#t&/x&}Q!$WP!bQ;=`<%l!!Q~!$`Ot~~!$ee%z~wx!%v}!O!%v!Q![!$`![!]!'U!c!}!$`#R#S!$`#T#o!$`$p$q!$`${$|!$`%Q%R!$`%W%o!$`%p&a!$`&b#BY!$`#BZ$IS!$`&/x&Et!$`&Gh;'S!$`;'S;=`!'O?&r?Bj!$`?Hw?Ic!$`?Ii?JT!$`?J`?L{!$`~!%ya!c!}!$`#R#S!$`#T#o!$`$p$q!$`${$|!$`%Q%R!$`%W%o!$`%p&a!$`&b#BY!$`#BZ$IS!$`&/x&Et!$`&Gh;'S!$`;'S;=`!'O?&r?Bj!$`?Hw?Ic!$`?Ii?JT!$`?J`?L{!$`~!'RP;=`<%l!$`~!'XP![!]!%v~!'aO!P~~!'fO!O~P!'kT%RP$x$y!'f$y$z!'f%P%Q!'f$Kh$Ki!'f$Kl$Kt!'f",
|
|
1681
1902
|
tokenizers: [smileyToken, blockComment, podToken, heredocToken, methodDotToken, nameToken, versionToken, regexToken, quoteToken, termToken, 0, 1],
|
|
1682
|
-
topRules: {"Program":[0,30],"Regex":[1,
|
|
1683
|
-
specialized: [{term:
|
|
1684
|
-
tokenPrec:
|
|
1903
|
+
topRules: {"Program":[0,30],"Regex":[1,191],"Heredoc":[2,192],"StringLiteral":[3,193]},
|
|
1904
|
+
specialized: [{term: 226, get: (value) => spec_identifier[value] || -1},{term: 229, get: (value) => spec_capIdentifier[value] || -1}],
|
|
1905
|
+
tokenPrec: 3559
|
|
1685
1906
|
});
|
|
1686
1907
|
|
|
1687
1908
|
// The keywords of the grammar, with the tag each is highlighted with.
|
|
@@ -1810,8 +2031,8 @@ class Gatherer {
|
|
|
1810
2031
|
this.declaration(child);
|
|
1811
2032
|
else if (child.firstChild)
|
|
1812
2033
|
this.content(child);
|
|
1813
|
-
//
|
|
1814
|
-
// declaration node: constant
|
|
2034
|
+
// A constant that is declared with a backslash has its name after
|
|
2035
|
+
// the declaration node: constant \limit = 3
|
|
1815
2036
|
declaring = name == "ConstantDeclaration" && child.lastChild.name == "constant";
|
|
1816
2037
|
}
|
|
1817
2038
|
}
|
|
@@ -2378,7 +2599,7 @@ const baseLanguage = LRLanguage.define({
|
|
|
2378
2599
|
Parens: delimitedIndent({ closing: ")" }),
|
|
2379
2600
|
Brackets: delimitedIndent({ closing: "]" }),
|
|
2380
2601
|
// The lines of these are text, which keeps its indentation.
|
|
2381
|
-
"StringLiteral Heredoc Pod BlockComment": () => null
|
|
2602
|
+
"StringLiteral Heredoc Pod BlockComment DocComment": () => null
|
|
2382
2603
|
}),
|
|
2383
2604
|
foldNodeProp.add({
|
|
2384
2605
|
"Block Parens Brackets": foldInside,
|
|
@@ -2388,7 +2609,10 @@ const baseLanguage = LRLanguage.define({
|
|
|
2388
2609
|
// A heredoc starts with the line break before its first line.
|
|
2389
2610
|
Heredoc(tree) { return { from: tree.from, to: tree.to }; }
|
|
2390
2611
|
}),
|
|
2391
|
-
styleTags(Object.assign(Object.assign({}, keywordTags), { "True False": tags.bool, Nil: tags.null, Identifier: tags.function(tags.variableName), TypeName: tags.typeName, PackageName: tags.definition(tags.className), "EnumName SubsetName": tags.definition(tags.typeName), ConstantName: tags.definition(tags.constant(tags.variableName)), "RoutineName RegexName": tags.function(tags.definition(tags.variableName)), MethodName: tags.function(tags.propertyName), VariableName: tags.variableName, AttributeName: tags.propertyName, SpecialVariable: tags.special(tags.variableName), PairKey: tags.attributeName, Number: tags.number, Version: tags.literal,
|
|
2612
|
+
styleTags(Object.assign(Object.assign({}, keywordTags), { "True False": tags.bool, Nil: tags.null, Identifier: tags.function(tags.variableName), TypeName: tags.typeName, PackageName: tags.definition(tags.className), "EnumName SubsetName": tags.definition(tags.typeName), ConstantName: tags.definition(tags.constant(tags.variableName)), "RoutineName RegexName": tags.function(tags.definition(tags.variableName)), MethodName: tags.function(tags.propertyName), VariableName: tags.variableName, AttributeName: tags.propertyName, SpecialVariable: tags.special(tags.variableName), PairKey: tags.attributeName, Number: tags.number, Version: tags.literal,
|
|
2613
|
+
// A pair of delimiters in a quote is text of it, and a tag
|
|
2614
|
+
// does not reach the text in a child node.
|
|
2615
|
+
"StringLiteral Heredoc NestedDelimiters": tags.string, Regex: tags.regexp, CharacterClass: tags.character, Assertion: tags.function(tags.variableName), "Pod PodFormat": tags.docComment, PodDirective: tags.meta,
|
|
2392
2616
|
// These are still part of a comment, and are styled as one where
|
|
2393
2617
|
// a theme has no style for the second tag.
|
|
2394
2618
|
PodHeading: [tags.docComment, tags.heading], PodStrong: [tags.docComment, tags.strong], PodEmphasis: [tags.docComment, tags.emphasis], PodCode: [tags.docComment, tags.monospace], PodLink: [tags.docComment, tags.link], Escape: tags.escape, "Interpolation/{ Interpolation/}": tags.special(tags.brace), LineComment: tags.lineComment, BlockComment: tags.blockComment, DocComment: tags.docComment, Operator: tags.operator, ".": tags.derefOperator, ", ;": tags.separator, ":": tags.punctuation, "( )": tags.paren, "[ ]": tags.squareBracket, "{ }": tags.brace }))
|