Skip to content

Commit 2b833dd

Browse files
authored
enh(swift) RAW string support (#2902)
1 parent c0b6ddb commit 2b833dd

File tree

7 files changed

+204
-30
lines changed

7 files changed

+204
-30
lines changed

AUTHORS.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,4 @@ Contributors:
310310
- Kyle Brown <kylebrown9@github>
311311
- Marcus Ortiz <mportiz08@gmail.com>
312312
- Guillaume Grossetie <ggrossetie@yuzutech.fr>
313+
- Steven Van Impe <steven.vanimpe@icloud.com>

CHANGES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ New Languages:
77
Language improvements:
88

99
- enh(makefile): Add `make` as an alias (#2883) [tripleee][]
10+
- enh(swift) Improved grammar for strings (#2819) [Steven Van Impe][]
1011
- fix(asciidoc): Handle section titles level 5 (#2868) [Vaibhav Chanana][]
1112

12-
1313
Grammar improvements:
1414

1515
- enh(vb) Large rework of VB.net grammar (#2808) [Jan Pilzer][]
@@ -29,6 +29,7 @@ Grammar improvements:
2929
[Oldes Huhuman]: https://github.com/Oldes
3030
[Josh Goebel]: https://github.com/joshgoebel
3131
[tripleee]: https://github.com/tripleee
32+
[Steven Van Impe]: https://github.com/svanimpe/
3233
[Vaibhav Chanana]: https://github.com/il3ven
3334

3435
## Version 10.4.1 (tentative)

src/languages/swift.js

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
Language: Swift
33
Description: Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
44
Author: Chris Eidhof <chris@eidhof.nl>
5-
Contributors: Nate Cook <natecook@gmail.com>, Alexander Lichter <manniL@gmx.net>
5+
Contributors: Nate Cook <natecook@gmail.com>, Alexander Lichter <manniL@gmx.net>, Steven Van Impe <steven.vanimpe@icloud.com>
66
Website: https://swift.org
77
Category: common, system
88
*/
99

10+
import { concat } from "../lib/regex.js";
1011

12+
/** @type LanguageFn */
1113
export default function(hljs) {
12-
var SWIFT_KEYWORDS = {
14+
const SWIFT_KEYWORDS = {
1315
// override the pattern since the default of of /\w+/ is not sufficient to
1416
// capture the keywords that start with the character "#"
1517
$pattern: /[\w#]+/,
@@ -41,43 +43,29 @@ export default function(hljs) {
4143
'withUnsafePointer withUnsafePointers withVaList zip'
4244
};
4345

44-
var TYPE = {
46+
const TYPE = {
4547
className: 'type',
4648
begin: '\\b[A-Z][\\w\u00C0-\u02B8\']*',
4749
relevance: 0
4850
};
4951
// slightly more special to swift
50-
var OPTIONAL_USING_TYPE = {
52+
const OPTIONAL_USING_TYPE = {
5153
className: 'type',
5254
begin: '\\b[A-Z][\\w\u00C0-\u02B8\']*[!?]'
5355
};
54-
var BLOCK_COMMENT = hljs.COMMENT(
56+
const BLOCK_COMMENT = hljs.COMMENT(
5557
'/\\*',
5658
'\\*/',
5759
{
5860
contains: ['self']
5961
}
6062
);
61-
var SUBST = {
62-
className: 'subst',
63-
begin: /\\\(/, end: '\\)',
64-
keywords: SWIFT_KEYWORDS,
65-
contains: [] // assigned later
66-
};
67-
var STRING = {
68-
className: 'string',
69-
contains: [hljs.BACKSLASH_ESCAPE, SUBST],
70-
variants: [
71-
{begin: /"""/, end: /"""/},
72-
{begin: /"/, end: /"/},
73-
]
74-
};
7563

7664
// https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#grammar_numeric-literal
7765
// TODO: Update for leading `-` after lookbehind is supported everywhere
78-
var decimalDigits = '([0-9]_*)+';
79-
var hexDigits = '([0-9a-fA-F]_*)+';
80-
var NUMBER = {
66+
const decimalDigits = '([0-9]_*)+';
67+
const hexDigits = '([0-9a-fA-F]_*)+';
68+
const NUMBER = {
8169
className: 'number',
8270
relevance: 0,
8371
variants: [
@@ -96,7 +84,53 @@ export default function(hljs) {
9684
{ begin: /\b0b([01]_*)+\b/ },
9785
]
9886
};
99-
SUBST.contains = [NUMBER];
87+
88+
// https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#grammar_string-literal
89+
const ESCAPED_CHARACTER = (rawDelimiter = "") => ({
90+
className: 'subst',
91+
variants: [
92+
{ begin: concat(/\\/, rawDelimiter, /[0\\tnr"']/) },
93+
{ begin: concat(/\\/, rawDelimiter, /u\{[0-9a-fA-F]{1,8}\}/) }
94+
]
95+
});
96+
const ESCAPED_NEWLINE = (rawDelimiter = "") => ({
97+
className: 'subst',
98+
begin: concat(/\\/, rawDelimiter, /[\t ]*(?:[\r\n]|\r\n)/)
99+
});
100+
const INTERPOLATION = (rawDelimiter = "") => ({
101+
className: 'subst',
102+
label: "interpol",
103+
begin: concat(/\\/, rawDelimiter, /\(/),
104+
end: /\)/
105+
});
106+
const MULTILINE_STRING = (rawDelimiter = "") => ({
107+
begin: concat(rawDelimiter, /"""/),
108+
end: concat(/"""/, rawDelimiter),
109+
contains: [ESCAPED_CHARACTER(rawDelimiter), ESCAPED_NEWLINE(rawDelimiter), INTERPOLATION(rawDelimiter)]
110+
});
111+
const SINGLE_LINE_STRING = (rawDelimiter = "") => ({
112+
begin: concat(rawDelimiter, /"/),
113+
end: concat(/"/, rawDelimiter),
114+
contains: [ESCAPED_CHARACTER(rawDelimiter), INTERPOLATION(rawDelimiter)]
115+
});
116+
const STRING = {
117+
className: 'string',
118+
variants: [
119+
MULTILINE_STRING(),
120+
MULTILINE_STRING("#"),
121+
MULTILINE_STRING("##"),
122+
MULTILINE_STRING("###"),
123+
SINGLE_LINE_STRING(),
124+
SINGLE_LINE_STRING("#"),
125+
SINGLE_LINE_STRING("##"),
126+
SINGLE_LINE_STRING("###"),
127+
]
128+
};
129+
for (const variant of STRING.variants) {
130+
const interpolation = variant.contains.find(mode => mode.label === "interpol");
131+
// TODO: Interpolation can contain any expression, so there's room for improvement here.
132+
interpolation.contains = [STRING, NUMBER];
133+
}
100134

101135
return {
102136
name: 'Swift',

test/markup/swift/multiline-string.expect.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

test/markup/swift/multiline-string.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<span class="hljs-string">&quot;escaped characters <span class="hljs-subst">\0</span><span class="hljs-subst">\\</span><span class="hljs-subst">\t</span><span class="hljs-subst">\n</span><span class="hljs-subst">\r</span><span class="hljs-subst">\&quot;</span><span class="hljs-subst">\&#x27;</span>&quot;</span>
2+
<span class="hljs-string">&quot;escaped unicode <span class="hljs-subst">\u{0}</span><span class="hljs-subst">\u{12}</span><span class="hljs-subst">\u{345}</span><span class="hljs-subst">\u{6789}</span><span class="hljs-subst">\u{abcde}</span><span class="hljs-subst">\u{fABCDE}</span><span class="hljs-subst">\u{F012345}</span><span class="hljs-subst">\u{67890abc}</span>&quot;</span>
3+
<span class="hljs-string">#&quot;escaped characters <span class="hljs-subst">\#0</span><span class="hljs-subst">\#\</span><span class="hljs-subst">\#t</span><span class="hljs-subst">\#n</span><span class="hljs-subst">\#r</span><span class="hljs-subst">\#&quot;</span><span class="hljs-subst">\#&#x27;</span>&quot;#</span>
4+
<span class="hljs-string">#&quot;escaped unicode <span class="hljs-subst">\#u{0}</span><span class="hljs-subst">\#u{12}</span><span class="hljs-subst">\#u{345}</span><span class="hljs-subst">\#u{6789}</span><span class="hljs-subst">\#u{abcde}</span><span class="hljs-subst">\#u{fABCDE}</span><span class="hljs-subst">\#u{F012345}</span><span class="hljs-subst">\#u{67890abc}</span>&quot;#</span>
5+
<span class="hljs-string">#&quot;raw characters \0\\\t\n\r\&quot;\&#x27;\u{6789}&quot;#</span>
6+
<span class="hljs-string">##&quot;escaped characters <span class="hljs-subst">\##0</span><span class="hljs-subst">\##\</span><span class="hljs-subst">\##t</span><span class="hljs-subst">\##n</span><span class="hljs-subst">\##r</span><span class="hljs-subst">\##&quot;</span><span class="hljs-subst">\##&#x27;</span>&quot;##</span>
7+
<span class="hljs-string">##&quot;escaped unicode <span class="hljs-subst">\##u{0}</span><span class="hljs-subst">\##u{12}</span><span class="hljs-subst">\##u{345}</span><span class="hljs-subst">\##u{6789}</span><span class="hljs-subst">\##u{abcde}</span><span class="hljs-subst">\##u{fABCDE}</span><span class="hljs-subst">\##u{F012345}</span><span class="hljs-subst">\##u{67890abc}</span>&quot;##</span>
8+
<span class="hljs-string">##&quot;raw characters \0\\\t\n\r\&quot;\&#x27;\u{6789} \#0\#\\#t\#n\#r\#&quot;\#&#x27;\#u{6789}&quot;##</span>
9+
<span class="hljs-string">###&quot;escaped characters <span class="hljs-subst">\###0</span><span class="hljs-subst">\###\</span><span class="hljs-subst">\###t</span><span class="hljs-subst">\###n</span><span class="hljs-subst">\###r</span><span class="hljs-subst">\###&quot;</span><span class="hljs-subst">\###&#x27;</span>&quot;###</span>
10+
<span class="hljs-string">###&quot;escaped unicode <span class="hljs-subst">\###u{0}</span><span class="hljs-subst">\###u{12}</span><span class="hljs-subst">\###u{345}</span><span class="hljs-subst">\###u{6789}</span><span class="hljs-subst">\###u{abcde}</span><span class="hljs-subst">\###u{fABCDE}</span><span class="hljs-subst">\###u{F012345}</span><span class="hljs-subst">\###u{67890abc}</span>&quot;###</span>
11+
<span class="hljs-string">###&quot;raw characters \0\\\t\n\r\&quot;\&#x27;\u{6789} \#0\#\\#t\#n\#r\#&quot;\#&#x27;\#u{6789} \##0\##\\##t\##n\##r\##&quot;\##&#x27;\##u{6789}&quot;###</span>
12+
13+
<span class="hljs-string">&quot;&quot;&quot;
14+
escaped characters <span class="hljs-subst">\0</span><span class="hljs-subst">\\</span><span class="hljs-subst">\t</span><span class="hljs-subst">\n</span><span class="hljs-subst">\r</span><span class="hljs-subst">\&quot;</span><span class="hljs-subst">\&#x27;</span>
15+
escaped unicode <span class="hljs-subst">\u{0}</span><span class="hljs-subst">\u{12}</span><span class="hljs-subst">\u{345}</span><span class="hljs-subst">\u{6789}</span><span class="hljs-subst">\u{abcde}</span><span class="hljs-subst">\u{fABCDE}</span><span class="hljs-subst">\u{F012345}</span><span class="hljs-subst">\u{67890abc}</span>
16+
&quot;&quot;&quot;</span>
17+
<span class="hljs-string">#&quot;&quot;&quot;
18+
escaped characters <span class="hljs-subst">\#0</span><span class="hljs-subst">\#\</span><span class="hljs-subst">\#t</span><span class="hljs-subst">\#n</span><span class="hljs-subst">\#r</span><span class="hljs-subst">\#&quot;</span><span class="hljs-subst">\#&#x27;</span>
19+
escaped unicode <span class="hljs-subst">\#u{0}</span><span class="hljs-subst">\#u{12}</span><span class="hljs-subst">\#u{345}</span><span class="hljs-subst">\#u{6789}</span><span class="hljs-subst">\#u{abcde}</span><span class="hljs-subst">\#u{fABCDE}</span><span class="hljs-subst">\#u{F012345}</span><span class="hljs-subst">\#u{67890abc}</span>
20+
raw characters \0\\\t\n\r\&quot;\&#x27;\u{6789}
21+
&quot;&quot;&quot;#</span>
22+
<span class="hljs-string">##&quot;&quot;&quot;
23+
escaped characters <span class="hljs-subst">\##0</span><span class="hljs-subst">\##\</span><span class="hljs-subst">\##t</span><span class="hljs-subst">\##n</span><span class="hljs-subst">\##r</span><span class="hljs-subst">\##&quot;</span><span class="hljs-subst">\##&#x27;</span>
24+
escaped unicode <span class="hljs-subst">\##u{0}</span><span class="hljs-subst">\##u{12}</span><span class="hljs-subst">\##u{345}</span><span class="hljs-subst">\##u{6789}</span><span class="hljs-subst">\##u{abcde}</span><span class="hljs-subst">\##u{fABCDE}</span><span class="hljs-subst">\##u{F012345}</span><span class="hljs-subst">\##u{67890abc}</span>
25+
raw characters \0\\\t\n\r\&quot;\&#x27;\u{6789} \#0\#\\#t\#n\#r\#&quot;\#&#x27;\#u{6789}
26+
&quot;&quot;&quot;##</span>
27+
<span class="hljs-string">###&quot;&quot;&quot;
28+
escaped characters <span class="hljs-subst">\###0</span><span class="hljs-subst">\###\</span><span class="hljs-subst">\###t</span><span class="hljs-subst">\###n</span><span class="hljs-subst">\###r</span><span class="hljs-subst">\###&quot;</span><span class="hljs-subst">\###&#x27;</span>
29+
escaped unicode <span class="hljs-subst">\###u{0}</span><span class="hljs-subst">\###u{12}</span><span class="hljs-subst">\###u{345}</span><span class="hljs-subst">\###u{6789}</span><span class="hljs-subst">\###u{abcde}</span><span class="hljs-subst">\###u{fABCDE}</span><span class="hljs-subst">\###u{F012345}</span><span class="hljs-subst">\###u{67890abc}</span>
30+
raw characters \0\\\t\n\r\&quot;\&#x27;\u{6789} \#0\#\\#t\#n\#r\#&quot;\#&#x27;\#u{6789} \##0\##\\##t\##n\##r\##&quot;\##&#x27;\##u{6789}
31+
&quot;&quot;&quot;###</span>
32+
33+
<span class="hljs-string">&quot;&quot;&quot;
34+
escaped newline <span class="hljs-subst">\
35+
</span>same line
36+
&quot;&quot;&quot;</span>
37+
<span class="hljs-string">#&quot;&quot;&quot;
38+
escaped newline <span class="hljs-subst">\#
39+
</span>same line
40+
&quot;&quot;&quot;#</span>
41+
<span class="hljs-string">##&quot;&quot;&quot;
42+
escaped newline <span class="hljs-subst">\##
43+
</span>same line
44+
&quot;&quot;&quot;##</span>
45+
<span class="hljs-string">###&quot;&quot;&quot;
46+
escaped newline <span class="hljs-subst">\###
47+
</span>same line
48+
&quot;&quot;&quot;###</span>
49+
50+
<span class="hljs-string">&quot;interpolation <span class="hljs-subst">\(x)</span>&quot;</span>
51+
<span class="hljs-string">#&quot;interpolation <span class="hljs-subst">\#(<span class="hljs-number">123</span>)</span> raw \(123)&quot;#</span>
52+
<span class="hljs-string">##&quot;interpolation <span class="hljs-subst">\##(<span class="hljs-number">1.23</span>)</span> raw \#(1.23) raw \(1.23)&quot;##</span>
53+
<span class="hljs-string">###&quot;interpolation <span class="hljs-subst">\###(<span class="hljs-string">&quot;string&quot;</span>)</span> raw \##(&quot;string&quot;) raw \#(&quot;string&quot;) raw \(&quot;string&quot;)&quot;###</span>
54+
55+
<span class="hljs-string">&quot;&quot;&quot;
56+
interpolation <span class="hljs-subst">\(x)</span>
57+
&quot;&quot;&quot;</span>
58+
<span class="hljs-string">#&quot;&quot;&quot;
59+
interpolation <span class="hljs-subst">\#(<span class="hljs-number">123</span>)</span>
60+
raw \(123)
61+
&quot;&quot;&quot;#</span>
62+
<span class="hljs-string">##&quot;&quot;&quot;
63+
interpolation <span class="hljs-subst">\##(<span class="hljs-number">1.23</span>)</span>
64+
raw \#(1.23)
65+
raw \(1.23)
66+
&quot;&quot;&quot;##</span>
67+
<span class="hljs-string">###&quot;&quot;&quot;
68+
interpolation <span class="hljs-subst">\###(<span class="hljs-string">&quot;string&quot;</span>)</span>
69+
raw \##(&quot;string&quot;)
70+
raw \#(&quot;string&quot;)
71+
raw \(&quot;string&quot;)
72+
&quot;&quot;&quot;###</span>

test/markup/swift/strings.txt

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"escaped characters \0\\\t\n\r\"\'"
2+
"escaped unicode \u{0}\u{12}\u{345}\u{6789}\u{abcde}\u{fABCDE}\u{F012345}\u{67890abc}"
3+
#"escaped characters \#0\#\\#t\#n\#r\#"\#'"#
4+
#"escaped unicode \#u{0}\#u{12}\#u{345}\#u{6789}\#u{abcde}\#u{fABCDE}\#u{F012345}\#u{67890abc}"#
5+
#"raw characters \0\\\t\n\r\"\'\u{6789}"#
6+
##"escaped characters \##0\##\\##t\##n\##r\##"\##'"##
7+
##"escaped unicode \##u{0}\##u{12}\##u{345}\##u{6789}\##u{abcde}\##u{fABCDE}\##u{F012345}\##u{67890abc}"##
8+
##"raw characters \0\\\t\n\r\"\'\u{6789} \#0\#\\#t\#n\#r\#"\#'\#u{6789}"##
9+
###"escaped characters \###0\###\\###t\###n\###r\###"\###'"###
10+
###"escaped unicode \###u{0}\###u{12}\###u{345}\###u{6789}\###u{abcde}\###u{fABCDE}\###u{F012345}\###u{67890abc}"###
11+
###"raw characters \0\\\t\n\r\"\'\u{6789} \#0\#\\#t\#n\#r\#"\#'\#u{6789} \##0\##\\##t\##n\##r\##"\##'\##u{6789}"###
12+
13+
"""
14+
escaped characters \0\\\t\n\r\"\'
15+
escaped unicode \u{0}\u{12}\u{345}\u{6789}\u{abcde}\u{fABCDE}\u{F012345}\u{67890abc}
16+
"""
17+
#"""
18+
escaped characters \#0\#\\#t\#n\#r\#"\#'
19+
escaped unicode \#u{0}\#u{12}\#u{345}\#u{6789}\#u{abcde}\#u{fABCDE}\#u{F012345}\#u{67890abc}
20+
raw characters \0\\\t\n\r\"\'\u{6789}
21+
"""#
22+
##"""
23+
escaped characters \##0\##\\##t\##n\##r\##"\##'
24+
escaped unicode \##u{0}\##u{12}\##u{345}\##u{6789}\##u{abcde}\##u{fABCDE}\##u{F012345}\##u{67890abc}
25+
raw characters \0\\\t\n\r\"\'\u{6789} \#0\#\\#t\#n\#r\#"\#'\#u{6789}
26+
"""##
27+
###"""
28+
escaped characters \###0\###\\###t\###n\###r\###"\###'
29+
escaped unicode \###u{0}\###u{12}\###u{345}\###u{6789}\###u{abcde}\###u{fABCDE}\###u{F012345}\###u{67890abc}
30+
raw characters \0\\\t\n\r\"\'\u{6789} \#0\#\\#t\#n\#r\#"\#'\#u{6789} \##0\##\\##t\##n\##r\##"\##'\##u{6789}
31+
"""###
32+
33+
"""
34+
escaped newline \
35+
same line
36+
"""
37+
#"""
38+
escaped newline \#
39+
same line
40+
"""#
41+
##"""
42+
escaped newline \##
43+
same line
44+
"""##
45+
###"""
46+
escaped newline \###
47+
same line
48+
"""###
49+
50+
"interpolation \(x)"
51+
#"interpolation \#(123) raw \(123)"#
52+
##"interpolation \##(1.23) raw \#(1.23) raw \(1.23)"##
53+
###"interpolation \###("string") raw \##("string") raw \#("string") raw \("string")"###
54+
55+
"""
56+
interpolation \(x)
57+
"""
58+
#"""
59+
interpolation \#(123)
60+
raw \(123)
61+
"""#
62+
##"""
63+
interpolation \##(1.23)
64+
raw \#(1.23)
65+
raw \(1.23)
66+
"""##
67+
###"""
68+
interpolation \###("string")
69+
raw \##("string")
70+
raw \#("string")
71+
raw \("string")
72+
"""###

0 commit comments

Comments
 (0)