-
Notifications
You must be signed in to change notification settings - Fork 728
/
swift.rb
186 lines (149 loc) · 5.57 KB
/
swift.rb
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
# -*- 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(
break case continue default do else fallthrough if in for return switch where while try catch throw guard defer repeat
as dynamicType is new super self Self Type __COLUMN__ __FILE__ __FUNCTION__ __LINE__
associativity didSet get infix inout mutating none nonmutating operator override postfix precedence prefix set unowned weak willSet throws rethrows precedencegroup
#available #colorLiteral #column #else #elseif #endif #error #file #fileLiteral #function #if #imageLiteral #line #selector #sourceLocation #warning
)
declarations = Set.new %w(
class deinit enum convenience extension final func import init internal lazy let optional private protocol public required static struct subscript typealias var dynamic indirect associatedtype open fileprivate some
)
constants = Set.new %w(
true false nil
)
start { push :bol }
# 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{[()\[\]{}:;,?\\]}, Punctuation
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/(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/#available\([^)]+\)/, Keyword::Declaration
rule %r/(#(?:selector|keyPath)\()([^)]+?(?:[(].*?[)])?)(\))/ do
groups Keyword::Declaration, Name::Function, Keyword::Declaration
end
rule %r/#(line|file|column|function|dsohandle)/, Keyword::Declaration
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
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
end
end
end