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
|
# -*- coding: utf-8 -*- #
# frozen_string_literal: true
module Rouge
module Lexers
class Swift < RegexLexer
tag 'swift'
filenames '*.swift'
title "Swift"
desc 'Multi paradigm, compiled programming language developed by Apple for iOS and OS X development. (developer.apple.com/swift)'
id_head = /_|(?!\p{Mc})\p{Alpha}|[^\u0000-\uFFFF]/
id_rest = /[\p{Alnum}_]|[^\u0000-\uFFFF]/
id = /#{id_head}#{id_rest}*/
keywords = Set.new %w(
autoreleasepool await break case catch consume continue default defer discard do each else fallthrough guard if in for repeat return switch throw try where while
as dynamicType is new super self Self Type
associativity async didSet get infix inout isolated left mutating none nonmutating operator override postfix precedence precedencegroup prefix rethrows right set throws unowned weak willSet
)
declarations = Set.new %w(
actor any associatedtype borrowing class consuming deinit distributed dynamic enum convenience extension fileprivate final func import indirect init internal lazy let macro nonisolated open optional package private protocol public required some static struct subscript typealias var
)
constants = Set.new %w(
true false nil
)
start do
push :bol
@re_delim = "" # multi-line regex delimiter
end
# beginning of line
state :bol do
rule %r/#(?![#"\/]).*/, Comment::Preproc
mixin :inline_whitespace
rule(//) { pop! }
end
state :inline_whitespace do
rule %r/\s+/m, Text
mixin :has_comments
end
state :whitespace do
rule %r/\n+/m, Text, :bol
rule %r(\/\/.*?$), Comment::Single, :bol
mixin :inline_whitespace
end
state :has_comments do
rule %r(/[*]), Comment::Multiline, :nested_comment
end
state :nested_comment do
mixin :has_comments
rule %r([*]/), Comment::Multiline, :pop!
rule %r([^*/]+)m, Comment::Multiline
rule %r/./, Comment::Multiline
end
state :root do
mixin :whitespace
rule %r/\$(([1-9]\d*)?\d)/, Name::Variable
rule %r/\$#{id}/, Name
rule %r/~Copyable\b/, Keyword::Type
rule %r{[()\[\]{}:;,?\\]}, Punctuation
rule %r{(#*)/(?!\s).*(?<![\s\\])/\1}, Str::Regex
rule %r([-/=+*%<>!&|^.~]+), Operator
rule %r/@?"/, Str, :dq
rule %r/'(\\.|.)'/, Str::Char
rule %r/(\d+(?:_\d+)*\*|(?:\d+(?:_\d+)*)*\.\d+(?:_\d)*)(e[+-]?\d+(?:_\d)*)?/i, Num::Float
rule %r/\d+e[+-]?[0-9]+/i, Num::Float
rule %r/0o?[0-7]+(?:_[0-7]+)*/, Num::Oct
rule %r/0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*((\.[0-9A-F]+(?:_[0-9A-F]+)*)?p[+-]?\d+)?/, Num::Hex
rule %r/0b[01]+(?:_[01]+)*/, Num::Bin
rule %r{[\d]+(?:_\d+)*}, Num::Integer
rule %r/@#{id}/, Keyword::Declaration
rule %r/##{id}/, Keyword
rule %r/(private|internal)(\([ ]*)(\w+)([ ]*\))/ do |m|
if m[3] == 'set'
token Keyword::Declaration
else
groups Keyword::Declaration, Keyword::Declaration, Error, Keyword::Declaration
end
end
rule %r/(unowned\([ ]*)(\w+)([ ]*\))/ do |m|
if m[2] == 'safe' || m[2] == 'unsafe'
token Keyword::Declaration
else
groups Keyword::Declaration, Error, Keyword::Declaration
end
end
rule %r/(let|var)\b(\s*)(#{id})/ do
groups Keyword, Text, Name::Variable
end
rule %r/(let|var)\b(\s*)([(])/ do
groups Keyword, Text, Punctuation
push :tuple
end
rule %r/(?!\b(if|while|for|private|internal|unowned|switch|case)\b)\b#{id}(?=(\?|!)?\s*[(])/ do |m|
if m[0] =~ /^[[:upper:]]/
token Keyword::Type
else
token Name::Function
end
end
rule %r/as[?!]?(?=\s)/, Keyword
rule %r/try[!]?(?=\s)/, Keyword
rule %r/(#?(?!default)(?![[:upper:]])#{id})(\s*)(:)/ do
groups Name::Variable, Text, Punctuation
end
rule id do |m|
if keywords.include? m[0]
token Keyword
elsif declarations.include? m[0]
token Keyword::Declaration
elsif constants.include? m[0]
token Keyword::Constant
elsif m[0] =~ /^[[:upper:]]/
token Keyword::Type
else
token Name
end
end
rule %r/(`)(#{id})(`)/ do
groups Punctuation, Name::Variable, Punctuation
end
rule %r{(#+)/\n} do |m|
@re_delim = m[1]
token Str::Regex
push :re_multi
end
end
state :tuple do
rule %r/(#{id})/, Name::Variable
rule %r/(`)(#{id})(`)/ do
groups Punctuation, Name::Variable, Punctuation
end
rule %r/,/, Punctuation
rule %r/[(]/, Punctuation, :push
rule %r/[)]/, Punctuation, :pop!
mixin :inline_whitespace
end
state :dq do
rule %r/\\[\\0tnr'"]/, Str::Escape
rule %r/\\[(]/, Str::Escape, :interp
rule %r/\\u\{\h{1,8}\}/, Str::Escape
rule %r/[^\\"]+/, Str
rule %r/"""/, Str, :pop!
rule %r/"/, Str, :pop!
end
state :interp do
rule %r/[(]/, Punctuation, :interp_inner
rule %r/[)]/, Str::Escape, :pop!
mixin :root
end
state :interp_inner do
rule %r/[(]/, Punctuation, :push
rule %r/[)]/, Punctuation, :pop!
mixin :root
end
state :re_multi do
rule %r{^\s*/#+} do |m|
token Str::Regex
if m[0].end_with?("/#{@re_delim}")
@re_delim = ""
pop!
end
end
rule %r/#.*/, Comment::Single
rule %r/./m, Str::Regex
end
end
end
end
|