Completed arithmetic support, added initial incomplete code for intrinsic functions.
git-svn-id: https://shellinabox.googlecode.com/svn/trunk@108 0da03de8-d603-11dd-86c2-0f8696b7b6f9
This commit is contained in:
parent
c1e181ec98
commit
82a68e1797
2 changed files with 132 additions and 44 deletions
88
demo/demo.js
88
demo/demo.js
|
@ -514,14 +514,14 @@ Demo.prototype.expr = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Demo.prototype.term = function() {
|
Demo.prototype.term = function() {
|
||||||
var value = this.factor();
|
var value = this.expn();
|
||||||
while (value) {
|
while (value) {
|
||||||
var token = this.tokens.peekToken();
|
var token = this.tokens.peekToken();
|
||||||
if (token != '*' && token != '/' && token != '\\') {
|
if (token != '*' && token != '/' && token != '\\') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.tokens.consume();
|
this.tokens.consume();
|
||||||
var v = this.factor();
|
var v = this.expn();
|
||||||
if (!v) {
|
if (!v) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -548,29 +548,68 @@ Demo.prototype.term = function() {
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Demo.prototype.expn = function() {
|
||||||
|
var value = this.intrinsic();
|
||||||
|
var token = this.tokens.peekToken();
|
||||||
|
if (token == '^') {
|
||||||
|
this.tokens.consume();
|
||||||
|
var exp = this.intrinsic();
|
||||||
|
if (exp == undefined || exp.val() == NaN) {
|
||||||
|
return exp;
|
||||||
|
}
|
||||||
|
if (value.type() != 1 /* TYPE_NUMBER */ || exp.type() != 1 /* TYPE_NUMBER */) {
|
||||||
|
return this.error("Numeric value expected");
|
||||||
|
}
|
||||||
|
var v = Math.pow(value.val(), exp.val());
|
||||||
|
value = new this.Value(1 /* TYPE_NUMBER */, '' + v, v);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Demo.prototype.intrinsic = function() {
|
||||||
|
var token = this.tokens.peekToken();
|
||||||
|
if (token.match(/^(?:ABS|ASC|ATN|CHR\$|COS|EXP|INT|LEN|LOG|POS|RND|SGN|SIN|SPC|SQR|STR\$|TAN|VAL)$/)) {
|
||||||
|
return this.error('Unimplemented');
|
||||||
|
} else if (token.match(/^(?:LEFT\$|RIGHT\$)$/)) {
|
||||||
|
return this.error('Unimplemented');
|
||||||
|
} else if (token == 'MID$') {
|
||||||
|
return this.error('Unimplemented');
|
||||||
|
} else {
|
||||||
|
return this.factor();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Demo.prototype.factor = function() {
|
Demo.prototype.factor = function() {
|
||||||
var token = this.tokens.nextToken();
|
var token = this.tokens.nextToken();
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return this.error();
|
return this.error();
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = undefined;
|
var value = undefined;
|
||||||
var str;
|
if (token == '(') {
|
||||||
if ((str = token.match(/^"(.*)"/)) != null) {
|
value = this.expr();
|
||||||
value = new this.Value(0 /* TYPE_STRING */, str[1], str[1]);
|
token = this.tokens.nextToken();
|
||||||
} else if (token.match(/^[0-9]/)) {
|
if (token != ')' && value != undefined) {
|
||||||
var number;
|
return this.error('")" expected');
|
||||||
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();
|
var str;
|
||||||
|
if ((str = token.match(/^"(.*)"/)) != null) {
|
||||||
|
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 {
|
||||||
|
return this.error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
@ -641,11 +680,16 @@ Demo.prototype.Tokens.prototype.peekToken = function() {
|
||||||
}
|
}
|
||||||
} 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(/^(?:CHR\$|STR\$|LEFT\$|RIGHT\$|MID\$)/i);
|
||||||
if (!token) {
|
if (token) {
|
||||||
token = undefined;
|
|
||||||
} else {
|
|
||||||
token = token[0].toUpperCase();
|
token = token[0].toUpperCase();
|
||||||
|
} else {
|
||||||
|
token = tokens.match(/^[A-Za-z][A-Za-z0-9_]*/);
|
||||||
|
if (!token) {
|
||||||
|
token = undefined;
|
||||||
|
} else {
|
||||||
|
token = token[0].toUpperCase();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
token = '';
|
token = '';
|
||||||
|
|
|
@ -514,14 +514,14 @@ Demo.prototype.expr = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Demo.prototype.term = function() {
|
Demo.prototype.term = function() {
|
||||||
var value = this.factor();
|
var value = this.expn();
|
||||||
while (value) {
|
while (value) {
|
||||||
var token = this.tokens.peekToken();
|
var token = this.tokens.peekToken();
|
||||||
if (token != '*' && token != '/' && token != '\\') {
|
if (token != '*' && token != '/' && token != '\\') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.tokens.consume();
|
this.tokens.consume();
|
||||||
var v = this.factor();
|
var v = this.expn();
|
||||||
if (!v) {
|
if (!v) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -548,29 +548,68 @@ Demo.prototype.term = function() {
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Demo.prototype.expn = function() {
|
||||||
|
var value = this.intrinsic();
|
||||||
|
var token = this.tokens.peekToken();
|
||||||
|
if (token == '^') {
|
||||||
|
this.tokens.consume();
|
||||||
|
var exp = this.intrinsic();
|
||||||
|
if (exp == undefined || exp.val() == NaN) {
|
||||||
|
return exp;
|
||||||
|
}
|
||||||
|
if (value.type() != TYPE_NUMBER || exp.type() != TYPE_NUMBER) {
|
||||||
|
return this.error("Numeric value expected");
|
||||||
|
}
|
||||||
|
var v = Math.pow(value.val(), exp.val());
|
||||||
|
value = new this.Value(TYPE_NUMBER, '' + v, v);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Demo.prototype.intrinsic = function() {
|
||||||
|
var token = this.tokens.peekToken();
|
||||||
|
if (token.match(/^(?:ABS|ASC|ATN|CHR\$|COS|EXP|INT|LEN|LOG|POS|RND|SGN|SIN|SPC|SQR|STR\$|TAN|VAL)$/)) {
|
||||||
|
return this.error('Unimplemented');
|
||||||
|
} else if (token.match(/^(?:LEFT\$|RIGHT\$)$/)) {
|
||||||
|
return this.error('Unimplemented');
|
||||||
|
} else if (token == 'MID$') {
|
||||||
|
return this.error('Unimplemented');
|
||||||
|
} else {
|
||||||
|
return this.factor();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Demo.prototype.factor = function() {
|
Demo.prototype.factor = function() {
|
||||||
var token = this.tokens.nextToken();
|
var token = this.tokens.nextToken();
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return this.error();
|
return this.error();
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = undefined;
|
var value = undefined;
|
||||||
var str;
|
if (token == '(') {
|
||||||
if ((str = token.match(/^"(.*)"/)) != null) {
|
value = this.expr();
|
||||||
value = new this.Value(TYPE_STRING, str[1], str[1]);
|
token = this.tokens.nextToken();
|
||||||
} else if (token.match(/^[0-9]/)) {
|
if (token != ')' && value != undefined) {
|
||||||
var number;
|
return this.error('")" expected');
|
||||||
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();
|
var str;
|
||||||
|
if ((str = token.match(/^"(.*)"/)) != null) {
|
||||||
|
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 {
|
||||||
|
return this.error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
@ -641,11 +680,16 @@ Demo.prototype.Tokens.prototype.peekToken = function() {
|
||||||
}
|
}
|
||||||
} 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(/^(?:CHR\$|STR\$|LEFT\$|RIGHT\$|MID\$)/i);
|
||||||
if (!token) {
|
if (token) {
|
||||||
token = undefined;
|
|
||||||
} else {
|
|
||||||
token = token[0].toUpperCase();
|
token = token[0].toUpperCase();
|
||||||
|
} else {
|
||||||
|
token = tokens.match(/^[A-Za-z][A-Za-z0-9_]*/);
|
||||||
|
if (!token) {
|
||||||
|
token = undefined;
|
||||||
|
} else {
|
||||||
|
token = token[0].toUpperCase();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
token = '';
|
token = '';
|
||||||
|
|
Loading…
Reference in a new issue