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