Skip to content

Instantly share code, notes, and snippets.

@chaitanyagupta
Forked from tanakahx/json-parser.lisp
Created April 2, 2018 12:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chaitanyagupta/ed528beb77269e0cdc41a3a1a51b9ae5 to your computer and use it in GitHub Desktop.
Save chaitanyagupta/ed528beb77269e0cdc41a3a1a51b9ae5 to your computer and use it in GitHub Desktop.
JSON parser implemented with cl-lex and CL-Yacc
#|
JSON parser implemented with cl-lex and CL-Yacc
USAGE:
JSON-PARSER> (parse-with-lexer (json-lexer
"{\"foo\":\"bar\",\"baz\":\"bang\",\"bing\":100,\"bingo\":1.1,\"bazo\": [1,2,\"foo\"]}")
json-parser)
(:OBJ ("foo" . "bar") ("baz" . "bang") ("bing" . 100) ("bingo" . 1.1) ("bazo" 1 2 "foo"))
JSON-PARSER> (with-open-file (*standard-input* "test.json")
(parse-with-lexer (stream-lexer #'read-line
#'json-lexer
#'(lambda (c) (declare (ignore c)))
#'(lambda (c) (declare (ignore c))))
json-parser))
(:OBJ ("foo" . "bar") ("baz" . "bang") ("bing" . 100) ("bingo" . 1.1) ("bazo" 1 2 "foo"))
|#
(in-package :cl-user)
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload '(:yacc :cl-lex) :silent t))
(defpackage :json-parser
(:use :cl :yacc :cl-lex))
(in-package :json-parser)
(define-string-lexer json-lexer
("{" (return (values '{ $@)))
("}" (return (values '} $@)))
("\\[" (return (values '[ '[)))
("\\]" (return (values '] '])))
(":" (return (values '|:| '|:|)))
("," (return (values '|,| '|,|)))
("'" (return (values '|'| '|'|)))
("\"([^\\\"]|\\.)*?\"" (return (values 'string (string-trim "\"" $@))))
("-?0|[1-9][0-9]*(\\.[0-9]*)?([e|E][+-]?[0-9]+)?" (return (values 'number (read-from-string $@))))
("true" (return (values 'true 'true)))
("false" (return (values 'false 'false)))
("null" (return (values 'null 'null))))
(define-parser json-parser
(:start-symbol json)
(:terminals ({ } [ ] |:| |,| |'| string number true false null))
(json object
array
string
number
true
false
null)
(array ([ ]
#'(lambda (_lp _rp)
(declare (ignore _lp _rp))
(list :array)))
([ sequence ]
#'(lambda (_lp sequence _rp)
(declare (ignore _lp _rp))
sequence)))
(sequence json
(json |,| sequence
#'(lambda (json _c sequence)
(declare (ignore _c))
(if (listp sequence)
(cons json sequence)
(list json sequence)))))
(object ({ }
#'(lambda (_lp _rp)
(declare (ignore _lp _rp))
(list :obj)))
({ members }
#'(lambda (_lp members _rp)
(declare (ignore _lp _rp))
(cons :obj members))))
(member (string |:| json
#'(lambda (string _c json)
(declare (ignore _c))
(cons string json))))
(members member
(member |,| members
#'(lambda (member _c members)
(declare (ignore _c))
(if (listp (car members))
(cons member members)
(list member members))))))
Copy link

ghost commented Nov 27, 2018

Nice example using cl-lex! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment