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.cjs
CHANGED
|
@@ -7,13 +7,13 @@ var highlight = require('@lezer/highlight');
|
|
|
7
7
|
var state = require('@codemirror/state');
|
|
8
8
|
|
|
9
9
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
10
|
-
const smiley =
|
|
11
|
-
noSmiley =
|
|
10
|
+
const smiley = 201,
|
|
11
|
+
noSmiley = 202,
|
|
12
12
|
BlockComment = 1,
|
|
13
13
|
podStart = 2,
|
|
14
|
-
podEnd =
|
|
14
|
+
podEnd = 203,
|
|
15
15
|
podEndDirective = 3,
|
|
16
|
-
podText =
|
|
16
|
+
podText = 204,
|
|
17
17
|
PodDirective = 4,
|
|
18
18
|
PodHeading = 5,
|
|
19
19
|
PodStrong = 6,
|
|
@@ -23,17 +23,18 @@ const smiley = 199,
|
|
|
23
23
|
PodFormat = 10,
|
|
24
24
|
rawHeredoc = 11,
|
|
25
25
|
interpolatingHeredoc = 12,
|
|
26
|
-
heredocStart =
|
|
26
|
+
heredocStart = 205,
|
|
27
27
|
methodDot = 13,
|
|
28
28
|
MethodName = 14,
|
|
29
|
-
declaredName =
|
|
30
|
-
declaredMethodName =
|
|
29
|
+
declaredName = 206,
|
|
30
|
+
declaredMethodName = 207,
|
|
31
|
+
declaredVariable = 208,
|
|
31
32
|
Version = 15,
|
|
32
|
-
regexStart =
|
|
33
|
-
regexBodyEnd =
|
|
34
|
-
regexLitOpen =
|
|
35
|
-
regexLitClose =
|
|
36
|
-
regexText =
|
|
33
|
+
regexStart = 209,
|
|
34
|
+
regexBodyEnd = 210,
|
|
35
|
+
regexLitOpen = 211,
|
|
36
|
+
regexLitClose = 212,
|
|
37
|
+
regexText = 213,
|
|
37
38
|
CharacterClass = 16,
|
|
38
39
|
Assertion = 17,
|
|
39
40
|
regexQuote = 18,
|
|
@@ -41,18 +42,18 @@ const smiley = 199,
|
|
|
41
42
|
regexComment = 20,
|
|
42
43
|
regexBlockComment = 21,
|
|
43
44
|
regexCapture = 22,
|
|
44
|
-
quoteContent =
|
|
45
|
-
quoteNestOpen =
|
|
46
|
-
quoteNestClose =
|
|
47
|
-
quoteEnd =
|
|
48
|
-
rawString =
|
|
49
|
-
quoteStart =
|
|
45
|
+
quoteContent = 214,
|
|
46
|
+
quoteNestOpen = 215,
|
|
47
|
+
quoteNestClose = 216,
|
|
48
|
+
quoteEnd = 217,
|
|
49
|
+
rawString = 218,
|
|
50
|
+
quoteStart = 219,
|
|
50
51
|
interpolatingWordList = 23,
|
|
51
52
|
regexLiteral = 24,
|
|
52
53
|
transliteration = 25,
|
|
53
|
-
plainName =
|
|
54
|
+
plainName = 220,
|
|
54
55
|
wordOperator = 26,
|
|
55
|
-
multiName =
|
|
56
|
+
multiName = 221,
|
|
56
57
|
operatorVariable = 27,
|
|
57
58
|
LineComment = 28,
|
|
58
59
|
DocComment = 29,
|
|
@@ -74,25 +75,26 @@ const smiley = 199,
|
|
|
74
75
|
TypeName = 80,
|
|
75
76
|
Number = 81,
|
|
76
77
|
quotedString = 82,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
78
|
+
NestedDelimiters = 83,
|
|
79
|
+
Interpolation = 84,
|
|
80
|
+
PairKey = 85,
|
|
81
|
+
multi = 96,
|
|
82
|
+
proto = 97,
|
|
83
|
+
only = 98,
|
|
84
|
+
self = 165,
|
|
85
|
+
True = 166,
|
|
86
|
+
False = 167,
|
|
87
|
+
Nil = 168,
|
|
88
|
+
Operator = 187,
|
|
89
|
+
Regex = 191,
|
|
90
|
+
Heredoc = 192,
|
|
91
|
+
StringLiteral = 193;
|
|
90
92
|
|
|
91
93
|
// Opening bracket -> closing bracket, for the delimiters of quotes and
|
|
92
94
|
// embedded comments. Raku accepts any Unicode bracket pair; this lists
|
|
93
95
|
// the ones that are likely to be typed.
|
|
94
96
|
const brackets$1 = {};
|
|
95
|
-
for (let pair of ["()", "[]", "{}", "<>", "«»", "「」", "『』", "()", "[]", "{}", "【】", "〈〉", "《》", "〔〕"])
|
|
97
|
+
for (let pair of ["()", "[]", "{}", "<>", "«»", "「」", "「」", "『』", "()", "[]", "{}", "【】", "〈〉", "《》", "〔〕"])
|
|
96
98
|
brackets$1[pair.charCodeAt(0)] = pair.charCodeAt(1);
|
|
97
99
|
function isAsciiLetter(ch) { return ch >= 97 /* Ch.a */ && ch <= 122 /* Ch.z */ || ch >= 65 /* Ch.A */ && ch <= 90 /* Ch.Z */; }
|
|
98
100
|
function isDigit(ch) { return ch >= 48 /* Ch._0 */ && ch <= 57 /* Ch._9 */; }
|
|
@@ -156,9 +158,7 @@ function word(input, from, to) {
|
|
|
156
158
|
}
|
|
157
159
|
// A quote that is being read piece by piece because it interpolates.
|
|
158
160
|
class Quote {
|
|
159
|
-
constructor(parent, open, close, count,
|
|
160
|
-
// How many nested opening delimiters are unclosed.
|
|
161
|
-
depth, interpolates,
|
|
161
|
+
constructor(parent, open, close, count, interpolates,
|
|
162
162
|
// Whether a backslash that does not start an escape still
|
|
163
163
|
// takes the delimiter after it out of play: q:c[a \] b]
|
|
164
164
|
escapes) {
|
|
@@ -166,22 +166,18 @@ class Quote {
|
|
|
166
166
|
this.open = open;
|
|
167
167
|
this.close = close;
|
|
168
168
|
this.count = count;
|
|
169
|
-
this.depth = depth;
|
|
170
169
|
this.interpolates = interpolates;
|
|
171
170
|
this.escapes = escapes;
|
|
172
171
|
let hash = parent ? parent.hash : 7;
|
|
173
|
-
for (let part of [open, count,
|
|
172
|
+
for (let part of [open, count, interpolates, escapes ? 1 : 0])
|
|
174
173
|
hash = (hash * 31 + part) | 0;
|
|
175
174
|
this.hash = hash;
|
|
176
175
|
}
|
|
177
|
-
withDepth(depth) {
|
|
178
|
-
return new Quote(this.parent, this.open, this.close, this.count, depth, this.interpolates, this.escapes);
|
|
179
|
-
}
|
|
180
176
|
}
|
|
181
177
|
const noHeredocs = [];
|
|
182
178
|
// The quote that the text of a heredoc is read as. It has no
|
|
183
179
|
// delimiters, and ends where the text does.
|
|
184
|
-
const heredocQuote = new Quote(null, -1, -1, 1,
|
|
180
|
+
const heredocQuote = new Quote(null, -1, -1, 1, 63 /* Interpolate.All */, true);
|
|
185
181
|
// The body of a regex declaration, or the inside of a regex literal,
|
|
186
182
|
// that is being read piece by piece.
|
|
187
183
|
class RegexBody {
|
|
@@ -274,11 +270,11 @@ for (let term of [VariableName, AttributeName, SpecialVariable, operatorVariable
|
|
|
274
270
|
regexText, CharacterClass, Assertion, regexQuote, regexOperator, regexComment,
|
|
275
271
|
regexBlockComment, regexCapture])
|
|
276
272
|
termModes.set(term, 1 /* Mode.AfterTerm */);
|
|
277
|
-
for (let term of [Identifier, TypeName, smiley, noSmiley, declaredName, declaredMethodName, PackageName, RoutineName,
|
|
273
|
+
for (let term of [Identifier, TypeName, smiley, noSmiley, declaredName, declaredMethodName, declaredVariable, PackageName, RoutineName,
|
|
278
274
|
methodRoutineName, multiName, multiRoutineName, RegexName, EnumName, SubsetName, ConstantName])
|
|
279
275
|
termModes.set(term, 2 /* Mode.AfterName */);
|
|
280
276
|
// The `}` of "{...}" in a string does not take a subscript.
|
|
281
|
-
for (let term of [quoteContent, Interpolation])
|
|
277
|
+
for (let term of [quoteContent, quoteNestOpen, quoteNestClose, NestedDelimiters, Interpolation])
|
|
282
278
|
termModes.set(term, 0 /* Mode.Term */);
|
|
283
279
|
for (let term of [multi, proto, only])
|
|
284
280
|
termModes.set(term, 4 /* Mode.AfterMulti */);
|
|
@@ -288,6 +284,10 @@ function modeAfterOperator(first, second, third, after) {
|
|
|
288
284
|
// A lone `*` is as often the whatever star as a multiplication.
|
|
289
285
|
if (first == 42 /* Ch.Star */ && !isOperatorChar(second))
|
|
290
286
|
return 2 /* Mode.AfterName */;
|
|
287
|
+
// A power in superscript, $x², leaves the term complete. These are
|
|
288
|
+
// the characters that the grammar's Operator token takes for one.
|
|
289
|
+
if (first == 0xb2 || first == 0xb3 || first == 0xb9 || first == 0x2070 || first >= 0x2074 && first <= 0x207b)
|
|
290
|
+
return 1 /* Mode.AfterTerm */;
|
|
291
291
|
// Postfix increment and decrement leave the term complete.
|
|
292
292
|
if ((first == 43 /* Ch.Plus */ || first == 45 /* Ch.Hyphen */) && second == first && !isOperatorChar(third) &&
|
|
293
293
|
(after == 1 /* Mode.AfterTerm */ || after == 3 /* Mode.AfterBlock */))
|
|
@@ -369,15 +369,16 @@ function hasNewline(input, from, to) {
|
|
|
369
369
|
}
|
|
370
370
|
// The heredocs that are open after a reused node, of which the input is
|
|
371
371
|
// at the start. As when tokens are shifted, a line break between tokens
|
|
372
|
-
// and the text of a heredoc close the ones before them.
|
|
373
|
-
|
|
372
|
+
// and the text of a heredoc close the ones before them. `inQuote` tells
|
|
373
|
+
// that the node is a run of pieces of a quote.
|
|
374
|
+
function heredocsAfter(node, input, before, inQuote) {
|
|
374
375
|
// Most reused nodes are single tokens.
|
|
375
376
|
if (!node.children.length && !stringTerms.has(node.type.id) && !heredocTerms.has(node.type.id))
|
|
376
377
|
return before;
|
|
377
378
|
let cursor = node.cursor(), found = [], closedAt = -1;
|
|
378
379
|
// Goes over the node at the cursor from its end, and tells whether
|
|
379
380
|
// the heredocs before some point in it are closed.
|
|
380
|
-
function scan() {
|
|
381
|
+
function scan(text = false) {
|
|
381
382
|
let type = cursor.type.id, { from, to } = cursor;
|
|
382
383
|
if (heredocTerms.has(type)) {
|
|
383
384
|
closedAt = to;
|
|
@@ -396,7 +397,7 @@ function heredocsAfter(node, input, before) {
|
|
|
396
397
|
if (!cursor.lastChild())
|
|
397
398
|
return false;
|
|
398
399
|
// Between the pieces of a string lies its text, not whitespace.
|
|
399
|
-
let gaps = !isString;
|
|
400
|
+
let gaps = !isString && !text && type != NestedDelimiters;
|
|
400
401
|
for (let gapEnd = to;;) {
|
|
401
402
|
if (gaps && hasNewline(input, cursor.to, gapEnd)) {
|
|
402
403
|
closedAt = gapEnd;
|
|
@@ -414,7 +415,8 @@ function heredocsAfter(node, input, before) {
|
|
|
414
415
|
cursor.parent();
|
|
415
416
|
return closedAt >= 0;
|
|
416
417
|
}
|
|
417
|
-
|
|
418
|
+
// A piece on its own, such as an Interpolation, is a named node.
|
|
419
|
+
scan(inQuote && node.type.isAnonymous);
|
|
418
420
|
if (!found.length && closedAt < 0)
|
|
419
421
|
return before;
|
|
420
422
|
let after = found.filter(opener => opener.pos >= closedAt).sort((a, b) => a.pos - b.pos).map(opener => opener.heredoc);
|
|
@@ -479,17 +481,9 @@ const trackContext = new lr.ContextTracker({
|
|
|
479
481
|
let opening = wordListOpening(input, 0) || readOpening(input);
|
|
480
482
|
if (!opening)
|
|
481
483
|
return context;
|
|
482
|
-
let quote = new Quote(context.quote, opening.open, opening.close, opening.count,
|
|
484
|
+
let quote = new Quote(context.quote, opening.open, opening.close, opening.count, opening.interpolates, opening.escapes);
|
|
483
485
|
return context.withQuote(0 /* Mode.Term */, quote, withHeredocAt(context.heredocs, input, 0));
|
|
484
486
|
}
|
|
485
|
-
case quoteNestOpen:
|
|
486
|
-
case quoteNestClose: {
|
|
487
|
-
let quote = context.quote;
|
|
488
|
-
if (!quote)
|
|
489
|
-
return context;
|
|
490
|
-
let depth = quote.depth + (term == quoteNestOpen ? 1 : -1);
|
|
491
|
-
return context.withQuote(0 /* Mode.Term */, quote.withDepth(depth));
|
|
492
|
-
}
|
|
493
487
|
case quoteEnd:
|
|
494
488
|
return context.withQuote(1 /* Mode.AfterTerm */, context.quote && context.quote.parent);
|
|
495
489
|
}
|
|
@@ -513,8 +507,13 @@ const trackContext = new lr.ContextTracker({
|
|
|
513
507
|
return term == Identifier || term == Interpolation ? context.withMode(modeAfter(term, input, 0, context.mode))
|
|
514
508
|
: context;
|
|
515
509
|
},
|
|
516
|
-
|
|
517
|
-
|
|
510
|
+
// A node that is reused leaves the quote and the regex of the context
|
|
511
|
+
// as they are: the grammar pairs the delimiters that nest in a quote
|
|
512
|
+
// (NestedDelimiters) and the braces of a block, so a node closes what
|
|
513
|
+
// it opens.
|
|
514
|
+
reuse(context, node, stack, input) {
|
|
515
|
+
let inQuote = context.quote != null && inQuoteText(stack);
|
|
516
|
+
context = context.withHeredocs(heredocsAfter(node, input, context.heredocs, inQuote));
|
|
518
517
|
// The node's positions count from its start, where the input is.
|
|
519
518
|
let last = lastToken$1(node.topNode);
|
|
520
519
|
// What comes before a trailing `++` in a reused node is a term.
|
|
@@ -542,16 +541,24 @@ const blockComment = new lr.ExternalTokenizer(input => {
|
|
|
542
541
|
let end = embeddedCommentEnd(input, 0);
|
|
543
542
|
if (!end)
|
|
544
543
|
return;
|
|
544
|
+
// A declarator comment with brackets, #|( ... ) and #=( ... ), is
|
|
545
|
+
// still a declarator comment.
|
|
546
|
+
let term = input.peek(1) == 96 /* Ch.Backtick */ ? BlockComment : DocComment;
|
|
545
547
|
if (end < 0)
|
|
546
548
|
skipToEnd(input);
|
|
547
549
|
else
|
|
548
550
|
input.advance(end);
|
|
549
|
-
input.acceptToken(
|
|
551
|
+
input.acceptToken(term);
|
|
550
552
|
});
|
|
551
553
|
// The offset after the embedded comment that starts at offset `at`.
|
|
552
554
|
// Zero when none starts there, and -1 when it is not closed.
|
|
555
|
+
//
|
|
556
|
+
// A declarator comment with brackets that is not closed is none: it is
|
|
557
|
+
// left to be a comment of one line, so that one that is being typed
|
|
558
|
+
// does not take the declarations after it.
|
|
553
559
|
function embeddedCommentEnd(input, at) {
|
|
554
|
-
|
|
560
|
+
let mark = input.peek(at + 1);
|
|
561
|
+
if (input.peek(at) != 35 /* Ch.Hash */ || mark != 96 /* Ch.Backtick */ && mark != 124 /* Ch.Pipe */ && mark != 61 /* Ch.Equals */)
|
|
555
562
|
return 0;
|
|
556
563
|
let open = input.peek(at + 2), close = brackets$1[open];
|
|
557
564
|
if (close == null)
|
|
@@ -559,7 +566,8 @@ function embeddedCommentEnd(input, at) {
|
|
|
559
566
|
let count = 1;
|
|
560
567
|
while (input.peek(at + 2 + count) == open)
|
|
561
568
|
count++;
|
|
562
|
-
|
|
569
|
+
let end = rawEnd(input, at + 2 + count, { open, close, count, escapes: false });
|
|
570
|
+
return end < 0 && mark != 96 /* Ch.Backtick */ ? 0 : end;
|
|
563
571
|
}
|
|
564
572
|
function isBlank(ch) { return ch == 32 /* Ch.Space */ || ch == 9 /* Ch.Tab */ || ch == 13 /* Ch.Return */; }
|
|
565
573
|
// The offset of the first character at or after `pos` that is not a blank.
|
|
@@ -792,7 +800,9 @@ function quoteCharOpening(open, close, at, interpolates, escapes = true) {
|
|
|
792
800
|
// The delimiters, other than brackets, that are accepted after a quote word.
|
|
793
801
|
function isQuoteDelimiter(ch) {
|
|
794
802
|
return ch == 47 /* Ch.Slash */ || ch == 33 /* Ch.Bang */ || ch == 124 /* Ch.Pipe */ || ch == 126 /* Ch.Tilde */ || ch == 94 /* Ch.Caret */ ||
|
|
795
|
-
ch == 37 /* Ch.Percent */ || ch == 64 /* Ch.At */ || ch == 34 /* Ch.DoubleQuote */ || ch == 39 /* Ch.Apostrophe
|
|
803
|
+
ch == 37 /* Ch.Percent */ || ch == 64 /* Ch.At */ || ch == 34 /* Ch.DoubleQuote */ || ch == 39 /* Ch.Apostrophe */ || ch == 96 /* Ch.Backtick */ ||
|
|
804
|
+
// A symbol outside of ASCII: Q♥a♥
|
|
805
|
+
ch > 0xa0 && ch != 0xd7 && ch != 0xf7 && !isIdentifierStart(ch) && !isSpace(ch) && ch < 0xd800;
|
|
796
806
|
}
|
|
797
807
|
// Reads the start of a quote at offset `at`: a quote character, or a
|
|
798
808
|
// quote word (q, qq, m, s, ...) with its adverbs and its delimiter.
|
|
@@ -807,8 +817,16 @@ function readOpening(input, at = 0) {
|
|
|
807
817
|
return quoteCharOpening(next, 0x201d, at, 63 /* Interpolate.All */);
|
|
808
818
|
if (next == 0x2018 /* ‘ */)
|
|
809
819
|
return quoteCharOpening(next, 0x2019, at, 0);
|
|
820
|
+
if (next == 0x201e /* „ */)
|
|
821
|
+
return quoteCharOpening(next, 0x201d, at, 63 /* Interpolate.All */);
|
|
822
|
+
if (next == 0x201d /* ” */)
|
|
823
|
+
return quoteCharOpening(next, next, at, 63 /* Interpolate.All */);
|
|
824
|
+
if (next == 0x201a /* ‚ */)
|
|
825
|
+
return quoteCharOpening(next, 0x2019, at, 0);
|
|
810
826
|
if (next == 0x300c /* 「 */)
|
|
811
827
|
return quoteCharOpening(next, 0x300d, at, 0, false);
|
|
828
|
+
if (next == 0xff62 /* 「 */)
|
|
829
|
+
return quoteCharOpening(next, 0xff63, at, 0, false);
|
|
812
830
|
if (!isAsciiLetter(next))
|
|
813
831
|
return null;
|
|
814
832
|
let pos = at + 1;
|
|
@@ -887,14 +905,14 @@ function readOpening(input, at = 0) {
|
|
|
887
905
|
// The offset after the delimiter that closes a quote whose content
|
|
888
906
|
// starts at `pos`, or -1 when it is not closed.
|
|
889
907
|
function rawEnd(input, pos, opening) {
|
|
890
|
-
let { open, close, count } = opening;
|
|
908
|
+
let { open, close, count } = opening, other = otherClose(open);
|
|
891
909
|
for (let depth = 1;;) {
|
|
892
910
|
let ch = input.peek(pos);
|
|
893
911
|
if (ch < 0)
|
|
894
912
|
return -1;
|
|
895
913
|
if (ch == 92 /* Ch.Backslash */ && opening.escapes)
|
|
896
914
|
pos += 2;
|
|
897
|
-
else if (ch == close && repeats(input, pos, close, count)) {
|
|
915
|
+
else if (ch == close && repeats(input, pos, close, count) || ch == other) {
|
|
898
916
|
pos += count;
|
|
899
917
|
if (--depth == 0)
|
|
900
918
|
return pos;
|
|
@@ -907,26 +925,111 @@ function rawEnd(input, pos, opening) {
|
|
|
907
925
|
pos++;
|
|
908
926
|
}
|
|
909
927
|
}
|
|
928
|
+
// The character that closes a quote in a regex that opens with `ch`,
|
|
929
|
+
// or 0 when `ch` opens none: 'a', "a", ‘a’, ‚a’, “a”, „a”, 「a」
|
|
930
|
+
function quoteClose(ch) {
|
|
931
|
+
return ch == 39 /* Ch.Apostrophe */ || ch == 34 /* Ch.DoubleQuote */ ? ch : ch == 0x2018 || ch == 0x201a ? 0x2019 :
|
|
932
|
+
ch == 0x201c || ch == 0x201e ? 0x201d : ch == 0xff62 ? 0xff63 : 0;
|
|
933
|
+
}
|
|
934
|
+
// A low quote is also closed by the quote that points the other way:
|
|
935
|
+
// ‚a‘, „a“. This is that quote for the given opening one, or -1.
|
|
936
|
+
function otherClose(open) { return open == 0x201a ? 0x2018 : open == 0x201e ? 0x201c : -1; }
|
|
910
937
|
// The offset after a quoted string that starts at `pos`, or -1.
|
|
911
938
|
function quotedEnd(input, pos) {
|
|
912
|
-
let
|
|
939
|
+
let open = input.peek(pos), close = quoteClose(open), other = otherClose(open);
|
|
913
940
|
for (pos++;;) {
|
|
914
941
|
let ch = input.peek(pos);
|
|
915
942
|
if (ch < 0 || ch == 10 /* Ch.Newline */)
|
|
916
943
|
return -1;
|
|
917
|
-
|
|
944
|
+
// Nothing is escaped in 「...」.
|
|
945
|
+
if (ch == 92 /* Ch.Backslash */ && open != 0xff62)
|
|
918
946
|
pos += 2;
|
|
919
|
-
else if (ch ==
|
|
947
|
+
else if (ch == close || ch == other)
|
|
920
948
|
return pos + 1;
|
|
921
949
|
else
|
|
922
950
|
pos++;
|
|
923
951
|
}
|
|
924
952
|
}
|
|
953
|
+
// The offset after the arguments of the assertion that starts with the
|
|
954
|
+
// `<` at `pos`, or 0 when it has none on its line. The arguments are
|
|
955
|
+
// code, in which the delimiter of the regex does not end it:
|
|
956
|
+
// <name(1/2)>, <:name(/x/)>, <name: /a<b>+/ >
|
|
957
|
+
function assertionArgumentsEnd(input, pos) {
|
|
958
|
+
// An assertion can add up several names: <+:Lu +:name(/SMALL/)>
|
|
959
|
+
for (let at = pos + 1;;) {
|
|
960
|
+
while (isAssertionMark(input.peek(at)) || isBlank(input.peek(at)))
|
|
961
|
+
at++;
|
|
962
|
+
let end = nameEnd(input, at);
|
|
963
|
+
if (end < 0)
|
|
964
|
+
return 0;
|
|
965
|
+
// With parentheses, up to the one that closes them. After a colon
|
|
966
|
+
// and a space, up to the `>` that closes the assertion.
|
|
967
|
+
let open = input.peek(end);
|
|
968
|
+
if (open == 40 /* Ch.ParenOpen */)
|
|
969
|
+
return balancedEnd(input, end + 1, 40 /* Ch.ParenOpen */, 41 /* Ch.ParenClose */);
|
|
970
|
+
if (open == 58 /* Ch.Colon */ && isBlank(input.peek(end + 1)))
|
|
971
|
+
return balancedEnd(input, end + 1, 60 /* Ch.Less */, 62 /* Ch.Greater */);
|
|
972
|
+
at = end;
|
|
973
|
+
if (!isAssertionMark(input.peek(at)) && !isBlank(input.peek(at)))
|
|
974
|
+
return 0;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
// The characters that come before the name in an assertion: <.ws>, <?before>, <+alpha>
|
|
978
|
+
function isAssertionMark(ch) {
|
|
979
|
+
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 */ ||
|
|
980
|
+
ch == 45 /* Ch.Hyphen */;
|
|
981
|
+
}
|
|
982
|
+
// The offset after the code that the `<` or `:` at `pos` in a regex
|
|
983
|
+
// starts, or 0 when it starts none.
|
|
984
|
+
function regexCodeEnd(input, pos) {
|
|
985
|
+
return input.peek(pos) == 60 /* Ch.Less */ ? assertionArgumentsEnd(input, pos) : regexDeclarationEnd(input, pos);
|
|
986
|
+
}
|
|
987
|
+
// The offset after the declaration that starts with the `:` at `pos`
|
|
988
|
+
// in a regex, or 0 when none does: `:my $c = $/;`. It is code up to
|
|
989
|
+
// its `;`, in which the delimiter of the regex does not end it.
|
|
990
|
+
function regexDeclarationEnd(input, pos) {
|
|
991
|
+
let end = nameEnd(input, pos + 1);
|
|
992
|
+
if (end < 0 || end - pos > 9 || !isBlank(input.peek(end)) ||
|
|
993
|
+
!/^(my|our|state|constant|temp|let)$/.test(word(input, pos + 1, end)))
|
|
994
|
+
return 0;
|
|
995
|
+
for (;;) {
|
|
996
|
+
let ch = input.peek(end);
|
|
997
|
+
if (ch < 0 || ch == 10 /* Ch.Newline */)
|
|
998
|
+
return 0;
|
|
999
|
+
if (ch == 59 /* Ch.Semicolon */)
|
|
1000
|
+
return end + 1;
|
|
1001
|
+
let quoted = quoteClose(ch) ? quotedEnd(input, end) : -1;
|
|
1002
|
+
end = quoted > 0 ? quoted : end + 1;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
// The offset after the `close` that matches an `open` before `pos`, or
|
|
1006
|
+
// 0 when there is none on the line. Quotes are gone over.
|
|
1007
|
+
function balancedEnd(input, pos, open, close) {
|
|
1008
|
+
for (let depth = 1;;) {
|
|
1009
|
+
let ch = input.peek(pos);
|
|
1010
|
+
if (ch < 0 || ch == 10 /* Ch.Newline */)
|
|
1011
|
+
return 0;
|
|
1012
|
+
if (ch == 92 /* Ch.Backslash */)
|
|
1013
|
+
pos += 2;
|
|
1014
|
+
else if (quoteClose(ch)) {
|
|
1015
|
+
let quoted = quotedEnd(input, pos);
|
|
1016
|
+
pos = quoted < 0 ? pos + 1 : quoted;
|
|
1017
|
+
}
|
|
1018
|
+
else {
|
|
1019
|
+
pos++;
|
|
1020
|
+
if (ch == open)
|
|
1021
|
+
depth++;
|
|
1022
|
+
else if (ch == close && --depth == 0)
|
|
1023
|
+
return pos;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
925
1027
|
// The offset of the delimiter that closes a regex whose content starts
|
|
926
1028
|
// at `pos`, or -1. Delimiters do not count inside quotes, character
|
|
927
|
-
// classes, comments and code blocks.
|
|
928
|
-
|
|
929
|
-
|
|
1029
|
+
// classes, comments and code blocks. `code` is set for the inside of a
|
|
1030
|
+
// code block, where a `<` is an operator.
|
|
1031
|
+
function regexEnd(input, { start: pos, open, close, count }, code = false) {
|
|
1032
|
+
for (let depth = 1, codeEnd;;) {
|
|
930
1033
|
let ch = input.peek(pos);
|
|
931
1034
|
if (ch < 0)
|
|
932
1035
|
return -1;
|
|
@@ -942,10 +1045,25 @@ function regexEnd(input, { start: pos, open, close, count }) {
|
|
|
942
1045
|
pos += count;
|
|
943
1046
|
depth++;
|
|
944
1047
|
}
|
|
945
|
-
else if (ch
|
|
1048
|
+
else if (quoteClose(ch)) {
|
|
946
1049
|
let end = quotedEnd(input, pos);
|
|
947
1050
|
pos = end < 0 ? pos + 1 : end;
|
|
948
1051
|
}
|
|
1052
|
+
else if (!code && ch == 60 /* Ch.Less */ && isBlank(input.peek(pos + 1))) {
|
|
1053
|
+
// A list of words, in which quotes are text: < a ' b >
|
|
1054
|
+
let end = pos + 2;
|
|
1055
|
+
while (input.peek(end) != 62 /* Ch.Greater */ && input.peek(end) != 10 /* Ch.Newline */ && input.peek(end) >= 0)
|
|
1056
|
+
end++;
|
|
1057
|
+
pos = input.peek(end) == 62 /* Ch.Greater */ ? end + 1 : pos + 1;
|
|
1058
|
+
}
|
|
1059
|
+
else if (!code && (ch == 60 /* Ch.Less */ || ch == 58 /* Ch.Colon */) && (codeEnd = regexCodeEnd(input, pos)) > 0) {
|
|
1060
|
+
pos = codeEnd;
|
|
1061
|
+
}
|
|
1062
|
+
else if (!code && (ch == 36 /* Ch.Dollar */ || ch == 64 /* Ch.At */) && input.peek(pos + 1) == 40 /* Ch.ParenOpen */) {
|
|
1063
|
+
// Code that is interpolated: $( rx/ a / )
|
|
1064
|
+
let end = balancedEnd(input, pos + 2, 40 /* Ch.ParenOpen */, 41 /* Ch.ParenClose */);
|
|
1065
|
+
pos = end > 0 ? end : pos + 1;
|
|
1066
|
+
}
|
|
949
1067
|
else if (ch == 60 /* Ch.Less */ && (input.peek(pos + 1) == 91 /* Ch.BracketOpen */ ||
|
|
950
1068
|
(input.peek(pos + 1) == 45 /* Ch.Hyphen */ || input.peek(pos + 1) == 43 /* Ch.Plus */) && input.peek(pos + 2) == 91 /* Ch.BracketOpen */)) {
|
|
951
1069
|
// <[...]>, <-[...]>, and combinations: <+[a..z]-[aeiou]>
|
|
@@ -986,7 +1104,7 @@ function regexEnd(input, { start: pos, open, close, count }) {
|
|
|
986
1104
|
pos++;
|
|
987
1105
|
}
|
|
988
1106
|
else if (ch == 123 /* Ch.BraceOpen */ && close != 125 /* Ch.BraceClose */) {
|
|
989
|
-
let end = regexEnd(input, { start: pos + 1, open: 123 /* Ch.BraceOpen */, close: 125 /* Ch.BraceClose */, count: 1 });
|
|
1107
|
+
let end = regexEnd(input, { start: pos + 1, open: 123 /* Ch.BraceOpen */, close: 125 /* Ch.BraceClose */, count: 1 }, true);
|
|
990
1108
|
pos = end < 0 ? pos + 1 : end + 1;
|
|
991
1109
|
}
|
|
992
1110
|
else {
|
|
@@ -994,6 +1112,21 @@ function regexEnd(input, { start: pos, open, close, count }) {
|
|
|
994
1112
|
}
|
|
995
1113
|
}
|
|
996
1114
|
}
|
|
1115
|
+
// The offset after the `/` that closes the replacement of s/a/b/, which
|
|
1116
|
+
// starts at `pos`, or -1. A `$/` in it does not close it, when a `/`
|
|
1117
|
+
// follows on the same line: in s/a/$/, the `$` is text.
|
|
1118
|
+
function replacementEnd(input, pos) {
|
|
1119
|
+
for (let match = false;;) {
|
|
1120
|
+
let ch = input.peek(pos);
|
|
1121
|
+
if (ch < 0 || match && ch == 10 /* Ch.Newline */)
|
|
1122
|
+
return -1;
|
|
1123
|
+
if (ch == 47 /* Ch.Slash */)
|
|
1124
|
+
return pos + 1;
|
|
1125
|
+
if (ch == 36 /* Ch.Dollar */ && input.peek(pos + 1) == 47 /* Ch.Slash */)
|
|
1126
|
+
match = true;
|
|
1127
|
+
pos += match && ch == 36 /* Ch.Dollar */ || ch == 92 /* Ch.Backslash */ ? 2 : 1;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
997
1130
|
// The offset after a regex or substitution, given its opening, or -1.
|
|
998
1131
|
function regexTokenEnd(input, opening) {
|
|
999
1132
|
let end = regexEnd(input, opening);
|
|
@@ -1001,8 +1134,12 @@ function regexTokenEnd(input, opening) {
|
|
|
1001
1134
|
return -1;
|
|
1002
1135
|
end += opening.count;
|
|
1003
1136
|
// s/a/b/ has a second part. s{a} = 'b' does not.
|
|
1004
|
-
if (opening.kind != "regex" && opening.open == opening.close)
|
|
1005
|
-
|
|
1137
|
+
if (opening.kind != "regex" && opening.open == opening.close) {
|
|
1138
|
+
// A `$/` in the replacement is the match variable, not a `$` before
|
|
1139
|
+
// the closing delimiter: s/(a)/[$/]/. Unless nothing closes it then.
|
|
1140
|
+
let withMatch = opening.close == 47 /* Ch.Slash */ ? replacementEnd(input, end) : -1;
|
|
1141
|
+
end = withMatch < 0 ? rawEnd(input, end, opening) : withMatch;
|
|
1142
|
+
}
|
|
1006
1143
|
return end;
|
|
1007
1144
|
}
|
|
1008
1145
|
// The opening of a bare regex: /a/
|
|
@@ -1106,6 +1243,8 @@ const declarators$1 = /^(sub|method|submethod|token|rule|regex)$/;
|
|
|
1106
1243
|
function startsDeclarator(name) {
|
|
1107
1244
|
return ["sub", "method", "submethod", "token", "rule", "regex"].some(declarator => declarator.startsWith(name));
|
|
1108
1245
|
}
|
|
1246
|
+
// What stands between the parentheses of a set operator.
|
|
1247
|
+
const setOperators = /^(<=?|>=?|<\+|>\+|==|[|&\-^+.]|elem|cont)$/;
|
|
1109
1248
|
const operatorCategory = /^(infix|prefix|postfix|circumfix|postcircumfix|term)$/;
|
|
1110
1249
|
function isWordOperator(name) {
|
|
1111
1250
|
return name == "x" || name == "xx" || name == "min" || name == "max" || name == "Z" || name == "X";
|
|
@@ -1121,6 +1260,16 @@ const termToken = new lr.ExternalTokenizer((input, stack) => {
|
|
|
1121
1260
|
return;
|
|
1122
1261
|
}
|
|
1123
1262
|
let next = input.next, { mode } = context(stack);
|
|
1263
|
+
// The set operators that are written in parentheses: $a (<=) $b, $x (elem) $s
|
|
1264
|
+
// Not right after the term, where the parentheses hold arguments: $f(elem)
|
|
1265
|
+
if (next == 40 /* Ch.ParenOpen */ && mode == 1 /* Mode.AfterTerm */ && isSpace(input.peek(-1))) {
|
|
1266
|
+
let end = 1;
|
|
1267
|
+
while (end < 6 && input.peek(end) != 41 /* Ch.ParenClose */ && input.peek(end) >= 0)
|
|
1268
|
+
end++;
|
|
1269
|
+
if (input.peek(end) == 41 /* Ch.ParenClose */ && setOperators.test(word(input, 1, end)))
|
|
1270
|
+
input.acceptToken(wordOperator, end + 1);
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1124
1273
|
if (isIdentifierStart(next)) {
|
|
1125
1274
|
// The Z, X and R meta operators: Z+, X~, R-, Z=>
|
|
1126
1275
|
if (mode == 1 /* Mode.AfterTerm */ && (next == 90 /* Ch.Z */ || next == 88 /* Ch.X */ || next == 82 /* Ch.R */) &&
|
|
@@ -1163,7 +1312,25 @@ const termToken = new lr.ExternalTokenizer((input, stack) => {
|
|
|
1163
1312
|
// space before it, it is a variable: `my Array[Int] %h`.
|
|
1164
1313
|
if (mode == 1 /* Mode.AfterTerm */ && isIdentifierStart(input.peek(1)) && !isSpace(input.peek(-1)))
|
|
1165
1314
|
return input.acceptToken(wordOperator, 1);
|
|
1166
|
-
// An operator as a routine: &
|
|
1315
|
+
// An operator as a routine: &[+], &[»+»], &[max]
|
|
1316
|
+
// After a term, the `&` is an operator: $a &[1, 2]
|
|
1317
|
+
if (next == 38 /* Ch.Amp */ && input.peek(1) == 91 /* Ch.BracketOpen */ && mode != 1 /* Mode.AfterTerm */) {
|
|
1318
|
+
// A meta operator brings brackets of its own: &[R[~~]]
|
|
1319
|
+
for (let end = 2, depth = 1; end < 14; end++) {
|
|
1320
|
+
let ch = input.peek(end);
|
|
1321
|
+
if (ch < 0 || isSpace(ch))
|
|
1322
|
+
break;
|
|
1323
|
+
if (ch == 91 /* Ch.BracketOpen */)
|
|
1324
|
+
depth++;
|
|
1325
|
+
else if (ch == 93 /* Ch.BracketClose */ && --depth == 0) {
|
|
1326
|
+
if (end > 2)
|
|
1327
|
+
input.acceptToken(operatorVariable, end + 1);
|
|
1328
|
+
break;
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1333
|
+
// The same by its full name: &infix:<+>
|
|
1167
1334
|
if (next == 38 /* Ch.Amp */) {
|
|
1168
1335
|
let end = nameEnd(input, 1);
|
|
1169
1336
|
if (end > 0 && operatorCategory.test(word(input, 1, end))) {
|
|
@@ -1236,17 +1403,25 @@ function hasPostfix(input, end) {
|
|
|
1236
1403
|
let methodEnd = nameEnd(input, end + 1);
|
|
1237
1404
|
return methodEnd > 0 && input.peek(methodEnd) == 40 /* Ch.ParenOpen */;
|
|
1238
1405
|
}
|
|
1406
|
+
// Whether the parser is between the pieces of a quote, as opposed to
|
|
1407
|
+
// in the code of a block in it.
|
|
1408
|
+
function inQuoteText(stack) { return stack.canShift(quoteContent); }
|
|
1409
|
+
// Whether the parser is, in a quote, right after a variable or after a
|
|
1410
|
+
// subscript or a call on one: where the grammar takes a quotePostfix.
|
|
1411
|
+
// This is asked of the parser and not of the mode, which is not known
|
|
1412
|
+
// to this precision after a reused node that ends in text of the quote.
|
|
1413
|
+
function afterQuotedVariable(stack) { return stack.canShift(rawString); }
|
|
1239
1414
|
// The pieces of a quote that interpolates.
|
|
1240
1415
|
const quoteToken = new lr.ExternalTokenizer((input, stack) => {
|
|
1241
|
-
if (!stack
|
|
1416
|
+
if (!inQuoteText(stack))
|
|
1242
1417
|
return;
|
|
1243
|
-
let { quote
|
|
1418
|
+
let { quote } = context(stack);
|
|
1244
1419
|
if (!quote)
|
|
1245
1420
|
return;
|
|
1246
|
-
let { open, close, count, interpolates } = quote, nests = open != close;
|
|
1421
|
+
let { open, close, count, interpolates } = quote, nests = open != close, other = otherClose(open);
|
|
1247
1422
|
// After a variable, a subscript or a call continues the interpolation.
|
|
1248
1423
|
// `[` and `(` are left to the grammar's own tokens.
|
|
1249
|
-
if (
|
|
1424
|
+
if (afterQuotedVariable(stack)) {
|
|
1250
1425
|
if (input.next == 91 /* Ch.BracketOpen */ || input.next == 40 /* Ch.ParenOpen */)
|
|
1251
1426
|
return;
|
|
1252
1427
|
let end = subscriptEnd(input);
|
|
@@ -1261,12 +1436,13 @@ const quoteToken = new lr.ExternalTokenizer((input, stack) => {
|
|
|
1261
1436
|
let next = input.next;
|
|
1262
1437
|
if (next < 0)
|
|
1263
1438
|
break;
|
|
1264
|
-
let atClose = next == close && repeats(input, 0, close, count);
|
|
1439
|
+
let atClose = next == close && repeats(input, 0, close, count) || next == other;
|
|
1265
1440
|
if (atClose || nests && next == open && repeats(input, 0, open, count)) {
|
|
1266
1441
|
if (input.pos > start)
|
|
1267
1442
|
break;
|
|
1268
1443
|
input.advance(count);
|
|
1269
|
-
|
|
1444
|
+
// Inside a nested pair, a closing delimiter closes that pair.
|
|
1445
|
+
return input.acceptToken(!atClose ? quoteNestOpen : stack.canShift(quoteNestClose) ? quoteNestClose : quoteEnd);
|
|
1270
1446
|
}
|
|
1271
1447
|
if (next == 92 /* Ch.Backslash */) {
|
|
1272
1448
|
if (interpolates & 32 /* Interpolate.Backslash */)
|
|
@@ -1366,14 +1542,21 @@ function isRegexOperator(ch) {
|
|
|
1366
1542
|
// When it is not closed on its line, this is the negated offset of the
|
|
1367
1543
|
// end of the text that was gone over to find that out.
|
|
1368
1544
|
function assertionEnd(input) {
|
|
1545
|
+
// A list of words, in which quotes and brackets are text: < a ' b >
|
|
1546
|
+
let words = isBlank(input.peek(1));
|
|
1369
1547
|
for (let pos = 1, depth = 1;;) {
|
|
1370
1548
|
let ch = input.peek(pos);
|
|
1371
1549
|
if (ch < 0 || ch == 10 /* Ch.Newline */)
|
|
1372
1550
|
return -pos;
|
|
1373
|
-
if (
|
|
1551
|
+
if (words) {
|
|
1552
|
+
pos++;
|
|
1553
|
+
if (ch == 62 /* Ch.Greater */)
|
|
1554
|
+
return pos;
|
|
1555
|
+
}
|
|
1556
|
+
else if (ch == 92 /* Ch.Backslash */) {
|
|
1374
1557
|
pos += input.peek(pos + 1) == 10 /* Ch.Newline */ || input.peek(pos + 1) < 0 ? 1 : 2;
|
|
1375
1558
|
}
|
|
1376
|
-
else if (ch
|
|
1559
|
+
else if (quoteClose(ch)) {
|
|
1377
1560
|
let end = quotedEnd(input, pos);
|
|
1378
1561
|
pos = end < 0 ? pos + 1 : end;
|
|
1379
1562
|
}
|
|
@@ -1467,7 +1650,7 @@ const regexToken = new lr.ExternalTokenizer((input, stack) => {
|
|
|
1467
1650
|
skipLine(input);
|
|
1468
1651
|
return input.acceptToken(regexComment);
|
|
1469
1652
|
}
|
|
1470
|
-
if (next
|
|
1653
|
+
if (quoteClose(next)) {
|
|
1471
1654
|
let end = quotedEnd(input, 0);
|
|
1472
1655
|
if (end > 0 && end <= limit)
|
|
1473
1656
|
return input.acceptToken(regexQuote, end);
|
|
@@ -1533,7 +1716,7 @@ const regexToken = new lr.ExternalTokenizer((input, stack) => {
|
|
|
1533
1716
|
input.advance();
|
|
1534
1717
|
let ch = input.next;
|
|
1535
1718
|
if (ch < 0 || input.pos == literalEnd ||
|
|
1536
|
-
ch == 10 /* Ch.Newline */ || ch == 92 /* Ch.Backslash */ || ch
|
|
1719
|
+
ch == 10 /* Ch.Newline */ || ch == 92 /* Ch.Backslash */ || quoteClose(ch) ||
|
|
1537
1720
|
ch == 60 /* Ch.Less */ || ch == 62 /* Ch.Greater */ || ch == 171 /* Ch.GuillemetOpen */ || ch == 187 /* Ch.GuillemetClose */ ||
|
|
1538
1721
|
ch == 41 /* Ch.ParenClose */ && input.peek(1) == 62 /* Ch.Greater */ ||
|
|
1539
1722
|
ch == 123 /* Ch.BraceOpen */ || ch == 125 /* Ch.BraceClose */ || ch == 35 /* Ch.Hash */ || ch == 36 /* Ch.Dollar */ ||
|
|
@@ -1555,9 +1738,8 @@ const methodDotToken = new lr.ExternalTokenizer((input, stack) => {
|
|
|
1555
1738
|
next = input.peek(++size);
|
|
1556
1739
|
if (!isIdentifierStart(next))
|
|
1557
1740
|
return;
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
(mode != 1 /* Mode.AfterTerm */ || input.peek(nameEnd(input, size)) != 40 /* Ch.ParenOpen */))
|
|
1741
|
+
if (context(stack).quote && inQuoteText(stack) &&
|
|
1742
|
+
(!afterQuotedVariable(stack) || input.peek(nameEnd(input, size)) != 40 /* Ch.ParenOpen */))
|
|
1561
1743
|
return;
|
|
1562
1744
|
input.acceptToken(methodDot, size);
|
|
1563
1745
|
});
|
|
@@ -1582,6 +1764,26 @@ function categoryEnd(input, nameStart, pos) {
|
|
|
1582
1764
|
let close = first == 60 /* Ch.Less */ ? 62 /* Ch.Greater */ : first == 171 /* Ch.GuillemetOpen */ ? 187 /* Ch.GuillemetClose */ : -1;
|
|
1583
1765
|
if (close < 0)
|
|
1584
1766
|
return pos;
|
|
1767
|
+
// With double angles, blanks can surround the operator, which can
|
|
1768
|
+
// hold a `>` itself: infix:<< stash-eq >>, infix:<<(>=)>>
|
|
1769
|
+
// When this is not that form, the operator starts with `<`: infix:<<=>
|
|
1770
|
+
if (first == 60 /* Ch.Less */ && input.peek(open + 1) == 60 /* Ch.Less */) {
|
|
1771
|
+
let start = blanksEnd(input, open + 2);
|
|
1772
|
+
let closes = (at) => input.peek(at) == close && input.peek(at + 1) == close && input.peek(at + 2) != close;
|
|
1773
|
+
// An operator is short, and a token must not look far past its end.
|
|
1774
|
+
for (let end = start; end < start + maxGap; end++) {
|
|
1775
|
+
let ch = input.peek(end);
|
|
1776
|
+
// Not a shift in code without spaces: infix:<<=>($a){$a>>1}
|
|
1777
|
+
if (end > start && closes(end) && !continuesName(input, end + 2) && input.peek(end + 2) != 36 /* Ch.Dollar */)
|
|
1778
|
+
return end + 2;
|
|
1779
|
+
if (ch < 0 || isSpace(ch)) {
|
|
1780
|
+
let after = blanksEnd(input, end);
|
|
1781
|
+
if (end > start && closes(after))
|
|
1782
|
+
return after + 2;
|
|
1783
|
+
break;
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1585
1787
|
// The two halves of a circumfix are separated by one space.
|
|
1586
1788
|
let spaces = /circumfix$/.test(word(input, nameStart, pos)) ? 1 : 0;
|
|
1587
1789
|
for (let i = open + 1;; i++) {
|
|
@@ -1597,8 +1799,17 @@ function categoryEnd(input, nameStart, pos) {
|
|
|
1597
1799
|
// specialized identifiers, and specialization does not look at the
|
|
1598
1800
|
// parse state, so these positions get tokens of their own.
|
|
1599
1801
|
const nameToken = new lr.ExternalTokenizer((input, stack) => {
|
|
1802
|
+
let next = input.next;
|
|
1803
|
+
// The name of a constant can have a sigil: constant $LIMIT = 3
|
|
1804
|
+
if ((next == 36 /* Ch.Dollar */ || next == 64 /* Ch.At */ || next == 37 /* Ch.Percent */ || next == 38 /* Ch.Amp */) && stack.canShift(declaredVariable)) {
|
|
1805
|
+
let end = nameEnd(input, 1);
|
|
1806
|
+
// constant &infix:<plus> = &infix:<+>
|
|
1807
|
+
if (end > 0)
|
|
1808
|
+
input.acceptToken(declaredVariable, next == 38 /* Ch.Amp */ ? categoryEnd(input, 1, end) : end);
|
|
1809
|
+
return;
|
|
1810
|
+
}
|
|
1600
1811
|
// Only a method declaration takes a mark: `method !private`, `method ^meta`.
|
|
1601
|
-
let mark =
|
|
1812
|
+
let mark = next == 33 /* Ch.Bang */ || next == 94 /* Ch.Caret */ ? 1 : 0;
|
|
1602
1813
|
let end = nameEnd(input, mark);
|
|
1603
1814
|
if (end < 0)
|
|
1604
1815
|
return;
|
|
@@ -1607,7 +1818,17 @@ const nameToken = new lr.ExternalTokenizer((input, stack) => {
|
|
|
1607
1818
|
input.acceptToken(MethodName, end);
|
|
1608
1819
|
return;
|
|
1609
1820
|
}
|
|
1821
|
+
let named = end;
|
|
1610
1822
|
end = categoryEnd(input, mark, end);
|
|
1823
|
+
// Blanks can come before the `:sym<...>` of a declaration: token c :sym<a> { a }
|
|
1824
|
+
if (end == named) {
|
|
1825
|
+
let sym = gapEnd(input, end);
|
|
1826
|
+
if (sym > end && word(input, sym, sym + 4) == ":sym") {
|
|
1827
|
+
let symEnd = categoryEnd(input, mark, sym);
|
|
1828
|
+
if (symEnd > sym)
|
|
1829
|
+
end = symEnd;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1611
1832
|
if (!mark && stack.canShift(declaredName))
|
|
1612
1833
|
input.acceptToken(declaredName, end);
|
|
1613
1834
|
else if (stack.canShift(declaredMethodName))
|
|
@@ -1663,27 +1884,27 @@ const versionToken = new lr.ExternalTokenizer((input, stack) => {
|
|
|
1663
1884
|
});
|
|
1664
1885
|
|
|
1665
1886
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
1666
|
-
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:
|
|
1667
|
-
const spec_capIdentifier = {__proto__:null,True:
|
|
1887
|
+
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};
|
|
1888
|
+
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};
|
|
1668
1889
|
const parser$1 = lr.LRParser.deserialize({
|
|
1669
1890
|
version: 14,
|
|
1670
|
-
states: "
|
|
1671
|
-
stateData: "
|
|
1672
|
-
goto: ",
|
|
1673
|
-
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",
|
|
1674
|
-
maxTerm:
|
|
1891
|
+
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",
|
|
1892
|
+
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~",
|
|
1893
|
+
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",
|
|
1894
|
+
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",
|
|
1895
|
+
maxTerm: 233,
|
|
1675
1896
|
context: trackContext,
|
|
1676
1897
|
nodeProps: [
|
|
1677
1898
|
["openedBy", 33,"(",36,"[",46,"{"],
|
|
1678
1899
|
["closedBy", 34,")",37,"]",47,"}"]
|
|
1679
1900
|
],
|
|
1680
1901
|
skippedNodes: [0,1,11,12,28,29],
|
|
1681
|
-
repeatNodeCount:
|
|
1682
|
-
tokenData: "
|
|
1902
|
+
repeatNodeCount: 6,
|
|
1903
|
+
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",
|
|
1683
1904
|
tokenizers: [smileyToken, blockComment, podToken, heredocToken, methodDotToken, nameToken, versionToken, regexToken, quoteToken, termToken, 0, 1],
|
|
1684
|
-
topRules: {"Program":[0,30],"Regex":[1,
|
|
1685
|
-
specialized: [{term:
|
|
1686
|
-
tokenPrec:
|
|
1905
|
+
topRules: {"Program":[0,30],"Regex":[1,191],"Heredoc":[2,192],"StringLiteral":[3,193]},
|
|
1906
|
+
specialized: [{term: 226, get: (value) => spec_identifier[value] || -1},{term: 229, get: (value) => spec_capIdentifier[value] || -1}],
|
|
1907
|
+
tokenPrec: 3559
|
|
1687
1908
|
});
|
|
1688
1909
|
|
|
1689
1910
|
// The keywords of the grammar, with the tag each is highlighted with.
|
|
@@ -1812,8 +2033,8 @@ class Gatherer {
|
|
|
1812
2033
|
this.declaration(child);
|
|
1813
2034
|
else if (child.firstChild)
|
|
1814
2035
|
this.content(child);
|
|
1815
|
-
//
|
|
1816
|
-
// declaration node: constant
|
|
2036
|
+
// A constant that is declared with a backslash has its name after
|
|
2037
|
+
// the declaration node: constant \limit = 3
|
|
1817
2038
|
declaring = name == "ConstantDeclaration" && child.lastChild.name == "constant";
|
|
1818
2039
|
}
|
|
1819
2040
|
}
|
|
@@ -2380,7 +2601,7 @@ const baseLanguage = language.LRLanguage.define({
|
|
|
2380
2601
|
Parens: language.delimitedIndent({ closing: ")" }),
|
|
2381
2602
|
Brackets: language.delimitedIndent({ closing: "]" }),
|
|
2382
2603
|
// The lines of these are text, which keeps its indentation.
|
|
2383
|
-
"StringLiteral Heredoc Pod BlockComment": () => null
|
|
2604
|
+
"StringLiteral Heredoc Pod BlockComment DocComment": () => null
|
|
2384
2605
|
}),
|
|
2385
2606
|
language.foldNodeProp.add({
|
|
2386
2607
|
"Block Parens Brackets": language.foldInside,
|
|
@@ -2390,7 +2611,10 @@ const baseLanguage = language.LRLanguage.define({
|
|
|
2390
2611
|
// A heredoc starts with the line break before its first line.
|
|
2391
2612
|
Heredoc(tree) { return { from: tree.from, to: tree.to }; }
|
|
2392
2613
|
}),
|
|
2393
|
-
highlight.styleTags(Object.assign(Object.assign({}, keywordTags), { "True False": highlight.tags.bool, Nil: highlight.tags.null, Identifier: highlight.tags.function(highlight.tags.variableName), TypeName: highlight.tags.typeName, PackageName: highlight.tags.definition(highlight.tags.className), "EnumName SubsetName": highlight.tags.definition(highlight.tags.typeName), ConstantName: highlight.tags.definition(highlight.tags.constant(highlight.tags.variableName)), "RoutineName RegexName": highlight.tags.function(highlight.tags.definition(highlight.tags.variableName)), MethodName: highlight.tags.function(highlight.tags.propertyName), VariableName: highlight.tags.variableName, AttributeName: highlight.tags.propertyName, SpecialVariable: highlight.tags.special(highlight.tags.variableName), PairKey: highlight.tags.attributeName, Number: highlight.tags.number, Version: highlight.tags.literal,
|
|
2614
|
+
highlight.styleTags(Object.assign(Object.assign({}, keywordTags), { "True False": highlight.tags.bool, Nil: highlight.tags.null, Identifier: highlight.tags.function(highlight.tags.variableName), TypeName: highlight.tags.typeName, PackageName: highlight.tags.definition(highlight.tags.className), "EnumName SubsetName": highlight.tags.definition(highlight.tags.typeName), ConstantName: highlight.tags.definition(highlight.tags.constant(highlight.tags.variableName)), "RoutineName RegexName": highlight.tags.function(highlight.tags.definition(highlight.tags.variableName)), MethodName: highlight.tags.function(highlight.tags.propertyName), VariableName: highlight.tags.variableName, AttributeName: highlight.tags.propertyName, SpecialVariable: highlight.tags.special(highlight.tags.variableName), PairKey: highlight.tags.attributeName, Number: highlight.tags.number, Version: highlight.tags.literal,
|
|
2615
|
+
// A pair of delimiters in a quote is text of it, and a tag
|
|
2616
|
+
// does not reach the text in a child node.
|
|
2617
|
+
"StringLiteral Heredoc NestedDelimiters": highlight.tags.string, Regex: highlight.tags.regexp, CharacterClass: highlight.tags.character, Assertion: highlight.tags.function(highlight.tags.variableName), "Pod PodFormat": highlight.tags.docComment, PodDirective: highlight.tags.meta,
|
|
2394
2618
|
// These are still part of a comment, and are styled as one where
|
|
2395
2619
|
// a theme has no style for the second tag.
|
|
2396
2620
|
PodHeading: [highlight.tags.docComment, highlight.tags.heading], PodStrong: [highlight.tags.docComment, highlight.tags.strong], PodEmphasis: [highlight.tags.docComment, highlight.tags.emphasis], PodCode: [highlight.tags.docComment, highlight.tags.monospace], PodLink: [highlight.tags.docComment, highlight.tags.link], Escape: highlight.tags.escape, "Interpolation/{ Interpolation/}": highlight.tags.special(highlight.tags.brace), LineComment: highlight.tags.lineComment, BlockComment: highlight.tags.blockComment, DocComment: highlight.tags.docComment, Operator: highlight.tags.operator, ".": highlight.tags.derefOperator, ", ;": highlight.tags.separator, ":": highlight.tags.punctuation, "( )": highlight.tags.paren, "[ ]": highlight.tags.squareBracket, "{ }": highlight.tags.brace }))
|