apl.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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("apl", function() {
  13. var builtInOps = {
  14. ".": "innerProduct",
  15. "\\": "scan",
  16. "/": "reduce",
  17. "⌿": "reduce1Axis",
  18. "⍀": "scan1Axis",
  19. "¨": "each",
  20. "⍣": "power"
  21. };
  22. var builtInFuncs = {
  23. "+": ["conjugate", "add"],
  24. "−": ["negate", "subtract"],
  25. "×": ["signOf", "multiply"],
  26. "÷": ["reciprocal", "divide"],
  27. "⌈": ["ceiling", "greaterOf"],
  28. "⌊": ["floor", "lesserOf"],
  29. "∣": ["absolute", "residue"],
  30. "⍳": ["indexGenerate", "indexOf"],
  31. "?": ["roll", "deal"],
  32. "⋆": ["exponentiate", "toThePowerOf"],
  33. "⍟": ["naturalLog", "logToTheBase"],
  34. "○": ["piTimes", "circularFuncs"],
  35. "!": ["factorial", "binomial"],
  36. "⌹": ["matrixInverse", "matrixDivide"],
  37. "<": [null, "lessThan"],
  38. "≤": [null, "lessThanOrEqual"],
  39. "=": [null, "equals"],
  40. ">": [null, "greaterThan"],
  41. "≥": [null, "greaterThanOrEqual"],
  42. "≠": [null, "notEqual"],
  43. "≡": ["depth", "match"],
  44. "≢": [null, "notMatch"],
  45. "∈": ["enlist", "membership"],
  46. "⍷": [null, "find"],
  47. "∪": ["unique", "union"],
  48. "∩": [null, "intersection"],
  49. "∼": ["not", "without"],
  50. "∨": [null, "or"],
  51. "∧": [null, "and"],
  52. "⍱": [null, "nor"],
  53. "⍲": [null, "nand"],
  54. "⍴": ["shapeOf", "reshape"],
  55. ",": ["ravel", "catenate"],
  56. "⍪": [null, "firstAxisCatenate"],
  57. "⌽": ["reverse", "rotate"],
  58. "⊖": ["axis1Reverse", "axis1Rotate"],
  59. "⍉": ["transpose", null],
  60. "↑": ["first", "take"],
  61. "↓": [null, "drop"],
  62. "⊂": ["enclose", "partitionWithAxis"],
  63. "⊃": ["diclose", "pick"],
  64. "⌷": [null, "index"],
  65. "⍋": ["gradeUp", null],
  66. "⍒": ["gradeDown", null],
  67. "⊤": ["encode", null],
  68. "⊥": ["decode", null],
  69. "⍕": ["format", "formatByExample"],
  70. "⍎": ["execute", null],
  71. "⊣": ["stop", "left"],
  72. "⊢": ["pass", "right"]
  73. };
  74. var isOperator = /[\.\/⌿⍀¨⍣]/;
  75. var isNiladic = /⍬/;
  76. var isFunction = /[\+−×÷⌈⌊∣⍳\?⋆⍟○!⌹<≤=>≥≠≡≢∈⍷∪∩∼∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⌷⍋⍒⊤⊥⍕⍎⊣⊢]/;
  77. var isArrow = /←/;
  78. var isComment = /[⍝#].*$/;
  79. var stringEater = function(type) {
  80. var prev;
  81. prev = false;
  82. return function(c) {
  83. prev = c;
  84. if (c === type) {
  85. return prev === "\\";
  86. }
  87. return true;
  88. };
  89. };
  90. return {
  91. startState: function() {
  92. return {
  93. prev: false,
  94. func: false,
  95. op: false,
  96. string: false,
  97. escape: false
  98. };
  99. },
  100. token: function(stream, state) {
  101. var ch, funcName, word;
  102. if (stream.eatSpace()) {
  103. return null;
  104. }
  105. ch = stream.next();
  106. if (ch === '"' || ch === "'") {
  107. stream.eatWhile(stringEater(ch));
  108. stream.next();
  109. state.prev = true;
  110. return "string";
  111. }
  112. if (/[\[{\(]/.test(ch)) {
  113. state.prev = false;
  114. return null;
  115. }
  116. if (/[\]}\)]/.test(ch)) {
  117. state.prev = true;
  118. return null;
  119. }
  120. if (isNiladic.test(ch)) {
  121. state.prev = false;
  122. return "niladic";
  123. }
  124. if (/[¯\d]/.test(ch)) {
  125. if (state.func) {
  126. state.func = false;
  127. state.prev = false;
  128. } else {
  129. state.prev = true;
  130. }
  131. stream.eatWhile(/[\w\.]/);
  132. return "number";
  133. }
  134. if (isOperator.test(ch)) {
  135. return "operator apl-" + builtInOps[ch];
  136. }
  137. if (isArrow.test(ch)) {
  138. return "apl-arrow";
  139. }
  140. if (isFunction.test(ch)) {
  141. funcName = "apl-";
  142. if (builtInFuncs[ch] != null) {
  143. if (state.prev) {
  144. funcName += builtInFuncs[ch][1];
  145. } else {
  146. funcName += builtInFuncs[ch][0];
  147. }
  148. }
  149. state.func = true;
  150. state.prev = false;
  151. return "function " + funcName;
  152. }
  153. if (isComment.test(ch)) {
  154. stream.skipToEnd();
  155. return "comment";
  156. }
  157. if (ch === "∘" && stream.peek() === ".") {
  158. stream.next();
  159. return "function jot-dot";
  160. }
  161. stream.eatWhile(/[\w\$_]/);
  162. word = stream.current();
  163. state.prev = true;
  164. return "keyword";
  165. }
  166. };
  167. });
  168. CodeMirror.defineMIME("text/apl", "apl");
  169. });