File size: 1,832 Bytes
119e586 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | var SExprParser = {
parse: function(input) {
input = input.trim();
if (!input) return null;
return this._readAtom(input, 0).value;
},
_readAtom: function(input, pos) {
while (pos < input.length && input[pos] === ' ') pos++;
if (pos >= input.length) return { value: null, pos: pos };
if (input[pos] === '(') {
return this._readList(input, pos + 1);
} else if (input[pos] === '"') {
return this._readString(input, pos + 1);
} else {
return this._readSymbol(input, pos);
}
},
_readList: function(input, pos) {
var items = [];
while (pos < input.length) {
while (pos < input.length && input[pos] === ' ') pos++;
if (pos >= input.length) break;
if (input[pos] === ')') return { value: items, pos: pos + 1 };
var result = this._readAtom(input, pos);
items.push(result.value);
pos = result.pos;
}
return { value: items, pos: pos };
},
_readString: function(input, pos) {
var start = pos;
while (pos < input.length && input[pos] !== '"') pos++;
return { value: input.substring(start, pos), pos: pos + 1 };
},
_readSymbol: function(input, pos) {
var start = pos;
while (pos < input.length && '() '.indexOf(input[pos]) === -1) pos++;
var raw = input.substring(start, pos);
var num = Number(raw);
if (!isNaN(num) && raw !== '') return { value: num, pos: pos };
return { value: raw, pos: pos };
},
toString: function(expr) {
if (expr === null) return 'nil';
if (typeof expr === 'string') return '"' + expr + '"';
if (typeof expr === 'number') return String(expr);
if (Array.isArray(expr)) {
return '(' + expr.map(this.toString.bind(this)).join(' ') + ')';
}
return String(expr);
}
};
|