def anychar(s): if s == "": return None return (s[0], s[1:]) def chartest(pred): def _(s): c = anychar(s) if c and pred(c[0]): return (c[0], c[1]) return None return _ def matchchr(targetchr): return chartest(lambda x: x == targetchr) def oneof(target): chars = set([x for x in target]) return chartest(lambda x: x in chars) alpha = oneof('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') loweralpha = oneof('abcdefghijklmnopqrstuvwxyz') upperalpha = oneof('ABCDEFGHIJKLMNOPQRSTUVWXYZ') digit = oneof('0123456789') hexdigit = oneof('0123456789abcdefABCDEF') whitespace = oneof(' \t\n\r') def matchstr(target): if not target: return lambda strn: ("", strn) def _(strn): c = matchchr(target[0])(strn) if c: cs = matchstr(target[1:])(c[1]) if cs: return (c[0] + cs[0], cs[1]) return None return _ def optional(parserfn): def _(strn): c = parserfn(strn) if c: return c return ('', strn) return _ def repeat(parser): def _(strn): c = parser(strn) if c: cs = repeat0(parser)(c[1]) return (c[0] + cs[0], cs[1]) return None return _ def repeat0(parser): return optional(repeat(parser)) def alt(*parsers): def _(strn): for p in parsers: result = p(strn) if result: return result return _ def sequence(*parsers): def _(strn): parsed = '' rest = strn for p in parsers: result = p(rest) if result: rest = result[1] parsed += result[0] else: return None return (parsed, rest) return _ # JSON parser here... def betweenchrs(p, left="(", right=")"): def _(strn): lres = matchchr(left)(strn) if lres: pres = p(lres[1]) if pres: rres = matchchr(right)(pres[1]) if rres: return (left + pres[0] + right, rres[1]) return None return _ betweenparens = lambda p: betweenchrs(p, left="(", right=")") betweenbrackets = lambda p: betweenchrs(p, left="[", right="]") betweencurlies = lambda p: betweenchrs(p, left="{", right="}") def charorquoted(strn): c = anychar(strn) if c[0] == '"': return None elif c[0] == '\\': c2 = chartest(lambda x: x in ('\\', '"'))(c[1]) if c2: return (c[0] + c2[0], c2[1]) else: return c def ignorews(p): def _(strn): w = repeat0(whitespace)(strn) if w: pres = p(w[1]) if pres: w2 = repeat0(whitespace)(pres[1]) if w2: return (pres[0], w2[1]) return None return _ class Forward(object): def __init__(self): self.p = None def __call__(self, *args, **kwargs): return self.p(*args, **kwargs) def __ilshift__(self, p): self.p = p return self anint = sequence(optional(matchchr("-")), repeat(digit)) astring = betweenchrs(repeat0(charorquoted), left='"', right='"') acolon = matchchr(':') acomma = matchchr(',') akey = ignorews(alt(anint, astring)) avalue = Forward() #ignorews(alt(anint, astring)) akeyvaluepair = sequence(akey, acolon, avalue) def commaseparated(p): def _(strn): r = repeat0(sequence(p, acomma))(strn) if r: r2 = p(r[1]) if r2: return (r[0] + r2[0], r2[1]) elif r: return r return None return _ adict = betweencurlies(commaseparated(akeyvaluepair)) alist = betweenbrackets(commaseparated(avalue)) avalue <<= alt(ignorews(adict), ignorews(alist), ignorews(anint), ignorews(astring)) json = alt(adict, alist) print json('''{"hello": {1: "how are you?"}, "i is": "fine", "how": "are you?", 1: ["these", "values", "work", 2]}''') # ('{"hello":{1:"how are you?"},"i is":"fine","how":"are you?",1:["these","values","work",2]}', '')