Skip to content

Commit 17aa8e9

Browse files
deathaxemitranim
authored andcommitted
[Perl] Fix single-quoted escapes (sublimehq#2406)
* [Perl] Fix single-quoted escapes Fixes sublimehq#2398 Only the closing characters of a single quoted string and the corresponding q// functions may be escaped. All other characters are interpreted as is. * [Perl] Hardening the fix for single-quoted escapes The backslash may be escaped as well. Need to handle it to keep string quotes balanced.
1 parent f09b3c7 commit 17aa8e9

File tree

2 files changed

+107
-40
lines changed

2 files changed

+107
-40
lines changed

Perl/Perl.sublime-syntax

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,8 @@ contexts:
791791
- match: \'
792792
scope: punctuation.definition.string.end.perl
793793
pop: true
794+
- match: \\[\\']
795+
scope: constant.character.escape.perl
794796
- include: literal-common
795797

796798
string-format:
@@ -1418,6 +1420,8 @@ contexts:
14181420
- include: interpolated-common
14191421

14201422
interpolated-common:
1423+
- match: \\.
1424+
scope: constant.character.escape.perl
14211425
- include: literal-common
14221426
- include: variables-interpolation
14231427

@@ -1430,16 +1434,20 @@ contexts:
14301434
- match: \}
14311435
scope: punctuation.section.braces.end.perl
14321436
pop: true
1433-
- include: literal-braces-nested
1434-
- include: literal-common
1437+
- include: literal-braces-common
14351438

14361439
literal-braces-nested:
14371440
- match: \{
14381441
push:
14391442
- match: \}
14401443
pop: true
1441-
- include: literal-braces-nested
1442-
- include: literal-common
1444+
- include: literal-braces-common
1445+
1446+
literal-braces-common:
1447+
- match: \\[\\\}]
1448+
scope: constant.character.escape.perl
1449+
- include: literal-braces-nested
1450+
- include: literal-common
14431451

14441452
literal-brackets-pop:
14451453
- match: \[
@@ -1450,16 +1458,20 @@ contexts:
14501458
- match: \]
14511459
scope: punctuation.section.brackets.end.perl
14521460
pop: true
1453-
- include: literal-brackets-nested
1454-
- include: literal-common
1461+
- include: literal-brackets-common
14551462

14561463
literal-brackets-nested:
14571464
- match: \[
14581465
push:
14591466
- match: \]
14601467
pop: true
1461-
- include: literal-brackets-nested
1462-
- include: literal-common
1468+
- include: literal-brackets-common
1469+
1470+
literal-brackets-common:
1471+
- match: \\[\\\]]
1472+
scope: constant.character.escape.perl
1473+
- include: literal-brackets-nested
1474+
- include: literal-common
14631475

14641476
literal-angle-pop:
14651477
- match: \<
@@ -1470,16 +1482,20 @@ contexts:
14701482
- match: \>
14711483
scope: punctuation.section.generic.end.perl
14721484
pop: true
1473-
- include: literal-angle-nested
1474-
- include: literal-common
1485+
- include: literal-angle-common
14751486

14761487
literal-angle-nested:
14771488
- match: \<
14781489
push:
14791490
- match: \>
14801491
pop: true
1481-
- include: literal-angle-nested
1482-
- include: literal-common
1492+
- include: literal-angle-common
1493+
1494+
literal-angle-common:
1495+
- match: \\[\\\>]
1496+
scope: constant.character.escape.perl
1497+
- include: literal-angle-nested
1498+
- include: literal-common
14831499

14841500
literal-parens-pop:
14851501
- match: \(
@@ -1490,31 +1506,38 @@ contexts:
14901506
- match: \)
14911507
scope: punctuation.section.parens.end.perl
14921508
pop: true
1493-
- include: literal-parens-nested
1494-
- include: literal-common
1509+
- include: literal-parens-common
14951510

14961511
literal-parens-nested:
14971512
- match: \(
14981513
push:
14991514
- match: \)
15001515
pop: true
1501-
- include: literal-parens-nested
1502-
- include: literal-common
1516+
- include: literal-parens-common
1517+
1518+
literal-parens-common:
1519+
- match: \\[\\\)]
1520+
scope: constant.character.escape.perl
1521+
- include: literal-parens-nested
1522+
- include: literal-common
15031523

15041524
literal-generic-pop:
15051525
- match: ({{regexp_delim}})
15061526
scope: punctuation.section.generic.begin.perl
15071527
set:
15081528
- meta_scope: meta.generic.perl
15091529
- meta_content_scope: meta.string.perl string.unquoted.perl
1510-
- match: \1
1530+
# Need a lookbehind here to avoid popping on escaped end-of-string token
1531+
# as a normal `\\\1` rule fails to run. As backrefs use oniguruma anyway
1532+
# it shouldn't hurt performance much.
1533+
- match: '{{no_escape_behind}}\1'
15111534
scope: punctuation.section.generic.end.perl
15121535
pop: true
15131536
- include: literal-common
15141537

15151538
literal-common:
15161539
# SEE: https://perldoc.perl.org/functions/sprintf.html
1517-
- match: '%%|\\.'
1540+
- match: '%%'
15181541
scope: constant.character.escape.perl
15191542
- match: |-
15201543
(?x:

Perl/syntax_test_perl.pl

Lines changed: 66 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,24 +1485,34 @@ =head1 B<--param>
14851485
# ^ meta.string.perl string.quoted.angle.perl
14861486
# ^ meta.string.perl string.quoted.angle.perl punctuation.definition.string.end.perl
14871487
# ^ - meta.string - string
1488-
"quoted \"interpolated\" foo 'bar' $baz $"
1488+
"quoted \"interpolated\" \foo 'bar' $baz $"
14891489
# ^ punctuation.definition.string.begin.perl
1490-
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.perl string.quoted.double.perl - meta.interpolation
1491-
# ^^^^ meta.string.perl meta.interpolation.perl - string
1492-
# ^^^ meta.string.perl string.quoted.double.perl - meta.interpolation
1490+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.perl string.quoted.double.perl - meta.interpolation
1491+
# ^^^^ meta.string.perl meta.interpolation.perl - string
1492+
# ^^^ meta.string.perl string.quoted.double.perl - meta.interpolation
14931493
# ^^ constant.character.escape.perl
14941494
# ^^ constant.character.escape.perl
1495-
# ^^^^ variable.other.readwrite.perl
1496-
# ^ - variable
1497-
# ^ punctuation.definition.string.end.perl
1498-
'quoted "interpolated" foo \'bar\' $baz $'
1495+
# ^^ constant.character.escape.perl
1496+
# ^^^^ variable.other.readwrite.perl
1497+
# ^ - variable
1498+
# ^ punctuation.definition.string.end.perl
1499+
'quoted "interpolated" \foo \'bar\' $baz $'
14991500
# ^ punctuation.definition.string.begin.perl
1500-
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.perl string.quoted.single.perl
1501-
# ^^ constant.character.escape.perl
1502-
# ^^ constant.character.escape.perl
1503-
# ^^^^ - variable
1504-
# ^ - variable
1505-
# ^ punctuation.definition.string.end.perl
1501+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.perl string.quoted.single.perl
1502+
# ^^ - constant.character.escape
1503+
# ^^ constant.character.escape.perl
1504+
# ^^ constant.character.escape.perl
1505+
# ^^^^ - variable
1506+
# ^ - variable
1507+
# ^ punctuation.definition.string.end.perl
1508+
'foo \' foo\\\' bar\\\\'
1509+
# ^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.perl string.quoted.single.perl
1510+
# ^ punctuation.definition.string.begin.perl
1511+
# ^^ constant.character.escape.perl
1512+
# ^^^^ constant.character.escape.perl
1513+
# ^^^^ constant.character.escape.perl
1514+
# ^ punctuation.definition.string.end.perl
1515+
# ^ - meta.string - string
15061516
`quoted "interpolated" foo \`bar\` $baz $`
15071517
# ^ punctuation.definition.string.begin.perl
15081518
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.perl string.quoted.backtick.perl - meta.interpolation
@@ -1543,22 +1553,29 @@ =head1 B<--param>
15431553
# ^ - variable
15441554
# ^ punctuation.definition.string.end.perl
15451555
# ^ keyword.operator.comparison.perl
1556+
# Note: The \/ can't be highlighted as escaped due to ST backref limitations.
15461557
q/quoted "interpolated" foo 'bar' \/ $baz/
15471558
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.perl
15481559
# ^ support.function.perl
15491560
# ^ punctuation.section.generic.begin.perl - string
15501561
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.perl string.unquoted.perl - meta.interpolation
1551-
# ^^ constant.character.escape.perl
15521562
# ^^^^ - variable
15531563
# ^ punctuation.section.generic.end.perl - string
1554-
q\quoted "interpolated" foo 'bar' / $baz\
1555-
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.perl
1564+
q/foo \/ foo\\\/ bar\\\\/
1565+
# ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.perl
15561566
# ^ support.function.perl
15571567
# ^ punctuation.section.generic.begin.perl - string
1558-
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.unquoted.perl
1559-
# ^^^^ - variable
1560-
# ^ punctuation.section.generic.end.perl - string
1561-
q{quoted "interpolated" {foo} 'bar' \/ $baz}
1568+
# ^ punctuation.section.generic.end.perl - meta.string - string
1569+
q\quoted "interpolated" foo 'bar' \\ $baz\
1570+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.perl
1571+
# ^ support.function.perl
1572+
# ^ punctuation.section.generic.begin.perl - string
1573+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.unquoted.perl
1574+
# ^ punctuation.section.generic.end.perl - string
1575+
# ^ keyword.operator.reference.perl
1576+
# ^^^^ variable.other.readwrite.perl
1577+
# ^ keyword.operator.reference.perl
1578+
q{quoted "interpolated" {foo} 'bar' \} $baz}
15621579
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.perl
15631580
# ^ support.function.perl
15641581
# ^ punctuation.section.braces.begin.perl - string
@@ -1576,6 +1593,15 @@ =head1 B<--param>
15761593
# ^^ constant.character.escape.perl
15771594
# ^^^^ - variable
15781595
# ^ punctuation.section.brackets.end.perl - string
1596+
q[foo \] foo\\\] bar\\\\]
1597+
# ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.perl
1598+
# ^ support.function.perl
1599+
# ^ punctuation.section.brackets.begin.perl - string
1600+
# ^^ constant.character.escape.perl
1601+
# ^^^^ constant.character.escape.perl
1602+
# ^^^^ constant.character.escape.perl
1603+
# ^ punctuation.section.brackets.end.perl
1604+
# ^ - meta.string - string
15791605
q<quoted "interpolated" <foo> 'bar' \> $baz>
15801606
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.perl
15811607
# ^ support.function.perl
@@ -1585,7 +1611,16 @@ =head1 B<--param>
15851611
# ^^ constant.character.escape.perl
15861612
# ^^^^ - variable
15871613
# ^ punctuation.section.generic.end.perl - string
1588-
q(quoted "interpolated" [foo] 'bar' \] $baz)
1614+
q<foo \> foo\\\> bar\\\\>
1615+
# ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.perl
1616+
# ^ support.function.perl
1617+
# ^ punctuation.section.generic.begin.perl - string
1618+
# ^^ constant.character.escape.perl
1619+
# ^^^^ constant.character.escape.perl
1620+
# ^^^^ constant.character.escape.perl
1621+
# ^ punctuation.section.generic.end.perl
1622+
# ^ - meta.string - string
1623+
q(quoted "interpolated" [foo] 'bar' \) $baz)
15891624
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.perl
15901625
# ^ support.function.perl
15911626
# ^ punctuation.section.parens.begin.perl - string
@@ -1594,6 +1629,15 @@ =head1 B<--param>
15941629
# ^^ constant.character.escape.perl
15951630
# ^^^^ - variable
15961631
# ^ punctuation.section.parens.end.perl - string
1632+
q(foo \) foo\\\) bar\\\\)
1633+
# ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.perl
1634+
# ^ support.function.perl
1635+
# ^ punctuation.section.parens.begin.perl - string
1636+
# ^^ constant.character.escape.perl
1637+
# ^^^^ constant.character.escape.perl
1638+
# ^^^^ constant.character.escape.perl
1639+
# ^ punctuation.section.parens.end.perl
1640+
# ^ - meta.string - string
15971641
q['
15981642
# ^ support.function.perl
15991643
# ^ punctuation.section.brackets.begin.perl - string

0 commit comments

Comments
 (0)