123 lines
4.0 KiB
Racket
123 lines
4.0 KiB
Racket
#lang racket
|
|
|
|
(require scribble/decode
|
|
(except-in scribble/struct
|
|
element?)
|
|
(only-in scribble/core
|
|
content?
|
|
element?
|
|
make-style
|
|
make-table-columns)
|
|
)
|
|
|
|
(provide (contract-out
|
|
[BNF (-> (cons/c (or/c block? content?)
|
|
(non-empty-listof (or/c block? content?)))
|
|
...
|
|
table?)]
|
|
[BNF-etc element?]
|
|
;; operate on content
|
|
[BNF-seq (-> content? ...
|
|
(or/c element? ""))]
|
|
[BNF-seq-lines (-> (listof content?) ...
|
|
block?)]
|
|
[BNF-alt (-> content? ...
|
|
element?)]
|
|
[BNF-alt/close (-> content? ...
|
|
element?)]
|
|
;; operate on pre-content
|
|
[BNF-group (-> pre-content? ...
|
|
element?)]
|
|
[nonterm (-> pre-content? ...
|
|
element?)]
|
|
[optional (-> pre-content? ...
|
|
element?)]
|
|
[kleenestar (-> pre-content? ...
|
|
element?)]
|
|
[kleeneplus (-> pre-content? ...
|
|
element?)]
|
|
[kleenerange (-> any/c any/c pre-content? ...
|
|
element?)]
|
|
))
|
|
|
|
|
|
(define spacer (make-element 'hspace (list " ")))
|
|
(define equals (make-element 'tt (list spacer "::=" spacer)))
|
|
(define alt (make-element 'tt (list spacer spacer "|" spacer spacer)))
|
|
|
|
(define (as-flow i) (make-flow (list (if (block? i)
|
|
i
|
|
(make-paragraph (list i))))))
|
|
|
|
|
|
(define baseline (make-style #f '(baseline)))
|
|
|
|
(define (BNF . defns)
|
|
(make-table
|
|
(make-style #f
|
|
(list
|
|
(make-table-columns
|
|
(list baseline baseline baseline baseline))))
|
|
(apply
|
|
append
|
|
(map (match-lambda
|
|
[(cons lhs (cons rhs0 more-rhs))
|
|
(cons
|
|
(list (as-flow spacer) (as-flow lhs) (as-flow equals) (as-flow rhs0))
|
|
(map (lambda (i)
|
|
(list (as-flow spacer) (as-flow " ") (as-flow alt) (as-flow i)))
|
|
more-rhs))])
|
|
defns))))
|
|
|
|
;; interleave : (listof content?) element? -> element?
|
|
(define (interleave l spacer)
|
|
(make-element #f (cons (car l)
|
|
(apply append
|
|
(map (lambda (i)
|
|
(list spacer i))
|
|
(cdr l))))))
|
|
|
|
(define (BNF-seq . l)
|
|
(if (null? l)
|
|
""
|
|
(interleave l spacer)))
|
|
|
|
(define (BNF-seq-lines . l)
|
|
(make-table #f (map (lambda (row) (list (as-flow (apply BNF-seq row))))
|
|
l)))
|
|
|
|
(define (BNF-alt . l)
|
|
(interleave l alt))
|
|
|
|
(define (BNF-alt/close . l)
|
|
(interleave l (make-element 'roman " | ")))
|
|
|
|
(define BNF-etc (make-element 'roman "..."))
|
|
|
|
(define (nonterm . s)
|
|
(make-element 'roman (append (list 'lang)
|
|
(list (make-element 'italic (decode-content s)))
|
|
(list 'rang))))
|
|
|
|
(define (optional . s)
|
|
(make-element #f (append (list (make-element 'roman "["))
|
|
(decode-content s)
|
|
(list (make-element 'roman "]")))))
|
|
|
|
(define (BNF-group . s)
|
|
(make-element #f (append (list (make-element 'roman "{"))
|
|
(list (apply BNF-seq (decode-content s)))
|
|
(list (make-element 'roman "}")))))
|
|
|
|
(define (kleenestar . s)
|
|
(make-element #f (append (decode-content s) (list (make-element 'roman "*")))))
|
|
|
|
(define (kleeneplus . s)
|
|
(make-element #f (append (decode-content s) (list (make-element 'superscript (list "+"))))))
|
|
|
|
(define (kleenerange a b . s)
|
|
(make-element #f (append (decode-content s)
|
|
(list (make-element 'roman
|
|
(make-element 'superscript
|
|
(list (format "{~a,~a}" a b))))))))
|