You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
8.6 KiB

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