Skip to content

Instantly share code, notes, and snippets.

@wedesoft
Created April 10, 2014 09:27
Show Gist options
  • Save wedesoft/10361176 to your computer and use it in GitHub Desktop.
Save wedesoft/10361176 to your computer and use it in GitHub Desktop.
Read CSV data with Guile (GNU Scheme)
(use-modules (system base lalr))
(define csv-parse
(lalr-parser
(CELL COMMA NEWLINE RETURN)
(csv () : '()
(csv row) : (cons $2 $1))
(row (nl) : (list "")
(COMMA row) : (cons "" $2)
(CELL nl) : (list $1)
(CELL COMMA row) : (cons $1 $3))
(nl (NEWLINE) : #f
(RETURN NEWLINE) : #f)))
(define (read-string port l)
(let ((c (peek-char port)))
(if (or (char=? c #\,) (char=? c #\newline))
(apply string (reverse l))
(read-string port (cons (read-char port) l)))))
(define (read-quoted port l)
(let ((c (read-char port))
(c2 (peek-char port)))
(cond ((and (char=? c #\") (char=? c2 #\")) (read-quoted port (cons (read-char port) l)))
((char=? c #\") (apply string (reverse l)))
(else (read-quoted port (cons c l))))))
(define (lex port err)
(lambda ()
(let* ((line (port-line port))
(col (port-column port))
(loc (make-source-location port line col -1 -1))
(c (read-char port)))
(cond ((eof-object? c) '*eoi*)
((char=? c #\newline) (make-lexical-token 'NEWLINE loc #f))
((char=? c #\return) (make-lexical-token 'RETURN loc #f))
((char=? c #\,) (make-lexical-token 'COMMA loc #f))
((char=? c #\") (make-lexical-token 'CELL loc (read-quoted port '())))
(else (make-lexical-token 'CELL loc (read-string port (list c))))))))
(define (err msg . args) (display msg))
(write (call-with-input-string "a,b\n\"c\",d\n,f\ng,\n\"h\"\"i\"\"\",j\n\"\",k\nlm,\"\"\n"
(lambda (port) (reverse (csv-parse (lex port err) err)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment