(defpackage :nerdl (:use :clex2 :parse2 :cl)) (in-package :nerdl) (defun parse-nerdl (input) (parse (input) ;; Phrase grammar ( top -> value) ( value -> string -> :symbol -> :number -> array -> object) ( object -> "{" (* value-pair) "}" => `(:object ,@$2)) ( value-pair -> value value => (list $1 $2)) ( array -> "[" (* value) "]" => `(:array ,@$2)) ( string -> :string => (unescape $1) -> :backtick-string -> pipe-run -> prose) ( pipe-run -> (+ :pipe-line) "^" => (format nil "~{~A~^ ~}" $1)) ( prose -> (+ :gt-line) "^" => (format nil "~{~A~^~%~}" $1)) ;; Macros (= int "[0-9]+") (= frac "[.][0-9]+") (= exp "[eE][-+]?[0-9]+") ;; Lexemes (:number -> (and (? #\-) int (? frac) (? exp)) => (with-standard-io-syntax (let ((*read-default-float-format* 'double-float)) (read-from-string $$)))) ;; No idea what they really say here. (:symbol -> "[-+_a-zA-Z0-9.]+" => (intern (string-upcase $$))) (:string -> #\" (= it (* (or (- t #\\ #\") (and #\\ t)))) #\" => it) (:backtick-string -> #\` (= it (* (or (- t #\\ #\") (and #\\ t)))) #\` => it) (:pipe-line -> "[|](.*)" => $1) (:gt-line -> "[>](.*)" => $1) ;; WS and comments (-> "\\s+") (-> "#.*"))) (defun unescape (string &key (start 0) (end nil)) (with-output-to-string (bag) (lexing (string :start start :end end) (:syntax :extended) ((and #\\ #\a) (write-char (code-char 7) bag)) ((and #\\ #\v) (write-char (code-char 11) bag)) ((and #\\ #\") (write-char #\" bag)) ((and #\\ #\\) (write-char #\\ bag)) ((and #\\ #\b) (write-char #\Backspace bag)) ((and #\\ #\f) (write-char #\Page bag)) ((and #\\ #\n) (write-char #\Newline bag)) ((and #\\ #\r) (write-char #\Return bag)) ((and #\\ #\t) (write-char #\Tab bag)) ((and #\\ #\u (= code "[0-9a-fA-F]{4}")) (write-char (code-char (parse-integer code :radix 16)) bag)) ((and #\\ (= c t)) (lex-warn "Unknown escape sequence: ~A" $$) (write-string c bag)) ((* (- t #\\)) (write-string (:buffer 0) bag :start (:start 0) :end (:end 0))) (:eof (return))))) (defparameter *fodder* "# What now brown cow { the-wind \"bullseye\" the-trees false the-sparrows his-eye poem # I don't know if you can hear me |His eye # or if # you're even there |is on # I don't know if you can listen |The sparrow ^ # to a gypsy's prayer this-should-still-work 15.0 other |And I know |He's watching |Over me ^ `force push` >I sing >because >I'm happy ^ \"I am sysadmin\" true \"I am webadmin\" false \"you are so wrong\" null wendover [ { so 1 much -10 gambling 100 but 1000 also -1000 apparently 10000 paramedics -10000 and 1.01 } { die in a fire } 15 |this |that ^ >Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do >eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim >ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut >aliquip ex ea commodo consequat. Duis aute irure dolor in >reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla >pariatur. Excepteur sint occaecat cupidatat non proident, sunt in >culpa qui officia deserunt mollit anim id est laborum.\" ^ ] }") (defun run () (parse-nerdl *fodder*))