diff options
Diffstat (limited to 'imports/codemirror/mode/erlang')
-rw-r--r-- | imports/codemirror/mode/erlang/erlang.js | 251 | ||||
-rw-r--r-- | imports/codemirror/mode/erlang/index.html | 61 |
2 files changed, 312 insertions, 0 deletions
diff --git a/imports/codemirror/mode/erlang/erlang.js b/imports/codemirror/mode/erlang/erlang.js new file mode 100644 index 00000000..5c094f8e --- /dev/null +++ b/imports/codemirror/mode/erlang/erlang.js | |||
@@ -0,0 +1,251 @@ | |||
1 | // erlang -> CodeMirror tag | ||
2 | // | ||
3 | // atom -> atom | ||
4 | // attribute -> attribute | ||
5 | // builtin -> builtin | ||
6 | // comment -> comment | ||
7 | // error -> error | ||
8 | // fun -> meta | ||
9 | // function -> tag | ||
10 | // guard -> property | ||
11 | // keyword -> keyword | ||
12 | // macro -> variable-2 | ||
13 | // number -> number | ||
14 | // operator -> operator | ||
15 | // record -> bracket | ||
16 | // string -> string | ||
17 | // type -> def | ||
18 | // variable -> variable | ||
19 | |||
20 | CodeMirror.defineMIME("text/x-erlang", "erlang"); | ||
21 | |||
22 | CodeMirror.defineMode("erlang", function(cmCfg, modeCfg) { | ||
23 | |||
24 | var typeWords = [ | ||
25 | "-type", "-spec", "-export_type", "-opaque"]; | ||
26 | |||
27 | var keywordWords = [ | ||
28 | "after","begin","catch","case","cond","end","fun","if", | ||
29 | "let","of","query","receive","try","when"]; | ||
30 | |||
31 | var operatorWords = [ | ||
32 | "and","andalso","band","bnot","bor","bsl","bsr","bxor", | ||
33 | "div","not","or","orelse","rem","xor"]; | ||
34 | |||
35 | var operatorSymbols = [ | ||
36 | "+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-"]; | ||
37 | |||
38 | var guardWords = [ | ||
39 | "is_atom","is_binary","is_bitstring","is_boolean","is_float", | ||
40 | "is_function","is_integer","is_list","is_number","is_pid", | ||
41 | "is_port","is_record","is_reference","is_tuple", | ||
42 | "atom","binary","bitstring","boolean","function","integer","list", | ||
43 | "number","pid","port","record","reference","tuple"]; | ||
44 | |||
45 | var bifWords = [ | ||
46 | "abs","adler32","adler32_combine","alive","apply","atom_to_binary", | ||
47 | "atom_to_list","binary_to_atom","binary_to_existing_atom", | ||
48 | "binary_to_list","binary_to_term","bit_size","bitstring_to_list", | ||
49 | "byte_size","check_process_code","contact_binary","crc32", | ||
50 | "crc32_combine","date","decode_packet","delete_module", | ||
51 | "disconnect_node","element","erase","exit","float","float_to_list", | ||
52 | "garbage_collect","get","get_keys","group_leader","halt","hd", | ||
53 | "integer_to_list","internal_bif","iolist_size","iolist_to_binary", | ||
54 | "is_alive","is_atom","is_binary","is_bitstring","is_boolean", | ||
55 | "is_float","is_function","is_integer","is_list","is_number","is_pid", | ||
56 | "is_port","is_process_alive","is_record","is_reference","is_tuple", | ||
57 | "length","link","list_to_atom","list_to_binary","list_to_bitstring", | ||
58 | "list_to_existing_atom","list_to_float","list_to_integer", | ||
59 | "list_to_pid","list_to_tuple","load_module","make_ref","module_loaded", | ||
60 | "monitor_node","node","node_link","node_unlink","nodes","notalive", | ||
61 | "now","open_port","pid_to_list","port_close","port_command", | ||
62 | "port_connect","port_control","pre_loaded","process_flag", | ||
63 | "process_info","processes","purge_module","put","register", | ||
64 | "registered","round","self","setelement","size","spawn","spawn_link", | ||
65 | "spawn_monitor","spawn_opt","split_binary","statistics", | ||
66 | "term_to_binary","time","throw","tl","trunc","tuple_size", | ||
67 | "tuple_to_list","unlink","unregister","whereis"]; | ||
68 | |||
69 | function isMember(element,list) { | ||
70 | return (-1 < list.indexOf(element)); | ||
71 | } | ||
72 | |||
73 | function isPrev(stream,string) { | ||
74 | var start = stream.start; | ||
75 | var len = string.length; | ||
76 | if (len <= start) { | ||
77 | var word = stream.string.slice(start-len,start); | ||
78 | return word == string; | ||
79 | }else{ | ||
80 | return false; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | var smallRE = /[a-z_]/; | ||
85 | var largeRE = /[A-Z_]/; | ||
86 | var digitRE = /[0-9]/; | ||
87 | var octitRE = /[0-7]/; | ||
88 | var idRE = /[a-z_A-Z0-9]/; | ||
89 | |||
90 | function tokenize(stream, state) { | ||
91 | if (stream.eatSpace()) { | ||
92 | return null; | ||
93 | } | ||
94 | |||
95 | // attributes and type specs | ||
96 | if (stream.sol() && stream.peek() == '-') { | ||
97 | stream.next(); | ||
98 | if (stream.eat(smallRE) && stream.eatWhile(idRE)) { | ||
99 | if (stream.peek() == "(") { | ||
100 | return "attribute"; | ||
101 | }else if (isMember(stream.current(),typeWords)) { | ||
102 | return "def"; | ||
103 | }else{ | ||
104 | return null; | ||
105 | } | ||
106 | } | ||
107 | stream.backUp(1); | ||
108 | } | ||
109 | |||
110 | var ch = stream.next(); | ||
111 | |||
112 | // comment | ||
113 | if (ch == '%') { | ||
114 | stream.skipToEnd(); | ||
115 | return "comment"; | ||
116 | } | ||
117 | |||
118 | // macro | ||
119 | if (ch == '?') { | ||
120 | stream.eatWhile(idRE); | ||
121 | return "variable-2"; | ||
122 | } | ||
123 | |||
124 | // record | ||
125 | if ( ch == "#") { | ||
126 | stream.eatWhile(idRE); | ||
127 | return "bracket"; | ||
128 | } | ||
129 | |||
130 | // char | ||
131 | if ( ch == "$") { | ||
132 | if (stream.next() == "\\") { | ||
133 | if (!stream.eatWhile(octitRE)) { | ||
134 | stream.next(); | ||
135 | } | ||
136 | } | ||
137 | return "string"; | ||
138 | } | ||
139 | |||
140 | // quoted atom | ||
141 | if (ch == '\'') { | ||
142 | return singleQuote(stream); | ||
143 | } | ||
144 | |||
145 | // string | ||
146 | if (ch == '"') { | ||
147 | return doubleQuote(stream); | ||
148 | } | ||
149 | |||
150 | // variable | ||
151 | if (largeRE.test(ch)) { | ||
152 | stream.eatWhile(idRE); | ||
153 | return "variable"; | ||
154 | } | ||
155 | |||
156 | // atom/keyword/BIF/function | ||
157 | if (smallRE.test(ch)) { | ||
158 | stream.eatWhile(idRE); | ||
159 | |||
160 | if (stream.peek() == "/") { | ||
161 | stream.next(); | ||
162 | if (stream.eatWhile(digitRE)) { | ||
163 | return "meta"; // f/0 style fun | ||
164 | }else{ | ||
165 | stream.backUp(1); | ||
166 | return "atom"; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | var w = stream.current(); | ||
171 | |||
172 | if (isMember(w,keywordWords)) { | ||
173 | return "keyword"; // keyword | ||
174 | } | ||
175 | if (stream.peek() == "(") { | ||
176 | if (isMember(w,bifWords) && | ||
177 | (!isPrev(stream,":") || isPrev(stream,"erlang:"))) { | ||
178 | return "builtin"; // BIF | ||
179 | }else{ | ||
180 | return "tag"; // function | ||
181 | } | ||
182 | } | ||
183 | if (isMember(w,guardWords)) { | ||
184 | return "property"; // guard | ||
185 | } | ||
186 | if (isMember(w,operatorWords)) { | ||
187 | return "operator"; // operator | ||
188 | } | ||
189 | |||
190 | |||
191 | if (stream.peek() == ":") { | ||
192 | if (w == "erlang") { // f:now() is highlighted incorrectly | ||
193 | return "builtin"; | ||
194 | } else { | ||
195 | return "tag"; // function application | ||
196 | } | ||
197 | } | ||
198 | |||
199 | return "atom"; | ||
200 | } | ||
201 | |||
202 | // number | ||
203 | if (digitRE.test(ch)) { | ||
204 | stream.eatWhile(digitRE); | ||
205 | if (stream.eat('#')) { | ||
206 | stream.eatWhile(digitRE); // 16#10 style integer | ||
207 | } else { | ||
208 | if (stream.eat('.')) { // float | ||
209 | stream.eatWhile(digitRE); | ||
210 | } | ||
211 | if (stream.eat(/[eE]/)) { | ||
212 | stream.eat(/[-+]/); // float with exponent | ||
213 | stream.eatWhile(digitRE); | ||
214 | } | ||
215 | } | ||
216 | return "number"; // normal integer | ||
217 | } | ||
218 | |||
219 | return null; | ||
220 | } | ||
221 | |||
222 | function doubleQuote(stream) { | ||
223 | return Quote(stream, '"', '\\', "string"); | ||
224 | } | ||
225 | |||
226 | function singleQuote(stream) { | ||
227 | return Quote(stream,'\'','\\',"atom"); | ||
228 | } | ||
229 | |||
230 | function Quote(stream,quoteChar,escapeChar,tag) { | ||
231 | while (!stream.eol()) { | ||
232 | var ch = stream.next(); | ||
233 | if (ch == quoteChar) { | ||
234 | return tag; | ||
235 | }else if (ch == escapeChar) { | ||
236 | stream.next(); | ||