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