Index: trunk/csv.lisp
===================================================================
--- trunk/csv.lisp	(revision trunk,8)
+++ trunk/csv.lisp	(revision trunk,8)
@@ -0,0 +1,29 @@
+(require '#:parse)
+(require '#:cl-ppcre)
+(import 'parse::substring)
+(import 'parse::with-gensyms)
+(import 'cl-ppcre:scan)
+(load "lisp/parse/parse3")
+
+(defmacro defparser (name rule)
+  (with-gensyms (input next match)
+  `(defun ,name (,input)
+    (if-matches ,input ,rule (,next ,match)
+      (values t ,next (list ',name ,match))))))
+
+(defmacro defgrammar (&body definitions)
+  (flet ((x (definition)
+	   (destructuring-bind (name rule) definition
+	     `(defparser ,name ,rule))))
+    `(progv () ,@(mapcar #'x definitions))))
+
+(defgrammar
+  (file (+ row))
+  (row (value (* (comma value)) #\Newline))
+  (comma #\,)
+  (value (? (/ dquoted-value squoted-value raw-value)))
+  (dquoted-value (#\" (^ "(?:[^\"]|\"\")*") #\"))
+  (squoted-value (#\' (^ "(?:[^']|'')*") #\'))
+  (raw-value (^ "[^,'\"\\n]*")))
+
+;;; (deparser test (* (#\a #\b))) doesn't grab the match.
