annotate .cms/lib/codemirror/mode/erlang/erlang.js @ 1:1d486627aa1e draft default tip

24.10
author Coffee CMS <info@coffee-cms.ru>
date Sat, 12 Oct 2024 02:51:39 +0000
parents 78edf6b517a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
2 // Distributed under an MIT license: https://codemirror.net/5/LICENSE
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
3
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
4 /*jshint unused:true, eqnull:true, curly:true, bitwise:true */
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
5 /*jshint undef:true, latedef:true, trailing:true */
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
6 /*global CodeMirror:true */
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
7
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
8 // erlang mode.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
9 // tokenizer -> token types -> CodeMirror styles
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
10 // tokenizer maintains a parse stack
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
11 // indenter uses the parse stack
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
12
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
13 // TODO indenter:
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
14 // bit syntax
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
15 // old guard/bif/conversion clashes (e.g. "float/1")
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
16 // type/spec/opaque
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
17
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
18 (function(mod) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
19 if (typeof exports == "object" && typeof module == "object") // CommonJS
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
20 mod(require("../../lib/codemirror"));
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
21 else if (typeof define == "function" && define.amd) // AMD
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
22 define(["../../lib/codemirror"], mod);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
23 else // Plain browser env
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
24 mod(CodeMirror);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
25 })(function(CodeMirror) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
26 "use strict";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
27
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
28 CodeMirror.defineMIME("text/x-erlang", "erlang");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
29
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
30 CodeMirror.defineMode("erlang", function(cmCfg) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
31 "use strict";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
32
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
33 /////////////////////////////////////////////////////////////////////////////
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
34 // constants
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
35
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
36 var typeWords = [
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
37 "-type", "-spec", "-export_type", "-opaque"];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
38
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
39 var keywordWords = [
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
40 "after","begin","catch","case","cond","end","fun","if",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
41 "let","of","query","receive","try","when"];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
42
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
43 var separatorRE = /[\->,;]/;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
44 var separatorWords = [
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
45 "->",";",","];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
46
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
47 var operatorAtomWords = [
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
48 "and","andalso","band","bnot","bor","bsl","bsr","bxor",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
49 "div","not","or","orelse","rem","xor"];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
50
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
51 var operatorSymbolRE = /[\+\-\*\/<>=\|:!]/;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
52 var operatorSymbolWords = [
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
53 "=","+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-","!"];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
54
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
55 var openParenRE = /[<\(\[\{]/;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
56 var openParenWords = [
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
57 "<<","(","[","{"];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
58
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
59 var closeParenRE = /[>\)\]\}]/;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
60 var closeParenWords = [
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
61 "}","]",")",">>"];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
62
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
63 var guardWords = [
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
64 "is_atom","is_binary","is_bitstring","is_boolean","is_float",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
65 "is_function","is_integer","is_list","is_number","is_pid",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
66 "is_port","is_record","is_reference","is_tuple",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
67 "atom","binary","bitstring","boolean","function","integer","list",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
68 "number","pid","port","record","reference","tuple"];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
69
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
70 var bifWords = [
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
71 "abs","adler32","adler32_combine","alive","apply","atom_to_binary",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
72 "atom_to_list","binary_to_atom","binary_to_existing_atom",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
73 "binary_to_list","binary_to_term","bit_size","bitstring_to_list",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
74 "byte_size","check_process_code","contact_binary","crc32",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
75 "crc32_combine","date","decode_packet","delete_module",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
76 "disconnect_node","element","erase","exit","float","float_to_list",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
77 "garbage_collect","get","get_keys","group_leader","halt","hd",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
78 "integer_to_list","internal_bif","iolist_size","iolist_to_binary",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
79 "is_alive","is_atom","is_binary","is_bitstring","is_boolean",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
80 "is_float","is_function","is_integer","is_list","is_number","is_pid",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
81 "is_port","is_process_alive","is_record","is_reference","is_tuple",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
82 "length","link","list_to_atom","list_to_binary","list_to_bitstring",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
83 "list_to_existing_atom","list_to_float","list_to_integer",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
84 "list_to_pid","list_to_tuple","load_module","make_ref","module_loaded",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
85 "monitor_node","node","node_link","node_unlink","nodes","notalive",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
86 "now","open_port","pid_to_list","port_close","port_command",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
87 "port_connect","port_control","pre_loaded","process_flag",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
88 "process_info","processes","purge_module","put","register",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
89 "registered","round","self","setelement","size","spawn","spawn_link",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
90 "spawn_monitor","spawn_opt","split_binary","statistics",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
91 "term_to_binary","time","throw","tl","trunc","tuple_size",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
92 "tuple_to_list","unlink","unregister","whereis"];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
93
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
94 // upper case: [A-Z] [Ø-Þ] [À-Ö]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
95 // lower case: [a-z] [ß-ö] [ø-ÿ]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
96 var anumRE = /[\w@Ø-ÞÀ-Öß-öø-ÿ]/;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
97 var escapesRE =
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
98 /[0-7]{1,3}|[bdefnrstv\\"']|\^[a-zA-Z]|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}/;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
99
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
100 /////////////////////////////////////////////////////////////////////////////
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
101 // tokenizer
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
102
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
103 function tokenizer(stream,state) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
104 // in multi-line string
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
105 if (state.in_string) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
106 state.in_string = (!doubleQuote(stream));
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
107 return rval(state,stream,"string");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
108 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
109
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
110 // in multi-line atom
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
111 if (state.in_atom) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
112 state.in_atom = (!singleQuote(stream));
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
113 return rval(state,stream,"atom");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
114 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
115
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
116 // whitespace
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
117 if (stream.eatSpace()) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
118 return rval(state,stream,"whitespace");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
119 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
120
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
121 // attributes and type specs
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
122 if (!peekToken(state) &&
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
123 stream.match(/-\s*[a-zß-öø-ÿ][\wØ-ÞÀ-Öß-öø-ÿ]*/)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
124 if (is_member(stream.current(),typeWords)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
125 return rval(state,stream,"type");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
126 }else{
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
127 return rval(state,stream,"attribute");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
128 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
129 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
130
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
131 var ch = stream.next();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
132
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
133 // comment
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
134 if (ch == '%') {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
135 stream.skipToEnd();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
136 return rval(state,stream,"comment");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
137 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
138
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
139 // colon
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
140 if (ch == ":") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
141 return rval(state,stream,"colon");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
142 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
143
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
144 // macro
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
145 if (ch == '?') {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
146 stream.eatSpace();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
147 stream.eatWhile(anumRE);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
148 return rval(state,stream,"macro");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
149 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
150
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
151 // record
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
152 if (ch == "#") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
153 stream.eatSpace();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
154 stream.eatWhile(anumRE);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
155 return rval(state,stream,"record");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
156 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
157
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
158 // dollar escape
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
159 if (ch == "$") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
160 if (stream.next() == "\\" && !stream.match(escapesRE)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
161 return rval(state,stream,"error");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
162 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
163 return rval(state,stream,"number");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
164 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
165
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
166 // dot
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
167 if (ch == ".") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
168 return rval(state,stream,"dot");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
169 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
170
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
171 // quoted atom
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
172 if (ch == '\'') {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
173 if (!(state.in_atom = (!singleQuote(stream)))) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
174 if (stream.match(/\s*\/\s*[0-9]/,false)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
175 stream.match(/\s*\/\s*[0-9]/,true);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
176 return rval(state,stream,"fun"); // 'f'/0 style fun
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
177 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
178 if (stream.match(/\s*\(/,false) || stream.match(/\s*:/,false)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
179 return rval(state,stream,"function");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
180 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
181 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
182 return rval(state,stream,"atom");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
183 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
184
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
185 // string
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
186 if (ch == '"') {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
187 state.in_string = (!doubleQuote(stream));
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
188 return rval(state,stream,"string");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
189 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
190
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
191 // variable
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
192 if (/[A-Z_Ø-ÞÀ-Ö]/.test(ch)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
193 stream.eatWhile(anumRE);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
194 return rval(state,stream,"variable");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
195 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
196
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
197 // atom/keyword/BIF/function
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
198 if (/[a-z_ß-öø-ÿ]/.test(ch)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
199 stream.eatWhile(anumRE);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
200
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
201 if (stream.match(/\s*\/\s*[0-9]/,false)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
202 stream.match(/\s*\/\s*[0-9]/,true);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
203 return rval(state,stream,"fun"); // f/0 style fun
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
204 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
205
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
206 var w = stream.current();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
207
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
208 if (is_member(w,keywordWords)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
209 return rval(state,stream,"keyword");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
210 }else if (is_member(w,operatorAtomWords)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
211 return rval(state,stream,"operator");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
212 }else if (stream.match(/\s*\(/,false)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
213 // 'put' and 'erlang:put' are bifs, 'foo:put' is not
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
214 if (is_member(w,bifWords) &&
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
215 ((peekToken(state).token != ":") ||
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
216 (peekToken(state,2).token == "erlang"))) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
217 return rval(state,stream,"builtin");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
218 }else if (is_member(w,guardWords)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
219 return rval(state,stream,"guard");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
220 }else{
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
221 return rval(state,stream,"function");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
222 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
223 }else if (lookahead(stream) == ":") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
224 if (w == "erlang") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
225 return rval(state,stream,"builtin");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
226 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
227 return rval(state,stream,"function");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
228 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
229 }else if (is_member(w,["true","false"])) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
230 return rval(state,stream,"boolean");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
231 }else{
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
232 return rval(state,stream,"atom");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
233 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
234 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
235
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
236 // number
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
237 var digitRE = /[0-9]/;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
238 var radixRE = /[0-9a-zA-Z]/; // 36#zZ style int
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
239 if (digitRE.test(ch)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
240 stream.eatWhile(digitRE);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
241 if (stream.eat('#')) { // 36#aZ style integer
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
242 if (!stream.eatWhile(radixRE)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
243 stream.backUp(1); //"36#" - syntax error
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
244 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
245 } else if (stream.eat('.')) { // float
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
246 if (!stream.eatWhile(digitRE)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
247 stream.backUp(1); // "3." - probably end of function
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
248 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
249 if (stream.eat(/[eE]/)) { // float with exponent
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
250 if (stream.eat(/[-+]/)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
251 if (!stream.eatWhile(digitRE)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
252 stream.backUp(2); // "2e-" - syntax error
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
253 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
254 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
255 if (!stream.eatWhile(digitRE)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
256 stream.backUp(1); // "2e" - syntax error
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
257 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
258 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
259 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
260 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
261 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
262 return rval(state,stream,"number"); // normal integer
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
263 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
264
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
265 // open parens
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
266 if (nongreedy(stream,openParenRE,openParenWords)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
267 return rval(state,stream,"open_paren");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
268 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
269
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
270 // close parens
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
271 if (nongreedy(stream,closeParenRE,closeParenWords)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
272 return rval(state,stream,"close_paren");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
273 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
274
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
275 // separators
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
276 if (greedy(stream,separatorRE,separatorWords)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
277 return rval(state,stream,"separator");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
278 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
279
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
280 // operators
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
281 if (greedy(stream,operatorSymbolRE,operatorSymbolWords)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
282 return rval(state,stream,"operator");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
283 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
284
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
285 return rval(state,stream,null);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
286 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
287
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
288 /////////////////////////////////////////////////////////////////////////////
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
289 // utilities
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
290 function nongreedy(stream,re,words) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
291 if (stream.current().length == 1 && re.test(stream.current())) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
292 stream.backUp(1);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
293 while (re.test(stream.peek())) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
294 stream.next();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
295 if (is_member(stream.current(),words)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
296 return true;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
297 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
298 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
299 stream.backUp(stream.current().length-1);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
300 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
301 return false;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
302 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
303
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
304 function greedy(stream,re,words) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
305 if (stream.current().length == 1 && re.test(stream.current())) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
306 while (re.test(stream.peek())) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
307 stream.next();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
308 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
309 while (0 < stream.current().length) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
310 if (is_member(stream.current(),words)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
311 return true;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
312 }else{
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
313 stream.backUp(1);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
314 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
315 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
316 stream.next();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
317 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
318 return false;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
319 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
320
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
321 function doubleQuote(stream) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
322 return quote(stream, '"', '\\');
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
323 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
324
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
325 function singleQuote(stream) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
326 return quote(stream,'\'','\\');
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
327 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
328
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
329 function quote(stream,quoteChar,escapeChar) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
330 while (!stream.eol()) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
331 var ch = stream.next();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
332 if (ch == quoteChar) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
333 return true;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
334 }else if (ch == escapeChar) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
335 stream.next();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
336 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
337 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
338 return false;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
339 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
340
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
341 function lookahead(stream) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
342 var m = stream.match(/^\s*([^\s%])/, false)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
343 return m ? m[1] : "";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
344 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
345
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
346 function is_member(element,list) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
347 return (-1 < list.indexOf(element));
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
348 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
349
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
350 function rval(state,stream,type) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
351
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
352 // parse stack
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
353 pushToken(state,realToken(type,stream));
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
354
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
355 // map erlang token type to CodeMirror style class
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
356 // erlang -> CodeMirror tag
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
357 switch (type) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
358 case "atom": return "atom";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
359 case "attribute": return "attribute";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
360 case "boolean": return "atom";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
361 case "builtin": return "builtin";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
362 case "close_paren": return null;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
363 case "colon": return null;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
364 case "comment": return "comment";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
365 case "dot": return null;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
366 case "error": return "error";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
367 case "fun": return "meta";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
368 case "function": return "tag";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
369 case "guard": return "property";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
370 case "keyword": return "keyword";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
371 case "macro": return "variable-2";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
372 case "number": return "number";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
373 case "open_paren": return null;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
374 case "operator": return "operator";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
375 case "record": return "bracket";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
376 case "separator": return null;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
377 case "string": return "string";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
378 case "type": return "def";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
379 case "variable": return "variable";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
380 default: return null;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
381 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
382 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
383
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
384 function aToken(tok,col,ind,typ) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
385 return {token: tok,
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
386 column: col,
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
387 indent: ind,
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
388 type: typ};
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
389 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
390
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
391 function realToken(type,stream) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
392 return aToken(stream.current(),
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
393 stream.column(),
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
394 stream.indentation(),
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
395 type);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
396 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
397
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
398 function fakeToken(type) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
399 return aToken(type,0,0,type);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
400 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
401
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
402 function peekToken(state,depth) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
403 var len = state.tokenStack.length;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
404 var dep = (depth ? depth : 1);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
405
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
406 if (len < dep) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
407 return false;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
408 }else{
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
409 return state.tokenStack[len-dep];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
410 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
411 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
412
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
413 function pushToken(state,token) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
414
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
415 if (!(token.type == "comment" || token.type == "whitespace")) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
416 state.tokenStack = maybe_drop_pre(state.tokenStack,token);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
417 state.tokenStack = maybe_drop_post(state.tokenStack);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
418 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
419 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
420
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
421 function maybe_drop_pre(s,token) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
422 var last = s.length-1;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
423
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
424 if (0 < last && s[last].type === "record" && token.type === "dot") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
425 s.pop();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
426 }else if (0 < last && s[last].type === "group") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
427 s.pop();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
428 s.push(token);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
429 }else{
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
430 s.push(token);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
431 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
432 return s;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
433 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
434
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
435 function maybe_drop_post(s) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
436 if (!s.length) return s
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
437 var last = s.length-1;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
438
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
439 if (s[last].type === "dot") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
440 return [];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
441 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
442 if (last > 1 && s[last].type === "fun" && s[last-1].token === "fun") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
443 return s.slice(0,last-1);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
444 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
445 switch (s[last].token) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
446 case "}": return d(s,{g:["{"]});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
447 case "]": return d(s,{i:["["]});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
448 case ")": return d(s,{i:["("]});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
449 case ">>": return d(s,{i:["<<"]});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
450 case "end": return d(s,{i:["begin","case","fun","if","receive","try"]});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
451 case ",": return d(s,{e:["begin","try","when","->",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
452 ",","(","[","{","<<"]});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
453 case "->": return d(s,{r:["when"],
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
454 m:["try","if","case","receive"]});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
455 case ";": return d(s,{E:["case","fun","if","receive","try","when"]});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
456 case "catch":return d(s,{e:["try"]});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
457 case "of": return d(s,{e:["case"]});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
458 case "after":return d(s,{e:["receive","try"]});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
459 default: return s;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
460 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
461 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
462
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
463 function d(stack,tt) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
464 // stack is a stack of Token objects.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
465 // tt is an object; {type:tokens}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
466 // type is a char, tokens is a list of token strings.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
467 // The function returns (possibly truncated) stack.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
468 // It will descend the stack, looking for a Token such that Token.token
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
469 // is a member of tokens. If it does not find that, it will normally (but
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
470 // see "E" below) return stack. If it does find a match, it will remove
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
471 // all the Tokens between the top and the matched Token.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
472 // If type is "m", that is all it does.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
473 // If type is "i", it will also remove the matched Token and the top Token.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
474 // If type is "g", like "i", but add a fake "group" token at the top.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
475 // If type is "r", it will remove the matched Token, but not the top Token.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
476 // If type is "e", it will keep the matched Token but not the top Token.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
477 // If type is "E", it behaves as for type "e", except if there is no match,
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
478 // in which case it will return an empty stack.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
479
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
480 for (var type in tt) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
481 var len = stack.length-1;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
482 var tokens = tt[type];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
483 for (var i = len-1; -1 < i ; i--) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
484 if (is_member(stack[i].token,tokens)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
485 var ss = stack.slice(0,i);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
486 switch (type) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
487 case "m": return ss.concat(stack[i]).concat(stack[len]);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
488 case "r": return ss.concat(stack[len]);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
489 case "i": return ss;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
490 case "g": return ss.concat(fakeToken("group"));
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
491 case "E": return ss.concat(stack[i]);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
492 case "e": return ss.concat(stack[i]);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
493 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
494 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
495 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
496 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
497 return (type == "E" ? [] : stack);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
498 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
499
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
500 /////////////////////////////////////////////////////////////////////////////
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
501 // indenter
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
502
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
503 function indenter(state,textAfter) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
504 var t;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
505 var unit = cmCfg.indentUnit;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
506 var wordAfter = wordafter(textAfter);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
507 var currT = peekToken(state,1);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
508 var prevT = peekToken(state,2);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
509
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
510 if (state.in_string || state.in_atom) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
511 return CodeMirror.Pass;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
512 }else if (!prevT) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
513 return 0;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
514 }else if (currT.token == "when") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
515 return currT.column+unit;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
516 }else if (wordAfter === "when" && prevT.type === "function") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
517 return prevT.indent+unit;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
518 }else if (wordAfter === "(" && currT.token === "fun") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
519 return currT.column+3;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
520 }else if (wordAfter === "catch" && (t = getToken(state,["try"]))) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
521 return t.column;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
522 }else if (is_member(wordAfter,["end","after","of"])) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
523 t = getToken(state,["begin","case","fun","if","receive","try"]);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
524 return t ? t.column : CodeMirror.Pass;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
525 }else if (is_member(wordAfter,closeParenWords)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
526 t = getToken(state,openParenWords);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
527 return t ? t.column : CodeMirror.Pass;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
528 }else if (is_member(currT.token,[",","|","||"]) ||
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
529 is_member(wordAfter,[",","|","||"])) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
530 t = postcommaToken(state);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
531 return t ? t.column+t.token.length : unit;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
532 }else if (currT.token == "->") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
533 if (is_member(prevT.token, ["receive","case","if","try"])) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
534 return prevT.column+unit+unit;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
535 }else{
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
536 return prevT.column+unit;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
537 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
538 }else if (is_member(currT.token,openParenWords)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
539 return currT.column+currT.token.length;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
540 }else{
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
541 t = defaultToken(state);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
542 return truthy(t) ? t.column+unit : 0;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
543 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
544 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
545
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
546 function wordafter(str) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
547 var m = str.match(/,|[a-z]+|\}|\]|\)|>>|\|+|\(/);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
548
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
549 return truthy(m) && (m.index === 0) ? m[0] : "";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
550 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
551
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
552 function postcommaToken(state) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
553 var objs = state.tokenStack.slice(0,-1);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
554 var i = getTokenIndex(objs,"type",["open_paren"]);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
555
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
556 return truthy(objs[i]) ? objs[i] : false;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
557 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
558
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
559 function defaultToken(state) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
560 var objs = state.tokenStack;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
561 var stop = getTokenIndex(objs,"type",["open_paren","separator","keyword"]);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
562 var oper = getTokenIndex(objs,"type",["operator"]);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
563
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
564 if (truthy(stop) && truthy(oper) && stop < oper) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
565 return objs[stop+1];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
566 } else if (truthy(stop)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
567 return objs[stop];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
568 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
569 return false;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
570 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
571 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
572
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
573 function getToken(state,tokens) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
574 var objs = state.tokenStack;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
575 var i = getTokenIndex(objs,"token",tokens);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
576
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
577 return truthy(objs[i]) ? objs[i] : false;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
578 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
579
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
580 function getTokenIndex(objs,propname,propvals) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
581
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
582 for (var i = objs.length-1; -1 < i ; i--) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
583 if (is_member(objs[i][propname],propvals)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
584 return i;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
585 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
586 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
587 return false;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
588 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
589
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
590 function truthy(x) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
591 return (x !== false) && (x != null);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
592 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
593
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
594 /////////////////////////////////////////////////////////////////////////////
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
595 // this object defines the mode
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
596
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
597 return {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
598 startState:
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
599 function() {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
600 return {tokenStack: [],
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
601 in_string: false,
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
602 in_atom: false};
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
603 },
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
604
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
605 token:
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
606 function(stream, state) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
607 return tokenizer(stream, state);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
608 },
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
609
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
610 indent:
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
611 function(state, textAfter) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
612 return indenter(state,textAfter);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
613 },
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
614
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
615 lineComment: "%"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
616 };
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
617 });
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
618
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
619 });