// erlang -> CodeMirror tag // // atom -> atom // attribute -> attribute // builtin -> builtin // comment -> comment // error -> error // fun -> meta // function -> tag // guard -> property // keyword -> keyword // macro -> variable-2 // number -> number // operator -> operator // record -> bracket // string -> string // type -> def // variable -> variable CodeMirror.defineMIME("text/x-erlang", "erlang"); CodeMirror.defineMode("erlang", function(cmCfg, modeCfg) { var typeWords = [ "-type", "-spec", "-export_type", "-opaque"]; var keywordWords = [ "after","begin","catch","case","cond","end","fun","if", "let","of","query","receive","try","when"]; var operatorWords = [ "and","andalso","band","bnot","bor","bsl","bsr","bxor", "div","not","or","orelse","rem","xor"]; var operatorSymbols = [ "+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-"]; var guardWords = [ "is_atom","is_binary","is_bitstring","is_boolean","is_float", "is_function","is_integer","is_list","is_number","is_pid", "is_port","is_record","is_reference","is_tuple", "atom","binary","bitstring","boolean","function","integer","list", "number","pid","port","record","reference","tuple"]; var bifWords = [ "abs","adler32","adler32_combine","alive","apply","atom_to_binary", "atom_to_list","binary_to_atom","binary_to_existing_atom", "binary_to_list","binary_to_term","bit_size","bitstring_to_list", "byte_size","check_process_code","contact_binary","crc32", "crc32_combine","date","decode_packet","delete_module", "disconnect_node","element","erase","exit","float","float_to_list", "garbage_collect","get","get_keys","group_leader","halt","hd", "integer_to_list","internal_bif","iolist_size","iolist_to_binary", "is_alive","is_atom","is_binary","is_bitstring","is_boolean", "is_float","is_function","is_integer","is_list","is_number","is_pid", "is_port","is_process_alive","is_record","is_reference","is_tuple", "length","link","list_to_atom","list_to_binary","list_to_bitstring", "list_to_existing_atom","list_to_float","list_to_integer", "list_to_pid","list_to_tuple","load_module","make_ref","module_loaded", "monitor_node","node","node_link","node_unlink","nodes","notalive", "now","open_port","pid_to_list","port_close","port_command", "port_connect","port_control","pre_loaded","process_flag", "process_info","processes","purge_module","put","register", "registered","round","self","setelement","size","spawn","spawn_link", "spawn_monitor","spawn_opt","split_binary","statistics", "term_to_binary","time","throw","tl","trunc","tuple_size", "tuple_to_list","unlink","unregister","whereis"]; function isMember(element,list) { return (-1 < list.indexOf(element)); } function isPrev(stream,string) { var start = stream.start; var len = string.length; if (len <= start) { var word = stream.string.slice(start-len,start); return word == string; }else{ return false; } } var smallRE = /[a-z_]/; var largeRE = /[A-Z_]/; var digitRE = /[0-9]/; var octitRE = /[0-7]/; var idRE = /[a-z_A-Z0-9]/; function tokenize(stream, state) { if (stream.eatSpace()) { return null; } // attributes and type specs if (stream.sol() && stream.peek() == '-') { stream.next(); if (stream.eat(smallRE) && stream.eatWhile(idRE)) { if (stream.peek() == "(") { return "attribute"; }else if (isMember(stream.current(),typeWords)) { return "def"; }else{ return null; } } stream.backUp(1); } var ch = stream.next(); // comment if (ch == '%') { stream.skipToEnd(); return "comment"; } // macro if (ch == '?') { stream.eatWhile(idRE); return "variable-2"; } // record if ( ch == "#") { stream.eatWhile(idRE); return "bracket"; } // char if ( ch == "$") { if (stream.next() == "\\") { if (!stream.eatWhile(octitRE)) { stream.next(); } } return "string"; } // quoted atom if (ch == '\'') { return singleQuote(stream); } // string if (ch == '"') { return doubleQuote(stream); } // variable if (largeRE.test(ch)) { stream.eatWhile(idRE); return "variable"; } // atom/keyword/BIF/function if (smallRE.test(ch)) { stream.eatWhile(idRE); if (stream.peek() == "/") { stream.next(); if (stream.eatWhile(digitRE)) { return "meta"; // f/0 style fun }else{ stream.backUp(1); return "atom"; } } var w = stream.current(); if (isMember(w,keywordWords)) { return "keyword"; // keyword } if (stream.peek() == "(") { if (isMember(w,bifWords) && (!isPrev(stream,":") || isPrev(stream,"erlang:"))) { return "builtin"; // BIF }else{ return "tag"; // function } } if (isMember(w,guardWords)) { return "property"; // guard } if (isMember(w,operatorWords)) { return "operator"; // operator } if (stream.peek() == ":") { if (w == "erlang") { // f:now() is highlighted incorrectly return "builtin"; } else { return "tag"; // function application } } return "atom"; } // number if (digitRE.test(ch)) { stream.eatWhile(digitRE); if (stream.eat('#')) { stream.eatWhile(digitRE); // 16#10 style integer } else { if (stream.eat('.')) { // float stream.eatWhile(digitRE); } if (stream.eat(/[eE]/)) { stream.eat(/[-+]/); // float with exponent stream.eatWhile(digitRE); } } return "number"; // normal integer } return null; } function doubleQuote(stream) { return Quote(stream, '"', '\\', "string"); } function singleQuote(stream) { return Quote(stream,'\'','\\',"atom"); } function Quote(stream,quoteChar,escapeChar,tag) { while (!stream.eol()) { var ch = stream.next(); if (ch == quoteChar) { return tag; }else if (ch == escapeChar) { stream.next(); } } return "error"; } return { startState: function() { return {}; }, token: function(stream, state) { return tokenize(stream, state); } }; });