From dcbd78df550c27a6df7b130b4d0aaa999c6d78a4 Mon Sep 17 00:00:00 2001 From: zodiac Date: Mon, 27 Apr 2009 15:45:34 +0000 Subject: [PATCH] Added support for END and GOTO. GOTO allows computed line numbers, so technically, the language is now Turing complete. git-svn-id: https://shellinabox.googlecode.com/svn/trunk@116 0da03de8-d603-11dd-86c2-0f8696b7b6f9 --- demo/demo.js | 159 ++++++++++++++++++++++++++++++------------------- demo/demo.jspp | 145 +++++++++++++++++++++++++++----------------- 2 files changed, 189 insertions(+), 115 deletions(-) diff --git a/demo/demo.js b/demo/demo.js index 532be15..091ef19 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -68,9 +68,8 @@ // #define STATE_PROMPT 2 // #define STATE_READLINE 3 // #define STATE_COMMAND 4 -// #define STATE_EVAL 5 -// #define STATE_EXEC 6 -// #define STATE_NEW_Y_N 7 +// #define STATE_EXEC 5 +// #define STATE_NEW_Y_N 6 // #define TYPE_STRING 0 // #define TYPE_NUMBER 1 @@ -90,7 +89,7 @@ function Demo(container) { extend(Demo, VT100); Demo.prototype.keysPressed = function(ch) { - if (this.state == 6 /* STATE_EXEC */) { + if (this.state == 5 /* STATE_EXEC */) { for (var i = 0; i < ch.length; i++) { var c = ch.charAt(i); if (c == '\u0003') { @@ -123,7 +122,7 @@ Demo.prototype.demo = function() { this.nextTimer = undefined; while (!done) { var state = this.state; - this.state = 0 /* STATE_IDLE */; + this.state = 2 /* STATE_PROMPT */; switch (state) { case 1 /* STATE_INIT */: done = this.doInit(); @@ -137,16 +136,12 @@ Demo.prototype.demo = function() { case 4 /* STATE_COMMAND */: done = this.doCommand(); break; - case 5 /* STATE_EVAL */: - done = this.doEval(); - break; - case 6 /* STATE_EXEC */: + case 5 /* STATE_EXEC */: done = this.doExec(); break; - case 7 /* STATE_NEW_Y_N */: + case 6 /* STATE_NEW_Y_N */: done = this.doNewYN(); break; - case 0 /* STATE_IDLE */: default: done = true; break; @@ -258,6 +253,7 @@ Demo.prototype.doCommand = function() { this.program.splice(index, 1); } } else { + tokens.reset(); if (index >= 0) { // Replace line in program this.program[index].setTokens(tokens); @@ -270,27 +266,32 @@ Demo.prototype.doCommand = function() { } else { this.currentLineIndex = -1; this.evalLineIndex = -1; + tokens.reset(); this.tokens = tokens; - this.gotoState(5 /* STATE_EVAL */); + return this.doEval(); } } - tokens.reset(); return false; }; Demo.prototype.doEval = function() { - this.gotoState(2 /* STATE_PROMPT */); var token = this.tokens.peekToken(); if (token == "DIM") { this.tokens.consume(); this.doDim(); + } else if (token == "END") { + this.tokens.consume(); + this.doEnd(); + } else if (token == "GOTO") { + this.tokens.consume(); + this.doGoto(); } else if (token == "HELP") { this.tokens.consume(); if (this.tokens.nextToken() != undefined) { this.error('HELP does not take any arguments'); } else { this.vt100('Supported commands:\r\n' + - 'DIM HELP LET LIST NEW PRINT RUN\r\n'+ + 'DIM END GOTO HELP LET LIST NEW PRINT RUN\r\n'+ '\r\n'+ 'Supported functions:\r\n'+ 'ABS() ASC() ATN() CHR$() COS() EXP() INT() LEFT$() LEN()\r\n'+ @@ -313,7 +314,7 @@ Demo.prototype.doEval = function() { this.ok(); } else { this.vt100('Do you really want to delete the program (y/N) '); - this.gotoState(7 /* STATE_NEW_Y_N */); + this.gotoState(6 /* STATE_NEW_Y_N */); } } else if (token == "PRINT" || token == "?") { this.tokens.consume(); @@ -325,7 +326,7 @@ Demo.prototype.doEval = function() { } else if (this.program.length > 0) { this.currentLineIndex = 0; this.vars = new Object(); - this.gotoState(6 /* STATE_EXEC */); + this.gotoState(5 /* STATE_EXEC */); } else { this.ok(); } @@ -335,48 +336,6 @@ Demo.prototype.doEval = function() { return false; }; -Demo.prototype.doDim = function() { - for (;;) { - var token = this.tokens.nextToken(); - if (token == undefined) { - return; - } - if (!token || !token.match(/^[A-Za-z][A-Za-z0-9_]*$/)) { - return this.error('Identifier expected'); - } - token = this.tokens.nextToken(); - if (token == '$' || token == '%') { - token = this.tokens.nextToken(); - } - if (token != '(') { - return this.error('"(" expected'); - } - do { - var size = this.expr(); - if (!size) { - return size; - } - if (size.type() != 1 /* TYPE_NUMBER */) { - return this.error('Numeric value expected'); - } - if (Math.floor(size.val()) < 1) { - return this.error('Range error'); - } - token = this.tokens.nextToken(); - } while (token == ','); - if (token != ')') { - return this.error('")" expected'); - } - if (this.tokens.peekToken() != ',') { - break; - } - this.tokens.consume(); - } - if (this.tokens.peekToken() != undefined) { - return this.error(); - } -}; - Demo.prototype.arrayIndex = function() { var token = this.tokens.peekToken(); var arr = ''; @@ -457,6 +416,83 @@ Demo.prototype.doAssignment = function() { } }; +Demo.prototype.doDim = function() { + for (;;) { + var token = this.tokens.nextToken(); + if (token == undefined) { + return; + } + if (!token || !token.match(/^[A-Za-z][A-Za-z0-9_]*$/)) { + return this.error('Identifier expected'); + } + token = this.tokens.nextToken(); + if (token == '$' || token == '%') { + token = this.tokens.nextToken(); + } + if (token != '(') { + return this.error('"(" expected'); + } + do { + var size = this.expr(); + if (!size) { + return size; + } + if (size.type() != 1 /* TYPE_NUMBER */) { + return this.error('Numeric value expected'); + } + if (Math.floor(size.val()) < 1) { + return this.error('Range error'); + } + token = this.tokens.nextToken(); + } while (token == ','); + if (token != ')') { + return this.error('")" expected'); + } + if (this.tokens.peekToken() != ',') { + break; + } + this.tokens.consume(); + } + if (this.tokens.peekToken() != undefined) { + return this.error(); + } +}; + +Demo.prototype.doEnd = function() { + if (this.evalLineIndex < 0) { + return this.error('Cannot use END interactively'); + } + if (this.tokens.nextToken() != undefined) { + return this.error('END does not take any arguments'); + } + this.currentLineIndex = this.program.length; +}; + +Demo.prototype.doGoto = function() { + if (this.evalLineIndex < 0) { + return this.error('Cannot use GOTO interactively'); + } + var value = this.expr(); + if (value == undefined) { + return; + } + if (value.type() != 1 /* TYPE_NUMBER */) { + return this.error('Numeric value expected'); + } + if (this.tokens.nextToken() != undefined) { + return this.error('GOTO takes exactly one numeric argument'); + } + var number = this.toInt(value.val()); + if (number <= 0) { + return this.error('Range error'); + } + var idx = this.findLine(number); + if (idx < 0) { + return this.error('No line number ' + line); + } + this.currentLineIndex = idx; +}; + Demo.prototype.doList = function() { var start = undefined; var stop = undefined; @@ -586,10 +622,11 @@ Demo.prototype.doExec = function() { if (this.currentLineIndex < 0) { return false; } else if (this.currentLineIndex >= this.program.length) { + this.currentLineIndex = -1; this.ok(); return false; } else { - this.gotoState(6 /* STATE_EXEC */, 20); + this.gotoState(5 /* STATE_EXEC */, 20); return true; } }; @@ -613,7 +650,7 @@ Demo.prototype.doNewYN = function() { this.vt100('\u0007'); } } - this.gotoState(7 /* STATE_NEW_Y_N */); + this.gotoState(6 /* STATE_NEW_Y_N */); return true; }; diff --git a/demo/demo.jspp b/demo/demo.jspp index d3e585e..4bcb318 100644 --- a/demo/demo.jspp +++ b/demo/demo.jspp @@ -68,9 +68,8 @@ #define STATE_PROMPT 2 #define STATE_READLINE 3 #define STATE_COMMAND 4 -#define STATE_EVAL 5 -#define STATE_EXEC 6 -#define STATE_NEW_Y_N 7 +#define STATE_EXEC 5 +#define STATE_NEW_Y_N 6 #define TYPE_STRING 0 #define TYPE_NUMBER 1 @@ -123,7 +122,7 @@ Demo.prototype.demo = function() { this.nextTimer = undefined; while (!done) { var state = this.state; - this.state = STATE_IDLE; + this.state = STATE_PROMPT; switch (state) { case STATE_INIT: done = this.doInit(); @@ -137,16 +136,12 @@ Demo.prototype.demo = function() { case STATE_COMMAND: done = this.doCommand(); break; - case STATE_EVAL: - done = this.doEval(); - break; case STATE_EXEC: done = this.doExec(); break; case STATE_NEW_Y_N: done = this.doNewYN(); break; - case STATE_IDLE: default: done = true; break; @@ -258,6 +253,7 @@ Demo.prototype.doCommand = function() { this.program.splice(index, 1); } } else { + tokens.reset(); if (index >= 0) { // Replace line in program this.program[index].setTokens(tokens); @@ -270,27 +266,32 @@ Demo.prototype.doCommand = function() { } else { this.currentLineIndex = -1; this.evalLineIndex = -1; + tokens.reset(); this.tokens = tokens; - this.gotoState(STATE_EVAL); + return this.doEval(); } } - tokens.reset(); return false; }; Demo.prototype.doEval = function() { - this.gotoState(STATE_PROMPT); var token = this.tokens.peekToken(); if (token == "DIM") { this.tokens.consume(); this.doDim(); + } else if (token == "END") { + this.tokens.consume(); + this.doEnd(); + } else if (token == "GOTO") { + this.tokens.consume(); + this.doGoto(); } else if (token == "HELP") { this.tokens.consume(); if (this.tokens.nextToken() != undefined) { this.error('HELP does not take any arguments'); } else { this.vt100('Supported commands:\r\n' + - 'DIM HELP LET LIST NEW PRINT RUN\r\n'+ + 'DIM END GOTO HELP LET LIST NEW PRINT RUN\r\n'+ '\r\n'+ 'Supported functions:\r\n'+ 'ABS() ASC() ATN() CHR$() COS() EXP() INT() LEFT$() LEN()\r\n'+ @@ -335,48 +336,6 @@ Demo.prototype.doEval = function() { return false; }; -Demo.prototype.doDim = function() { - for (;;) { - var token = this.tokens.nextToken(); - if (token == undefined) { - return; - } - if (!token || !token.match(/^[A-Za-z][A-Za-z0-9_]*$/)) { - return this.error('Identifier expected'); - } - token = this.tokens.nextToken(); - if (token == '$' || token == '%') { - token = this.tokens.nextToken(); - } - if (token != '(') { - return this.error('"(" expected'); - } - do { - var size = this.expr(); - if (!size) { - return size; - } - if (size.type() != TYPE_NUMBER) { - return this.error('Numeric value expected'); - } - if (Math.floor(size.val()) < 1) { - return this.error('Range error'); - } - token = this.tokens.nextToken(); - } while (token == ','); - if (token != ')') { - return this.error('")" expected'); - } - if (this.tokens.peekToken() != ',') { - break; - } - this.tokens.consume(); - } - if (this.tokens.peekToken() != undefined) { - return this.error(); - } -}; - Demo.prototype.arrayIndex = function() { var token = this.tokens.peekToken(); var arr = ''; @@ -457,6 +416,83 @@ Demo.prototype.doAssignment = function() { } }; +Demo.prototype.doDim = function() { + for (;;) { + var token = this.tokens.nextToken(); + if (token == undefined) { + return; + } + if (!token || !token.match(/^[A-Za-z][A-Za-z0-9_]*$/)) { + return this.error('Identifier expected'); + } + token = this.tokens.nextToken(); + if (token == '$' || token == '%') { + token = this.tokens.nextToken(); + } + if (token != '(') { + return this.error('"(" expected'); + } + do { + var size = this.expr(); + if (!size) { + return size; + } + if (size.type() != TYPE_NUMBER) { + return this.error('Numeric value expected'); + } + if (Math.floor(size.val()) < 1) { + return this.error('Range error'); + } + token = this.tokens.nextToken(); + } while (token == ','); + if (token != ')') { + return this.error('")" expected'); + } + if (this.tokens.peekToken() != ',') { + break; + } + this.tokens.consume(); + } + if (this.tokens.peekToken() != undefined) { + return this.error(); + } +}; + +Demo.prototype.doEnd = function() { + if (this.evalLineIndex < 0) { + return this.error('Cannot use END interactively'); + } + if (this.tokens.nextToken() != undefined) { + return this.error('END does not take any arguments'); + } + this.currentLineIndex = this.program.length; +}; + +Demo.prototype.doGoto = function() { + if (this.evalLineIndex < 0) { + return this.error('Cannot use GOTO interactively'); + } + var value = this.expr(); + if (value == undefined) { + return; + } + if (value.type() != TYPE_NUMBER) { + return this.error('Numeric value expected'); + } + if (this.tokens.nextToken() != undefined) { + return this.error('GOTO takes exactly one numeric argument'); + } + var number = this.toInt(value.val()); + if (number <= 0) { + return this.error('Range error'); + } + var idx = this.findLine(number); + if (idx < 0) { + return this.error('No line number ' + line); + } + this.currentLineIndex = idx; +}; + Demo.prototype.doList = function() { var start = undefined; var stop = undefined; @@ -586,6 +622,7 @@ Demo.prototype.doExec = function() { if (this.currentLineIndex < 0) { return false; } else if (this.currentLineIndex >= this.program.length) { + this.currentLineIndex = -1; this.ok(); return false; } else {