From 423ac382f9e73bf1ca7fc6b400f98db087cd7d22 Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Wed, 5 Jun 2024 09:21:25 -0500 Subject: Write executable This involved moving `src' to `lib' and making `bin'. `bin' holds the program, which only imports `jimmy.main' from lib. --- lib/read.scm | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 lib/read.scm (limited to 'lib/read.scm') diff --git a/lib/read.scm b/lib/read.scm new file mode 100644 index 0000000..1b611bb --- /dev/null +++ b/lib/read.scm @@ -0,0 +1,88 @@ +(declare (module (jimmy read))) + +(import scheme (chicken base) + (jimmy util) + (only (chicken io) read-lines) + (only (chicken string) string-split)) + +(define-public line-types + ;; (sigil type inlines word-select) + `((default para (link) ,identity) ; if nothing else matches + ("```" verb) + ("=>" link) + (">" quot) + ("#" hdr1) + ("##" hdr2) + ("###" hdr3) + ("*" list) + ;; extra! + (":" meta))) + +(define-public (parse #!optional port) + (parse-lines (read-lines (or port (current-input-port))) '())) + +(define (line-type line) + (let ((lin (if (string? line) (string-split line) line)) + (def (cdr (assoc 'default line-types)))) + (cond + ((null? lin) def) ; empty line + ((assoc (car lin) line-types) => cdr) ; a line type exists + (else def)))) ; otherwise ... + +(define (parse-lines lines doc) + (if (null? lines) (reverse doc) + (let ((words (string-split (car lines)))) + (cond + ((null? words) ; empty line + (parse-lines (cdr lines) doc)) + ((equal? (car words) "```") ; verbatim + ;; Format for verbatim header: + ;; ``` ?html | command ... + ;; -- only run command on block with html output. + ;; other outputs process the block normally + ;; ``` ?!html | command ... + ;; -- only run command on block when *not* outputting html. + ;; html processes the block normally + ;; ``` ?:html | command ... + ;; -- like ?html, but ignore the block in non-html outputs. + ;;;; FIXME: I think this necessitates a special emit-verbatim + ;;;; function. + (parse-verbatim (cdr lines) doc '() + #; (if (< 1 (length words)) + (cons 'verb (cdr words)) + 'verb) + 'verb)) + (else ; another line type + (apply parse-stanza lines doc '() (line-type words))))))) + +(define (parse-verbatim lines doc block bhead) + (define (close-verbatim) (cons (cons bhead (reverse block)) doc)) + (cond + ((null? lines) ; end of document + (parse-lines lines (close-verbatim))) + ((equal? (car lines) "```") ; end of verbatim block + (parse-lines (cdr lines) (close-verbatim))) + (else ; verbatim block continues + (parse-verbatim (cdr lines) doc (cons (list (car lines)) block) bhead)))) + +(define (parse-stanza lines doc stanza st-type + #!optional (st-inlines '()) (st-words cdr)) + (define (close-stanza) (cons (cons st-type (reverse stanza)) doc)) + (if (null? lines) ; end of document + (parse-lines lines (close-stanza)) + (let* ((ln (car lines)) + (ws (string-split ln)) + (lt (line-type ln))) + (cond + ((null? ws) ; end of stanza (blank line) + (parse-lines (cdr lines) (close-stanza))) + ((memq (car lt) st-inlines) ; in-line for *this* stanza + (parse-stanza (cdr lines) doc + (cons (cons (car lt) (cdr ws)) stanza) + st-type st-inlines st-words)) + ((not (eq? st-type (car (line-type ws)))) ; beginning of a new stanza + (parse-lines lines (close-stanza))) + (else ; continue this stanza + (parse-stanza (cdr lines) doc + (cons (st-words ws) stanza) + st-type st-inlines st-words)))))) -- cgit 1.4.1-21-gabe81