(in-package #:monparser) (defmacro literal (word) (when (not (stringp word)) (error "Literal only accepts strings as input.")) (let ((binding-list '()) (name-list '())) (loop :for c :across word :do (when c (let ((name (gensym))) (push name name-list) (push `(,name (unit ,c)) binding-list)))) `(comp ,(reverse binding-list) ,(cons 'list (reverse name-list))))) (defparameter nothing (new nil)) (defun optional (p) (one-of p nothing)) (defun many (p &key all) (comp ((x p) (xs (if all (one-of end (many p :all all)) (optional (many p))))) (if x (cons x xs) xs))) (defun repeat (p min &optional (max 0)) (if (> min 0) (comp ((x p) (xs (repeat p (1- min) (1- max)))) (cons x xs)) (if (> max 0) (comp ((x (optional p)) (xs (repeat p 0 (if x (1- max) 0)))) (if x (cons x xs) x)) nothing))) (defun whitespace? (x) (or (char= x #\Space) (not (graphic-char-p x)))) (defun separated-list (p separator) (comp ((v p) (sep (optional separator)) (vn (if sep (separated-list p separator) nothing))) (cons v vn)))