@(define value (v))@\ @(cases)@\ @(string v)@(or)@(num v)@(or)@(object v)@(or)@\ @(keyword v)@(or)@(array v)@\ @(end)@\ @(end) @(define ws)@/[\n\t ]*/@(end) @(define string (g))@\ @(local s hex)@\ @(ws)@\ "@(coll :gap 0 :vars (s))@\ @(cases)@\ \"@(bind s """)@(or)@\ \\@(bind s "\\\\")@(or)@\ \/@(bind s "\\/")@(or)@\ \b@(bind s "")@(or)@\ \f@(bind s " ")@(or)@\ \n@(bind s " ")@(or)@\ \r@(bind s " ")@(or)@\ \t@(bind s " ")@(or)@\ \u@{hex /[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]/}@\ @(bind s `&#x@hex;`)@(or)@\ @{s /[^"\\]*/}@(filter :to_html s)@\ @(end)@\ @(until)"@\ @(end)"@\ @(ws)@\ @(cat s "")@\ @(filter :from_html s)@\ @(bind g ("S" s))@\ @(end) @(define num (v))@\ @(local n)@\ @(ws)@{n /-?[0-9]+((\.[0-9]+)?([Ee][+\-]?[0-9]+)?)?/}@(ws)@\ @(bind v ("N" n))@\ @(end) @(define keyword (v))@\ @(local k)@\ @(all)@(ws)@{k /true|false|null/}@(trailer)@/[^A-Za-z0-9_]/@(end)@(ws)@\ @(bind v ("K" k))@\ @(end) @(define object (v))@\ @(local p e pair)@\ @(ws){@(ws)@(coll :gap 0 :vars (pair))@\ @(string p):@(value e)@/,?/@\ @(bind pair (p e))@\ @(until)}@\ @(end)}@(ws)@\ @(bind v ("O" pair))@\ @(end) @(define array (v))@\ @(local e)@\ @(ws)[@(ws)@(coll :gap 0 :var (e))@(value e)@/,?/@(until)]@(end)]@(ws)@\ @(bind v ("A" e))@\ @(end) @(freeform) @(maybe)@(value v)@(end)@badsyntax