Initial support for PRINT command. So far, we can only print strings.

git-svn-id: https://shellinabox.googlecode.com/svn/trunk@105 0da03de8-d603-11dd-86c2-0f8696b7b6f9
This commit is contained in:
zodiac 2009-04-01 04:14:33 +00:00
parent 7f32534490
commit f5a3c95a44
2 changed files with 389 additions and 65 deletions

View file

@ -72,6 +72,15 @@
// #define STATE_EXEC 6 // #define STATE_EXEC 6
// #define STATE_NEW_Y_N 7 // #define STATE_NEW_Y_N 7
// #define TYPE_STRING 0
// #define TYPE_NUMBER 1
// #define TYPE_VAR 2
// #define TYPE_STRVAR 3
// #define TYPE_INTVAR 4
// #define TYPE_ARR 5
// #define TYPE_STRARR 6
// #define TYPE_INTARR 7
function extend(subClass, baseClass) { function extend(subClass, baseClass) {
function inheritance() { } function inheritance() { }
inheritance.prototype = baseClass.prototype; inheritance.prototype = baseClass.prototype;
@ -156,15 +165,16 @@ Demo.prototype.demo = function() {
Demo.prototype.ok = function() { Demo.prototype.ok = function() {
this.vt100('OK\r\n'); this.vt100('OK\r\n');
this.gotoState(2 /* STATE_PROMPT */); this.gotoState(2 /* STATE_PROMPT */);
} };
Demo.prototype.error = function(msg) { Demo.prototype.error = function(msg) {
if (msg == undefined) { if (msg == undefined) {
msg = 'Syntax Error'; msg = 'Syntax Error';
} }
this.vt100('\u0007? ' + msg + '\r\n'); this.vt100((this.cursorX != 0 ? '\r\n' : '') + '\u0007? ' + msg + '\r\n');
this.gotoState(2 /* STATE_PROMPT */); this.gotoState(2 /* STATE_PROMPT */);
this.currentLineIndex = -1; this.currentLineIndex = -1;
return undefined;
}; };
Demo.prototype.doInit = function() { Demo.prototype.doInit = function() {
@ -237,7 +247,7 @@ Demo.prototype.doCommand = function() {
this.line = ''; this.line = '';
var cmd = tokens.nextToken(); var cmd = tokens.nextToken();
if (cmd) { if (cmd) {
cmd = cmd.toUpperCase(); cmd = cmd;
if (cmd.match(/^[0-9]+$/)) { if (cmd.match(/^[0-9]+$/)) {
tokens.removeLineNumber(); tokens.removeLineNumber();
var lineNumber = parseInt(cmd); var lineNumber = parseInt(cmd);
@ -269,26 +279,13 @@ Demo.prototype.doCommand = function() {
Demo.prototype.doEval = function() { Demo.prototype.doEval = function() {
this.gotoState(2 /* STATE_PROMPT */); this.gotoState(2 /* STATE_PROMPT */);
var cmd = this.tokens.nextToken().toUpperCase(); var token = this.tokens.nextToken();
if (cmd == "HELP") { if (token == "HELP") {
this.vt100('Supported commands:\r\n' + this.vt100('Supported commands:\r\n' +
' HELP LIST NEW RUN\r\n'); ' HELP LIST NEW PRINT RUN\r\n');
} else if (cmd == "LIST") { } else if (token == "LIST") {
if (this.tokens.nextToken() != null) { this.doList();
this.error(); } else if (token == "NEW") {
} else {
for (var i = 0; i < this.program.length; i++) {
var line = this.program[i];
this.vt100('' + line.lineNumber());
line.tokens().reset();
for (var token; (token = line.tokens().nextToken()) != null; ) {
this.vt100(' ' + token);
}
line.tokens().reset();
this.vt100('\r\n');
}
}
} else if (cmd == "NEW") {
if (this.currentLineIndex >= 0) { if (this.currentLineIndex >= 0) {
this.error('Cannot call NEW from a program'); this.error('Cannot call NEW from a program');
} else if (this.program.length == 0) { } else if (this.program.length == 0) {
@ -297,7 +294,9 @@ Demo.prototype.doEval = function() {
this.vt100('Do you really want to delete the program (y/N) '); this.vt100('Do you really want to delete the program (y/N) ');
this.gotoState(7 /* STATE_NEW_Y_N */); this.gotoState(7 /* STATE_NEW_Y_N */);
} }
} else if (cmd == "RUN") { } else if (token == "PRINT" || token == "?") {
this.doPrint();
} else if (token == "RUN") {
if (this.tokens.nextToken() != null) { if (this.tokens.nextToken() != null) {
this.error(); this.error();
} else if (this.program.length > 0) { } else if (this.program.length > 0) {
@ -312,6 +311,110 @@ Demo.prototype.doEval = function() {
return false; return false;
}; };
Demo.prototype.doList = function() {
var start = undefined;
var stop = undefined;
var token = this.tokens.nextToken();
if (token) {
if (!token.match(/[0-9]+/)) {
return this.error();
}
start = parseInt(token);
token = this.tokens.nextToken();
if (token) {
if (token != ',') {
return this.error();
}
token = this.tokens.nextToken();
if (!token || !token.match(/[0-9]+/)) {
return this.error();
}
stop = token.parseInt(token);
if (stop < start) {
return this.error();
}
}
}
for (var i = 0; i < this.program.length; i++) {
var line = this.program[i];
var lineNumber = line.lineNumber();
if (start != undefined && start > lineNumber) {
continue;
}
if (stop != undefined && stop < lineNumber) {
break;
}
this.vt100('' + line.lineNumber() + ' ');
line.tokens().reset();
var space = true;
var id = false;
for (var token; (token = line.tokens().nextToken()) != null; ) {
switch (token) {
case '=':
case '+':
case '-':
case '*':
case '/':
case '\\':
case '^':
this.vt100((space ? '' : ' ') + token + ' ');
space = true;
id = false;
break;
case '(':
case ')':
case '?':
case '$':
case '%':
case '#':
this.vt100(token);
space = false;
id = false;
break;
case ',':
case ';':
case ':':
this.vt100(token + ' ');
space = true;
id = false;
break;
default:
this.vt100((id ? ' ' : '') + token);
space = false;
id = true;
break;
}
}
this.vt100('\r\n');
}
};
Demo.prototype.doPrint = function() {
var tokens = this.tokens;
var last = undefined;
for (var token; (token = tokens.peekToken()); ) {
last = token;
if (token == ',') {
this.vt100('\t');
tokens.consume();
} else if (token == ';') {
// Do nothing
tokens.consume();
} else {
var value = this.expr();
if (value == undefined) {
return;
}
this.vt100(value.toString());
}
}
if (last != ';') {
this.vt100('\r\n');
}
};
Demo.prototype.doExec = function() { Demo.prototype.doExec = function() {
this.tokens = this.program[this.currentLineIndex++].tokens(); this.tokens = this.program[this.currentLineIndex++].tokens();
this.tokens.reset(); this.tokens.reset();
@ -366,13 +469,33 @@ Demo.prototype.findLine = function(lineNumber) {
return -l - 1; return -l - 1;
}; };
Demo.prototype.expr = function() {
var token = this.tokens.nextToken();
if (!token) {
return token;
}
var value = undefined;
var str;
if ((str = token.match(/^"(.*)"/)) != null) {
value = new this.Value(0 /* TYPE_STRING */, str[1]);
} else {
return this.error();
}
return value;
};
Demo.prototype.Tokens = function(line) { Demo.prototype.Tokens = function(line) {
this.line = line; this.line = line;
this.tokens = line; this.tokens = line;
this.len = undefined;
}; };
Demo.prototype.Tokens.prototype.nextToken = function() { Demo.prototype.Tokens.prototype.peekToken = function() {
var tokens = this.tokens.replace(/^[ \t]*/, ''); this.len = undefined;
this.tokens = this.tokens.replace(/^[ \t]*/, '');
var tokens = this.tokens;
if (!tokens.length) { if (!tokens.length) {
return null; return null;
} }
@ -397,39 +520,69 @@ Demo.prototype.Tokens.prototype.nextToken = function() {
case '-': case '-':
case '*': case '*':
case '/': case '/':
case '\\':
case '^':
case '(': case '(':
case ')': case ')':
case '?': case '?':
case ',': case ',':
case ';': case ';':
case '"':
case ':': case ':':
case '$': case '$':
case '%': case '%':
case '#': case '#':
break; break;
case '"':
token = tokens.match(/"((?:""|[^"])*)"/); // "
if (!token) {
token = undefined;
} else {
this.len = token[0].length;
token = '"' + token[1].replace(/""/g, '"') + '"';
}
break;
default: default:
if (token >= '0' && token <= '9' || token == '.') { if (token >= '0' && token <= '9' || token == '.') {
token = tokens.match(/^[0-9]*(?:[.][0-9]*)?(?:[eE][-+]?[0-9]+)?/); token = tokens.match(/^[0-9]*(?:[.][0-9]*)?(?:[eE][-+]?[0-9]+)?/);
if (token) { if (!token) {
token = undefined;
} else {
token = token[0]; token = token[0];
} }
} else if (token >= 'A' && token <= 'Z' || } else if (token >= 'A' && token <= 'Z' ||
token >= 'a' && token <= 'z') { token >= 'a' && token <= 'z') {
token = tokens.match(/^[A-Za-z][A-Za-z0-9_]*/); token = tokens.match(/^[A-Za-z][A-Za-z0-9_]*/);
if (token) { if (!token) {
token = token[0]; token = undefined;
} else {
token = token[0].toUpperCase();
} }
} else { } else {
token = ''; token = '';
} }
} }
if (this.len == undefined) {
if (token) { if (token) {
this.tokens = tokens.substr(token.length); this.len = token.length;
} else { } else {
this.tokens = tokens.substr(1); this.len = 1;
token = undefined;
} }
}
return token;
};
Demo.prototype.Tokens.prototype.consume = function() {
if (this.len) {
this.tokens = this.tokens.substr(this.len);
this.len = undefined;
}
};
Demo.prototype.Tokens.prototype.nextToken = function() {
var token = this.peekToken();
this.consume();
return token; return token;
}; };
@ -461,3 +614,12 @@ Demo.prototype.Line.prototype.setTokens = function(tokens) {
Demo.prototype.Line.prototype.sort = function(a, b) { Demo.prototype.Line.prototype.sort = function(a, b) {
return a.lineNumber_ - b.lineNumber_; return a.lineNumber_ - b.lineNumber_;
}; };
Demo.prototype.Value = function(type, str) {
this.type = type;
this.str = str;
};
Demo.prototype.Value.prototype.toString = function() {
return this.str;
};

View file

@ -72,6 +72,15 @@
#define STATE_EXEC 6 #define STATE_EXEC 6
#define STATE_NEW_Y_N 7 #define STATE_NEW_Y_N 7
#define TYPE_STRING 0
#define TYPE_NUMBER 1
#define TYPE_VAR 2
#define TYPE_STRVAR 3
#define TYPE_INTVAR 4
#define TYPE_ARR 5
#define TYPE_STRARR 6
#define TYPE_INTARR 7
function extend(subClass, baseClass) { function extend(subClass, baseClass) {
function inheritance() { } function inheritance() { }
inheritance.prototype = baseClass.prototype; inheritance.prototype = baseClass.prototype;
@ -156,15 +165,16 @@ Demo.prototype.demo = function() {
Demo.prototype.ok = function() { Demo.prototype.ok = function() {
this.vt100('OK\r\n'); this.vt100('OK\r\n');
this.gotoState(STATE_PROMPT); this.gotoState(STATE_PROMPT);
} };
Demo.prototype.error = function(msg) { Demo.prototype.error = function(msg) {
if (msg == undefined) { if (msg == undefined) {
msg = 'Syntax Error'; msg = 'Syntax Error';
} }
this.vt100('\u0007? ' + msg + '\r\n'); this.vt100((this.cursorX != 0 ? '\r\n' : '') + '\u0007? ' + msg + '\r\n');
this.gotoState(STATE_PROMPT); this.gotoState(STATE_PROMPT);
this.currentLineIndex = -1; this.currentLineIndex = -1;
return undefined;
}; };
Demo.prototype.doInit = function() { Demo.prototype.doInit = function() {
@ -190,7 +200,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(STATE_READLINE); this.gotoState(STATE_READLINE);
return false; return false;
}; };
@ -237,7 +247,7 @@ Demo.prototype.doCommand = function() {
this.line = ''; this.line = '';
var cmd = tokens.nextToken(); var cmd = tokens.nextToken();
if (cmd) { if (cmd) {
cmd = cmd.toUpperCase(); cmd = cmd;
if (cmd.match(/^[0-9]+$/)) { if (cmd.match(/^[0-9]+$/)) {
tokens.removeLineNumber(); tokens.removeLineNumber();
var lineNumber = parseInt(cmd); var lineNumber = parseInt(cmd);
@ -269,25 +279,12 @@ Demo.prototype.doCommand = function() {
Demo.prototype.doEval = function() { Demo.prototype.doEval = function() {
this.gotoState(STATE_PROMPT); this.gotoState(STATE_PROMPT);
var token = this.tokens.nextToken().toUpperCase(); var token = this.tokens.nextToken();
if (token == "HELP") { if (token == "HELP") {
this.vt100('Supported commands:\r\n' + this.vt100('Supported commands:\r\n' +
' HELP LIST NEW RUN\r\n'); ' HELP LIST NEW PRINT RUN\r\n');
} else if (token == "LIST") { } else if (token == "LIST") {
if (this.tokens.nextToken() != null) { this.doList();
this.error();
} else {
for (var i = 0; i < this.program.length; i++) {
var line = this.program[i];
this.vt100('' + line.lineNumber());
line.tokens().reset();
for (var token; (token = line.tokens().nextToken()) != null; ) {
this.vt100(' ' + token);
}
line.tokens().reset();
this.vt100('\r\n');
}
}
} else if (token == "NEW") { } else if (token == "NEW") {
if (this.currentLineIndex >= 0) { if (this.currentLineIndex >= 0) {
this.error('Cannot call NEW from a program'); this.error('Cannot call NEW from a program');
@ -297,6 +294,8 @@ Demo.prototype.doEval = function() {
this.vt100('Do you really want to delete the program (y/N) '); this.vt100('Do you really want to delete the program (y/N) ');
this.gotoState(STATE_NEW_Y_N); this.gotoState(STATE_NEW_Y_N);
} }
} else if (token == "PRINT" || token == "?") {
this.doPrint();
} else if (token == "RUN") { } else if (token == "RUN") {
if (this.tokens.nextToken() != null) { if (this.tokens.nextToken() != null) {
this.error(); this.error();
@ -312,6 +311,110 @@ Demo.prototype.doEval = function() {
return false; return false;
}; };
Demo.prototype.doList = function() {
var start = undefined;
var stop = undefined;
var token = this.tokens.nextToken();
if (token) {
if (!token.match(/[0-9]+/)) {
return this.error();
}
start = parseInt(token);
token = this.tokens.nextToken();
if (token) {
if (token != ',') {
return this.error();
}
token = this.tokens.nextToken();
if (!token || !token.match(/[0-9]+/)) {
return this.error();
}
stop = token.parseInt(token);
if (stop < start) {
return this.error();
}
}
}
for (var i = 0; i < this.program.length; i++) {
var line = this.program[i];
var lineNumber = line.lineNumber();
if (start != undefined && start > lineNumber) {
continue;
}
if (stop != undefined && stop < lineNumber) {
break;
}
this.vt100('' + line.lineNumber() + ' ');
line.tokens().reset();
var space = true;
var id = false;
for (var token; (token = line.tokens().nextToken()) != null; ) {
switch (token) {
case '=':
case '+':
case '-':
case '*':
case '/':
case '\\':
case '^':
this.vt100((space ? '' : ' ') + token + ' ');
space = true;
id = false;
break;
case '(':
case ')':
case '?':
case '$':
case '%':
case '#':
this.vt100(token);
space = false;
id = false;
break;
case ',':
case ';':
case ':':
this.vt100(token + ' ');
space = true;
id = false;
break;
default:
this.vt100((id ? ' ' : '') + token);
space = false;
id = true;
break;
}
}
this.vt100('\r\n');
}
};
Demo.prototype.doPrint = function() {
var tokens = this.tokens;
var last = undefined;
for (var token; (token = tokens.peekToken()); ) {
last = token;
if (token == ',') {
this.vt100('\t');
tokens.consume();
} else if (token == ';') {
// Do nothing
tokens.consume();
} else {
var value = this.expr();
if (value == undefined) {
return;
}
this.vt100(value.toString());
}
}
if (last != ';') {
this.vt100('\r\n');
}
};
Demo.prototype.doExec = function() { Demo.prototype.doExec = function() {
this.tokens = this.program[this.currentLineIndex++].tokens(); this.tokens = this.program[this.currentLineIndex++].tokens();
this.tokens.reset(); this.tokens.reset();
@ -366,13 +469,33 @@ Demo.prototype.findLine = function(lineNumber) {
return -l - 1; return -l - 1;
}; };
Demo.prototype.expr = function() {
var token = this.tokens.nextToken();
if (!token) {
return token;
}
var value = undefined;
var str;
if ((str = token.match(/^"(.*)"/)) != null) {
value = new this.Value(TYPE_STRING, str[1]);
} else {
return this.error();
}
return value;
};
Demo.prototype.Tokens = function(line) { Demo.prototype.Tokens = function(line) {
this.line = line; this.line = line;
this.tokens = line; this.tokens = line;
this.len = undefined;
}; };
Demo.prototype.Tokens.prototype.nextToken = function() { Demo.prototype.Tokens.prototype.peekToken = function() {
var tokens = this.tokens.replace(/^[ \t]*/, ''); this.len = undefined;
this.tokens = this.tokens.replace(/^[ \t]*/, '');
var tokens = this.tokens;
if (!tokens.length) { if (!tokens.length) {
return null; return null;
} }
@ -397,39 +520,69 @@ Demo.prototype.Tokens.prototype.nextToken = function() {
case '-': case '-':
case '*': case '*':
case '/': case '/':
case '\\':
case '^':
case '(': case '(':
case ')': case ')':
case '?': case '?':
case ',': case ',':
case ';': case ';':
case '"':
case ':': case ':':
case '$': case '$':
case '%': case '%':
case '#': case '#':
break; break;
case '"':
token = tokens.match(/"((?:""|[^"])*)"/); // "
if (!token) {
token = undefined;
} else {
this.len = token[0].length;
token = '"' + token[1].replace(/""/g, '"') + '"';
}
break;
default: default:
if (token >= '0' && token <= '9' || token == '.') { if (token >= '0' && token <= '9' || token == '.') {
token = tokens.match(/^[0-9]*(?:[.][0-9]*)?(?:[eE][-+]?[0-9]+)?/); token = tokens.match(/^[0-9]*(?:[.][0-9]*)?(?:[eE][-+]?[0-9]+)?/);
if (token) { if (!token) {
token = undefined;
} else {
token = token[0]; token = token[0];
} }
} else if (token >= 'A' && token <= 'Z' || } else if (token >= 'A' && token <= 'Z' ||
token >= 'a' && token <= 'z') { token >= 'a' && token <= 'z') {
token = tokens.match(/^[A-Za-z][A-Za-z0-9_]*/); token = tokens.match(/^[A-Za-z][A-Za-z0-9_]*/);
if (token) { if (!token) {
token = token[0]; token = undefined;
} else {
token = token[0].toUpperCase();
} }
} else { } else {
token = ''; token = '';
} }
} }
if (this.len == undefined) {
if (token) { if (token) {
this.tokens = tokens.substr(token.length); this.len = token.length;
} else { } else {
this.tokens = tokens.substr(1); this.len = 1;
token = undefined;
} }
}
return token;
};
Demo.prototype.Tokens.prototype.consume = function() {
if (this.len) {
this.tokens = this.tokens.substr(this.len);
this.len = undefined;
}
};
Demo.prototype.Tokens.prototype.nextToken = function() {
var token = this.peekToken();
this.consume();
return token; return token;
}; };
@ -461,3 +614,12 @@ Demo.prototype.Line.prototype.setTokens = function(tokens) {
Demo.prototype.Line.prototype.sort = function(a, b) { Demo.prototype.Line.prototype.sort = function(a, b) {
return a.lineNumber_ - b.lineNumber_; return a.lineNumber_ - b.lineNumber_;
}; };
Demo.prototype.Value = function(type, str) {
this.type = type;
this.str = str;
};
Demo.prototype.Value.prototype.toString = function() {
return this.str;
};