diff --git a/NEWS b/NEWS index 0b3b30c..51048ba 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,9 @@ Copyright (C) Artyom V. Poptsov are permitted in any medium without royalty provided the copyright notice and this notice are preserved. +* Unreleased +** Parsers now can check if the table rows have consistent lengths + * Changes in version 0.7.1 (2023-10-22) ** =dsv= now handles =--number= option This option allows to add numbers to rows and columns of a table. diff --git a/modules/dsv.scm b/modules/dsv.scm index d85ca78..4f2c0a4 100644 --- a/modules/dsv.scm +++ b/modules/dsv.scm @@ -84,6 +84,7 @@ #:key (format 'unix) (comment-prefix 'default) + (validate? #f) (debug-mode? #f) (log-driver #f) (log-opt '())) @@ -100,10 +101,12 @@ values, or throw 'dsv-parser-error' on an error." (unix:dsv->scm port #:delimiter delimiter #:comment-prefix comment-prefix + #:validate? validate? #:debug-mode? debug-mode?)) ((rfc4180) (rfc4180:dsv->scm port #:delimiter delimiter + #:validate? validate? #:debug-mode? debug-mode?)) (else (dsv-error "Unknown format" format)))) diff --git a/modules/dsv/cli/common.scm b/modules/dsv/cli/common.scm index bf5d144..d3e9275 100644 --- a/modules/dsv/cli/common.scm +++ b/modules/dsv/cli/common.scm @@ -142,6 +142,7 @@ of numbers, or #f if an error occurred." (error "Could not determine a file delimiter" input-port)) (let* ((table (remove-empty-rows (dsv->scm input-port delim #:format fmt + #:validate? #t #:debug-mode? debug-mode?))) (table (if filter-col-proc (table-filter-column filter-col-proc table) diff --git a/modules/dsv/fsm/dsv-context.scm b/modules/dsv/fsm/dsv-context.scm index 3279fb4..7126b79 100644 --- a/modules/dsv/fsm/dsv-context.scm +++ b/modules/dsv/fsm/dsv-context.scm @@ -91,9 +91,41 @@ context (add-field context))) +(define (throw-row-length-error context row row-length expected-row-length) + (context-log-error context + "Inconsistent length mismatch on line ~a: expected ~a, got ~a" + (context-row-number context) + expected-row-length + row-length) + (error (format #f + "Inconsistent row length on line ~a: expected ~a, got ~a; " + (context-row-number context) + expected-row-length + row-length) + (context-port context) + (context-row-number context) + (context-col-number context) + row + context)) + (define* (add-row context #:optional char) - (clear-stanza - (push-event-to-result context (context-stanza/reversed context)))) + (let ((result (context-result context)) + (stanza (context-stanza/reversed context))) + (if (or (not (hash-ref (context-custom-data context) 'validate?)) + (null? result)) + (clear-stanza + (push-event-to-result context (context-stanza/reversed context))) + (let* ((stanza-length (length stanza)) + (last-row (car result)) + (last-row-length (length last-row))) + (if (not (equal? stanza-length last-row-length)) + (throw-row-length-error context + stanza + stanza-length + last-row-length) + (clear-stanza + (push-event-to-result context + (context-stanza/reversed context)))))))) (define* (prepare-result context #:optional char) (reverse-result context)) diff --git a/modules/dsv/rfc4180.scm b/modules/dsv/rfc4180.scm index a620893..955b90f 100644 --- a/modules/dsv/rfc4180.scm +++ b/modules/dsv/rfc4180.scm @@ -107,6 +107,7 @@ (define* (dsv->scm port #:key (debug-mode? #f) + (validate? #f) (delimiter %default-delimiter)) (let* ((fsm (make #:pre-action pre-action @@ -119,6 +120,7 @@ `((delimiter . ,(if (equal? delimiter 'default) %default-delimiter delimiter)) + (validate? . ,validate?) (comment-prefix . #f))))))) (context-result context))) diff --git a/modules/dsv/unix.scm b/modules/dsv/unix.scm index c9ceb90..71570b9 100644 --- a/modules/dsv/unix.scm +++ b/modules/dsv/unix.scm @@ -73,6 +73,7 @@ #:key (debug-mode? #f) (delimiter %default-delimiter) + (validate? #f) (comment-prefix %default-comment-prefix)) (let* ((fsm (make #:pre-action pre-action @@ -85,6 +86,7 @@ `((delimiter . ,(if (equal? delimiter 'default) %default-delimiter delimiter)) + (validate? . ,validate?) (comment-prefix . ,(if (equal? comment-prefix 'default) %default-comment-prefix comment-prefix))))))))