;; ws <- `[ \t\n\r]* (define ws (zero-or-more (in (string->char-set " \t\n\r")))) ;; begin-array <- #\[ (define begin-array (is #\[)) ;; begin-object <- #\{ (define begin-object (is #\{)) ;; end-array <- #\] (define end-array (is #\])) ;; end-object <- #\} (define end-object (is #\})) ;; name-separator <- #\: (define name-separator (is #\:)) ;; value-separator <- #\, (define value-separator (is #\,)) ;; false <- "false" ;; -> handle-false (define false (bind (char-seq "false") handle-false)) ;; true <- "true" ;; -> handle-true (define true (bind (char-seq "true") handle-true)) ;; null <- "null" ;; -> handle-null (define null (bind (char-seq "null") handle-null)) ;; escape <- ["\\/bfnrt] ;; -> handle-escape (define escape (bind (in char-set:json-escaped) handle-escape)) ;; unicode <- #\u [[:xdigit:]]{4} ;; -> handle-unicode (define unicode (bind (as-string (preceded-by (is #\u) (repeated (in char-set:hex-digit) min: 4 max: 4))) handle-unicode)) ;; char <- #\\ ( escape / unicode ) / (![[:cntrl:]"\\] .) (define char (any-of (preceded-by (is #\\) (any-of escape unicode)) (none-of* (satisfies json-char?) item))) ;; raw-string <- #\" char* #\" ;; -> handle-string/raw (define raw-string (memoize (as-string (enclosed-by (is #\") (zero-or-more char) (is #\"))))) ;; member <- ws raw-string ws name-separator value ;; -> handle-member (define member (recursive-parser (sequence* ((_ ws) (name raw-string) (_ (preceded-by ws name-separator)) (value value)) (handle-member name value)))) ;; object <- begin-object ws ( member ( value-separator member )* )? end-object ;; -> handle-object (define object (bind (enclosed-by (preceded-by begin-object ws) (any-of (sequence* ((first-member (member)) (more-members (zero-or-more (preceded-by value-separator (member))))) (result (cons first-member more-members))) (result '())) end-object) handle-object)) ;; array <- begin-array ws ( value ( value-separator value )* )? end-array ;; -> handle-array (define array (recursive-parser (bind (enclosed-by (preceded-by begin-array ws) (any-of (sequence* ((first-value value) (more-values (zero-or-more (preceded-by value-separator value)))) (result (cons first-value more-values))) (result '())) end-array) handle-array))) ;; exp <- [Ee] ([+-])? ([[:digit:]])+ ;; -> as-string (define exp (as-string (sequence* ((e (in #\E #\e)) (sig (maybe (in #\+ #\-))) (digits (one-or-more (in char-set:digit)))) (result (cons* e sig digits))))) ;; frac <- ,#\. ([[:digit:]])+ ;; -> as-string (define frac (as-string (sequence* ((dec (is #\.)) (digits (one-or-more (in char-set:digit)))) (result (cons dec digits))))) ;; int <- ,"0" / ( [123456789] ([[:digit:]])* ) ;; -> as-string (define int (any-of (char-seq "0") (as-string (sequence* ((n (in (string->char-set "123456789"))) (ns (zero-or-more (in char-set:digit)))) (result (cons n ns)))))) ;; number <- ,"-"? int frac? exp? ;; -> handle-number (define number (bind (as-string (sequence (maybe (is #\-)) int (maybe frac) (maybe exp))) handle-number)) ;; string <- raw-string ;; -> handle-string (define string (bind raw-string handle-string)) ;; value <- ws ( null / false / true / object / array / number / string ) ws (define value (enclosed-by ws (any-of null false true object (array) number string) ws)) (define (trailing-ws input) (if (consume-trailing-whitespace?) (ws input) (cons #f input))) ;; document <- ws ( object / array ) ws (define document (enclosed-by ws (any-of object (array)) trailing-ws))