-
Notifications
You must be signed in to change notification settings - Fork 398
/
perl6.vim
2255 lines (2003 loc) · 72.7 KB
/
perl6.vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
" Vim syntax file
" Language: Perl 6
" Maintainer: vim-perl <vim-perl@googlegroups.com>
" Homepage: http://github.com/vim-perl/vim-perl/tree/master
" Bugs/requests: http://github.com/vim-perl/vim-perl/issues
" Last Change: 2013-07-21
" Contributors: Luke Palmer <fibonaci@babylonia.flatirons.org>
" Moritz Lenz <moritz@faui2k3.org>
" Hinrik Örn Sigurðsson <hinrik.sig@gmail.com>
"
" This is a big undertaking. Perl 6 is the sort of language that only Perl
" can parse. But I'll do my best to get vim to.
"
" You can associate the extension ".pl" with the filetype "perl6" by setting
" autocmd BufNewFile,BufRead *.pl setf perl6
" in your ~/.vimrc. But that will infringe on Perl 5, so you might want to
" put a modeline near the beginning or end of your Perl 6 files instead:
" # vim: filetype=perl6
" TODO:
" * Deal with s:Perl5//
" * m:s// is a match, not a substitution
" * Make these highlight as strings, not operators:
" <==> <=:=> <===> <=~> <« »> «>» «<»
" * Allow more keywords to match as function calls(leave() is export(), etc)
" * Optimization: use nextgroup instead of lookaround (:help syn-nextgroup)
" * Fix s''' substitutions being matched as package names
" * Match s/// and m/// better, so things like "$s/" won't match
" * Add more support for folding (:help syn-fold)
" * Add more syntax syncing hooks (:help syn-sync)
" * Q//:
" :to, :heredoc
" interpolate \q:s{$scalar} (though the spec isn't very clear on it)
"
" Impossible TODO?:
" * Unspace
" * Unicode bracketing characters for quoting (there are so many)
" * Various tricks depending on context. I.e. we can't know when Perl
" expects «*» to be a string or a hyperoperator. The latter is presumably
" more common, so that's what we assume.
" * Selective highlighting of Pod formatting codes with the :allow option
" * Arbitrary number, order, and negation of adverbs to Q//, q//, qq//.
" Currently only the first adverb is considered significant. Anything
" more would require an exponential amount of regexes, making this
" already slow syntax file even slower.
"
" If you want to have Pir code inside Q:PIR// strings highlighted, do:
" let perl6_embedded_pir=1
"
" The above requires pir.vim, which you can find in Parrot's repository:
" https://svn.parrot.org/parrot/trunk/editor/
"
" Some less than crucial things have been made optional to speed things up.
" Look at the comments near the if/else branches in this file to see exactly
" which features are affected. "perl6_extended_all" enables everything.
"
" The defaults are:
"
" unlet perl6_extended_comments
" unlet perl6_extended_q
" unlet perl6_extended_all
" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
let s:keepcpo= &cpo
set cpo&vim
" identifiers
syn match p6Normal display "\K\%(\k\|[-']\K\@=\)*"
" This is used in the for loops below
" Don't use the "syn keyword" construct because that always has higher
" priority than matches/regions, so the words can't be autoquoted with
" the "=>" and "p5=>" operators. All the lookaround stuff is to make sure
" we don't match them as part of some other identifier.
let s:before_keyword = " display \"\\%(\\k\\|\\K\\@<=[-']\\)\\@<!\\%("
let s:after_keyword = "\\)\\%(\\k\\|[-']\\K\\@=\\)\\@!\""
" Billions of keywords
let s:keywords = {
\ "p6Attention": [
\ "ACHTUNG ATTN ATTENTION FIXME NB TODO TBD WTF XXX NOTE",
\ ],
\ "p6DeclareRoutine": [
\ "macro sub submethod method multi proto only rule token regex category",
\ ],
\ "p6Module": [
\ "module class role package enum grammar slang subset",
\ ],
\ "p6Variable": [
\ "self",
\ ],
\ "p6Include": [
\ "use require",
\ ],
\ "p6Conditional": [
\ "if else elsif unless",
\ ],
\ "p6VarStorage": [
\ "let my our state temp has constant",
\ ],
\ "p6Repeat": [
\ "for loop repeat while until gather given",
\ ],
\ "p6FlowControl": [
\ "take do when next last redo return contend maybe defer",
\ "default exit make continue break goto leave async lift",
\ ],
\ "p6TypeConstraint": [
\ "is as but trusts of returns handles where augment supersede",
\ ],
\ "p6ClosureTrait": [
\ "BEGIN CHECK INIT START FIRST ENTER LEAVE KEEP",
\ "UNDO NEXT LAST PRE POST END CATCH CONTROL TEMP",
\ ],
\ "p6Exception": [
\ "die fail try warn",
\ ],
\ "p6Property": [
\ "prec irs ofs ors export deep binary unary reparsed rw parsed cached",
\ "readonly defequiv will ref copy inline tighter looser equiv assoc",
\ "required",
\ ],
\ "p6Number": [
\ "NaN Inf",
\ ],
\ "p6Pragma": [
\ "oo fatal",
\ ],
\ "p6Type": [
\ "Object Any Junction Whatever Capture Match",
\ "Signature Proxy Matcher Package Module Class",
\ "Grammar Scalar Array Hash KeyHash KeySet KeyBag",
\ "Pair List Seq Range Set Bag Mapping Void Undef",
\ "Failure Exception Code Block Routine Sub Macro",
\ "Method Submethod Regex Str Blob Char Byte",
\ "Codepoint Grapheme StrPos StrLen Version Num",
\ "Complex num complex Bit bit bool True False",
\ "Increasing Decreasing Ordered Callable AnyChar",
\ "Positional Associative Ordering KeyExtractor",
\ "Comparator OrderingPair IO KitchenSink Role",
\ "Int int int1 int2 int4 int8 int16 int32 int64",
\ "Rat rat rat1 rat2 rat4 rat8 rat16 rat32 rat64",
\ "Buf buf buf1 buf2 buf4 buf8 buf16 buf32 buf64",
\ "UInt uint uint1 uint2 uint4 uint8 uint16 uint32",
\ "uint64 Abstraction utf8 utf16 utf32",
\ ],
\ "p6Operator": [
\ "div x xx mod also leg cmp before after eq ne le lt",
\ "gt ge eqv ff fff and andthen Z X or xor",
\ "orelse extra m mm rx s tr",
\ ],
\ }
for [group, words] in items(s:keywords)
let s:words_space = join(words, " ")
let s:temp = split(s:words_space)
let s:words = join(s:temp, "\\|")
exec "syn match ". group ." ". s:before_keyword . s:words . s:after_keyword
endfor
unlet s:keywords s:words_space s:temp s:words
" More operators
" Don't put a "\+" at the end of the character class. That makes it so
" greedy that the "%" " in "+%foo" won't be allowed to match as a sigil,
" among other things
syn match p6Operator display "[-+/*~?|=^!%&,<>.;\\]"
syn match p6Operator display "\%(:\@<!::\@!\|::=\|\.::\)"
" these require whitespace on the left side
syn match p6Operator display "\%(\s\|^\)\@<=\%(xx=\|p5=>\)"
" "i" requires a digit to the left, and no keyword char to the right
syn match p6Operator display "\d\@<=i\k\@!"
" index overloading
syn match p6Operator display "\%(&\.(\@=\|@\.\[\@=\|%\.{\@=\)"
" all infix operators except nonassocative ones
let s:infix_a = [
\ "div % mod +& +< +> \\~& ?& \\~< \\~> +| +\\^ \\~| \\~\\^ ?| ?\\^ xx x",
\ "\\~ && & also <== ==> <<== ==>> == != < <= > >= \\~\\~ eq ne lt le gt",
\ "ge =:= === eqv before after \\^\\^ min max \\^ff ff\\^ \\^ff\\^",
\ "\\^fff fff\\^ \\^fff\\^ fff ff ::= := \\.= => , : p5=> Z minmax",
\ "\\.\\.\\. and andthen or orelse xor \\^ += -= /= \\*= \\~= //= ||=",
\ "+ - \\*\\* \\* // / \\~ || |",
\ ]
" nonassociative infix operators
let s:infix_n = "but does <=> leg cmp \\.\\. \\.\\.\\^\\^ \\^\\.\\. \\^\\.\\.\\^"
let s:infix_a_long = join(s:infix_a, " ")
let s:infix_a_words = split(s:infix_a_long)
let s:infix_a_pattern = join(s:infix_a_words, "\\|")
let s:infix_n_words = split(s:infix_n)
let s:infix_n_pattern = join(s:infix_n_words, "\\|")
let s:both = [s:infix_a_pattern, s:infix_n_pattern]
let s:infix = join(s:both, "\\|")
let s:infix_assoc = "!\\?\\%(" . s:infix_a_pattern . "\\)"
let s:infix = "!\\?\\%(" . s:infix . "\\)"
unlet s:infix_a s:infix_a_long s:infix_a_words s:infix_a_pattern
unlet s:infix_n s:infix_n_pattern s:both
" [+] reduce
exec "syn match p6ReduceOp display \"\\k\\@<!\\[[R\\\\]\\?!\\?". s:infix_assoc ."]\\%(«\\|<<\\)\\?\""
unlet s:infix_assoc
" Reverse and cross operators (Rop, Xop)
exec "syn match p6ReverseCrossOp display \"[RX]". s:infix ."\""
" q() or whatever() is always a function call
syn match p6Normal display "\K\%(\k\|[-']\K\@=\)*(\@="
" basically all builtins that can be followed by parentheses
let s:routines = [
\ "eager hyper substr index rindex grep map sort join lines hints chmod",
\ "split reduce min max reverse truncate zip cat roundrobin classify",
\ "first sum keys values pairs defined delete exists elems end kv any",
\ "all one wrap shape key value name pop push shift splice unshift floor",
\ "ceiling abs exp log log10 rand sign sqrt sin cos tan round strand",
\ "roots cis unpolar polar atan2 pick chop p5chop chomp p5chomp lc",
\ "lcfirst uc ucfirst capitalize normalize pack unpack quotemeta comb",
\ "samecase sameaccent chars nfd nfc nfkd nfkc printf sprintf caller",
\ "evalfile run runinstead nothing want bless chr ord gmtime time eof",
\ "localtime gethost getpw chroot getlogin getpeername kill fork wait",
\ "perl graphs codes bytes clone print open read write readline say seek",
\ "close opendir readdir slurp pos fmt vec link unlink symlink uniq pair",
\ "asin atan sec cosec cotan asec acosec acotan sinh cosh tanh asinh",
\ "acos acosh atanh sech cosech cotanh sech acosech acotanh asech ok",
\ "plan_ok dies_ok lives_ok skip todo pass flunk force_todo use_ok isa_ok",
\ "diag is_deeply isnt like skip_rest unlike cmp_ok eval_dies_ok nok_error",
\ "eval_lives_ok approx is_approx throws_ok version_lt plan eval succ pred",
\ "times nonce once signature new connect operator undef undefine sleep",
\ "from to infix postfix prefix circumfix postcircumfix minmax lazy count",
\ "unwrap getc pi e context void quasi body each contains rewinddir subst",
\ "can isa flush arity assuming rewind callwith callsame nextwith nextsame",
\ "attr eval_elsewhere none srand trim trim_start trim_end lastcall WHAT",
\ "WHERE HOW WHICH VAR WHO WHENCE ACCEPTS REJECTS does not true iterator by",
\ "re im invert flip",
\ ]
" we want to highlight builtins like split() though, so this comes afterwards
" TODO: check if this would be faster as one big regex
let s:words_space = join(s:routines, " ")
let s:temp = split(s:words_space)
let s:words = join(s:temp, "\\|")
exec "syn match p6Routine ". s:before_keyword . s:words . s:after_keyword
unlet s:before_keyword s:after_keyword s:words_space s:temp s:words s:routines
" packages, must come after all the keywords
syn match p6Normal display "\%(::\)\@<=\K\%(\k\|[-']\K\@=\)*"
syn match p6Normal display "\K\%(\k\|[-']\K\@=\)*\%(::\)\@="
" some standard packages
syn match p6Type display "\%(::\|\k\|\K\@<=[-']\)\@<!\%(Order\%(::Same\|::Increase\|::Decrease\)\?\)\%(\k\|[-']\K\@=\)\@!"
syn match p6Type display "\%(::\|\k\|\K\@<=[-']\)\@<!\%(Bool\%(::True\|::False\)\?\)\%(\k\|[-']\K\@=\)\@!"
syn match p6Shebang display "\%^#!.*"
syn match p6BlockLabel display "\%(^\s*\)\@<=\h\w*\s*::\@!\_s\@="
syn match p6Number display "\k\@<!_\@!\%(\d\|__\@!\)\+_\@<!\%([eE]_\@!+\?\%(\d\|_\)\+\)\?_\@<!"
syn match p6Float display "\k\@<!_\@!\%(\d\|__\@!\)\+_\@<![eE]_\@!-\%(\d\|_\)\+"
syn match p6Float display "\k\@<!_\@<!\%(\d\|__\@!\)*_\@<!\.\@<!\._\@!\.\@!\a\@!\%(\d\|_\)\+_\@<!\%([eE]_\@!\%(\d\|_\)\+\)\?"
syn match p6NumberBase display "[obxd]" contained
syn match p6Number display "\<0\%(o[0-7][0-7_]*\)\@=" nextgroup=p6NumberBase
syn match p6Number display "\<0\%(b[01][01_]*\)\@=" nextgroup=p6NumberBase
syn match p6Number display "\<0\%(x\x[[:xdigit:]_]*\)\@=" nextgroup=p6NumberBase
syn match p6Number display "\<0\%(d\d[[:digit:]_]*\)\@=" nextgroup=p6NumberBase
syn match p6Number display "\%(\<0o\)\@<=[0-7][0-7_]*"
syn match p6Number display "\%(\<0b\)\@<=[01][01_]*"
syn match p6Number display "\%(\<0x\)\@<=\x[[:xdigit:]_]*"
syn match p6Number display "\%(\<0d\)\@<=\d[[:digit:]_]*"
syn match p6Version display "\<v\d\@=" nextgroup=p6VersionNum
syn match p6VersionNum display "\d\+" nextgroup=p6VersionDot contained
syn match p6VersionDot display "\.\%(\d\|\*\)\@=" nextgroup=p6VersionNum contained
" try to distinguish the "is" function from the "is" trail auxiliary
syn match p6Routine display "\%(\%(\S\k\@<!\|^\)\s*\)\@<=is\>"
" does is a type constraint sometimes
syn match p6TypeConstraint display "does\%(\s*\%(\k\|[-']\K\@=\)\)\@="
" int is a type sometimes
syn match p6Type display "\<int\>\%(\s*(\|\s\+\d\)\@!"
" these Routine names are also Properties, if preceded by "is"
syn match p6Property display "\%(is\s\+\)\@<=\%(signature\|context\|also\|shape\)"
" The sigil in ::*Package
syn match p6PackageTwigil display "\%(::\)\@<=\*"
" $<match>
syn region p6MatchVarSigil
\ matchgroup=p6Variable
\ start="\$\%(<<\@!\)\@="
\ end=">\@<="
\ contains=p6MatchVar
syn region p6MatchVar
\ matchgroup=p6Twigil
\ start="<"
\ end=">"
\ contained
" Contextualizers
syn match p6Context display "\<\%(item\|list\|slice\|hash\)\>"
syn match p6Context display "\%(\$\|@\|%\|&\|@@\)(\@="
" the "$" placeholder in "$var1, $, var2 = @list"
syn match p6Placeholder display "\%(,\s*\)\@<=\$\%(\K\|\%([.^*?=!~]\|:\@<!::\@!\)\)\@!"
syn match p6Placeholder display "\$\%(\K\|\%([.^*?=!~]\|:\@<!::\@!\)\)\@!\%(,\s*\)\@="
" Quoting
" one cluster for every quote adverb
syn cluster p6Interp_s
\ add=p6InterpScalar
syn cluster p6Interp_scalar
\ add=p6InterpScalar
syn cluster p6Interp_a
\ add=p6InterpArray
syn cluster p6Interp_array
\ add=p6InterpArray
syn cluster p6Interp_h
\ add=p6InterpHash
syn cluster p6Interp_hash
\ add=p6InterpHash
syn cluster p6Interp_f
\ add=p6InterpFunction
syn cluster p6Interp_f
\ add=p6InterpFunction
syn cluster p6Interp_c
\ add=p6InterpClosure
syn cluster p6Interp_closure
\ add=p6InterpClosure
if exists("perl6_extended_q") || exists("perl6_extended_all")
syn cluster p6Interp_ww
\ add=p6StringSQ
\ add=p6StringDQ
syn cluster p6Interp_quotewords
\ add=p6StringSQ
\ add=p6StringDQ
endif
syn cluster p6Interp_q
\ add=p6EscQQ
\ add=p6EscBackSlash
syn cluster p6Interp_single
\ add=p6EscQQ
\ add=p6EscBackSlash
syn cluster p6Interp_b
\ add=@p6Interp_q
\ add=p6Escape
\ add=p6EscOpenCurly
\ add=p6EscCodePoint
\ add=p6EscHex
\ add=p6EscOct
\ add=p6EscOctOld
\ add=p6EscNull
syn cluster p6Interp_backslash
\ add=@p6Interp_q
\ add=p6Escape
\ add=p6EscOpenCurly
\ add=p6EscCodePoint
\ add=p6EscHex
\ add=p6EscOct
\ add=p6EscOctOld
\ add=p6EscNull
syn cluster p6Interp_qq
\ add=@p6Interp_scalar
\ add=@p6Interp_array
\ add=@p6Interp_hash
\ add=@p6Interp_function
\ add=@p6Interp_closure
\ add=@p6Interp_backslash
syn cluster p6Interp_double
\ add=@p6Interp_scalar
\ add=@p6Interp_array
\ add=@p6Interp_hash
\ add=@p6Interp_function
\ add=@p6Interp_closure
\ add=@p6Interp_backslash
syn region p6InterpScalar
\ start="\ze\z(\$\%(\%(\%(\d\+\|!\|/\|¢\)\|\%(\%(\%([.^*?=!~]\|:\@<!::\@!\)\K\@=\)\?\K\%(\k\|[-']\K\@=\)*\)\%(\.\%(\K\%(\k\|[-']\K\@=\)*\)\|\%(([^)]*)\|\[[^\]]*]\|<[^>]*>\|«[^»]*»\|{[^}]*}\)\)*\)\.\?\%(([^)]*)\|\[[^\]]*]\|<[^>]*>\|«[^»]*»\|{[^}]*}\)\)\)"
\ start="\ze\z(\$\%(\%(\%(\%([.^*?=!~]\|:\@<!::\@!\)\K\@=\)\?\K\%(\k\|[-']\K\@=\)*\)\|\%(\d\+\|!\|/\|¢\)\)\)"
\ end="\z1\zs"
\ contained
\ contains=TOP
\ keepend
syn region p6InterpScalar
\ matchgroup=p6Context
\ start="\$\ze()\@!"
\ skip="([^)]*)"
\ end=")\zs"
\ contained
\ contains=TOP
syn region p6InterpArray
\ start="\ze\z(@\$*\%(\%(\%(!\|/\|¢\)\|\%(\%(\%([.^*?=!~]\|:\@<!::\@!\)\K\@=\)\?\K\%(\k\|[-']\K\@=\)*\)\%(\.\%(\K\%(\k\|[-']\K\@=\)*\)\|\%(([^)]*)\|\[[^\]]*]\|<[^>]*>\|«[^»]*»\|{[^}]*}\)\)*\)\.\?\%(([^)]*)\|\[[^\]]*]\|<[^>]*>\|«[^»]*»\|{[^}]*}\)\)\)"
\ end="\z1\zs"
\ contained
\ contains=TOP
\ keepend
syn region p6InterpArray
\ matchgroup=p6Context
\ start="@\ze()\@!"
\ start="@@\ze()\@!"
\ skip="([^)]*)"
\ end=")\zs"
\ contained
\ contains=TOP
syn region p6InterpHash
\ start="\ze\z(%\$*\%(\%(\%(!\|/\|¢\)\|\%(\%(\%([.^*?=!~]\|:\@<!::\@!\)\K\@=\)\?\K\%(\k\|[-']\K\@=\)*\)\%(\.\%(\K\%(\k\|[-']\K\@=\)*\)\|\%(([^)]*)\|\[[^\]]*]\|<[^>]*>\|«[^»]*»\|{[^}]*}\)\)*\)\.\?\%(([^)]*)\|\[[^\]]*]\|<[^>]*>\|«[^»]*»\|{[^}]*}\)\)\)"
\ end="\z1\zs"
\ contained
\ contains=TOP
\ keepend
syn region p6InterpHash
\ matchgroup=p6Context
\ start="%\ze()\@!"
\ skip="([^)]*)"
\ end=")\zs"
\ contained
\ contains=TOP
syn region p6InterpFunction
\ start="\ze\z(&\%(\%(!\|/\|¢\)\|\%(\%(\%([.^*?=!~]\|:\@<!::\@!\)\K\@=\)\?\K\%(\k\|[-']\K\@=\)*\%(\.\%(\K\%(\k\|[-']\K\@=\)*\)\|\%(([^)]*)\|\[[^\]]*]\|<[^>]*>\|«[^»]*»\|{[^}]*}\)\)*\)\.\?\%(([^)]*)\|\[[^\]]*]\|<[^>]*>\|«[^»]*»\|{[^}]*}\)\)\)"
\ end="\z1\zs"
\ contained
\ contains=TOP
\ keepend
syn region p6InterpFunction
\ matchgroup=p6Context
\ start="&\ze()\@!"
\ skip="([^)]*)"
\ end=")\zs"
\ contained
\ contains=TOP
syn region p6InterpClosure
\ start="\\\@<!{}\@!"
\ skip="{[^}]*}"
\ end="}"
\ contained
\ contains=TOP
\ keepend
" generic escape
syn match p6Escape display "\\\S" contained
" escaped closing delimiters
syn match p6EscQuote display "\\'" contained
syn match p6EscDoubleQuote display "\\\"" contained
syn match p6EscCloseAngle display "\\>" contained
syn match p6EscCloseFrench display "\\»" contained
syn match p6EscBackTick display "\\`" contained
syn match p6EscForwardSlash display "\\/" contained
syn match p6EscVerticalBar display "\\|" contained
syn match p6EscExclamation display "\\!" contained
syn match p6EscComma display "\\," contained
syn match p6EscDollar display "\\\$" contained
syn match p6EscCloseCurly display "\\}" contained
syn match p6EscCloseBracket display "\\\]" contained
" misc escapes
syn match p6EscOctOld display "\\\d\{1,3}" contained
syn match p6EscNull display "\\0\d\@!" contained
syn match p6EscCodePoint display "\%(\\c\)\@<=\%(\d\|\S\|\[\)\@=" contained nextgroup=p6CodePoint
syn match p6EscHex display "\%(\\x\)\@<=\%(\x\|\[\)\@=" contained nextgroup=p6HexSequence
syn match p6EscOct display "\%(\\o\)\@<=\%(\o\|\[\)\@=" contained nextgroup=p6OctSequence
syn match p6EscQQ display "\\qq" contained nextgroup=p6QQSequence
syn match p6EscOpenCurly display "\\{" contained
syn match p6EscHash display "\\#" contained
syn match p6EscBackSlash display "\\\\" contained
syn region p6QQSequence
\ matchgroup=p6Escape
\ start="\["
\ skip="\[[^\]]*]"
\ end="]"
\ contained
\ transparent
\ contains=@p6Interp_qq
syn match p6CodePoint display "\%(\d\+\|\S\)" contained
syn region p6CodePoint
\ matchgroup=p6Escape
\ start="\["
\ end="]"
\ contained
syn match p6HexSequence display "\x\+" contained
syn region p6HexSequence
\ matchgroup=p6Escape
\ start="\["
\ end="]"
\ contained
syn match p6OctSequence display "\o\+" contained
syn region p6OctSequence
\ matchgroup=p6Escape
\ start="\["
\ end="]"
\ contained
" matches :key, :!key, :$var, :key<var>, etc
" Since we don't know in advance how the adverb ends, we use a trick.
" Consume nothing with the start pattern (\ze at the beginning),
" while capturing the whole adverb into \z1 and then putting it before
" the match start (\zs) of the end pattern.
syn region p6Adverb
\ start="\ze\z(:!\?\K\%(\k\|[-']\K\@=\)*\%(([^)]*)\|\[[^\]]*]\|<[^>]*>\|«[^»]*»\|{[^}]*}\)\?\)"
\ start="\ze\z(:!\?[@$%]\$*\%(::\|\%(\$\@<=\d\+\|!\|/\|¢\)\|\%(\%([.^*?=!~]\|:\@<!::\@!\)\K\)\|\%(\K\%(\k\|[-']\K\@=\)*\)\)\)"
\ end="\z1\zs"
\ contained
\ contains=TOP
\ keepend
" <words>
" FIXME: not sure how to distinguish this from the "less than" operator
" in all cases. For now, it matches if any of the following is true:
"
" * There is whitespace missing on either side of the "<", since
" people tend to put spaces around "less than"
" * It comes after "enum", "for", "any", "all", or "none"
" * It's the first or last thing on a line (ignoring whitespace)
" * It's preceded by "= "
"
" It never matches when:
"
" * Preceded by [<+~=] (e.g. <<foo>>, =<$foo>)
" * Followed by [-=] (e.g. <--, <=, <==)
syn region p6StringAngle
\ matchgroup=p6Quote
\ start="\%(\<\%(enum\|for\|any\|all\|none\)\>\s*(\?\s*\)\@<=<\%(<\|=>\|[-=]\{1,2}>\@!\)\@!"
\ start="\%(\s\|[<+~=]\)\@<!<\%(<\|=>\|[-=]\{1,2}>\@!\)\@!"
\ start="[<+~=]\@<!<\%(\s\|<\|=>\|[-=]\{1,2}>\@!\)\@!"
\ start="\%(^\s*\)\@<=<\%(<\|=>\|[-=]\{1,2}>\@!\)\@!"
\ start="[<+~=]\@<!<\%(\s*$\)\@="
\ start="\%(=\s\+\)\@=<\%(<\|=>\|[-=]\{1,2}>\@!\)\@!"
\ skip="\\\@<!\\>"
\ end=">"
\ contains=p6InnerAnglesOne,p6EscBackSlash,p6EscCloseAngle
syn region p6InnerAnglesOne
\ matchgroup=p6StringAngle
\ start="<"
\ skip="\\\@<!\\>"
\ end=">"
\ transparent
\ contained
\ contains=p6InnerAnglesOne
" <<words>>
syn region p6StringAngles
\ matchgroup=p6Quote
\ start="<<=\@!"
\ skip="\\\@<!\\>"
\ end=">>"
\ contains=p6InnerAnglesTwo,@p6Interp_qq,p6Comment,p6EscHash,p6EscCloseAngle,p6Adverb,p6StringSQ,p6StringDQ
syn region p6InnerAnglesTwo
\ matchgroup=p6StringAngles
\ start="<<"
\ skip="\\\@<!\\>"
\ end=">>"
\ transparent
\ contained
\ contains=p6InnerAnglesTwo
" «words»
syn region p6StringFrench
\ matchgroup=p6Quote
\ start="«"
\ skip="\\\@<!\\»"
\ end="»"
\ contains=p6InnerFrench,@p6Interp_qq,p6Comment,p6EscHash,p6EscCloseFrench,p6Adverb,p6StringSQ,p6StringDQ
syn region p6InnerFrench
\ matchgroup=p6StringFrench
\ start="«"
\ skip="\\\@<!\\»"
\ end="»"
\ transparent
\ contained
\ contains=p6InnerFrench
" 'string'
syn region p6StringSQ
\ matchgroup=p6Quote
\ start="'"
\ skip="\\\@<!\\'"
\ end="'"
\ contains=@p6Interp_q,p6EscQuote
" "string"
syn region p6StringDQ
\ matchgroup=p6Quote
\ start=+"+
\ skip=+\\\@<!\\"+
\ end=+"+
\ contains=@p6Interp_qq,p6EscDoubleQuote
" Q// and friends.
syn match p6QuoteQ display "\%([Qq]\%(ww\|to\|[qwxsahfcb]\)\?\)\>" nextgroup=p6QPairs skipwhite skipempty
syn match p6QPairs contained transparent skipwhite skipempty nextgroup=p6StringQ,p6StringQ_PIR "\%(\_s*:!\?\K\%(\k\|[-']\K\@=\)*\%(([^)]*)\|\[[^\]]*]\|<[^>]*>\|«[^»]*»\|{[^}]*}\)\?\)*"
if exists("perl6_embedded_pir")
syn include @p6PIR syntax/pir.vim
endif
" hardcoded set of delimiters
let s:delims = [
\ ["\\\"", "\\\"", "p6EscDoubleQuote", "\\\\\\@<!\\\\\\\""],
\ ["'", "'", "p6EscQuote", "\\\\\\@<!\\\\'"],
\ ["/", "/", "p6EscForwardSlash", "\\\\\\@<!\\\\/"],
\ ["`", "`", "p6EscBackTick", "\\\\\\@<!\\\\`"],
\ ["|", "|", "p6EscVerticalBar", "\\\\\\@<!\\\\|"],
\ ["!", "!", "p6EscExclamation", "\\\\\\@<!\\\\!"],
\ [",", ",", "p6EscComma", "\\\\\\@<!\\\\,"],
\ ["\\$", "\\$", "p6EscDollar", "\\\\\\@<!\\\\\\$"],
\ ["{", "}", "p6EscCloseCurly", "\\%(\\\\\\@<!\\\\}\\|{[^}]*}\\)"],
\ ["<", ">", "p6EscCloseAngle", "\\%(\\\\\\@<!\\\\>\\|<[^>]*>\\)"],
\ ["«", "»", "p6EscCloseFrench", "\\%(\\\\\\@<!\\\\»\\|«[^»]*»\\)"],
\ ["\\\[", "]", "p6EscCloseBracket", "\\%(\\\\\\@<!\\\\]\\|\\[^\\]]*]\\)"],
\ ["\\s\\@<=(", ")", "p6EscCloseParen", "\\%(\\\\\\@<!\\\\)\\|([^)]*)\\)"],
\ ]
" double and triple delimiters too
if exists("perl6_extended_q") || exists("perl6_extended_all")
call add(s:delims, ["««", "»»", "p6EscCloseFrench", "\\%(\\\\\\@<!\\\\»»\\|««\\%([^»]\\|»»\\@!\\)*»»\\)"])
call add(s:delims, ["«««", "»»»", "p6EscCloseFrench", "\\%(\\\\\\@<!\\\\»»»\\|«««\\%([^»]\\|»\\%(»»\\)\\@!\\)*»»»\\)"])
call add(s:delims, ["{{", "}}", "p6EscCloseCurly", "\\%(\\\\\\@<!\\\\}}\\|{{\\%([^}]\\|}}\\@!\\)*}}\\)"])
call add(s:delims, ["{{{", "}}}", "p6EscCloseCurly", "\\%(\\\\\\@<!\\\\}}}\\|{{{\\%([^}]\\|}\\%(}}\\)\\@!\\)*}}}\\)"])
call add(s:delims, ["\\\[\\\[", "]]", "p6EscCloseBracket", "\\%(\\\\\\@<!\\\\]]\\|\\[\\[\\%([^\\]]\\|]]\\@!\\)*]]\\)"])
call add(s:delims, ["\\\[\\\[\\\[", "]]]", "p6EscCloseBracket", "\\%(\\\\\\@<!\\\\]]]\\|\\[\\[\\[\\%([^\\]]\\|]\\%(]]\\)\\@!\\)*]]]\\)"])
call add(s:delims, ["\\s\\@<=((", "))", "p6EscCloseParen", "\\%(\\\\\\@<!\\\\))\\|((\\%([^)]\\|))\\@!\\)*))\\)"])
call add(s:delims, ["\\s\\@<=(((", ")))", "p6EscCloseParen", "\\%(\\\\\\@<!\\\\)))\\|(((\\%([^)]\\|)\\%())\\)\\@!\\)*)))\\)"])
call add(s:delims, ["\\s\\@<=<<", ">>", "p6EscCloseAngle", "\\%(\\\\\\@<!\\\\>>\\|<<\\%([^>]\\|>>\\@!\\)*>>\\)"])
call add(s:delims, ["\\s\\@<=<<<", ">>>", "p6EscCloseAngle", "\\%(\\\\\\@<!\\\\>>>\\|<<<\\%([^>]\\|>\\%(>>\\)\\@!\\)*>>>\\)"])
endif
if !exists("perl6_extended_q") && !exists("perl6_extended_all")
" simple version, no special highlighting within the string
for [start_delim, end_delim, end_group, skip] in s:delims
exec "syn region p6StringQ matchgroup=p6Quote start=\"".start_delim."\" skip=\"".skip."\" end=\"".end_delim."\" contains=".end_group." contained"
endfor
if exists("perl6_embedded_pir")
" highlight embedded PIR code
for [start_delim, end_delim, end_group, skip] in s:delims
exec "syn region p6StringQ_PIR matchgroup=p6Quote start=\"\\%(Q\\s*:PIR\\s*\\)\\@<=".start_delim."\" skip=\"".skip."\" end=\"".end_delim."\" contains=@p6PIR,".end_group." contained"
endfor
endif
else
let s:before = "syn region p6StringQ matchgroup=p6Quote start=\"\\%("
let s:after = "\\%(\\_s*:!\\?\\K\\%(\\k\\|[-']\\K\\@=\\)*\\%(([^)]*)\\|\\[[^\\]]*]\\|<[^>]*>\\|«[^»]*»\\|{[^}]*}\\)\\?\\)*\\_s*\\)\\@<="
let s:adverbs = [
\ ["s", "scalar"],
\ ["a", "array"],
\ ["h", "hash"],
\ ["f", "function"],
\ ["c", "closure"],
\ ["b", "backslash"],
\ ["w", "words"],
\ ["ww", "quotewords"],
\ ["x", "exec"],
\ ]
" these can't be conjoined with q and qq (e.g. as qqq and qqqq)
let s:q_adverbs = [
\ ["q", "single"],
\ ["qq", "double"],
\ ]
for [start_delim, end_delim, end_group, skip] in s:delims
" Q, q, and qq with any number of (ignored) adverbs
exec s:before ."Q". s:after .start_delim."\" end=\"". end_delim ."\""." contained"
exec s:before ."q". s:after .start_delim ."\" skip=\"". skip ."\" end=\"". end_delim ."\" contains=". end_group .",@p6Interp_q"." contained"
exec s:before ."qq". s:after .start_delim ."\" skip=\"". skip ."\" end=\"". end_delim ."\" contains=". end_group .",@p6Interp_qq"." contained"
for [short, long] in s:adverbs
" Qs, qs, qqs, Qa, qa, qqa, etc, with ignored adverbs
exec s:before ."Q".short. s:after .start_delim ."\" end=\"". end_delim ."\" contains=@p6Interp_".long." contained"
exec s:before ."q".short. s:after .start_delim ."\" skip=\"". skip ."\" end=\"". end_delim ."\" contains=". end_group .",@p6Interp_q,@p6Interp_".long." contained"
exec s:before ."qq".short. s:after .start_delim ."\" skip=\"". skip ."\" end=\"". end_delim ."\" contains=". end_group .",@p6Interp_qq,@p6Interp_".long." contained"
" Q, q, and qq, with one significant adverb
exec s:before ."Q\\s*:\\%(".short."\\|".long."\\)". s:after .start_delim ."\" end=\"". end_delim ."\" contains=@p6Interp_".long." contained"
for [q_short, q_long] in s:q_adverbs
exec s:before ."Q\\s*:\\%(".q_short."\\|".q_long."\\)". s:after .start_delim ."\" end=\"". end_delim ."\" contains=@p6Interp_".q_long." contained"
endfor
exec s:before ."q\\s*:\\%(".short."\\|".long."\\)". s:after .start_delim ."\" skip=\"". skip ."\" end=\"". end_delim ."\" contains=". end_group .",@p6Interp_q,@p6Interp_".long." contained"
exec s:before ."qq\\s*:\\%(".short."\\|".long."\\)". s:after .start_delim ."\" skip=\"". skip ."\" end=\"". end_delim ."\" contains=". end_group .",@p6Interp_qq,@p6Interp_".long." contained"
for [short2, long2] in s:adverbs
" Qs, qs, qqs, Qa, qa, qqa, etc, with one significant adverb
exec s:before ."Q".short."\\s*:\\%(".short2."\\|".long2."\\)". s:after .start_delim ."\" end=\"". end_delim ."\" contains=@p6Interp_".long.",@p6Interp_".long2." contained"
for [q_short2, q_long2] in s:q_adverbs
exec s:before ."Q".short."\\s*:\\%(".q_short2."\\|".q_long2."\\)". s:after .start_delim ."\" end=\"". end_delim ."\" contains=@p6Interp_".long.",@p6Interp_".q_long2." contained"
endfor
exec s:before ."q".short."\\s*:\\%(".short2."\\|".long2."\\)". s:after .start_delim ."\" skip=\"". skip ."\" end=\"". end_delim ."\" contains=". end_group .",@p6Interp_q,@p6Interp_".long.",@p6Interp_".long2." contained"
exec s:before ."qq".short."\\s*:\\%(".short2."\\|".long2."\\)". s:after .start_delim ."\" skip=\"". skip ."\" end=\"". end_delim ."\" contains=". end_group .",@p6Interp_qq,@p6Interp_".long.",@p6Interp_".long2." contained"
endfor
endfor
endfor
unlet s:before s:after s:adverbs s:q_adverbs
endif
unlet s:delims
" Match these so something else above can't. E.g. the "q" in "role q { }"
" should not be considered a string
syn match p6Normal display "\%(\<\%(role\|grammar\|slang\)\s\+\)\@<=\K\%(\k\|[-']\K\@=\)*"
" :key
syn match p6Operator display ":\@<!::\@!!\?" nextgroup=p6Key
syn match p6Key display "\k\%(\k\|[-']\K\@=\)*" contained
" => and p5=> autoquoting
syn match p6StringP5Auto display "\K\%(\k\|[-']\K\@=\)*\ze\s\+p5=>"
syn match p6StringAuto display "\K\%(\k\|[-']\K\@=\)*\ze\%(p5\)\@<!=>"
syn match p6StringAuto display "\K\%(\k\|[-']\K\@=\)*\ze\s\+=>"
syn match p6StringAuto display "\K\%(\k\|[-']\K\@=\)*p5\ze=>"
" Hyperoperators. Needs to come after the quoting operators (<>, «», etc)
exec "syn match p6HyperOp display \"»" .s:infix."»\\?\""
exec "syn match p6HyperOp display \"«\\?".s:infix."«\""
exec "syn match p6HyperOp display \"»" .s:infix."«\""
exec "syn match p6HyperOp display \"«" .s:infix. "»\""
exec "syn match p6HyperOp display \">>" .s:infix."\\%(>>\\)\\?\""
exec "syn match p6HyperOp display \"\\%(<<\\)\\?".s:infix."<<\""
exec "syn match p6HyperOp display \">>" .s:infix."<<\""
exec "syn match p6HyperOp display \"<<" .s:infix.">>\""
unlet s:infix
" Regexes and grammars
syn match p6RegexName display "\%(\<\%(regex\|rule\|token\)\s\+\)\@<=\K\%(\k\|[-']\K\@=\)*" nextgroup=p6RegexBlockCrap skipwhite skipempty
syn match p6RegexBlockCrap "[^{]*" nextgroup=p6RegexBlock skipwhite skipempty transparent contained
syn region p6RegexBlock
\ matchgroup=p6Normal
\ start="{"
\ end="}"
\ contained
\ contains=@p6Regexen,@p6Variables
" Perl 6 regex bits
syn cluster p6Regexen
\ add=p6RxMeta
\ add=p6RxEscape
\ add=p6EscHex
\ add=p6EscOct
\ add=p6EscNull
\ add=p6RxAnchor
\ add=p6RxCapture
\ add=p6RxGroup
\ add=p6RxAlternation
\ add=p6RxAdverb
\ add=p6RxAdverbArg
\ add=p6RxStorage
\ add=p6RxAssertion
\ add=p6RxQuoteWords
\ add=p6RxClosure
\ add=p6RxStringSQ
\ add=p6RxStringDQ
\ add=p6Comment
syn match p6RxMeta display contained ".\%(\k\|\s\)\@<!"
syn match p6RxAnchor display contained "[$^]"
syn match p6RxEscape display contained "\\\S"
syn match p6RxCapture display contained "[()]"
syn match p6RxAlternation display contained "|"
syn match p6RxRange display contained "\.\."
syn region p6RxClosure
\ matchgroup=p6Normal
\ start="{"
\ end="}"
\ contained
\ containedin=p6RxClosure
\ contains=TOP
syn region p6RxGroup
\ matchgroup=p6StringSpecial2
\ start="\["
\ end="]"
\ contained
\ contains=@p6Regexen,@p6Variables
syn region p6RxAssertion
\ matchgroup=p6StringSpecial2
\ start="<"
\ end=">"
\ contained
\ contains=@p6Regexen,@p6Variables,p6RxCharClass,p6RxAssertCall
syn region p6RxAssertCall
\ matchgroup=p6Normal
\ start="\%(::\|\%(\K\%(\k\|[-']\K\@=\)*\)\)\@<=(\@="
\ end=")\@<="
\ contained
\ contains=TOP
syn region p6RxCharClass
\ matchgroup=p6StringSpecial2
\ start="\%(<[-!+?]\?\)\@<=\["
\ skip="\\]"
\ end="]"
\ contained
\ contains=p6RxRange,p6RxEscape,p6EscHex,p6EscOct,p6EscNull
syn region p6RxQuoteWords
\ matchgroup=p6StringSpecial2
\ start="< "
\ end=">"
\ contained
syn region p6RxAdverb
\ start="\ze\z(:!\?\K\%(\k\|[-']\K\@=\)*\)"
\ end="\z1\zs"
\ contained
\ contains=TOP
\ keepend
syn region p6RxAdverbArg
\ start="\%(:!\?\K\%(\k\|[-']\K\@=\)*\)\@<=("
\ skip="([^)]*)"
\ end=")"
\ contained
\ contains=TOP
syn region p6RxStorage
\ matchgroup=p6Operator
\ start="\%(^\s*\)\@<=:\%(my\>\|temp\>\)\@="
\ end="$"
\ contains=TOP
\ contained
" Perl 5 regex bits
syn cluster p6RegexP5Base
\ add=p6RxP5Escape
\ add=p6RxP5Oct
\ add=p6RxP5Hex
\ add=p6RxP5EscMeta
\ add=p6RxP5CodePoint
\ add=p6RxP5Prop
" normal regex stuff
syn cluster p6RegexP5
\ add=@p6RegexP5Base
\ add=p6RxP5Quantifier
\ add=p6RxP5Meta
\ add=p6RxP5QuoteMeta
\ add=p6RxP5ParenMod
\ add=p6RxP5Verb
\ add=p6RxP5Count
\ add=p6RxP5Named
\ add=p6RxP5ReadRef
\ add=p6RxP5WriteRef
\ add=p6RxP5CharClass
\ add=p6RxP5Anchor
" inside character classes
syn cluster p6RegexP5Class
\ add=@p6RegexP5Base
\ add=p6RxP5Posix
\ add=p6RxP5Range
syn match p6RxP5Escape display contained "\\\S"
syn match p6RxP5CodePoint display contained "\\c\S\@=" nextgroup=p6RxP5CPId
syn match p6RxP5CPId display contained "\S"
syn match p6RxP5Oct display contained "\\\%(\o\{1,3}\)\@=" nextgroup=p6RxP5OctSeq
syn match p6RxP5OctSeq display contained "\o\{1,3}"
syn match p6RxP5Anchor display contained "[\^$]"
syn match p6RxP5Hex display contained "\\x\%({\x\+}\|\x\{1,2}\)\@=" nextgroup=p6RxP5HexSeq
syn match p6RxP5HexSeq display contained "\x\{1,2}"
syn region p6RxP5HexSeq
\ matchgroup=p6RxP5Escape
\ start="{"
\ end="}"
\ contained
syn region p6RxP5Named
\ matchgroup=p6RxP5Escape
\ start="\%(\\N\)\@<={"
\ end="}"
\ contained
syn match p6RxP5Quantifier display contained "\%([+*]\|(\@<!?\)"
syn match p6RxP5ReadRef display contained "\\[1-9]\d\@!"
syn match p6RxP5ReadRef display contained "\\k<\@=" nextgroup=p6RxP5ReadRefId
syn region p6RxP5ReadRefId
\ matchgroup=p6RxP5Escape
\ start="<"
\ end=">"
\ contained
syn match p6RxP5WriteRef display contained "\\g\%(\d\|{\)\@=" nextgroup=p6RxP5WriteRefId
syn match p6RxP5WriteRefId display contained "\d\+"
syn region p6RxP5WriteRefId
\ matchgroup=p6RxP5Escape
\ start="{"
\ end="}"
\ contained
syn match p6RxP5Prop display contained "\\[pP]\%(\a\|{\)\@=" nextgroup=p6RxP5PropId
syn match p6RxP5PropId display contained "\a"
syn region p6RxP5PropId
\ matchgroup=p6RxP5Escape
\ start="{"
\ end="}"
\ contained
syn match p6RxP5Meta display contained "[(|).]"
syn match p6RxP5ParenMod display contained "(\@<=?\@=" nextgroup=p6RxP5Mod,p6RxP5ModName,p6RxP5Code
syn match p6RxP5Mod display contained "?\%(<\?=\|<\?!\|[#:|]\)"
syn match p6RxP5Mod display contained "?-\?[impsx]\+"
syn match p6RxP5Mod display contained "?\%([-+]\?\d\+\|R\)"
syn match p6RxP5Mod display contained "?(DEFINE)"
syn match p6RxP5Mod display contained "?\%(&\|P[>=]\)" nextgroup=p6RxP5ModDef
syn match p6RxP5ModDef display contained "\h\w*"
syn region p6RxP5ModName
\ matchgroup=p6StringSpecial
\ start="?'"
\ end="'"
\ contained
syn region p6RxP5ModName
\ matchgroup=p6StringSpecial
\ start="?P\?<"
\ end=">"
\ contained
syn region p6RxP5Code
\ matchgroup=p6StringSpecial
\ start="??\?{"
\ end="})\@="
\ contained
\ contains=TOP
syn match p6RxP5EscMeta display contained "\\[?*.{}()[\]|\^$]"
syn match p6RxP5Count display contained "\%({\d\+\%(,\%(\d\+\)\?\)\?}\)\@=" nextgroup=p6RxP5CountId
syn region p6RxP5CountId
\ matchgroup=p6RxP5Escape
\ start="{"
\ end="}"
\ contained
syn match p6RxP5Verb display contained "(\@<=\*\%(\%(PRUNE\|SKIP\|THEN\)\%(:[^)]*\)\?\|\%(MARK\|\):[^)]*\|COMMIT\|F\%(AIL\)\?\|ACCEPT\)"
syn region p6RxP5QuoteMeta
\ matchgroup=p6RxP5Escape
\ start="\\Q"
\ end="\\E"
\ contained
\ contains=@p6Variables,p6EscBackSlash
syn region p6RxP5CharClass
\ matchgroup=p6StringSpecial
\ start="\[\^\?"
\ skip="\\]"
\ end="]"
\ contained
\ contains=@p6RegexP5Class
syn region p6RxP5Posix
\ matchgroup=p6RxP5Escape
\ start="\[:"
\ end=":]"
\ contained
syn match p6RxP5Range display contained "-"
" 'string' inside a regex
syn region p6RxStringSQ
\ matchgroup=p6Quote
\ start="'"
\ skip="\\\@<!\\'"
\ end="'"
\ contained
\ contains=p6EscQuote,p6EscBackSlash
" "string" inside a regex
syn region p6RxStringDQ
\ matchgroup=p6Quote
\ start=+"+
\ skip=+\\\@<!\\"+
\ end=+"+
\ contained
\ contains=p6EscDoubleQuote,p6EscBackSlash
" $!, $var, $!var, $::var, $package::var $*::package::var, etc
" Thus must come after the matches for the "$" regex anchor, but before