Skip to content

Instantly share code, notes, and snippets.

@icholy
Created March 15, 2015 17:10
Show Gist options
  • Save icholy/c622c70a0c726479e39c to your computer and use it in GitHub Desktop.
Save icholy/c622c70a0c726479e39c to your computer and use it in GitHub Desktop.
class JSONParser {
static parse(json: string): any {
var parser = new JSONParser(json);
return parser.parseValue();
}
private index: number = 0;
private ch: string;
private text: string;
constructor(text: string) {
this.text = text;
this.ch = this.text[0];
}
next(c?: string) {
if (typeof c !== 'undefined' && c !== this.ch) {
this.error("expected '" + c + "', got '" + this.ch + "'");
}
this.index++;
this.ch = this.text.charAt(this.index);
}
error(msg: string) {
throw new SyntaxError("SyntaxError at " + this.index + ": " + msg)
}
parseNumber(): number {
var s = '';
while ('0' <= this.ch && this.ch <= '9') {
s += this.ch;
this.next();
}
return parseFloat(s);
}
parseWord(): any {
switch (this.ch) {
case 'f':
this.next('f');
this.next('a');
this.next('l');
this.next('s');
this.next('e');
return false;
case 't':
this.next('t');
this.next('r');
this.next('u');
this.next('e');
return true;
case 'n':
this.next('n');
this.next('u');
this.next('l');
this.next('l');
return null;
default:
this.error('Invalid word');
}
}
parseString(): string {
var s = '';
this.next('"');
while(this.ch !== '"') {
s += this.ch;
this.next();
}
this.next('"');
return s;
}
skipWhitespace(): void {
var whitespace = ['\n', '\r', '\t', ' '];
while (whitespace.indexOf(this.ch) !== -1) {
this.next();
}
}
parseValue(): any {
switch (this.ch) {
case '[':
return this.parseArray();
case '{':
return this.parseObject();
case '"':
return this.parseString();
default:
if ('0' <= this.ch && this.ch <= '9') {
return this.parseNumber();
}
else {
return this.parseWord();
}
}
}
parseArray(): Array<any> {
var array = [];
this.next('[');
this.skipWhitespace();
while (this.ch !== ']') {
if (this.ch === ',') {
this.next(',');
}
else {
array.push(this.parseValue());
}
this.skipWhitespace();
}
this.next(']');
return array;
}
parseObject(): any {
var obj = {};
this.next('{');
while (this.ch !== '}') {
this.skipWhitespace();
var key = this.parseString();
this.skipWhitespace();
this.next(':');
this.skipWhitespace();
obj[key] = this.parseValue();
this.skipWhitespace();
if (this.ch === ',') {
this.next(',');
}
else if (this.ch !== '}') {
this.error("Invalid Object Literal");
}
}
this.next('}');
return obj;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment