Added support for simple arithmetic.

git-svn-id: https://shellinabox.googlecode.com/svn/trunk@106 0da03de8-d603-11dd-86c2-0f8696b7b6f9
This commit is contained in:
zodiac 2009-04-01 17:15:34 +00:00
parent f5a3c95a44
commit 15e4d5990f
2 changed files with 223 additions and 31 deletions

View file

@ -171,7 +171,10 @@ Demo.prototype.error = function(msg) {
if (msg == undefined) { if (msg == undefined) {
msg = 'Syntax Error'; msg = 'Syntax Error';
} }
this.vt100((this.cursorX != 0 ? '\r\n' : '') + '\u0007? ' + msg + '\r\n'); this.vt100((this.cursorX != 0 ? '\r\n' : '') + '\u0007? ' + msg +
(this.currentLineIndex >= 0 ?
' in line ' + this.program[this.currentLineIndex].lineNumber() :
'') + '\r\n');
this.gotoState(2 /* STATE_PROMPT */); this.gotoState(2 /* STATE_PROMPT */);
this.currentLineIndex = -1; this.currentLineIndex = -1;
return undefined; return undefined;
@ -200,7 +203,7 @@ Demo.prototype.doPrompt = function() {
this.keys = ''; this.keys = '';
this.line = ''; this.line = '';
this.currentLineIndex = -1; this.currentLineIndex = -1;
this.vt100('> '); this.vt100((this.cursorX != 0 ? '\r\n' : '') + '> ');
this.gotoState(3 /* STATE_READLINE */); this.gotoState(3 /* STATE_READLINE */);
return false; return false;
}; };
@ -297,8 +300,8 @@ Demo.prototype.doEval = function() {
} else if (token == "PRINT" || token == "?") { } else if (token == "PRINT" || token == "?") {
this.doPrint(); this.doPrint();
} else if (token == "RUN") { } else if (token == "RUN") {
if (this.tokens.nextToken() != null) { if (this.tokens.peekToken() != null) {
this.error(); this.error('RUN does not take any parameters');
} else if (this.program.length > 0) { } else if (this.program.length > 0) {
this.currentLineIndex = 0; this.currentLineIndex = 0;
this.gotoState(6 /* STATE_EXEC */); this.gotoState(6 /* STATE_EXEC */);
@ -306,7 +309,7 @@ Demo.prototype.doEval = function() {
this.ok(); this.ok();
} }
} else { } else {
this.error(); this.error(token ? 'Unknown command: ' + token : undefined);
} }
return false; return false;
}; };
@ -317,21 +320,22 @@ Demo.prototype.doList = function() {
var token = this.tokens.nextToken(); var token = this.tokens.nextToken();
if (token) { if (token) {
if (!token.match(/[0-9]+/)) { if (!token.match(/[0-9]+/)) {
return this.error(); return this.error('LIST can optional take a start and stop line number');
} }
start = parseInt(token); start = parseInt(token);
token = this.tokens.nextToken(); token = this.tokens.nextToken();
if (token) { if (token) {
if (token != ',') { if (token != ',') {
return this.error(); return this.error('Comma expected');
} }
token = this.tokens.nextToken(); token = this.tokens.nextToken();
if (!token || !token.match(/[0-9]+/)) { if (!token || !token.match(/[0-9]+/)) {
return this.error(); return this.error(
'LIST can optionally take a start and stop line number');
} }
stop = token.parseInt(token); stop = token.parseInt(token);
if (stop < start) { if (stop < start) {
return this.error(); return this.error('Start line number has to come before stop');
} }
} }
} }
@ -470,6 +474,77 @@ Demo.prototype.findLine = function(lineNumber) {
}; };
Demo.prototype.expr = function() { Demo.prototype.expr = function() {
var value = this.term();
while (value) {
var token = this.tokens.peekToken();
if (token != '+' && token != '-') {
break;
}
this.tokens.consume();
var v = this.term();
if (!v) {
return v;
}
if (value.type() != v.type()) {
if (value.type() != 0 /* TYPE_STRING */) {
value = new this.Value(0 /* TYPE_STRING */, ''+value.val(), ''+value.val());
}
if (v.type() != 0 /* TYPE_STRING */) {
v = new this.Value(0 /* TYPE_STRING */, ''+v.val(), ''+v.val());
}
}
if (token == '-') {
if (value.type() == 0 /* TYPE_STRING */) {
return this.error('Cannot subtract strings');
}
v = value.val() - v.val();
} else {
v = value.val() + v.val();
}
if (v == NaN) {
return this.error('Numeric range error');
}
value = new this.Value(value.type(), ''+v, v);
}
return value;
};
Demo.prototype.term = function() {
var value = this.factor();
while (value) {
var token = this.tokens.peekToken();
if (token != '*' && token != '/' && token != '\\') {
break;
}
this.tokens.consume();
var v = this.factor();
if (!v) {
return v;
}
if (value.type() != 1 /* TYPE_NUMBER */ || v.type() != 1 /* TYPE_NUMBER */) {
return this.error('Cannot multiply or divide strings');
}
if (token == '*') {
v = value.val() * v.val();
} else {
v = value.val() / v.val();
if (token == '\\') {
if (v < 0) {
v = -Math.floor(-v);
} else {
v = Math.floor( v);
}
}
}
if (v == NaN) {
return this.error('Numeric range error');
}
value = new this.Value(1 /* TYPE_NUMBER */, ''+v, v);
}
return value;
};
Demo.prototype.factor = function() {
var token = this.tokens.nextToken(); var token = this.tokens.nextToken();
if (!token) { if (!token) {
return token; return token;
@ -478,7 +553,18 @@ Demo.prototype.expr = function() {
var value = undefined; var value = undefined;
var str; var str;
if ((str = token.match(/^"(.*)"/)) != null) { if ((str = token.match(/^"(.*)"/)) != null) {
value = new this.Value(0 /* TYPE_STRING */, str[1]); value = new this.Value(0 /* TYPE_STRING */, str[1], str[1]);
} else if (token.match(/^[0-9]/)) {
var number;
if (token.match(/^[0-9]*$/)) {
number = parseInt(token);
} else {
number = parseFloat(token);
}
if (number == NaN) {
return this.error('Numeric range error');
}
value = new this.Value(1 /* TYPE_NUMBER */, token, number);
} else { } else {
return this.error(); return this.error();
} }
@ -615,11 +701,21 @@ Demo.prototype.Line.prototype.sort = function(a, b) {
return a.lineNumber_ - b.lineNumber_; return a.lineNumber_ - b.lineNumber_;
}; };
Demo.prototype.Value = function(type, str) { Demo.prototype.Value = function(type, str, val) {
this.type = type; this.t = type;
this.str = str; this.s = str;
this.v = val;
};
Demo.prototype.Value.prototype.type = function() {
return this.t;
};
Demo.prototype.Value.prototype.val = function() {
return this.v;
}; };
Demo.prototype.Value.prototype.toString = function() { Demo.prototype.Value.prototype.toString = function() {
return this.str; return this.s;
}; };

View file

@ -171,7 +171,10 @@ Demo.prototype.error = function(msg) {
if (msg == undefined) { if (msg == undefined) {
msg = 'Syntax Error'; msg = 'Syntax Error';
} }
this.vt100((this.cursorX != 0 ? '\r\n' : '') + '\u0007? ' + msg + '\r\n'); this.vt100((this.cursorX != 0 ? '\r\n' : '') + '\u0007? ' + msg +
(this.currentLineIndex >= 0 ?
' in line ' + this.program[this.currentLineIndex].lineNumber() :
'') + '\r\n');
this.gotoState(STATE_PROMPT); this.gotoState(STATE_PROMPT);
this.currentLineIndex = -1; this.currentLineIndex = -1;
return undefined; return undefined;
@ -297,8 +300,8 @@ Demo.prototype.doEval = function() {
} else if (token == "PRINT" || token == "?") { } else if (token == "PRINT" || token == "?") {
this.doPrint(); this.doPrint();
} else if (token == "RUN") { } else if (token == "RUN") {
if (this.tokens.nextToken() != null) { if (this.tokens.peekToken() != null) {
this.error(); this.error('RUN does not take any parameters');
} else if (this.program.length > 0) { } else if (this.program.length > 0) {
this.currentLineIndex = 0; this.currentLineIndex = 0;
this.gotoState(STATE_EXEC); this.gotoState(STATE_EXEC);
@ -306,7 +309,7 @@ Demo.prototype.doEval = function() {
this.ok(); this.ok();
} }
} else { } else {
this.error(); this.error(token ? 'Unknown command: ' + token : undefined);
} }
return false; return false;
}; };
@ -317,21 +320,22 @@ Demo.prototype.doList = function() {
var token = this.tokens.nextToken(); var token = this.tokens.nextToken();
if (token) { if (token) {
if (!token.match(/[0-9]+/)) { if (!token.match(/[0-9]+/)) {
return this.error(); return this.error('LIST can optional take a start and stop line number');
} }
start = parseInt(token); start = parseInt(token);
token = this.tokens.nextToken(); token = this.tokens.nextToken();
if (token) { if (token) {
if (token != ',') { if (token != ',') {
return this.error(); return this.error('Comma expected');
} }
token = this.tokens.nextToken(); token = this.tokens.nextToken();
if (!token || !token.match(/[0-9]+/)) { if (!token || !token.match(/[0-9]+/)) {
return this.error(); return this.error(
'LIST can optionally take a start and stop line number');
} }
stop = token.parseInt(token); stop = token.parseInt(token);
if (stop < start) { if (stop < start) {
return this.error(); return this.error('Start line number has to come before stop');
} }
} }
} }
@ -470,6 +474,77 @@ Demo.prototype.findLine = function(lineNumber) {
}; };
Demo.prototype.expr = function() { Demo.prototype.expr = function() {
var value = this.term();
while (value) {
var token = this.tokens.peekToken();
if (token != '+' && token != '-') {
break;
}
this.tokens.consume();
var v = this.term();
if (!v) {
return v;
}
if (value.type() != v.type()) {
if (value.type() != TYPE_STRING) {
value = new this.Value(TYPE_STRING, ''+value.val(), ''+value.val());
}
if (v.type() != TYPE_STRING) {
v = new this.Value(TYPE_STRING, ''+v.val(), ''+v.val());
}
}
if (token == '-') {
if (value.type() == TYPE_STRING) {
return this.error('Cannot subtract strings');
}
v = value.val() - v.val();
} else {
v = value.val() + v.val();
}
if (v == NaN) {
return this.error('Numeric range error');
}
value = new this.Value(value.type(), ''+v, v);
}
return value;
};
Demo.prototype.term = function() {
var value = this.factor();
while (value) {
var token = this.tokens.peekToken();
if (token != '*' && token != '/' && token != '\\') {
break;
}
this.tokens.consume();
var v = this.factor();
if (!v) {
return v;
}
if (value.type() != TYPE_NUMBER || v.type() != TYPE_NUMBER) {
return this.error('Cannot multiply or divide strings');
}
if (token == '*') {
v = value.val() * v.val();
} else {
v = value.val() / v.val();
if (token == '\\') {
if (v < 0) {
v = -Math.floor(-v);
} else {
v = Math.floor( v);
}
}
}
if (v == NaN) {
return this.error('Numeric range error');
}
value = new this.Value(TYPE_NUMBER, ''+v, v);
}
return value;
};
Demo.prototype.factor = function() {
var token = this.tokens.nextToken(); var token = this.tokens.nextToken();
if (!token) { if (!token) {
return token; return token;
@ -478,7 +553,18 @@ Demo.prototype.expr = function() {
var value = undefined; var value = undefined;
var str; var str;
if ((str = token.match(/^"(.*)"/)) != null) { if ((str = token.match(/^"(.*)"/)) != null) {
value = new this.Value(TYPE_STRING, str[1]); value = new this.Value(TYPE_STRING, str[1], str[1]);
} else if (token.match(/^[0-9]/)) {
var number;
if (token.match(/^[0-9]*$/)) {
number = parseInt(token);
} else {
number = parseFloat(token);
}
if (number == NaN) {
return this.error('Numeric range error');
}
value = new this.Value(TYPE_NUMBER, token, number);
} else { } else {
return this.error(); return this.error();
} }
@ -615,11 +701,21 @@ Demo.prototype.Line.prototype.sort = function(a, b) {
return a.lineNumber_ - b.lineNumber_; return a.lineNumber_ - b.lineNumber_;
}; };
Demo.prototype.Value = function(type, str) { Demo.prototype.Value = function(type, str, val) {
this.type = type; this.t = type;
this.str = str; this.s = str;
this.v = val;
};
Demo.prototype.Value.prototype.type = function() {
return this.t;
};
Demo.prototype.Value.prototype.val = function() {
return this.v;
}; };
Demo.prototype.Value.prototype.toString = function() { Demo.prototype.Value.prototype.toString = function() {
return this.str; return this.s;
}; };