Added comments to telml.scm and allowed numbers in tag names
Getty Ritter
9 years ago
| 16 | 16 | (title meta-title) |
| 17 | 17 | (tags meta-tags)) |
| 18 | 18 | |
| 19 | ;; This builds a stream abstraction, where a stream is a stream of | |
| 20 | ;; characters. This makes writing a parser a _lot_ easier. | |
| 19 | 21 | (define (mk-stream s) |
| 20 | 22 | (let ((lst (string->list s))) |
| 21 | 23 | (lambda (msg) |
| 32 | 34 | (cadr lst))) |
| 33 | 35 | ((eq? 'done msg) (null? lst)))))) |
| 34 | 36 | |
| 37 | ;; Special characters in TeLML are in the set [\{}|], and this also | |
| 38 | ;; considers EOF to be a special character. | |
| 35 | 39 | (define (special-char? c) |
| 36 | 40 | (or (eq? c #\\) |
| 37 | 41 | (eq? c #\{) |
| 39 | 43 | (eq? c #\|) |
| 40 | 44 | (not c))) |
| 41 | 45 | |
| 46 | ;; This turns a stream back into a proper list, mostly for debugging | |
| 47 | ;; purposes. | |
| 42 | 48 | (define (stream->list s) |
| 43 | 49 | (if (s 'peek) (cons (s 'next) (stream->list s)) '())) |
| 44 | 50 | |
| 51 | ;; Identifiers consist of the characters [A-Za-z0-9_-], which are | |
| 52 | ;; matched here by number. | |
| 45 | 53 | (define (ident-char? c) |
| 46 | 54 | (let ((i (char->integer c))) |
| 47 |
(or (= i 45) |
|
| 55 | (or (= i 45) | |
| 56 | (= i 95) | |
| 57 | (and (>= i 48) (<= i 57)) | |
| 48 | 58 | (and (>= i 64) (<= i 90)) |
| 49 | 59 | (and (>= i 97) (<= i 122))))) |
| 50 | 60 | |
| 61 | ;; Whitespace is in [\t\r\n ] | |
| 51 | 62 | (define (whitespace? c) |
| 52 | 63 | (let ((i (char->integer c))) |
| 53 | 64 | (or (= i 9) (= i 10) (= i 13) (= i 32)))) |
| 54 | 65 | |
| 66 | ;; Our parsing function consists of a number of mutually recursive | |
| 67 | ;; functions that operate over a stream of characters. | |
| 55 | 68 | (define (parse str) |
| 56 | 69 | (let ((s (mk-stream str))) |
| 57 | 70 | |
| 58 | 71 | (define (match-char c) |
| 59 |
(if (eq? (s 'next) c) #t ( |
|
| 72 | (if (eq? (s 'next) c) #t (throw 'unexpected-char c))) | |
| 60 | 73 | |
| 61 | 74 | (define (parse-tag) |
| 62 | 75 | (let* ((_ (match-char #\\)) |
| 187 | 200 | (partition (go document) '(()))) |
| 188 | 201 | |
| 189 | 202 | (define (string->sexp str) |
| 190 |
(ca |
|
| 203 | (catch 'read-error | |
| 204 | (lambda () (call-with-input-string str read)) | |
| 205 | (lambda _ #f))) | |
| 191 | 206 | |
| 192 | 207 | (define (escape-chars str) |
| 193 | 208 | (define (go c rest) |
| 204 | 219 | (define (telml->sxml telml tags) |
| 205 | 220 | (define (rec arg) |
| 206 | 221 | (cond ((string? arg) (escape-chars arg)) |
| 222 | ((null? arg) '()) | |
| 207 | 223 | ((symbol? (car arg)) |
| 208 | 224 | (let ((args (map rec (cdr arg))) |
| 209 | 225 | (func (assoc (car arg) tags))) |