Skip to content

Commit 4a1ed91

Browse files
TheSoundDefensemarijnh
authored andcommitted
[swift mode] Various improvements
- Added for as a defining keyword - Added new types and operators - Fixed numbers so basic integers are represented - Identifiers can now be surrounded with backticks - Properties and #/@ instructions are now distinct, with the latter represented as a builtin type - Properties are now matched before punctuation. Code can now fold. - Remove the regexp checking as that syntax does not currently exist in Swift - Added tests
1 parent dd10e2e commit 4a1ed91

File tree

3 files changed

+176
-14
lines changed

3 files changed

+176
-14
lines changed

mode/swift/swift.js

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,20 @@
2626
"defer","return","inout","mutating","nonmutating","catch","do","rethrows","throw","throws","try","didSet","get","set","willSet",
2727
"assignment","associativity","infix","left","none","operator","postfix","precedence","precedencegroup","prefix","right",
2828
"Any","AnyObject","Type","dynamicType","Self","Protocol","__COLUMN__","__FILE__","__FUNCTION__","__LINE__"])
29-
var definingKeywords = wordSet(["var","let","class","enum","extension","import","protocol","struct","func","typealias","associatedtype"])
29+
var definingKeywords = wordSet(["var","let","class","enum","extension","import","protocol","struct","func","typealias","associatedtype","for"])
3030
var atoms = wordSet(["true","false","nil","self","super","_"])
31-
var types = wordSet(["Array","Bool","Dictionary","Double","Float","Int","Never","Optional","String","Void"])
32-
var operators = "+-/*%=|&<>"
33-
var punc = ";,.(){}[]"
34-
var number = /^-?(?:(?:[\d_]+\.[_\d]*|\.[_\d]+|0o[0-7_\.]+|0b[01_\.]+)(?:e-?[\d_]+)?|0x[\d_a-f\.]+(?:p-?[\d_]+)?)/i
35-
var identifier = /^[_A-Za-z$][_A-Za-z$0-9]*/
36-
var property = /^[@\#\.][_A-Za-z$][_A-Za-z$0-9]*/
31+
var types = wordSet(["Array","Bool","Character","Dictionary","Double","Float","Int","Int8","Int16","Int32","Int64","Never","Optional","Set","String",
32+
"UInt8","UInt16","UInt32","UInt64","Void"])
33+
var operators = "+-/*%=|&<>~^?!"
34+
var punc = ":;,.(){}[]"
35+
var binary = /^\-?0b[01][01_]*/
36+
var octal = /^\-?0o[0-7][0-7_]*/
37+
var hexadecimal = /^\-?0x[\dA-Fa-f][\dA-Fa-f_]*(?:(?:\.[\dA-Fa-f][\dA-Fa-f_]*)?[Pp]\-?\d[\d_]*)?/
38+
var decimal = /^\-?\d[\d_]*(?:\.\d[\d_]*)?(?:[Ee]\-?\d[\d_]*)?/
39+
var identifier = /^\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1/
40+
var property = /^\.(?:\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1)/
41+
var instruction = /^\#[A-Za-z]+/
42+
var attribute = /^@(?:\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1)/
3743
var regexp = /^\/(?!\s)(?:\/\/)?(?:\\.|[^\/])+\//
3844

3945
function tokenBase(stream, state, prev) {
@@ -50,8 +56,14 @@
5056
state.tokenize.push(tokenComment)
5157
return tokenComment(stream, state)
5258
}
53-
if (stream.match(regexp)) return "string-2"
5459
}
60+
if (stream.match(instruction)) return "builtin"
61+
if (stream.match(attribute)) return "attribute"
62+
if (stream.match(binary)) return "number"
63+
if (stream.match(octal)) return "number"
64+
if (stream.match(hexadecimal)) return "number"
65+
if (stream.match(decimal)) return "number"
66+
if (stream.match(property)) return "property"
5567
if (operators.indexOf(ch) > -1) {
5668
stream.next()
5769
return "operator"
@@ -68,18 +80,15 @@
6880
return tokenize(stream, state)
6981
}
7082

71-
if (stream.match(number)) return "number"
72-
if (stream.match(property)) return "property"
73-
7483
if (stream.match(identifier)) {
7584
var ident = stream.current()
85+
if (types.hasOwnProperty(ident)) return "variable-2"
86+
if (atoms.hasOwnProperty(ident)) return "atom"
7687
if (keywords.hasOwnProperty(ident)) {
7788
if (definingKeywords.hasOwnProperty(ident))
7889
state.prev = "define"
7990
return "keyword"
8091
}
81-
if (types.hasOwnProperty(ident)) return "variable-2"
82-
if (atoms.hasOwnProperty(ident)) return "atom"
8392
if (prev == "define") return "def"
8493
return "variable"
8594
}
@@ -191,7 +200,9 @@
191200

192201
lineComment: "//",
193202
blockCommentStart: "/*",
194-
blockCommentEnd: "*/"
203+
blockCommentEnd: "*/",
204+
fold: "brace",
205+
closeBrackets: "()[]{}''\"\"``"
195206
}
196207
})
197208

mode/swift/test.js

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2+
// Distributed under an MIT license: http://codemirror.net/LICENSE
3+
4+
(function() {
5+
var mode = CodeMirror.getMode({indentUnit: 2}, "swift");
6+
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
7+
8+
// Ensure all number types are properly represented.
9+
MT("numbers",
10+
"[keyword var] [def a] [operator =] [number 17]",
11+
"[keyword var] [def b] [operator =] [number -0.5]",
12+
"[keyword var] [def c] [operator =] [number 0.3456e-4]",
13+
"[keyword var] [def d] [operator =] [number 345e2]",
14+
"[keyword var] [def e] [operator =] [number 0o7324]",
15+
"[keyword var] [def f] [operator =] [number 0b10010]",
16+
"[keyword var] [def g] [operator =] [number -0x35ade]",
17+
"[keyword var] [def h] [operator =] [number 0xaea.ep-13]".
18+
"[keyword var] [def i] [operator =] [number 0x13ep6");
19+
20+
// Variable/class/etc definition.
21+
MT("definition",
22+
"[keyword var] [def a] [operator =] [number 5]",
23+
"[keyword let] [def b][punctuation :] [variable-2 Int] [operator =] [number 10]",
24+
"[keyword class] [def C] [punctuation {] [punctuation }]",
25+
"[keyword struct] [def D] [punctuation {] [punctuation }]",
26+
"[keyword enum] [def E] [punctuation {] [punctuation }]",
27+
"[keyword extension] [def F] [punctuation {] [punctuation }]",
28+
"[keyword protocol] [def G] [punctuation {] [punctuation }]",
29+
"[keyword func] [def h][punctuation ()] [punctuation {] [punctuation }]",
30+
"[keyword import] [def Foundation]",
31+
"[keyword typealias] [def NewString] [operator =] [variable-2 String]",
32+
"[keyword associatedtype] [def I]",
33+
"[keyword for] [def j] [keyword in] [number 0][punctuation ..][operator <][number 3] [punctuation {] [punctuation }]");
34+
35+
// Strings and string interpolation.
36+
MT("strings",
37+
"[keyword var] [def a][punctuation :] [variable-2 String] [operator =] [string \"test\"]",
38+
"[keyword var] [def b][punctuation :] [variable-2 String] [operator =] [string \"\\(][variable a][string )\"]");
39+
40+
// Comments.
41+
MT("comments",
42+
"[comment // This is a comment]",
43+
"[comment /* This is another comment */]",
44+
"[keyword var] [def a] [operator =] [number 5] [comment // Third comment]");
45+
46+
// Atoms.
47+
MT("atoms",
48+
"[keyword class] [def FooClass] [punctuation {]",
49+
" [keyword let] [def fooBool][punctuation :] [variable-2 Bool][operator ?]",
50+
" [keyword let] [def fooInt][punctuation :] [variable-2 Int][operator ?]",
51+
" [keyword func] [keyword init][punctuation (][variable fooBool][punctuation :] [variable-2 Bool][punctuation ,] [variable barBool][punctuation :] [variable-2 Bool][punctuation )] [punctuation {]",
52+
" [atom super][property .init][punctuation ()]",
53+
" [atom self][property .fooBool] [operator =] [variable fooBool]",
54+
" [variable fooInt] [operator =] [atom nil]",
55+
" [keyword if] [variable barBool] [operator ==] [atom true] [punctuation {]",
56+
" [variable print][punctuation (][string \"True!\"][punctuation )]",
57+
" [punctuation }] [keyword else] [keyword if] [variable barBool] [operator ==] [atom false] [punctuation {]",
58+
" [keyword for] [atom _] [keyword in] [number 0][punctuation ...][number 5] [punctuation {]",
59+
" [variable print][punctuation (][string \"False!\"][punctuation )]",
60+
" [punctuation }]",
61+
" [punctuation }]",
62+
" [punctuation }]",
63+
"[punctuation }]");
64+
65+
// Types.
66+
MT("types",
67+
"[keyword var] [def a] [operator =] [variable-2 Array][operator <][variable-2 Int][operator >]",
68+
"[keyword var] [def b] [operator =] [variable-2 Set][operator <][variable-2 Bool][operator >]",
69+
"[keyword var] [def c] [operator =] [variable-2 Dictionary][operator <][variable-2 String][punctuation ,][variable-2 Character][operator >]",
70+
"[keyword var] [def d][punctuation :] [variable-2 Int64][operator ?] [operator =] [variable-2 Optional][punctuation (][number 8][punctuation )]",
71+
"[keyword func] [def e][punctuation ()] [operator ->] [variable-2 Void] [punctuation {]",
72+
" [keyword var] [def e1][punctuation :] [variable-2 Float] [operator =] [number 1.2]",
73+
"[punctuation }]",
74+
"[keyword func] [def f][punctuation ()] [operator ->] [variable-2 Never] [punctuation {]",
75+
" [keyword var] [def f1][punctuation :] [variable-2 Double] [operator =] [number 2.4]",
76+
"[punctuation }]");
77+
78+
// Operators.
79+
MT("operators",
80+
"[keyword var] [def a] [operator =] [number 1] [operator +] [number 2]",
81+
"[keyword var] [def b] [operator =] [number 1] [operator -] [number 2]",
82+
"[keyword var] [def c] [operator =] [number 1] [operator *] [number 2]",
83+
"[keyword var] [def d] [operator =] [number 1] [operator /] [number 2]",
84+
"[keyword var] [def e] [operator =] [number 1] [operator %] [number 2]",
85+
"[keyword var] [def f] [operator =] [number 1] [operator |] [number 2]",
86+
"[keyword var] [def g] [operator =] [number 1] [operator &] [number 2]",
87+
"[keyword var] [def h] [operator =] [number 1] [operator <<] [number 2]",
88+
"[keyword var] [def i] [operator =] [number 1] [operator >>] [number 2]",
89+
"[keyword var] [def j] [operator =] [number 1] [operator ^] [number 2]",
90+
"[keyword var] [def k] [operator =] [operator ~][number 1]",
91+
"[keyword var] [def l] [operator =] [variable foo] [operator ?] [number 1] [punctuation :] [number 2]",
92+
"[keyword var] [def m][punctuation :] [variable-2 Int] [operator =] [variable-2 Optional][punctuation (][number 8][punctuation )][operator !]");
93+
94+
// Punctuation.
95+
MT("punctuation",
96+
"[keyword let] [def a] [operator =] [number 1][punctuation ;] [keyword let] [def b] [operator =] [number 2]",
97+
"[keyword let] [def testArr][punctuation :] [punctuation [[][variable-2 Int][punctuation ]]] [operator =] [punctuation [[][variable a][punctuation ,] [variable b][punctuation ]]]",
98+
"[keyword for] [def i] [keyword in] [number 0][punctuation ..][operator <][variable testArr][property .count] [punctuation {]",
99+
" [variable print][punctuation (][variable testArr][punctuation [[][variable i][punctuation ]])]",
100+
"[punctuation }]");
101+
102+
// Identifiers.
103+
MT("identifiers",
104+
"[keyword let] [def abc] [operator =] [number 1]",
105+
"[keyword let] [def ABC] [operator =] [number 2]",
106+
"[keyword let] [def _123] [operator =] [number 3]",
107+
"[keyword let] [def _$1$2$3] [operator =] [number 4]",
108+
"[keyword let] [def A1$_c32_$_] [operator =] [number 5]",
109+
"[keyword let] [def `var`] [operator =] [punctuation [[][number 1][punctuation ,] [number 2][punctuation ,] [number 3][punctuation ]]]",
110+
"[keyword let] [def square$] [operator =] [variable `var`][property .map] [punctuation {][variable $0] [operator *] [variable $0][punctuation }]",
111+
"$$ [number 1][variable a] $[atom _] [variable _$] [variable __] `[variable a] [variable b]`");
112+
113+
// Properties.
114+
MT("properties",
115+
"[variable print][punctuation (][variable foo][property .abc][punctuation )]",
116+
"[variable print][punctuation (][variable foo][property .ABC][punctuation )]",
117+
"[variable print][punctuation (][variable foo][property ._123][punctuation )]",
118+
"[variable print][punctuation (][variable foo][property ._$1$2$3][punctuation )]",
119+
"[variable print][punctuation (][variable foo][property .A1$_c32_$_][punctuation )]",
120+
"[variable print][punctuation (][variable foo][property .`var`][punctuation )]",
121+
"[variable print][punctuation (][variable foo][property .__][punctuation )]");
122+
123+
// Instructions or other things that start with #.
124+
MT("instructions",
125+
"[keyword if] [instruction #available][punctuation (][variable iOS] [number 9][punctuation ,] [operator *][punctuation )] [punctuation {}",
126+
"[variable print][punctuation (][instruction #file][punctuation ,] [instruction #function][punctuation )]",
127+
"[variable print][punctuation (][instruction #line][punctuation ,] [instruction #column][punctuation )]",
128+
"[instruction #if] [atom true]",
129+
" [keyword import] [variable A]",
130+
"[instruction #elseif] [atom false]",
131+
" [keyword import] [variable B]",
132+
"[instruction #endif]",
133+
"[instruction #sourceLocation][punctuation (][variable file][punctuation :] [string \"file.swift\"][punctuation ,] [variable line][punctuation :] [number 2][punctuation )]");
134+
135+
// Attributes; things that start with @.
136+
MT("attributes",
137+
"[instruction @objc][punctuation (][variable objcFoo][punctuation :)]",
138+
"[instruction @available][punctuation (][variable iOS][punctuation )]");
139+
140+
// Property/number edge case.
141+
MT("property_number",
142+
"[variable print][punctuation (][variable foo][property ._123][punctuation )]",
143+
"[variable print][punctuation (]")
144+
145+
// TODO: correctly identify when multiple variables are being declared
146+
// by use of a comma-separated list.
147+
// TODO: correctly identify when variables are being declared in a tuple.
148+
// TODO: identify protocols as types when used before an extension?
149+
})();

test/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
<script src="../mode/slim/slim.js"></script>
3636
<script src="../mode/sql/sql.js"></script>
3737
<script src="../mode/stex/stex.js"></script>
38+
<script src="../mode/swift/swift.js"></script>
3839
<script src="../mode/textile/textile.js"></script>
3940
<script src="../mode/verilog/verilog.js"></script>
4041
<script src="../mode/xml/xml.js"></script>
@@ -122,6 +123,7 @@ <h2>Test Suite</h2>
122123
<script src="../mode/shell/test.js"></script>
123124
<script src="../mode/slim/test.js"></script>
124125
<script src="../mode/stex/test.js"></script>
126+
<script src="../mode/swift/test.js"></script>
125127
<script src="../mode/textile/test.js"></script>
126128
<script src="../mode/verilog/test.js"></script>
127129
<script src="../mode/xml/test.js"></script>

0 commit comments

Comments
 (0)