[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Parsing CSV files
From: |
Wolfgang Jaehrling |
Subject: |
Parsing CSV files |
Date: |
Tue, 30 Sep 2003 23:23:25 +0200 |
User-agent: |
Mutt/1.3.28i |
Hi there!
For those of you who want to read some interesting code, here is a
program to parse a file in CSV (Comma Separated Value) format. I
think it shows how one should use Scheme, but some might say it goes a
bit too far... (and I'd like to receive comments on this topic.)
Note `READ-TABLE' can be called with the source port as argument, or
without an argument to use the current input port.
;; Reading a table from a port where it resides in CSV format.
;; Copyright (C) 2003 Wolfgang Jährling <address@hidden>
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
(define field-delimiter #\,)
;; Return a procedure that calls CONSUMER with three arguments: The
;; value returned by the PRODUCER applied to the procedures arguments,
;; a list that is initially empty, and a thunk to restart this process
;; with the value given by the PRODUCER added at the beginning of the
;; list given to the CONSUMER.
(define (collectrec producer consumer)
(lambda args
(letrec ((loop (lambda (lst)
(let ((x (apply producer args)))
(consumer x lst (lambda ()
(loop (cons x lst))))))))
(loop '()))))
;; Read and return a field, that ends with the configured delimiter
;; character, or return false at the end of a line, or the eof-object
;; at end of file.
(define read-field
(collectrec read-char
(lambda (c chars loop)
(cond ((eof-object? c) c)
((char=? c field-delimiter)
(apply string (reverse chars)))
((char=? c #\newline) #f)
(else (loop))))))
;; Read a line and split it up into a list of fields which gets
;; returned, or false at the end of the file.
(define read-row
(collectrec read-field
(lambda (f fields loop)
(cond ((not f) (reverse fields))
((eof-object? f) #f)
(else (loop))))))
;; Read a table and return it as a list of rows, each row being a list
;; of fields, which are strings.
(define read-table
(collectrec read-row
(lambda (r rows loop)
(if (not r)
(reverse rows)
(loop)))))
;;;; End of code. ;;;;
Cheers,
GNU/Wolfgang
--
(define eq? (lambda (x y) #t)) ;; How could it be otherwise?
- Parsing CSV files,
Wolfgang Jaehrling <=