Index: trunk/THANKS.txt
===================================================================
--- trunk/THANKS.txt	(revision trunk,33)
+++ trunk/THANKS.txt	(revision trunk,33)
@@ -0,0 +1,3 @@
+Thanks to the following people for their contributions:
+
+Brent Millare
Index: trunk/csv.lisp
===================================================================
--- trunk/csv.lisp	(revision trunk,31)
+++ trunk/csv.lisp	(revision trunk,33)
@@ -2,5 +2,5 @@
 
 #|
-Copyright (C) 2007, 2008  David Owen <dsowen@fugue88.ws>
+Copyright (C) 2007, 2008, 2009  David Owen <dsowen@fugue88.ws>
 
 This program is free software: you can redistribute it and/or modify
@@ -26,4 +26,8 @@
 
 
+(defparameter *input* "7,'now is ''the'' time'
+13,\"for all good \"\"men\"\"\"
+")
+
 (flet ((trim (s) (substring s :start 1 :length (- (length s) 2))))
   (defun un-squote (s)
@@ -32,5 +36,5 @@
     (cl-ppcre:regex-replace-all "\"\"" (trim s) "\"")))
 
-(deflexer lex-csv
+(deflexer lex-csv (:priority-only t)
   ("," comma)
   ("\\r\\n?|\\n" newline)
@@ -70,6 +74,35 @@
   (file (+ row))
   (row (t-value (* row-rest) (= t-newline))
-       (lambda (row) (cons (caar row) (mapcar #'second (second row)))))
-  (row-rest ((= t-comma) t-value) car))
+       :filter (lambda (row) (cons (caar row) (mapcar #'second (second row)))))
+  (row-rest ((= t-comma) t-value) :filter 'car))
 
-;;; (defparser test (* (#\a #\b))) doesn't grab the match.
+
+
+;; Tokenize the input first...
+(let ((tokens (lex-all-csv *input*)))
+  ;; Then parse.
+  (format t "~S~%" (nth-value 2 (file tokens))))
+
+
+
+;; Or, do the tokenizing in the parser:
+(defgrammar ()
+  (file2 (+ row2))
+  (row2 (value (* row-rest2) (= newline))
+       :filter (lambda (row) (cons (car row) (mapcar #'second (second row)))))
+  (row-rest2 ((= comma) value) :filter 'identity)
+  (squoted-value ((= #\') (^ "([^']|'')+") (= #\'))
+                 :cclass t
+                 :filter
+                 (lambda (s) (cl-ppcre:regex-replace-all "''" (car s) "'")))
+  (dquoted-value ((= #\") (^ "([^\"]|\"\")+") (= #\"))
+                 :cclass t
+                 :filter
+                 (lambda (s) (cl-ppcre:regex-replace-all "\"\"" (car s) "\"")))
+  (unquoted-value (^ "[^,'\"\\n\\r]+") :cclass t)
+  (value (/ squoted-value dquoted-value unquoted-value) :cclass t)
+  (newline (^ "\\r\\n?|\\n"))
+  (comma #\,))
+
+;; Then parse directly.
+(format t "~S~%" (nth-value 2 (file2 *input*)))
Index: trunk/parsing.lisp
===================================================================
--- trunk/parsing.lisp	(revision trunk,32)
+++ trunk/parsing.lisp	(revision trunk,33)
@@ -2,5 +2,5 @@
 
 #|
-Copyright (C) 2007, 2008  David Owen <dsowen@fugue88.ws>
+Copyright (C) 2007, 2008, 2009  David Owen <dsowen@fugue88.ws>
 
 This program is free software: you can redistribute it and/or modify
@@ -37,6 +37,8 @@
   "Defines a grammar, being a collection of parsers.  The syntax is:
 
-(DEFGRAMMAR (options*) definitions*)
+\(DEFGRAMMAR (options*) definitions*)
 definitions: (name rule &key filter cclass)"
   (flet ((x (definition) `(defparser ,@definition)))
-    `(progv () ,@(mapcar #'x definitions))))
+    `(progn
+       ,@(mapcar #'x definitions)
+       '(,@(mapcar 'first definitions)))))
