about summary refs log tree commit diff stats
path: root/lib/read.scm
blob: ea43b0661e4d461f8a316d1a9a5198bb087f711d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
(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 known line type
     (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
          (parse-verbatim (cdr lines) doc '()
                          ;;; FIXME
                          (cons 'verb (cdr words))))
         (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 (list 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))))))