Skip to content

Commit 89a9bd4

Browse files
committed
Keyboard and VirtualKeyboard separated; test examples and apps; accept DSK images without disk or track ident
1 parent 23a6102 commit 89a9bd4

21 files changed

+1550
-1200
lines changed

BasicFormatter.js

Lines changed: 26 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,11 @@ BasicFormatter.prototype = {
2222

2323
this.lexer = this.options.lexer;
2424
this.parser = this.options.parser;
25-
this.iLine = 0; // current line (label)
25+
this.sLine = ""; // current line (label) for error messages
2626
},
2727

28-
/*
29-
reset: function () {
30-
this.iLine = 0; // current line (label)
31-
},
32-
*/
33-
34-
composeError: function () { // varargs
35-
var aArgs = Array.prototype.slice.call(arguments);
36-
37-
aArgs.unshift("BasicFormatter");
38-
return Utils.composeError.apply(null, aArgs);
28+
composeError: function (oError, message, value, pos) {
29+
return Utils.composeError("BasicFormatter", oError, message, value, pos, this.sLine);
3930
},
4031

4132
fnRenumber: function (sInput, aParseTree, iNew, iOld, iStep, iKeep) {
@@ -45,17 +36,16 @@ BasicFormatter.prototype = {
4536
oChanges = {},
4637

4738
fnCreateLineNumbersMap = function () { // create line numbers map
48-
var iLastLine = 0,
39+
var iLastLine = -1,
4940
i, oNode, sLine, iLine;
5041

51-
oLines[0] = { // dummy line 0 for: on error goto 0
52-
value: 0
53-
};
5442
for (i = 0; i < aParseTree.length; i += 1) {
5543
oNode = aParseTree[i];
5644
if (oNode.type === "label") {
5745
sLine = oNode.value;
58-
iLine = Number(oNode.value);
46+
that.sLine = sLine;
47+
48+
iLine = Number(sLine);
5949
if (sLine in oLines) {
6050
throw that.composeError(Error(), "Duplicate line number", sLine, oNode.pos);
6151
}
@@ -65,56 +55,23 @@ BasicFormatter.prototype = {
6555
if (iLine < 1 || iLine > 65535) {
6656
throw that.composeError(Error(), "Line number overflow", sLine, oNode.pos);
6757
}
68-
oLines[oNode.value] = {
58+
oLines[sLine] = {
6959
value: iLine,
7060
pos: oNode.pos,
71-
len: String(oNode.orig || oNode.value).length
61+
len: (oNode.orig || sLine).length
7262
};
7363
iLastLine = iLine;
7464
}
7565
}
7666
},
7767

78-
/*
79-
fnAddReferences = function (aNodes) {
80-
var i, oNode;
81-
82-
for (i = 0; i < aNodes.length; i += 1) {
83-
oNode = aNodes[i];
84-
if (oNode.type === "linenumber") {
85-
if (oNode.value in oLines) {
86-
aRefs.push({
87-
value: Number(oNode.value),
88-
pos: oNode.pos,
89-
len: String(oNode.orig || oNode.value).length
90-
});
91-
} else {
92-
throw that.composeError(Error(), "Line does not exist", oNode.value, oNode.pos);
93-
}
94-
}
95-
if (oNode.left) {
96-
fnAddReferences(oNode.left);
97-
}
98-
if (oNode.right) {
99-
fnAddReferences(oNode.right);
100-
}
101-
if (oNode.third) {
102-
fnAddReferences(oNode.third);
103-
}
104-
if (oNode.args) {
105-
fnAddReferences(oNode.args);
106-
}
107-
}
108-
},
109-
*/
110-
11168
fnAddSingleReference = function (oNode) {
11269
if (oNode.type === "linenumber") {
11370
if (oNode.value in oLines) {
11471
aRefs.push({
115-
value: Number(oNode.value),
72+
value: oNode.value,
11673
pos: oNode.pos,
117-
len: String(oNode.orig || oNode.value).length
74+
len: (oNode.orig || oNode.value).length
11875
});
11976
} else {
12077
throw that.composeError(Error(), "Line does not exist", oNode.value, oNode.pos);
@@ -129,20 +86,23 @@ BasicFormatter.prototype = {
12986
oNode = aNodes[i];
13087

13188
if (oNode.type === "label") {
132-
//TTT this.iLine = Number(oNode.value); // for error messages
89+
that.sLine = oNode.value;
13390
} else {
13491
fnAddSingleReference(oNode);
13592
}
13693

13794
if (oNode.left) {
13895
fnAddSingleReference(oNode.left);
139-
//fnAddReferences(oNode.left); // recursive for e.g. lineRange ?
14096
}
14197
if (oNode.right) {
14298
fnAddSingleReference(oNode.right);
14399
}
144100
if (oNode.args) {
145-
fnAddReferences(oNode.args); // recursive
101+
if (oNode.type === "onErrorGoto" && oNode.args.length === 1 && oNode.args[0].value === "0") {
102+
// ignore "on error goto 0"
103+
} else {
104+
fnAddReferences(oNode.args); // recursive
105+
}
146106
}
147107
if (oNode.args2) { // for "ELSE"
148108
fnAddReferences(oNode.args2); // recursive
@@ -152,11 +112,12 @@ BasicFormatter.prototype = {
152112

153113
fnRenumberLines = function () {
154114
var aKeys = Object.keys(oLines),
155-
i, oLine, oRef;
115+
i, oLine, iLine, oRef, sLine;
156116

157117
for (i = 0; i < aKeys.length; i += 1) {
158118
oLine = oLines[aKeys[i]];
159-
if (oLine.value >= iOld && oLine.value < iKeep) {
119+
iLine = Number(oLine.value);
120+
if (iLine >= iOld && iLine < iKeep) {
160121
if (iNew > 65535) {
161122
throw that.composeError(Error(), "Line number overflow", oLine.value, oLine.pos);
162123
}
@@ -168,9 +129,11 @@ BasicFormatter.prototype = {
168129

169130
for (i = 0; i < aRefs.length; i += 1) {
170131
oRef = aRefs[i];
171-
if (oRef.value >= iOld && oRef.value < iKeep) {
172-
if (oRef.value !== oLines[oRef.value].newLine) {
173-
oRef.newLine = oLines[oRef.value].newLine;
132+
sLine = oRef.value;
133+
iLine = Number(sLine);
134+
if (iLine >= iOld && iLine < iKeep) {
135+
if (iLine !== oLines[sLine].newLine) {
136+
oRef.newLine = oLines[sLine].newLine;
174137
oChanges[oRef.pos] = oRef;
175138
}
176139
}
@@ -210,6 +173,7 @@ BasicFormatter.prototype = {
210173
},
211174
aTokens, aParseTree, sOutput;
212175

176+
this.sLine = ""; // current line (label)
213177
try {
214178
aTokens = this.lexer.lex(sInput);
215179
aParseTree = this.parser.parse(aTokens);

BasicLexer.js

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,15 @@ function BasicLexer(options) {
2121

2222
BasicLexer.prototype = {
2323
init: function (options) {
24-
this.options = options || {}; // e.g. bQuiet
25-
this.reset();
26-
},
24+
this.bQuiet = options ? Boolean(options.bQuiet) : false;
2725

28-
reset: function () {
29-
this.iLine = 0; // for error messages
30-
this.bTakeNumberAsLine = true;
26+
// reset:
27+
this.sLine = "0"; // for error messages
28+
this.bTakeNumberAsLine = true; // first number in a line is assumed to be a line number
3129
},
3230

33-
composeError: function () { // varargs
34-
var aArgs = Array.prototype.slice.call(arguments);
35-
36-
aArgs.unshift("BasicLexer");
37-
aArgs.push(this.iLine);
38-
return Utils.composeError.apply(null, aArgs);
31+
composeError: function (oError, message, value, pos) {
32+
return Utils.composeError("BasicLexer", oError, message, value, pos, this.sLine);
3933
},
4034

4135
lex: function (input) { // eslint-disable-line complexity
@@ -185,7 +179,7 @@ BasicLexer.prototype = {
185179
addToken("number", String(iNumber), iStartPos, sToken);
186180
if (that.bTakeNumberAsLine) {
187181
that.bTakeNumberAsLine = false;
188-
that.iLine = String(iNumber); //TTT save just for error message
182+
that.sLine = String(iNumber); // save just for error message
189183
}
190184
},
191185
fnParseCompleteLineForRem = function () { // special handling for line comment
@@ -210,7 +204,7 @@ BasicLexer.prototype = {
210204
sChar = "";
211205
sToken = advanceWhile(isNotQuotes);
212206
if (!isQuotes(sChar)) {
213-
if (!that.options.bQuiet) {
207+
if (!that.bQuiet) {
214208
Utils.console.log(that.composeError({}, "Unterminated string", sToken, iStartPos + 1).message);
215209
}
216210
}
@@ -260,6 +254,8 @@ BasicLexer.prototype = {
260254
return sOut;
261255
};
262256

257+
this.sLine = "0"; // for error messages
258+
this.bTakeNumberAsLine = true;
263259

264260
while (iIndex < input.length) {
265261
iStartPos = iIndex;
@@ -307,7 +303,7 @@ BasicLexer.prototype = {
307303

308304
sToken = advanceWhile(isNotQuotes);
309305
if (!isQuotes(sChar)) {
310-
if (!that.options.bQuiet) {
306+
if (!that.bQuiet) {
311307
Utils.console.log(this.composeError({}, "Unterminated string", sToken, iStartPos + 1).message);
312308
}
313309
sToken += fnTryContinueString(); // heuristic to detect an LF in the string

BasicParser.js

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -248,21 +248,14 @@ BasicParser.mCloseTokens = {
248248

249249
BasicParser.prototype = {
250250
init: function (options) {
251-
this.options = options || {}; // e.g. tron, bQuiet
251+
this.bQuiet = options ? Boolean(options.bQuiet) : false;
252252

253-
this.reset();
253+
// reset:
254+
this.sLine = "0"; // for error messages
254255
},
255256

256-
reset: function () {
257-
this.iLine = 0; // for error messages
258-
},
259-
260-
composeError: function () { // varargs
261-
var aArgs = Array.prototype.slice.call(arguments);
262-
263-
aArgs.unshift("BasicParser");
264-
aArgs.push(this.iLine);
265-
return Utils.composeError.apply(null, aArgs);
257+
composeError: function (oError, message, value, pos) {
258+
return Utils.composeError("BasicParser", oError, message, value, pos, this.sLine);
266259
},
267260

268261
// http://crockford.com/javascript/tdop/tdop.html (old: http://javascript.crockford.com/tdop/tdop.html)
@@ -426,7 +419,7 @@ BasicParser.prototype = {
426419
oValue = oPreviousToken; // number token
427420
oValue.type = "label"; // number => label
428421
}
429-
that.iLine = oValue.value; // set line number for error messages
422+
that.sLine = oValue.value; // set line number for error messages
430423
oValue.args = statements(null);
431424

432425
if (oToken.type === "(eol)") {
@@ -711,7 +704,7 @@ BasicParser.prototype = {
711704
advance(oBracketClose ? oBracketClose.type : ")");
712705
aArgs.push(oBracketClose);
713706
if (oBrackets[oBracketOpen.type] !== oBracketClose.type) {
714-
if (!that.options.bQuiet) {
707+
if (!that.bQuiet) {
715708
Utils.console.warn(that.composeError({}, "Inconsistent bracket style", oPreviousToken.value, oPreviousToken.pos).message);
716709
}
717710
}
@@ -1119,7 +1112,7 @@ BasicParser.prototype = {
11191112

11201113
oValue.args = [];
11211114

1122-
if (!that.options.bQuiet) {
1115+
if (!that.bQuiet) {
11231116
Utils.console.warn(that.composeError({}, "ELSE: Weird use of ELSE", oPreviousToken.type, oPreviousToken.pos).message);
11241117
}
11251118

@@ -1252,7 +1245,7 @@ BasicParser.prototype = {
12521245
oToken2 = oToken;
12531246
aArgs = statements("else");
12541247
if (aArgs.length && aArgs[0].type !== "rem") {
1255-
if (!that.options.bQuiet) {
1248+
if (!that.bQuiet) {
12561249
Utils.console.warn(that.composeError({}, "IF: Unreachable code after THEN", oToken2.type, oToken2.pos).message);
12571250
}
12581251
}
@@ -1272,7 +1265,7 @@ BasicParser.prototype = {
12721265
oToken2 = oToken;
12731266
aArgs = statements("else");
12741267
if (aArgs.length) {
1275-
if (!that.options.bQuiet) {
1268+
if (!that.bQuiet) {
12761269
Utils.console.warn(that.composeError({}, "IF: Unreachable code after ELSE", oToken2.type, oToken2.pos).message);
12771270
}
12781271
}
@@ -1509,6 +1502,7 @@ BasicParser.prototype = {
15091502

15101503

15111504
// line
1505+
this.sLine = "0"; // for error messages
15121506
iIndex = 0;
15131507
advance();
15141508
while (oToken.type !== "(end)") {

0 commit comments

Comments
 (0)