dylan.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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. function tokenBase(stream, state) {
  132. // String
  133. var ch = stream.peek();
  134. if (ch == "'" || ch == '"') {
  135. stream.next();
  136. return chain(stream, state, tokenString(ch, "string"));
  137. }
  138. // Comment
  139. else if (ch == "/") {
  140. stream.next();
  141. if (stream.eat("*")) {
  142. return chain(stream, state, tokenComment);
  143. } else if (stream.eat("/")) {
  144. stream.skipToEnd();
  145. return "comment";
  146. }
  147. stream.backUp(1);
  148. }
  149. // Decimal
  150. else if (/[+\-\d\.]/.test(ch)) {
  151. if (stream.match(/^[+-]?[0-9]*\.[0-9]*([esdx][+-]?[0-9]+)?/i) ||
  152. stream.match(/^[+-]?[0-9]+([esdx][+-]?[0-9]+)/i) ||
  153. stream.match(/^[+-]?\d+/)) {
  154. return "number";
  155. }
  156. }
  157. // Hash
  158. else if (ch == "#") {
  159. stream.next();
  160. // Symbol with string syntax
  161. ch = stream.peek();
  162. if (ch == '"') {
  163. stream.next();
  164. return chain(stream, state, tokenString('"', "string"));
  165. }
  166. // Binary number
  167. else if (ch == "b") {
  168. stream.next();
  169. stream.eatWhile(/[01]/);
  170. return "number";
  171. }
  172. // Hex number
  173. else if (ch == "x") {
  174. stream.next();
  175. stream.eatWhile(/[\da-f]/i);
  176. return "number";
  177. }
  178. // Octal number
  179. else if (ch == "o") {
  180. stream.next();
  181. stream.eatWhile(/[0-7]/);
  182. return "number";
  183. }
  184. // Token concatenation in macros
  185. else if (ch == '#') {
  186. stream.next();
  187. return "punctuation";
  188. }
  189. // Sequence literals
  190. else if ((ch == '[') || (ch == '(')) {
  191. stream.next();
  192. return "bracket";
  193. // Hash symbol
  194. } else if (stream.match(/f|t|all-keys|include|key|next|rest/i)) {
  195. return "atom";
  196. } else {
  197. stream.eatWhile(/[-a-zA-Z]/);
  198. return "error";
  199. }
  200. } else if (ch == "~") {
  201. stream.next();
  202. ch = stream.peek();
  203. if (ch == "=") {
  204. stream.next();
  205. ch = stream.peek();
  206. if (ch == "=") {
  207. stream.next();
  208. return "operator";
  209. }
  210. return "operator";
  211. }
  212. return "operator";
  213. } else if (ch == ":") {
  214. stream.next();
  215. ch = stream.peek();
  216. if (ch == "=") {
  217. stream.next();
  218. return "operator";
  219. } else if (ch == ":") {
  220. stream.next();
  221. return "punctuation";
  222. }
  223. } else if ("[](){}".indexOf(ch) != -1) {
  224. stream.next();
  225. return "bracket";
  226. } else if (".,".indexOf(ch) != -1) {
  227. stream.next();
  228. return "punctuation";
  229. } else if (stream.match("end")) {
  230. return "keyword";
  231. }
  232. for (var name in patterns) {
  233. if (patterns.hasOwnProperty(name)) {
  234. var pattern = patterns[name];
  235. if ((pattern instanceof Array && pattern.some(function(p) {
  236. return stream.match(p);
  237. })) || stream.match(pattern))
  238. return patternStyles[name];
  239. }
  240. }
  241. if (/[+\-*\/^=<>&|]/.test(ch)) {
  242. stream.next();
  243. return "operator";
  244. }
  245. if (stream.match("define")) {
  246. return "def";
  247. } else {
  248. stream.eatWhile(/[\w\-]/);
  249. // Keyword
  250. if (wordLookup[stream.current()]) {
  251. return styleLookup[stream.current()];
  252. } else if (stream.current().match(symbol)) {
  253. return "variable";
  254. } else {
  255. stream.next();
  256. return "variable-2";
  257. }
  258. }
  259. }
  260. function tokenComment(stream, state) {
  261. var maybeEnd = false, maybeNested = false, nestedCount = 0, ch;
  262. while ((ch = stream.next())) {
  263. if (ch == "/" && maybeEnd) {
  264. if (nestedCount > 0) {
  265. nestedCount--;
  266. } else {
  267. state.tokenize = tokenBase;
  268. break;
  269. }
  270. } else if (ch == "*" && maybeNested) {
  271. nestedCount++;
  272. }
  273. maybeEnd = (ch == "*");
  274. maybeNested = (ch == "/");
  275. }
  276. return "comment";
  277. }
  278. function tokenString(quote, style) {
  279. return function(stream, state) {
  280. var escaped = false, next, end = false;
  281. while ((next = stream.next()) != null) {
  282. if (next == quote && !escaped) {
  283. end = true;
  284. break;
  285. }
  286. escaped = !escaped && next == "\\";
  287. }
  288. if (end || !escaped) {
  289. state.tokenize = tokenBase;
  290. }
  291. return style;
  292. };
  293. }
  294. // Interface
  295. return {
  296. startState: function() {
  297. return {
  298. tokenize: tokenBase,
  299. currentIndent: 0
  300. };
  301. },
  302. token: function(stream, state) {
  303. if (stream.eatSpace())
  304. return null;
  305. var style = state.tokenize(stream, state);
  306. return style;
  307. },
  308. blockCommentStart: "/*",
  309. blockCommentEnd: "*/"
  310. };
  311. });
  312. CodeMirror.defineMIME("text/x-dylan", "dylan");
  313. });