guile-user
[Top][All Lists]
Advanced

[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?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]