git @ Cat's Eye Technologies Matchbox / a3e35af
yoob.js-erize the script and the page. Chris Pressey 10 years ago
4 changed file(s) with 361 addition(s) and 134 deletion(s). Raw diff Collapse all Expand all
66
77 <h1>Matchbox</h1>
88
9 <textarea id="prog1">
10 MOV M0, R0
11 INC R0
12 MOV R0, M0
13 </textarea>
14
15 <textarea id="prog2">
16 MOV M0, R0
17 INC R0
18 INC R0
19 MOV R0, M0
20 </textarea>
21
22 <button onclick="interleave()">Interleave</button>
23
24 <pre id="output">
25 </pre>
9 <div id="container"></div>
2610
2711 </body>
2812 <script src="../src/matchbox.js"></script>
2913 <script>
30 "use strict";
31
32 var output = document.getElementById('output');
33
34 var x = parseCode(document.getElementById('prog1').value);
35 var y = parseCode(document.getElementById('prog2').value);
36
37 var interleave = function() {
38 output.innerHTML = '';
39 var interleavings = findAllInterleavings(x, y);
40 for (var i = 0; i < interleavings.length; i++) {
41 output.innerHTML += '[' + interleavings[i] + ']\n';
42 }
43 };
14 launch('../src/yoob/', 'container', {});
4415 </script>
00 "use strict";
11
2 /*
3 * A lexical analyzer.
4 * Create a new yoob.Scanner object, then call init, passing it an
5 * array of two-element arrays; first element of each of these is the
6 * type of token, the second element is a regular expression (in a
7 * String) which matches that token at the start of the string. The
8 * regular expression should have exactly one capturing group.
9 * Then call reset, passing it the string to be scanned.
10 *
11 */
12 var Scanner = function() {
13 this.text = undefined;
14 this.token = undefined;
15 this.type = undefined;
16 this.error = undefined;
17 this.table = undefined;
18 this.whitespacePattern = "^[ \\t\\n\\r]*";
19
20 this.init = function(table) {
21 this.table = table;
22 return this;
23 };
24
25 this.reset = function(text) {
26 this.text = text;
27 this.token = undefined;
28 this.type = undefined;
29 this.error = undefined;
30 this.scan();
31 };
32
33 this.scanPattern = function(pattern, type) {
34 var re = new RegExp(pattern);
35 var match = re.exec(this.text);
36 if (match === null) return false;
37 this.type = type;
38 this.token = match[1];
39 this.text = this.text.substr(match[0].length);
40 //console.log(this.type, this.token);
41 return true;
42 };
43
44 this.scan = function() {
45 this.scanPattern(this.whitespacePattern, "whitespace");
46 if (this.text.length === 0) {
47 this.token = null;
48 this.type = "EOF";
49 return;
50 }
51 for (var i = 0; i < this.table.length; i++) {
52 var type = this.table[i][0];
53 var pattern = this.table[i][1];
54 if (this.scanPattern(pattern, type)) return;
55 }
56 if (this.scanPattern("^([\\s\\S])", "unknown character")) return;
57 // should never get here
58 };
59
60 this.expect = function(token) {
61 if (this.token === token) {
62 this.scan();
63 } else {
64 this.error = "expected '" + token + "' but found '" + this.token + "'";
65 }
66 };
67
68 this.on = function(token) {
69 return this.token === token;
70 };
71
72 this.onType = function(type) {
73 return this.type === type;
74 };
75
76 this.checkType = function(type) {
77 if (this.type !== type) {
78 this.error = "expected " + type + " but found " + this.type + " (" + this.token + ")"
79 }
80 };
81
82 this.expectType = function(type) {
83 this.checkType(type);
84 this.scan();
85 };
86
87 this.consume = function(token) {
88 if (this.on(token)) {
89 this.scan();
90 return true;
91 } else {
92 return false;
93 }
94 };
95
96 };
97
98 var matchboxScanner = (new Scanner()).init([
99 ['immediate', "^(\\d+)"],
100 ['register', "^([rR]\\d+)"],
101 ['memory', "^([mM]\\d+)"],
102 ['opcode', "^([a-zA-Z]+)"],
103 ['comma', "^(,)"]
104 ]);
2 function launch(prefix, container, config) {
3 if (typeof container === 'string') {
4 container = document.getElementById(container);
5 }
6 config = config || {};
7 var deps = [
8 "scanner.js",
9 "element-factory.js"
10 ];
11 var loaded = 0;
12 for (var i = 0; i < deps.length; i++) {
13 var elem = document.createElement('script');
14 elem.src = prefix + deps[i];
15 elem.onload = function() {
16 if (++loaded < deps.length) return;
17
18 var prog1ta = yoob.makeTextArea(container, 20, 10);
19 var prog2ta = yoob.makeTextArea(container, 20, 10);
20
21 prog1ta.value = "MOV M0, R0\nINC R0\nMOV R0, M0";
22 prog2ta.value = "MOV M0, R0\nINC R0\nMOV R0, M0";
23
24 var interleaveBtn = yoob.makeButton(container, "Interleave");
25
26 var output = yoob.makePre(container);
27
28 initScanner();
29
30 interleaveBtn.onclick = function() {
31 var x = parseCode(prog1ta.value);
32 var y = parseCode(prog2ta.value);
33
34 output.innerHTML = '';
35 var interleavings = findAllInterleavings(x, y);
36 for (var i = 0; i < interleavings.length; i++) {
37 output.innerHTML += '[' + interleavings[i] + ']\n';
38 }
39 };
40
41 };
42 document.body.appendChild(elem);
43 }
44 }
45
46 var matchboxScanner;
47
48 function initScanner() {
49 matchboxScanner = (new yoob.Scanner());
50 matchboxScanner.init([
51 ['immediate', "^(\\d+)"],
52 ['register', "^([rR]\\d+)"],
53 ['memory', "^([mM]\\d+)"],
54 ['opcode', "^([a-zA-Z]+)"],
55 ['comma', "^(,)"]
56 ]);
57 }
10558
10659 /*
10760 * Each instruction is an object with some fields:
0 /*
1 * This file is part of yoob.js version 0.8
2 * Available from https://github.com/catseye/yoob.js/
3 * This file is in the public domain. See http://unlicense.org/ for details.
4 */
5 if (window.yoob === undefined) yoob = {};
6
7 /*
8 * Functions for creating elements.
9 */
10
11 yoob.makeCanvas = function(container, width, height) {
12 var canvas = document.createElement('canvas');
13 if (width) {
14 canvas.width = width;
15 }
16 if (height) {
17 canvas.height = height;
18 }
19 container.appendChild(canvas);
20 return canvas;
21 };
22
23 yoob.makeButton = function(container, labelText, fun) {
24 var button = document.createElement('button');
25 button.innerHTML = labelText;
26 container.appendChild(button);
27 if (fun) {
28 button.onclick = fun;
29 }
30 return button;
31 };
32
33 yoob.checkBoxNumber = 0;
34 yoob.makeCheckbox = function(container, checked, labelText, fun) {
35 var checkbox = document.createElement('input');
36 checkbox.type = "checkbox";
37 checkbox.id = 'cfzzzb_' + yoob.checkBoxNumber;
38 checkbox.checked = checked;
39 var label = document.createElement('label');
40 label.htmlFor = 'cfzzzb_' + yoob.checkBoxNumber;
41 yoob.checkBoxNumber += 1;
42 label.appendChild(document.createTextNode(labelText));
43
44 container.appendChild(checkbox);
45 container.appendChild(label);
46
47 if (fun) {
48 checkbox.onchange = function(e) {
49 fun(checkbox.checked);
50 };
51 }
52 return checkbox;
53 };
54
55 yoob.makeTextInput = function(container, size, value) {
56 var input = document.createElement('input');
57 input.size = "" + (size || 12);
58 input.value = value || "";
59 container.appendChild(input);
60 return input;
61 };
62
63 yoob.makeSlider = function(container, min, max, value, fun) {
64 var slider = document.createElement('input');
65 slider.type = "range";
66 slider.min = min;
67 slider.max = max;
68 slider.value = value || 0;
69 if (fun) {
70 slider.onchange = function(e) {
71 fun(parseInt(slider.value, 10));
72 };
73 }
74 container.appendChild(slider);
75 return slider;
76 };
77
78 yoob.makeParagraph = function(container, innerHTML) {
79 var p = document.createElement('p');
80 p.innerHTML = innerHTML || '';
81 container.appendChild(p);
82 return p;
83 };
84
85 yoob.makeSpan = function(container, innerHTML) {
86 var span = document.createElement('span');
87 span.innerHTML = innerHTML || '';
88 container.appendChild(span);
89 return span;
90 };
91
92 yoob.makeDiv = function(container, innerHTML) {
93 var div = document.createElement('div');
94 div.innerHTML = innerHTML || '';
95 container.appendChild(div);
96 return div;
97 };
98
99 yoob.makePre = function(container, innerHTML) {
100 var elem = document.createElement('pre');
101 elem.innerHTML = innerHTML || '';
102 container.appendChild(elem);
103 return elem;
104 };
105
106 yoob.makePanel = function(container, title, isOpen) {
107 isOpen = !!isOpen;
108 var panelContainer = document.createElement('div');
109 var button = document.createElement('button');
110 var innerContainer = document.createElement('div');
111 innerContainer.style.display = isOpen ? "block" : "none";
112
113 button.innerHTML = (isOpen ? "∇" : "⊳") + " " + title;
114 button.onclick = function(e) {
115 isOpen = !isOpen;
116 button.innerHTML = (isOpen ? "∇" : "⊳") + " " + title;
117 innerContainer.style.display = isOpen ? "block" : "none";
118 };
119
120 panelContainer.appendChild(button);
121 panelContainer.appendChild(innerContainer);
122 container.appendChild(panelContainer);
123 return innerContainer;
124 };
125
126 yoob.makeTextArea = function(container, cols, rows, initial) {
127 var textarea = document.createElement('textarea');
128 textarea.rows = "" + rows;
129 textarea.cols = "" + cols;
130 if (initial) {
131 container.value = initial;
132 }
133 container.appendChild(textarea);
134 return textarea;
135 };
136
137 yoob.makeLineBreak = function(container) {
138 var br = document.createElement('br');
139 container.appendChild(br);
140 return br;
141 };
142
143 yoob.makeSelect = function(container, labelText, optionsArray) {
144 var label = document.createElement('label');
145 label.innerHTML = labelText;
146 container.appendChild(label);
147
148 var select = document.createElement("select");
149
150 for (var i = 0; i < optionsArray.length; i++) {
151 var op = document.createElement("option");
152 op.value = optionsArray[i][0];
153 op.text = optionsArray[i][1];
154 if (optionsArray[i].length > 2) {
155 op.selected = optionsArray[i][2];
156 } else {
157 op.selected = false;
158 }
159 select.options.add(op);
160 }
161
162 container.appendChild(select);
163 return select;
164 };
165
166 SliderPlusTextInput = function() {
167 this.init = function(cfg) {
168 this.slider = cfg.slider;
169 this.textInput = cfg.textInput;
170 this.callback = cfg.callback;
171 return this;
172 };
173
174 this.set = function(value) {
175 this.slider.value = "" + value;
176 this.textInput.value = "" + value;
177 this.callback(value);
178 };
179 };
180
181 yoob.makeSliderPlusTextInput = function(container, label, min_, max_, size, value, fun) {
182 yoob.makeSpan(container, label);
183 var slider = yoob.makeSlider(container, min_, max_, value);
184 var s = "" + value;
185 var textInput = yoob.makeTextInput(container, size, s);
186 slider.onchange = function(e) {
187 textInput.value = slider.value;
188 fun(parseInt(slider.value, 10));
189 };
190 textInput.onchange = function(e) {
191 var v = parseInt(textInput.value, 10);
192 if (v !== NaN) {
193 slider.value = "" + v;
194 fun(v);
195 }
196 };
197 return new SliderPlusTextInput().init({
198 'slider': slider,
199 'textInput': textInput,
200 'callback': fun
201 });
202 };
0 /*
1 * This file is part of yoob.js version 0.3
2 * Available from https://github.com/catseye/yoob.js/
3 * This file is in the public domain. See http://unlicense.org/ for details.
4 */
5 if (window.yoob === undefined) yoob = {};
6
7 /*
8 * A lexical analyzer.
9 * Create a new yoob.Scanner object, then call init, passing it an
10 * array of two-element arrays; first element of each of these is the
11 * type of token, the second element is a regular expression (in a
12 * String) which matches that token at the start of the string. The
13 * regular expression should have exactly one capturing group.
14 * Then call reset, passing it the string to be scanned.
15 *
16 */
17 yoob.Scanner = function() {
18 this.text = undefined;
19 this.token = undefined;
20 this.type = undefined;
21 this.error = undefined;
22 this.table = undefined;
23 this.whitespacePattern = "^[ \\t\\n\\r]*";
24
25 this.init = function(table) {
26 this.table = table;
27 };
28
29 this.reset = function(text) {
30 this.text = text;
31 this.token = undefined;
32 this.type = undefined;
33 this.error = undefined;
34 this.scan();
35 };
36
37 this.scanPattern = function(pattern, type) {
38 var re = new RegExp(pattern);
39 var match = re.exec(this.text);
40 if (match === null) return false;
41 this.type = type;
42 this.token = match[1];
43 this.text = this.text.substr(match[0].length);
44 return true;
45 };
46
47 this.scan = function() {
48 this.scanPattern(this.whitespacePattern, "whitespace");
49 if (this.text.length === 0) {
50 this.token = null;
51 this.type = "EOF";
52 return;
53 }
54 for (var i = 0; i < this.table.length; i++) {
55 var type = this.table[i][0];
56 var pattern = this.table[i][1];
57 if (this.scanPattern(pattern, type)) return;
58 }
59 if (this.scanPattern("^([\\s\\S])", "unknown character")) return;
60 // should never get here
61 };
62
63 this.expect = function(token) {
64 if (this.token === token) {
65 this.scan();
66 } else {
67 this.error = "expected '" + token + "' but found '" + this.token + "'";
68 }
69 };
70
71 this.on = function(token) {
72 return this.token === token;
73 };
74
75 this.onType = function(type) {
76 return this.type === type;
77 };
78
79 this.checkType = function(type) {
80 if (this.type !== type) {
81 this.error = "expected " + type + " but found " + this.type + " (" + this.token + ")"
82 }
83 };
84
85 this.expectType = function(type) {
86 this.checkType(type);
87 this.scan();
88 };
89
90 this.consume = function(token) {
91 if (this.on(token)) {
92 this.scan();
93 return true;
94 } else {
95 return false;
96 }
97 };
98
99 };