scripts/CodeMirror/mode/elm/elm.js (view raw)
1// CodeMirror, copyright (c) by Marijn Haverbeke and others
2// Distributed under an MIT license: http://codemirror.net/LICENSE
3
4(function(mod) {
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"));
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror"], mod);
9 else // Plain browser env
10 mod(CodeMirror);
11})(function(CodeMirror) {
12 "use strict";
13
14 CodeMirror.defineMode("elm", function() {
15
16 function switchState(source, setState, f)
17 {
18 setState(f);
19 return f(source, setState);
20 }
21
22 var lowerRE = /[a-z]/;
23 var upperRE = /[A-Z]/;
24 var innerRE = /[a-zA-Z0-9_]/;
25
26 var digitRE = /[0-9]/;
27 var hexRE = /[0-9A-Fa-f]/;
28 var symbolRE = /[-&*+.\\/<>=?^|:]/;
29 var specialRE = /[(),[\]{}]/;
30 var spacesRE = /[ \v\f]/; // newlines are handled in tokenizer
31
32 function normal()
33 {
34 return function(source, setState)
35 {
36 if (source.eatWhile(spacesRE))
37 {
38 return null;
39 }
40
41 var char = source.next();
42
43 if (specialRE.test(char))
44 {
45 return (char === '{' && source.eat('-'))
46 ? switchState(source, setState, chompMultiComment(1))
47 : (char === '[' && source.match('glsl|'))
48 ? switchState(source, setState, chompGlsl)
49 : 'builtin';
50 }
51
52 if (char === '\'')
53 {
54 return switchState(source, setState, chompChar);
55 }
56
57 if (char === '"')
58 {
59 return source.eat('"')
60 ? source.eat('"')
61 ? switchState(source, setState, chompMultiString)
62 : 'string'
63 : switchState(source, setState, chompSingleString);
64 }
65
66 if (upperRE.test(char))
67 {
68 source.eatWhile(innerRE);
69 return 'variable-2';
70 }
71
72 if (lowerRE.test(char))
73 {
74 var isDef = source.pos === 1;
75 source.eatWhile(innerRE);
76 return isDef ? "def" : "variable";
77 }
78
79 if (digitRE.test(char))
80 {
81 if (char === '0')
82 {
83 if (source.eat(/[xX]/))
84 {
85 source.eatWhile(hexRE); // should require at least 1
86 return "number";
87 }
88 }
89 else
90 {
91 source.eatWhile(digitRE);
92 }
93 if (source.eat('.'))
94 {
95 source.eatWhile(digitRE); // should require at least 1
96 }
97 if (source.eat(/[eE]/))
98 {
99 source.eat(/[-+]/);
100 source.eatWhile(digitRE); // should require at least 1
101 }
102 return "number";
103 }
104
105 if (symbolRE.test(char))
106 {
107 if (char === '-' && source.eat('-'))
108 {
109 source.skipToEnd();
110 return "comment";
111 }
112 source.eatWhile(symbolRE);
113 return "keyword";
114 }
115
116 if (char === '_')
117 {
118 return "keyword";
119 }
120
121 return "error";
122 }
123 }
124
125 function chompMultiComment(nest)
126 {
127 if (nest == 0)
128 {
129 return normal();
130 }
131 return function(source, setState)
132 {
133 while (!source.eol())
134 {
135 var char = source.next();
136 if (char == '{' && source.eat('-'))
137 {
138 ++nest;
139 }
140 else if (char == '-' && source.eat('}'))
141 {
142 --nest;
143 if (nest === 0)
144 {
145 setState(normal());
146 return 'comment';
147 }
148 }
149 }
150 setState(chompMultiComment(nest));
151 return 'comment';
152 }
153 }
154
155 function chompMultiString(source, setState)
156 {
157 while (!source.eol())
158 {
159 var char = source.next();
160 if (char === '"' && source.eat('"') && source.eat('"'))
161 {
162 setState(normal());
163 return 'string';
164 }
165 }
166 return 'string';
167 }
168
169 function chompSingleString(source, setState)
170 {
171 while (source.skipTo('\\"')) { source.next(); source.next(); }
172 if (source.skipTo('"'))
173 {
174 source.next();
175 setState(normal());
176 return 'string';
177 }
178 source.skipToEnd();
179 setState(normal());
180 return 'error';
181 }
182
183 function chompChar(source, setState)
184 {
185 while (source.skipTo("\\'")) { source.next(); source.next(); }
186 if (source.skipTo("'"))
187 {
188 source.next();
189 setState(normal());
190 return 'string';
191 }
192 source.skipToEnd();
193 setState(normal());
194 return 'error';
195 }
196
197 function chompGlsl(source, setState)
198 {
199 while (!source.eol())
200 {
201 var char = source.next();
202 if (char === '|' && source.eat(']'))
203 {
204 setState(normal());
205 return 'string';
206 }
207 }
208 return 'string';
209 }
210
211 var wellKnownWords = {
212 case: 1,
213 of: 1,
214 as: 1,
215 if: 1,
216 then: 1,
217 else: 1,
218 let: 1,
219 in: 1,
220 type: 1,
221 alias: 1,
222 module: 1,
223 where: 1,
224 import: 1,
225 exposing: 1,
226 port: 1
227 };
228
229 return {
230 startState: function () { return { f: normal() }; },
231 copyState: function (s) { return { f: s.f }; },
232
233 token: function(stream, state) {
234 var type = state.f(stream, function(s) { state.f = s; });
235 var word = stream.current();
236 return (wellKnownWords.hasOwnProperty(word)) ? 'keyword' : type;
237 }
238 };
239
240 });
241
242 CodeMirror.defineMIME("text/x-elm", "elm");
243});