apl.js 4.2 KB

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