dylan.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. (function(mod) {
  4. if (typeof exports == "object" && typeof module == "object") // CommonJS
  5. mod(require("../../lib/codemirror"));
  6. else if (typeof define == "function" && define.amd) // AMD
  7. define(["../../lib/codemirror"], mod);
  8. else // Plain browser env
  9. mod(CodeMirror);
  10. })(function(CodeMirror) {
  11. "use strict";
  12. function forEach(arr, f) {
  13. for (var i = 0; i < arr.length; i++) f(arr[i], i)
  14. }
  15. function some(arr, f) {
  16. for (var i = 0; i < arr.length; i++) if (f(arr[i], i)) return true
  17. return false
  18. }
  19. CodeMirror.defineMode("dylan", function(_config) {
  20. // Words
  21. var words = {
  22. // Words that introduce unnamed definitions like "define interface"
  23. unnamedDefinition: ["interface"],
  24. // Words that introduce simple named definitions like "define library"
  25. namedDefinition: ["module", "library", "macro",
  26. "C-struct", "C-union",
  27. "C-function", "C-callable-wrapper"
  28. ],
  29. // Words that introduce type definitions like "define class".
  30. // These are also parameterized like "define method" and are
  31. // appended to otherParameterizedDefinitionWords
  32. typeParameterizedDefinition: ["class", "C-subtype", "C-mapped-subtype"],
  33. // Words that introduce trickier definitions like "define method".
  34. // These require special definitions to be added to startExpressions
  35. otherParameterizedDefinition: ["method", "function",
  36. "C-variable", "C-address"
  37. ],
  38. // Words that introduce module constant definitions.
  39. // These must also be simple definitions and are
  40. // appended to otherSimpleDefinitionWords
  41. constantSimpleDefinition: ["constant"],
  42. // Words that introduce module variable definitions.
  43. // These must also be simple definitions and are
  44. // appended to otherSimpleDefinitionWords
  45. variableSimpleDefinition: ["variable"],
  46. // Other words that introduce simple definitions
  47. // (without implicit bodies).
  48. otherSimpleDefinition: ["generic", "domain",
  49. "C-pointer-type",
  50. "table"
  51. ],
  52. // Words that begin statements with implicit bodies.
  53. statement: ["if", "block", "begin", "method", "case",
  54. "for", "select", "when", "unless", "until",
  55. "while", "iterate", "profiling", "dynamic-bind"
  56. ],
  57. // Patterns that act as separators in compound statements.
  58. // This may include any general pattern that must be indented
  59. // specially.
  60. separator: ["finally", "exception", "cleanup", "else",
  61. "elseif", "afterwards"
  62. ],
  63. // Keywords that do not require special indentation handling,
  64. // but which should be highlighted
  65. other: ["above", "below", "by", "from", "handler", "in",
  66. "instance", "let", "local", "otherwise", "slot",
  67. "subclass", "then", "to", "keyed-by", "virtual"
  68. ],
  69. // Condition signaling function calls
  70. signalingCalls: ["signal", "error", "cerror",
  71. "break", "check-type", "abort"
  72. ]
  73. };
  74. words["otherDefinition"] =
  75. words["unnamedDefinition"]
  76. .concat(words["namedDefinition"])
  77. .concat(words["otherParameterizedDefinition"]);
  78. words["definition"] =
  79. words["typeParameterizedDefinition"]
  80. .concat(words["otherDefinition"]);
  81. words["parameterizedDefinition"] =
  82. words["typeParameterizedDefinition"]
  83. .concat(words["otherParameterizedDefinition"]);
  84. words["simpleDefinition"] =
  85. words["constantSimpleDefinition"]
  86. .concat(words["variableSimpleDefinition"])
  87. .concat(words["otherSimpleDefinition"]);
  88. words["keyword"] =
  89. words["statement"]
  90. .concat(words["separator"])
  91. .concat(words["other"]);
  92. // Patterns
  93. var symbolPattern = "[-_a-zA-Z?!*@<>$%]+";
  94. var symbol = new RegExp("^" + symbolPattern);
  95. var patterns = {
  96. // Symbols with special syntax
  97. symbolKeyword: symbolPattern + ":",
  98. symbolClass: "<" + symbolPattern + ">",
  99. symbolGlobal: "\\*" + symbolPattern + "\\*",
  100. symbolConstant: "\\$" + symbolPattern
  101. };
  102. var patternStyles = {
  103. symbolKeyword: "atom",
  104. symbolClass: "tag",
  105. symbolGlobal: "variable-2",
  106. symbolConstant: "variable-3"
  107. };
  108. // Compile all patterns to regular expressions
  109. for (var patternName in patterns)
  110. if (patterns.hasOwnProperty(patternName))
  111. patterns[patternName] = new RegExp("^" + patterns[patternName]);
  112. // Names beginning "with-" and "without-" are commonly
  113. // used as statement macro
  114. patterns["keyword"] = [/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/];
  115. var styles = {};
  116. styles["keyword"] = "keyword";
  117. styles["definition"] = "def";
  118. styles["simpleDefinition"] = "def";
  119. styles["signalingCalls"] = "builtin";
  120. // protected words lookup table
  121. var wordLookup = {};
  122. var styleLookup = {};
  123. forEach([
  124. "keyword",
  125. "definition",
  126. "simpleDefinition",
  127. "signalingCalls"
  128. ], function(type) {
  129. forEach(words[type], function(word) {
  130. wordLookup[word] = type;
  131. styleLookup[word] = styles[type];
  132. });
  133. });
  134. function chain(stream, state, f) {
  135. state.tokenize = f;
  136. return f(stream, state);
  137. }
  138. function tokenBase(stream, state) {
  139. // String
  140. var ch = stream.peek();
  141. if (ch == "'" || ch == '"') {
  142. stream.next();
  143. return chain(stream, state, tokenString(ch, "string"));
  144. }
  145. // Comment
  146. else if (ch == "/") {
  147. stream.next();
  148. if (stream.eat("*")) {
  149. return chain(stream, state, tokenComment);
  150. } else if (stream.eat("/")) {
  151. stream.skipToEnd();
  152. return "comment";
  153. }
  154. stream.backUp(1);
  155. }
  156. // Decimal
  157. else if (/[+\-\d\.]/.test(ch)) {
  158. if (stream.match(/^[+-]?[0-9]*\.[0-9]*([esdx][+-]?[0-9]+)?/i) ||
  159. stream.match(/^[+-]?[0-9]+([esdx][+-]?[0-9]+)/i) ||
  160. stream.match(/^[+-]?\d+/)) {
  161. return "number";
  162. }
  163. }
  164. // Hash
  165. else if (ch == "#") {
  166. stream.next();
  167. // Symbol with string syntax
  168. ch = stream.peek();
  169. if (ch == '"') {
  170. stream.next();
  171. return chain(stream, state, tokenString('"', "string"));
  172. }
  173. // Binary number
  174. else if (ch == "b") {
  175. stream.next();
  176. stream.eatWhile(/[01]/);
  177. return "number";
  178. }
  179. // Hex number
  180. else if (ch == "x") {
  181. stream.next();
  182. stream.eatWhile(/[\da-f]/i);
  183. return "number";
  184. }
  185. // Octal number
  186. else if (ch == "o") {
  187. stream.next();
  188. stream.eatWhile(/[0-7]/);
  189. return "number";
  190. }
  191. // Token concatenation in macros
  192. else if (ch == '#') {
  193. stream.next();
  194. return "punctuation";
  195. }
  196. // Sequence literals
  197. else if ((ch == '[') || (ch == '(')) {
  198. stream.next();
  199. return "bracket";
  200. // Hash symbol
  201. } else if (stream.match(/f|t|all-keys|include|key|next|rest/i)) {
  202. return "atom";
  203. } else {
  204. stream.eatWhile(/[-a-zA-Z]/);
  205. return "error";
  206. }
  207. } else if (ch == "~") {
  208. stream.next();
  209. ch = stream.peek();
  210. if (ch == "=") {
  211. stream.next();
  212. ch = stream.peek();
  213. if (ch == "=") {
  214. stream.next();
  215. return "operator";
  216. }
  217. return "operator";
  218. }
  219. return "operator";
  220. } else if (ch == ":") {
  221. stream.next();
  222. ch = stream.peek();
  223. if (ch == "=") {
  224. stream.next();
  225. return "operator";
  226. } else if (ch == ":") {
  227. stream.next();
  228. return "punctuation";
  229. }
  230. } else if ("[](){}".indexOf(ch) != -1) {
  231. stream.next();
  232. return "bracket";
  233. } else if (".,".indexOf(ch) != -1) {
  234. stream.next();
  235. return "punctuation";
  236. } else if (stream.match("end")) {
  237. return "keyword";
  238. }
  239. for (var name in patterns) {
  240. if (patterns.hasOwnProperty(name)) {
  241. var pattern = patterns[name];
  242. if ((pattern instanceof Array && some(pattern, function(p) {
  243. return stream.match(p);
  244. })) || stream.match(pattern))
  245. return patternStyles[name];
  246. }
  247. }
  248. if (/[+\-*\/^=<>&|]/.test(ch)) {
  249. stream.next();
  250. return "operator";
  251. }
  252. if (stream.match("define")) {
  253. return "def";
  254. } else {
  255. stream.eatWhile(/[\w\-]/);
  256. // Keyword
  257. if (wordLookup.hasOwnProperty(stream.current())) {
  258. return styleLookup[stream.current()];
  259. } else if (stream.current().match(symbol)) {
  260. return "variable";
  261. } else {
  262. stream.next();
  263. return "variable-2";
  264. }
  265. }
  266. }
  267. function tokenComment(stream, state) {
  268. var maybeEnd = false, maybeNested = false, nestedCount = 0, ch;
  269. while ((ch = stream.next())) {
  270. if (ch == "/" && maybeEnd) {
  271. if (nestedCount > 0) {
  272. nestedCount--;
  273. } else {
  274. state.tokenize = tokenBase;
  275. break;
  276. }
  277. } else if (ch == "*" && maybeNested) {
  278. nestedCount++;
  279. }
  280. maybeEnd = (ch == "*");
  281. maybeNested = (ch == "/");
  282. }
  283. return "comment";
  284. }
  285. function tokenString(quote, style) {
  286. return function(stream, state) {
  287. var escaped = false, next, end = false;
  288. while ((next = stream.next()) != null) {
  289. if (next == quote && !escaped) {
  290. end = true;
  291. break;
  292. }
  293. escaped = !escaped && next == "\\";
  294. }
  295. if (end || !escaped) {
  296. state.tokenize = tokenBase;
  297. }
  298. return style;
  299. };
  300. }
  301. // Interface
  302. return {
  303. startState: function() {
  304. return {
  305. tokenize: tokenBase,
  306. currentIndent: 0
  307. };
  308. },
  309. token: function(stream, state) {
  310. if (stream.eatSpace())
  311. return null;
  312. var style = state.tokenize(stream, state);
  313. return style;
  314. },
  315. blockCommentStart: "/*",
  316. blockCommentEnd: "*/"
  317. };
  318. });
  319. CodeMirror.defineMIME("text/x-dylan", "dylan");
  320. });