An experiment in parentheses-free lisp (in JavaScript)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

115 lines
2.6 KiB

#! /usr/bin/node
// Tokenization, with no regular expressions, ala Rob Pike :)
function isDigit(a) {
if (!a)
return false;
var code = a.charCodeAt();
if (46 < code && code < 58 || code < 58 && code > 46)
return true;
return false;
}
var TokenStream = {
lookahead :
function(n) {
return this.tokstream[this.tokstream.length-n];
},
next :
function() {
return this.lookahead(2);
},
empty :
function() {
return this.tokstream.length === 0;
},
current :
function() {
return this.tokstream[this.tokstream.length-1];
},
pop :
function() {
this.tokstream.pop();
}
}
function MakeTokStream(tokens) {
this.tokstream = tokens;
}
MakeTokStream.prototype = TokenStream;
function tokenizeNum(tokstream) {
var number = [];
tokstream.pop();
while (isDigit(tokstream.current()) && !tokstream.empty()) {
number.push(tokstream.current());
tokstream.pop();
}
if (tokstream.current() === '.' && isDigit(tokstream.next())) {
number.push('.');
number.push(tokstream.next());
tokstream.pop();
tokstream.pop();
while (isDigit(tokstream.current()) && !tokstream.empty()) {
number.push(tokstream.current());
tokstream.pop();
}
return ["Float", parseFloat(number.join(''), 10)];
}
return ["Integer", parseInt(number.join(''), 10)];
}
function tokenize(tokstream) {
var tokens = [];
while (!tokstream.empty()) {
switch (tokstream.current()) {
case '(':
tokens.push(["left_paren", '(']);
break;
case ')':
tokens.push(["right_paren", ')']);
break;
case '{':
tokens.push(["left_brace", '{']);
break;
case '}':
tokens.push(["right_brace", '}']);
break;
case '[':
tokens.push(["left_square", '[']);
break;
case ']':
tokens.push(["right_square", ']']);
break;
case '+':
var num = tokenizeNum(tokstream);
if (num !== NaN)
tokens.push(num);
break;
case '-':
var num = tokenizeNum(tokstream);
if (num !== NaN)
tokens.push(num);
break;
case '.':
var num = tokenizeNum(tokstream);
if (num !== NaN)
tokens.push(num);
break;
default:
tokens.push(["identifier", tokstream.current()]);
tokstream.pop();
}
}
return tokens;
}
var input = process.argv.slice(2).reduce(function(acc, x) {return acc + " " + x}, "").trim().split('').reverse();
var test = new MakeTokStream(input);
console.log(tokenize(test));
//console.log(isDigit('0'));