source: tags/dso-csv-0.1/csv.lisp

Last change on this file was 2, checked in by dsowen, 19 years ago

Fixed import problem.

File size: 1.6 KB
Line 
1;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp -*-
2
3(defpackage #:dso-csv
4  (:use #:cl #:dso-lex #:dso-parse)
5  ;; TODO
6  (:import-from #:dso-parse #:substring)
7  (:export #:lex-all-csv
8           #:file
9           #:row
10           #:read-csv))
11
12(in-package #:dso-csv)
13
14
15
16(flet ((trim (s) (substring s :start 1 :length (- (length s) 2))))
17  (defun un-squote (s)
18    (cl-ppcre:regex-replace-all "''" (trim s) "'"))
19  (defun un-dquote (s)
20    (cl-ppcre:regex-replace-all "\"\"" (trim s) "\"")))
21
22(deflexer lex-csv
23  ("," comma)
24  ("\\r\\n?|\\n" newline)
25  ("'(?:[^']|'')*'" value un-squote)
26  ("\"(?:[^\"]|\"\")*\"" value un-dquote)
27  ("[^,'\"\\n\\r]+" value)
28  ("." illegal))
29
30(defun lex-all-csv (input)
31  (labels ((lex-all (start tokens)
32             (multiple-value-bind (class image next-offset)
33                 (lex-csv input start)
34               (cond
35                 ((and class (eq class 'illegal))
36                  (error "Illegal input"))
37                 (class
38                  (lex-all next-offset (cons (cons class image) tokens)))
39                 (t
40                  (nreverse tokens))))))
41    (setf input (coerce input 'simple-string))
42    (lex-all 0 nil)))
43
44(defmacro defmatcher (class)
45  (let ((fn-sym (intern (concatenate 'string "T-" (symbol-name class)))))
46    `(defun ,fn-sym (token-list)
47      (when token-list
48        (destructuring-bind (class . image) (first token-list)
49          (when (eq class ',class)
50            (values t (rest token-list) (list image))))))))
51
52(defmatcher comma)
53(defmatcher newline)
54(defmatcher value)
55
56
57
58(defgrammar ()
59  (file (+ row))
60  (row (t-value (* row-rest) (= t-newline))
61       (lambda (row) (cons (caar row) (mapcar #'second (second row)))))
62  (row-rest ((= t-comma) t-value) car))
63
64
65
66(defun read-csv (input)
67  (let ((tokens (lex-all-csv input)))
68    (file tokens)))
Note: See TracBrowser for help on using the repository browser.