grabbing an old version of the read library from beyond the grave of the moby probject
This commit is contained in:
parent
e80c54fc75
commit
e6877c3e19
161
js-assembler/runtime-src/read.js
Normal file
161
js-assembler/runtime-src/read.js
Normal file
|
@ -0,0 +1,161 @@
|
|||
var readSchemeExpressions;
|
||||
|
||||
|
||||
function tokenize(s) {
|
||||
|
||||
function replaceEscapes(s) {
|
||||
return s.replace(/\\./g, function(match, submatch, index) {
|
||||
// FIXME: add more escape sequences.
|
||||
if (match == '\\n') {
|
||||
return "\n";
|
||||
}
|
||||
else {
|
||||
return match.substring(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
var tokens = [];
|
||||
|
||||
var PATTERNS = [['whitespace' , /^(\s+)/],
|
||||
['comment' , /(^;[^\n]*)/],
|
||||
['(' , /^(\(|\[)/],
|
||||
[')' , /^(\)|\])/],
|
||||
['\'' , /^(\')/],
|
||||
['`' , /^(`)/],
|
||||
[',' , /^(,)/],
|
||||
['char', /^\#\\(newline)/],
|
||||
['char', /^\#\\(.)/],
|
||||
['number' , /^([+\-]?(?:\d+\.\d+|\d+\.|\.\d+|\d+))/],
|
||||
['string' , /^"((?:([^\\"]|(\\.)))*)"/], // comment (emacs getting confused with quote): "
|
||||
['symbol' ,/^([a-zA-Z\:\+\=\~\_\?\!\@\#\$\%\^\&\*\-\/\.\>\<][\w\:\+\=\~\_\?\!\@\#\$\%\^\&\*\-\/\.\>\<]*)/]
|
||||
];
|
||||
|
||||
while (true) {
|
||||
var shouldContinue = false;
|
||||
for (var i = 0; i < PATTERNS.length; i++) {
|
||||
var patternName = PATTERNS[i][0];
|
||||
var pattern = PATTERNS[i][1]
|
||||
var result = s.match(pattern);
|
||||
if (result != null) {
|
||||
if (patternName == 'string') {
|
||||
result[1] = replaceEscapes(result[1]);
|
||||
}
|
||||
if (patternName != 'whitespace' && patternName != 'comment') {
|
||||
tokens.push([patternName, result[1]]);
|
||||
}
|
||||
s = s.substring(result[0].length);
|
||||
shouldContinue = true;
|
||||
}
|
||||
}
|
||||
if (! shouldContinue) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [tokens, s];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
(function(){
|
||||
|
||||
|
||||
readSchemeExpressions = function(s) {
|
||||
var tokensAndError = tokenize(s);
|
||||
var tokens = tokensAndError[0];
|
||||
if (tokensAndError[1].length > 0) {
|
||||
throw new Error("Error while tokenizing: the rest of the stream is: " + tokensAndError[1]);
|
||||
}
|
||||
|
||||
var quoteSymbol = plt.types.Symbol.makeInstance("quote");
|
||||
var quasiquoteSymbol = plt.types.Symbol.makeInstance("quasiquote");
|
||||
var unquoteSymbol = plt.types.Symbol.makeInstance("unquote");
|
||||
var empty = plt.types.Empty.EMPTY;
|
||||
|
||||
function isType(type) {
|
||||
return (tokens.length > 0 && tokens[0][0] == type);
|
||||
}
|
||||
|
||||
function eat(expectedType) {
|
||||
if (tokens.length == 0)
|
||||
throw new Error("token stream exhausted while trying to eat " +
|
||||
expectedType);
|
||||
var t = tokens.shift();
|
||||
if (t[0] == expectedType) {
|
||||
return t;
|
||||
} else {
|
||||
throw new Error("Unexpected token " + t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function readExpr() {
|
||||
var t;
|
||||
if (isType('(')) {
|
||||
eat('(');
|
||||
var result = readExprs();
|
||||
eat(')');
|
||||
return result;
|
||||
} else if (isType("'")) {
|
||||
eat("'");
|
||||
var quoted = readExpr();
|
||||
return plt.Kernel.cons(quoteSymbol,
|
||||
plt.Kernel.cons(quoted, empty));
|
||||
} else if (isType('`')) {
|
||||
eat("`");
|
||||
return plt.Kernel.cons(quasiquoteSymbol,
|
||||
plt.kernel.cons(quoted, empty));
|
||||
} else if (isType(',')) {
|
||||
eat(",");
|
||||
return plt.Kernel.cons(unquoteSymbol,
|
||||
plt.kernel.cons(quoted, empty));
|
||||
} else if (isType('number')) {
|
||||
t = eat('number');
|
||||
if (t[1].match(/\./)) {
|
||||
return plt.types.FloatPoint.makeInstance(parseFloat(t[1]));
|
||||
} else {
|
||||
return plt.types.Rational.makeInstance(parseInt(t[1]), 1);
|
||||
}
|
||||
} else if (isType('string')) {
|
||||
t = eat('string');
|
||||
return plt.types.String.makeInstance(t[1]);
|
||||
} else if (isType('char')) {
|
||||
t = eat('char');
|
||||
if (t[1] == 'newline') {
|
||||
return plt.types.Char.makeInstance('\n');
|
||||
}
|
||||
else {
|
||||
return plt.types.Char.makeInstance(t[1]);
|
||||
}
|
||||
} else if (isType('symbol')) {
|
||||
t = eat('symbol');
|
||||
return plt.types.Symbol.makeInstance(t[1]);
|
||||
} else {
|
||||
throw new Error("Parse broke with token stream " + tokens);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function readExprs() {
|
||||
var result = plt.types.Empty.EMPTY;
|
||||
while (true) {
|
||||
if (tokens.length == 0 || isType(')')) {
|
||||
break;
|
||||
} else {
|
||||
var nextElt = readExpr();
|
||||
result = plt.types.Cons.makeInstance(nextElt, result);
|
||||
}
|
||||
}
|
||||
return plt.Kernel.reverse(result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return readExprs();
|
||||
}
|
||||
|
||||
}());
|
Loading…
Reference in New Issue
Block a user