#!/usr/bin/guile \ -e main -s !# (add-to-load-path (dirname (current-filename))) (add-to-load-path (string-append (getenv "HOME") "/lib/guile")) (use-modules (srfi srfi-1) (srfi srfi-8) (srfi srfi-9) (srfi srfi-26) (ice-9 rdelim) (ice-9 peg) (patterns) (macros arrow)) ;; var is the field to test ;; symb is the expected value (define-syntax-rule (ensure-symbol var symb) (unless (eqv? var symb) (throw 'symbol-not-equal "Expected ~s, got ~s~%" symb var))) (define (read-csv port) "Read from port into a peg:tree." (let* ((rawstr (read-delimited "" port)) (match (match-pattern file rawstr)) (tree (keyword-flatten '(line) (peg:tree match)))) tree)) ;;; TODO sometimes part is a symbol instead of a list, ;;; somehow an earlier part got consed on? or something? (define (get-part-data part) "Get data from field-part cells" (if (symbol? part) #f (begin (ensure-symbol (car part) 'field-part) (cadr part)))) (define (flatten-1 lst) "If list is of length one return the first element, otherwise return the full list" (if (= 1 (length lst)) (car lst) lst)) ;; ('line ('field ('field-part data) ...) ...) ;; -> ({(data ...) | data} ...) (define (clean-peg-tree tree) "Clean up input from read-csv, returns a more bare bones tree" (map (lambda (line) ; for every line (ensure-symbol (car line) 'line) (map (lambda (field) ; for every field in line (and (not (symbol? field)) ; if a symbol no data is present ;; else extract the data (begin (ensure-symbol (car field) 'field) (flatten-1 (map get-part-data (cdr field)))))) (cdr line))) tree)) (define-record-type csv (make-csv data) csv? (data get-data)) (use-modules (srfi srfi-9 gnu)) (define (csv-printer record port) (format port "#")) (set-record-type-printer! csv csv-printer) (define (tree->vector tree) (let ((fields (map string->symbol (car tree))) (data (cdr tree))) (list->vector ;; TODO this assoc list ought to be a hash map (map (cut map cons fields <>) data)))) ;;; This creates some form of weird object (define (load-csv filename) (-> (call-with-input-file filename read-csv) clean-peg-tree tree->vector make-csv)) (define-syntax-rule (ensure-csv csv) (unless (csv? csv) (throw 'type-error "Expected csv, got something else~%"))) ;;; TODO (csv? ) sometimes returns false. (define (csv-ref csv key row) #; (ensure-csv csv) (assoc-ref (vector-ref (get-data csv) row) key)) (define (csv-length csv) #; (ensure-csv csv) (vector-length (get-data csv)))