Hi all,
I've made an attempt at JSON parsing. I did this since json.l at
https://github.com/aw/picolisp-json does not handle floating numbers and
that is something I need. I also took it as an opportunity to implement
something bigger than a function and get some feedback about it - I used
xml.l from picolisp source as a reference. What would be a good way to use
this implementation to parse an json string - as opposed to input from a
file.
The code is located here -
https://gist.github.com/ckkashyap/90602086fd4edafa75897a131f8cb88a - I also
have it inline for the folks reluctant to click on the link :)

(de parse-json ()
 (skip)
 (case (peek)
  ("\"" (read-string))
  ("{" (read-object))
  ("[" (read-array))
  ("t" (read-bare-word "true"))
  ("f" (read-bare-word "false"))
  ("n" (read-bare-word "null"))
  (T (read-number))))

(de expect (C)
 (skip)
 (let P (peek)
   (unless (= P C) (quit (pack "Expected <" C "> Got <" P ">")))))

(de read-string ()
 (expect "\"")
 (char)
 (let R
  (make
    (while (not (= (peek) "\""))
      (case (peek)
       ("\\" (char) (link (char)))
       (T (link (char))))))
  (char)
  (pack R)))

(de read-object () (read-collection read-key-value "{" "}"))

(de read-array () (read-collection parse-json "[" "]"))

(de read-bare-word (W)
  (skip)
  (let R
    (pack
     (make (do (length W) (link (char)))))
   (prog (unless (= W R) (quit (pack "Expected " W ", got " R))) R)))

(de read-number ()
 (skip)
 (let (
       Neg (if (= "-" (peek)) (char))
       _ (unless (isNum (peek)) (quit (pack "Not an number " (peek))))
       Flt NIL
       R (make (while (isNum (peek)) (if (= "." (peek)) (setq Flt T))
(link (char)))))
   (round (pack (if Neg "-") R (unless Flt ".0")))))

(de read-key-value ()
 (let (
   k (read-string)
   _ (skip)
   _ (unless (= (char) ":") (exit ":" (peek)))
   v (parse-json))
   (list k v)))

(de read-collection (F S E)
 (expect S)
 (char)
 (let R
   (make
     (while (not (= (peek) E))
       (link (F))
       (skip)
       (if (= (peek) ",") (prog (char) (skip) (if (= E (peek)) (quit
"Incorrect collection termination"))))))
   (char)
   R))

(de isNum (n) (or (= "." n) (num? (format n))))


Regards,
Kashyap

Reply via email to