Skip to content

Commit 0b1e5e8

Browse files
committed
1 parent f847923 commit 0b1e5e8

File tree

2 files changed

+137
-47
lines changed

2 files changed

+137
-47
lines changed

swift-mode-lexer.el

Lines changed: 74 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,12 @@ Intended for `syntax-propertize-function'."
229229
(let* ((chunk (swift-mode:chunk-after (syntax-ppss start))))
230230
(cond
231231
((swift-mode:chunk:multiline-string-p chunk)
232-
(swift-mode:syntax-propertize:end-of-multiline-string end))
232+
(swift-mode:syntax-propertize:end-of-string
233+
end "\"\"\"" (swift-mode:chunk:pound-count chunk)))
233234

234235
((swift-mode:chunk:single-line-string-p chunk)
235-
(swift-mode:syntax-propertize:end-of-single-line-string end))
236+
(swift-mode:syntax-propertize:end-of-string
237+
end "\"" (swift-mode:chunk:pound-count chunk)))
236238

237239
((swift-mode:chunk:comment-p chunk)
238240
(goto-char (swift-mode:chunk:start chunk))
@@ -255,21 +257,21 @@ stops where the level becomes zero."
255257
(< (point) end)
256258
(search-forward-regexp pattern end t))
257259
(cond
258-
((equal "\"\"\"" (match-string-no-properties 0))
259-
(put-text-property (match-beginning 0) (1+ (match-beginning 0))
260+
((member (match-string-no-properties 0) '("\"\"\"" "\""))
261+
(let ((start (match-beginning 0))
262+
(pound-count 0)
263+
(quotation (match-string-no-properties 0)))
264+
(save-excursion
265+
(goto-char start)
266+
(skip-chars-backward "#")
267+
(setq pound-count (- start (point)))
268+
(setq start (point)))
269+
(put-text-property start (1+ start)
260270
'syntax-table
261271
(string-to-syntax "|"))
262-
(let ((start (match-beginning 0)))
263-
(swift-mode:syntax-propertize:end-of-multiline-string end)
264-
(put-text-property start (point) 'syntax-multiline t)))
265-
266-
((equal "\"" (match-string-no-properties 0))
267-
(put-text-property (match-beginning 0) (1+ (match-beginning 0))
268-
'syntax-table
269-
(string-to-syntax "|"))
270-
(let ((start (match-beginning 0)))
271-
(swift-mode:syntax-propertize:end-of-single-line-string end)
272-
(put-text-property start (point) 'syntax-multiline t)))
272+
(swift-mode:syntax-propertize:end-of-string
273+
end quotation pound-count)
274+
(put-text-property start (point) 'syntax-multiline t)))
273275

274276
((equal "//" (match-string-no-properties 0))
275277
(goto-char (match-beginning 0))
@@ -292,71 +294,84 @@ stops where the level becomes zero."
292294
(goto-char end))
293295
found-matching-parenthesis))
294296

295-
(defun swift-mode:syntax-propertize:end-of-multiline-string (end)
296-
"Move point to the end of multiline string.
297-
Assuming the cursor is on a multiline string.
298-
If the end of the string found, put a text property on it.
299-
If the string go beyond END, stop there."
300-
(swift-mode:syntax-propertize:end-of-string end "\"\"\""))
301-
302-
(defun swift-mode:syntax-propertize:end-of-single-line-string (end)
303-
"Move point to the end of single-line string.
304-
Assuming the cursor is on a single-line string.
305-
If the string go beyond END, stop there."
306-
(swift-mode:syntax-propertize:end-of-string end "\""))
307-
308-
(defun swift-mode:syntax-propertize:end-of-string (end quotation)
297+
(defun swift-mode:syntax-propertize:end-of-string (end quotation pound-count)
309298
"Move point to the end of single-line/multiline string.
299+
310300
Assuming the cursor is on a string.
311301
If the string go beyond END, stop there.
312-
The string should be terminated with QUOTATION."
302+
The string should be terminated with QUOTATION, followed by POUND-COUNT of
303+
pound signs."
313304
(if (and
314305
(< (point) end)
315306
(search-forward-regexp (concat (regexp-quote quotation) "\\|(") end t))
316307
(cond
317308
((and (equal quotation (match-string-no-properties 0))
318-
(not (swift-mode:escaped-p (match-beginning 0))))
309+
(not (swift-mode:escaped-p (match-beginning 0) pound-count))
310+
(progn
311+
(skip-chars-forward "#" (min end (+ (point) pound-count)))
312+
(= (- (point) (match-end 0)) pound-count)))
319313
(put-text-property (1- (point)) (point)
320314
'syntax-table
321315
(string-to-syntax "|")))
322316
((and (equal "(" (match-string-no-properties 0))
323-
(swift-mode:escaped-p (match-beginning 0)))
317+
(swift-mode:escaped-p (match-beginning 0) pound-count))
324318
;; Found an interpolated expression. Skips the expression.
325319
;; We cannot use `scan-sexps' because multiline strings are not yet
326320
;; propertized.
327-
(let ((start (- (point) 2)))
321+
(let ((pos-after-open-paren (point))
322+
(start
323+
(save-excursion
324+
(backward-char) ;; (
325+
(skip-chars-backward "#")
326+
(backward-char) ;; \
327+
(point))))
328+
;; Declares the backslash is not a escape-syntax characters.
328329
(put-text-property start (1+ start)
329330
'syntax-table
330331
(string-to-syntax "w"))
331-
(put-text-property (1+ start) (+ 2 start)
332+
;; Declares the open parentheses is a generic string delimiter.
333+
(put-text-property (1- pos-after-open-paren) pos-after-open-paren
332334
'syntax-table
333335
(string-to-syntax "|"))
334336
(when (swift-mode:syntax-propertize:scan end 1)
335337
;; Found the matching parenthesis. Going further.
338+
;; Declares the close parentheses is a generic string delimiter.
336339
(put-text-property (1- (point)) (point)
337340
'syntax-table
338341
(string-to-syntax "|"))
342+
;; Records the positions.
339343
(put-text-property (1- (point)) (point)
340344
'swift-mode:matching-parenthesis
341345
start)
342-
(put-text-property start (+ 2 start)
346+
(put-text-property start pos-after-open-paren
343347
'swift-mode:matching-parenthesis
344348
(1- (point)))
345-
(swift-mode:syntax-propertize:end-of-string end quotation))))
349+
(swift-mode:syntax-propertize:end-of-string
350+
end quotation pound-count))))
346351
(t
347-
(swift-mode:syntax-propertize:end-of-string end quotation)))
352+
(swift-mode:syntax-propertize:end-of-string end quotation pound-count)))
348353
(goto-char end)))
349354

350355

351-
(defun swift-mode:escaped-p (position)
352-
"Return t if the POSITION is proceeded by odd number of backslashes.
353-
Return nil otherwise."
356+
(defun swift-mode:escaped-p (position pound-count)
357+
"Return t if the POSITION in a string is escaped.
358+
359+
A position is escaped if it is proceeded by POUND-COUNT or more of pound signs
360+
and odd number of backslashes.
361+
Return nil otherwise." ;; FIXME pound-count
354362
(let ((p position)
355-
(count 0))
356-
(while (eq (char-before p) ?\\)
357-
(setq count (1+ count))
363+
(backslash-count 0))
364+
(while (eq (char-before p) ?#)
358365
(setq p (1- p)))
359-
(= (mod count 2) 1)))
366+
(and
367+
;; While it is a syntax error to have extra pound signs, we allow them
368+
;; here to prevent corruption.
369+
(<= pound-count (- position p))
370+
(progn
371+
(while (eq (char-before p) ?\\)
372+
(setq backslash-count (1+ backslash-count))
373+
(setq p (1- p)))
374+
(= (mod backslash-count 2) 1)))))
360375

361376
;;; Lexers
362377

@@ -911,8 +926,9 @@ This function does not return `implicit-;' or `type-:'."
911926
(point))))
912927

913928
;; String
914-
((eq (char-after) ?\")
929+
((looking-at "#*\"")
915930
(let ((pos-after-comment (point)))
931+
(skip-chars-forward "#")
916932
(forward-char)
917933
(swift-mode:end-of-string)
918934
(swift-mode:token
@@ -1160,8 +1176,11 @@ This function does not return `implicit-;' or `type-:'."
11601176
pos-before-comment)))
11611177

11621178
;; String
1163-
((eq (char-before) ?\")
1179+
((save-excursion
1180+
(skip-chars-backward "#")
1181+
(eq (char-before) ?\"))
11641182
(let ((pos-before-comment (point)))
1183+
(skip-chars-backward "#")
11651184
(backward-char)
11661185
(swift-mode:beginning-of-string)
11671186
(swift-mode:token
@@ -1325,6 +1344,14 @@ If this line ends with a single-line comment, goto just before the comment."
13251344
"Return non-nil if the CHUNK is a multiline string."
13261345
(eq (swift-mode:chunk:type chunk) 'multiline-string))
13271346

1347+
(defun swift-mode:chunk:pound-count (chunk)
1348+
"Return the number of pound signs before the start position of the CHUNK."
1349+
(save-excursion
1350+
(goto-char (swift-mode:chunk:start chunk))
1351+
(swift-mode:beginning-of-string)
1352+
(skip-chars-backward "#")
1353+
(- (swift-mode:chunk:start chunk) (point))))
1354+
13281355
(defun swift-mode:chunk-after (&optional parser-state)
13291356
"Return the chunk at the cursor.
13301357
@@ -1342,7 +1369,7 @@ If PARSER-STATE is given, it is used instead of (syntax-ppss)."
13421369
;; string delimiters. So (nth 3 parser-state) may be t even for
13431370
;; single-line string delimiters.
13441371
(if (save-excursion (goto-char (nth 8 parser-state))
1345-
(looking-at "\"\"\""))
1372+
(looking-at "#*\"\"\""))
13461373
(swift-mode:chunk 'multiline-string (nth 8 parser-state))
13471374
(swift-mode:chunk 'single-line-string (nth 8 parser-state))))
13481375
((eq (nth 4 parser-state) t)

test/swift-files/indent/strings.swift

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,67 @@ func f() {
9898
bar()
9999
)aaa"
100100
)
101+
102+
let x = """
103+
abc \(
104+
1 +
105+
(
106+
1 +
107+
1
108+
) +
109+
1
110+
)
111+
def ghi
112+
\"""
113+
aaa
114+
"""
115+
116+
let x = #"""
117+
abc \(
118+
1 +
119+
(
120+
1 + 1
121+
) +
122+
1
123+
)
124+
abc \#(
125+
1 +
126+
(
127+
1 + 1
128+
) +
129+
1
130+
)
131+
def ghi
132+
\"""
133+
\#"""#
134+
"""
135+
aaa
136+
"""#
137+
138+
let x = ##"""
139+
abc \(
140+
1 +
141+
(
142+
1 + 1
143+
) +
144+
1
145+
)
146+
abc \#(
147+
1 +
148+
(
149+
1 + 1
150+
) +
151+
1
152+
)
153+
def ghi
154+
\"""
155+
\#"""#
156+
"""
157+
aaa
158+
"""##
159+
160+
let x = "abc\( 1 + (2 + 3) ) \" a "
161+
let x = #"abc\( 1 + (2 + 3) ) \#( 1 + (2 + 3) ) \" \#"# " a \"#
162+
let x = ##"abc\( 1 + (2 + 3) ) \#( 1 + (2 + 3) ) \" \#"# " a \"##
163+
let x = 1
101164
}

0 commit comments

Comments
 (0)