diff options
Diffstat (limited to 'imports/codemirror/mode/rust/rust.js')
-rwxr-xr-x | imports/codemirror/mode/rust/rust.js | 411 |
1 files changed, 411 insertions, 0 deletions
diff --git a/imports/codemirror/mode/rust/rust.js b/imports/codemirror/mode/rust/rust.js new file mode 100755 index 00000000..5ab964c1 --- /dev/null +++ b/imports/codemirror/mode/rust/rust.js | |||
@@ -0,0 +1,411 @@ | |||
1 | CodeMirror.defineMode("rust", function() { | ||
2 | var indentUnit = 4, altIndentUnit = 2; | ||
3 | var valKeywords = { | ||
4 | "if": "if-style", "while": "if-style", "else": "else-style", | ||
5 | "do": "else-style", "ret": "else-style", "fail": "else-style", | ||
6 | "break": "atom", "cont": "atom", "const": "let", "resource": "fn", | ||
7 | "let": "let", "fn": "fn", "for": "for", "alt": "alt", "obj": "fn", | ||
8 | "lambda": "fn", "type": "type", "tag": "tag", "mod": "mod", | ||
9 | "as": "op", "true": "atom", "false": "atom", "assert": "op", "check": "op", | ||
10 | "claim": "op", "native": "ignore", "unsafe": "ignore", "import": "else-style", | ||
11 | "export": "else-style", "copy": "op", "log": "op", "log_err": "op", | ||
12 | "use": "op", "bind": "op" | ||
13 | }; | ||
14 | var typeKeywords = function() { | ||
15 | var keywords = {"fn": "fn", "block": "fn", "obj": "obj"}; | ||
16 | var atoms = "bool uint int i8 i16 i32 i64 u8 u16 u32 u64 float f32 f64 str char".split(" "); | ||
17 | for (var i = 0, e = atoms.length; i < e; ++i) keywords[atoms[i]] = "atom"; | ||
18 | return keywords; | ||
19 | }(); | ||
20 | var operatorChar = /[+\-*&%=<>!?|\.@]/; | ||
21 | |||
22 | // Tokenizer | ||
23 | |||
24 | // Used as scratch variable to communicate multiple values without | ||
25 | // consing up tons of objects. | ||
26 | var tcat, content; | ||
27 | function r(tc, style) { | ||
28 | tcat = tc; | ||
29 | return style; | ||
30 | } | ||
31 | |||
32 | function tokenBase(stream, state) { | ||
33 | var ch = stream.next(); | ||
34 | if (ch == '"') { | ||
35 | state.tokenize = tokenString; | ||
36 | return state.tokenize(stream, state); | ||
37 | } | ||
38 | if (ch == "'") { | ||
39 | tcat = "atom"; | ||
40 | if (stream.eat("\\")) { | ||
41 | if (stream.skipTo("'")) { stream.next(); return "string"; } | ||
42 | else { return "error"; } | ||
43 | } else { | ||
44 | stream.next(); | ||
45 | return stream.eat("'") ? "string" : "error"; | ||
46 | } | ||
47 | } | ||
48 | if (ch == "/") { | ||
49 | if (stream.eat("/")) { stream.skipToEnd(); return "comment"; } | ||
50 | if (stream.eat("*")) { | ||
51 | state.tokenize = tokenComment(1); | ||
52 | return state.tokenize(stream, state); | ||
53 | } | ||
54 | } | ||
55 | if (ch == "#") { | ||
56 | if (stream.eat("[")) { tcat = "open-attr"; return null; } | ||
57 | stream.eatWhile(/\w/); | ||
58 | return r("macro", "meta"); | ||
59 | } | ||
60 | if (ch == ":" && stream.match(":<")) { | ||
61 | return r("op", null); | ||
62 | } | ||
63 | if (ch.match(/\d/) || (ch == "." && stream.eat(/\d/))) { | ||
64 | var flp = false; | ||
65 | if (!stream.match(/^x[\da-f]+/i) && !stream.match(/^b[01]+/)) { | ||
66 | stream.eatWhile(/\d/); | ||
67 | if (stream.eat(".")) { flp = true; stream.eatWhile(/\d/); } | ||
68 | if (stream.match(/^e[+\-]?\d+/i)) { flp = true; } | ||
69 | } | ||
70 | if (flp) stream.match(/^f(?:32|64)/); | ||
71 | else stream.match(/^[ui](?:8|16|32|64)/); | ||
72 | return r("atom", "number"); | ||
73 | } | ||
74 | if (ch.match(/[()\[\]{}:;,]/)) return r(ch, null); | ||
75 | if (ch == "-" && stream.eat(">")) return r("->", null); | ||
76 | if (ch.match(operatorChar)) { | ||
77 | stream.eatWhile(operatorChar); | ||
78 | return r("op", null); | ||
79 | } | ||
80 | stream.eatWhile(/\w/); | ||
81 | content = stream.current(); | ||
82 | if (stream.match(/^::\w/)) { | ||
83 | stream.backUp(1); | ||
84 | return r("prefix", "variable-2"); | ||
85 | } | ||
86 | if (state.keywords.propertyIsEnumerable(content)) | ||
87 | return r(state.keywords[content], content.match(/true|false/) ? "atom" : "keyword"); | ||
88 | return r("name", "variable"); | ||
89 | } | ||
90 | |||
91 | function tokenString(stream, state) { | ||
92 | var ch, escaped = false; | ||
93 | while (ch = stream.next()) { | ||
94 | if (ch == '"' && !escaped) { | ||
95 | state.tokenize = tokenBase; | ||
96 | return r("atom", "string"); | ||
97 | } | ||
98 | escaped = !escaped && ch == "\\"; | ||
99 | } | ||
100 | // Hack to not confuse the parser when a string is split in | ||
101 | // pieces. | ||
102 | return r("op", "string"); | ||
103 | } | ||
104 | |||
105 | function tokenComment(depth) { | ||
106 | return function(stream, state) { | ||
107 | var lastCh = null, ch; | ||
108 | while (ch = stream.next()) { | ||
109 | if (ch == "/" && lastCh == "*") { | ||
110 | if (depth == 1) { | ||
111 | state.tokenize = tokenBase; | ||
112 | break; | ||
113 | } else { | ||
114 | state.tokenize = tokenComment(depth - 1); | ||
115 | return state.tokenize(stream, state); | ||
116 | } | ||
117 | } | ||
118 | if (ch == "*" && lastCh == "/") { | ||
119 | state.tokenize = tokenComment(depth + 1); | ||
120 | return state.tokenize(stream, state); | ||
121 | } | ||
122 | lastCh = ch; | ||
123 | } | ||
124 | return "comment"; | ||
125 | }; | ||
126 | } | ||
127 | |||
128 | // Parser | ||
129 | |||
130 | var cx = {state: null, stream: null, marked: null, cc: null}; | ||
131 | function pass() { | ||
132 | for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); | ||
133 | } | ||
134 | function cont() { | ||
135 | pass.apply(null, arguments); | ||
136 | return true; | ||
137 | } | ||
138 | |||
139 | function pushlex(type, info) { | ||
140 | var result = function() { | ||
141 | var state = cx.state; | ||
142 | state.lexical = {indented: state.indented, column: cx.stream.column(), | ||
143 | type: type, prev: state.lexical, info: info}; | ||
144 | }; | ||
145 | result.lex = true; | ||
146 | return result; | ||
147 | } | ||
148 | function poplex() { | ||
149 | var state = cx.state; | ||
150 | if (state.lexical.prev) { | ||
151 | if (state.lexical.type == ")") | ||
152 | state.indented = state.lexical.indented; | ||
153 | state.lexical = state.lexical.prev; | ||
154 | } | ||
155 | } | ||
156 | function typecx() { cx.state.keywords = typeKeywords; } | ||
157 | function valcx() { cx.state.keywords = valKeywords; } | ||
158 | poplex.lex = typecx.lex = valcx.lex = true; | ||
159 | |||
160 | function commasep(comb, end) { | ||
161 | function more(type) { | ||
162 | if (type == ",") return cont(comb, more); | ||
163 | if (type == end) return cont(); | ||
164 | return cont(more); | ||
165 | } | ||
166 | return function(type) { | ||
167 | if (type == end) return cont(); | ||
168 | return pass(comb, more); | ||
169 | }; | ||
170 | } | ||
171 | |||
172 | function block(type) { | ||
173 | if (type == "}") return cont(); | ||
174 | if (type == "let") return cont(pushlex("stat", "let"), letdef1, poplex, block); | ||
175 | if (type == "fn") return cont(pushlex("stat"), fndef, poplex, block); | ||
176 | if (type == "type") return cont(pushlex("stat"), tydef, endstatement, poplex, block); | ||
177 | if (type == "tag") return cont(pushlex("stat"), tagdef, poplex, block); | ||
178 | if (type == "mod") return cont(pushlex("stat"), mod, poplex, block); | ||
179 | if (type == "open-attr") return cont(pushlex("]"), commasep(expression, "]"), poplex); | ||
180 | if (type == "ignore" || type.match(/[\]\);,]/)) return cont(block); | ||
181 | return pass(pushlex("stat"), expression, poplex, endstatement, block); | ||
182 | } | ||
183 | function endstatement(type) { | ||
184 | if (type == ";") return cont(); | ||
185 | return pass(); | ||
186 | } | ||
187 | function expression(type) { | ||
188 | if (type == "atom" || type == "name") return cont(maybeop); | ||
189 | if (type == "{") return cont(pushlex("}"), exprbrace, poplex); | ||
190 | if (type.match(/[\[\(]/)) return matchBrackets(type, expression); | ||
191 | if (type.match(/[\]\)\};,]/)) return pass(); | ||
192 | if (type == "if-style") return cont(expression, expression); | ||
193 | if (type == "else-style" || type == "op") return cont(expression); | ||
194 | if (type == "for") return cont(pattern, maybetype, inop, expression, expression); | ||
195 | if (type == "alt") return cont(expression, altbody); | ||
196 | if (type == "fn") return cont(fndef); | ||
197 | if (type == "macro") return cont(macro); | ||
198 | return cont(); | ||
199 | } | ||
200 | function maybeop(type) { | ||
201 | if (content == ".") return cont(maybeprop); | ||
202 | if (content == "::<"){return cont(typarams, maybeop);} | ||
203 | if (type == "op" || content == ":") return cont(expression); | ||
204 | if (type == "(" || type == "[") return matchBrackets(type, expression); | ||
205 | return pass(); | ||
206 | } | ||
207 | function maybeprop(type) { | ||
208 | if (content.match(/^\w+$/)) {cx.marked = "variable"; return cont(maybeop);} | ||
209 | return pass(expression); | ||
210 | } | ||
211 | function exprbrace(type) { | ||
212 | if (type == "op") { | ||
213 | if (content == "|") return cont(blockvars, poplex, pushlex("}", "block"), block); | ||
214 | if (content == "||") return cont(poplex, pushlex("}", "block"), block); | ||
215 | } | ||
216 | if (content == "mutable" || (content.match(/^\w+$/) && cx.stream.peek() == ":" | ||
217 | && !cx.stream.match("::", false))) | ||
218 | return pass(record_of(expression)); | ||
219 | return pass(block); | ||
220 | } | ||
221 | function record_of(comb) { | ||
222 | function ro(type) { | ||
223 | if (content == "mutable" || content == "with") {cx.marked = "keyword"; return cont(ro);} | ||
224 | if (content.match(/^\w*$/)) {cx.marked = "variable"; return cont(ro);} | ||
225 | if (type == ":") return cont(comb, ro); | ||
226 | if (type == "}") return cont(); | ||
227 | return cont(ro); | ||
228 | } | ||
229 | return ro; | ||
230 | } | ||
231 | function blockvars(type) { | ||
232 | if (type == "name") {cx.marked = "def"; return cont(blockvars); |