Subject: Re: newbie post - by delimited text file reader suite any good?
From: rpw3@rpw3.org (Rob Warnock)
Date: Wed, 01 Mar 2006 22:09:26 -0600
Newsgroups: comp.lang.lisp
Message-ID: <Bd-dncGe4ppr8pvZRVn-tg@speakeasy.net>
Richard Smith  <r0d1s3@weldsmith4.co.uk> wrote:
+---------------
| "split-sequence" - yes, but it's got that "loop" construct in it, so
| I find it impenetrable.
+---------------

(*sigh*) So just rewrite it with DO [which is IMHO uglier
than the LOOP version, but YM obviously V]:

    > (with-open-file (s "x^2.txt")
	(do ((line (read-line s nil nil) (read-line s nil nil))
	     (results nil (cons (split-sequence:split-sequence #\tab line)
				results)))
	    ((null line) (reverse results))))

    (("0" "0") ("0.010101" "0.00010203") ("0.020202" "0.000408122")
     ("0.030303" "0.000918274"))
    >

Or, if you prefer an imperative, side-effecting style
[generates pretty much the same code]:

      (with-open-file (s "x^2.txt")
	(do ((line (read-line s nil nil) (read-line s nil nil))
	     (results nil))
	    ((null line) (reverse results))
	  (push (split-sequence:split-sequence #\tab line) results)))

+---------------
| "csv-parser" - got that working well on CSV files - but big "proper"
| (!) program to do much more complicated job.  Could have hacked it to
| do tab-delimited -- but started afresh.
+---------------

I didn't see that request in the thread, or I would have posted this
[of course, it uses that ugly LOOP thingy]:

    ;;; PARSE-CSV-LINE -- Parse one CSV line into a list of fields,
    ;;; stripping quotes and field-internal escape characters.
    ;;; Lexical states: '(normal quoted escaped quoted+escaped)
    ;;;
    (defun parse-csv-line (line)
      (when (or (string= line "")           ; special-case blank lines
		(char= #\# (char line 0)))  ; or those starting with "#"
	(return-from parse-csv-line '()))
      (loop for c across line
	    with state = 'normal
	    and results = '()
	    and chars = '() do
	(ecase state
	  ((normal)
	   (case c
	     ((#\") (setq state 'quoted))
	     ((#\\) (setq state 'escaped))
	     ((#\,)
	      (push (coerce (nreverse chars) 'string) results)
	      (setq chars '()))
	     (t (push c chars))))
	  ((quoted)
	   (case c
	     ((#\") (setq state 'normal))
	     ((#\\) (setq state 'quoted+escaped))
	     (t (push c chars))))
	  ((escaped) (push c chars) (setq state 'normal))
	  ((quoted+escaped) (push c chars) (setq state 'quoted)))
	finally
	 (progn
	   (push (coerce (nreverse chars) 'string) results) ; close open field
	   (return (nreverse results)))))


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607