commit a2d2f0472f09987e4d070ddff7cc4bfb26e91e9d
parent 58b270adbaad6ae4fa59f86e55b3554fa165549c
Author: Philip McGrath <philip@philipmcgrath.com>
Date: Sun, 15 Apr 2018 05:27:17 -0500
scribble/bnf: Add contracts & correct docs
Diffstat:
2 files changed, 78 insertions(+), 37 deletions(-)
diff --git a/scribble-doc/scribblings/scribble/bnf.scrbl b/scribble-doc/scribblings/scribble/bnf.scrbl
@@ -1,6 +1,7 @@
#lang scribble/doc
@(require scribble/manual "utils.rkt" scribble/bnf
- (for-label scribble/bnf))
+ ;; "utils.rkt" provides scribble/bnf for-label
+ )
@title[#:tag "bnf"]{BNF Grammars}
@@ -43,44 +44,48 @@ produces the output
See also @racket[racketgrammar].
-@defproc[(BNF [prod (cons element? (listof (or/c block? element?)))] ...) table?]{
+@defproc[(BNF [prod (cons/c (or/c block? content?)
+ (non-empty-listof (or/c block? content?)))]
+ ...)
+ table?]{
Typesets a grammar table. Each production starts with an element
(typically constructed with @racket[nonterm]) for the non-terminal
being defined, and then a list of possibilities (typically constructed
with @racket[BNF-seq], etc.) to show on separate lines.}
-@defproc[(nonterm (pre-content any/c) ...) element?]{
+@defproc[(nonterm [pre-content pre-content?] ...) element?]{
Typesets a non-terminal: italic in angle brackets.}
-@defproc[(BNF-seq [elem element?] ...) element?]{
+@defproc[(BNF-seq [elem content?] ...) (or/c element? "")]{
Typesets a sequence.}
-@defproc[(BNF-seq-lines [elems (listof element?)] ...) block?]{
+@defproc[(BNF-seq-lines [elems (listof content?)] ...) block?]{
Typesets a sequence that is broken into multiple lines, where each
@racket[elems] is one line.}
-@defproc[(BNF-group [pre-content any/c] ...) element?]{
+@defproc[(BNF-group [pre-content pre-content?] ...) element?]{
Typesets a group surrounded by curly braces (so the entire group can
be repeated, for example).}
-@defproc[(optional [pre-content any/c] ...) element?]{
+@defproc[(optional [pre-content pre-content?] ...) element?]{
Typesets an optional element: in square brackets.}
-@defproc[(kleenestar [pre-content any/c] ...) element?]{
+@defproc[(kleenestar [pre-content pre-content?] ...) element?]{
Typesets a 0-or-more repetition.}
-@defproc[(kleeneplus [pre-content any/c] ...) element?]{
+@defproc[(kleeneplus [pre-content pre-content?] ...) element?]{
Typesets a 1-or-more repetition.}
-@defproc[(kleenerange [n any/c] [m any/c] [pre-content any/c] ...) element?]{
+@defproc[(kleenerange [n any/c] [m any/c] [pre-content pre-content?] ...)
+ element?]{
Typesets a @racket[n]-to-@racket[m] repetition. The @racket[n] and
@racket[m] arguments are converted to a string using @racket[(format
@@ -92,6 +97,14 @@ Typesets alternatives for a production's right-hand side to appear on
a single line. The result is normally used as a single possibility in
a production list for @racket[BNF].}
-@defthing[BNF-etc string?]{
+@; BNF-alt/close is exported but undocumented.
+@; It looks like it produces a more densely packed version of
+@; BNF-alt, but I haven't confirmed this.
+
+@defthing[BNF-etc element?]{
+
+An element to use for omitted productions or content.
+Renders as: @BNF-etc
+}
+
-A string to use for omitted productions or content.}
diff --git a/scribble-lib/scribble/bnf.rkt b/scribble-lib/scribble/bnf.rkt
@@ -1,19 +1,45 @@
(module bnf racket
- (require "struct.rkt"
- "decode.rkt"
- (only-in "core.rkt"
+ (require scribble/decode
+ (except-in scribble/struct
+ element?)
+ (only-in scribble/core
+ content?
+ element?
make-style
make-table-columns)
- mzlib/kw)
-
- (provide BNF
- nonterm
- BNF-seq BNF-seq-lines
- BNF-alt BNF-alt/close ; single-line alternatives
- BNF-etc
- BNF-group
- optional kleenestar kleeneplus kleenerange)
-
+ )
+
+ (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)))
@@ -33,14 +59,16 @@
(list baseline baseline baseline baseline))))
(apply
append
- (map (lambda (defn)
- (cons
- (list (as-flow spacer) (as-flow (car defn)) (as-flow equals) (as-flow (cadr defn)))
- (map (lambda (i)
- (list (as-flow spacer) (as-flow " ") (as-flow alt) (as-flow i)))
- (cddr defn))))
+ (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
@@ -65,28 +93,28 @@
(define BNF-etc (make-element 'roman "..."))
- (define/kw (nonterm #:body s)
+ (define (nonterm . s)
(make-element 'roman (append (list 'lang)
(list (make-element 'italic (decode-content s)))
(list 'rang))))
- (define/kw (optional #:body s)
+ (define (optional . s)
(make-element #f (append (list (make-element 'roman "["))
(decode-content s)
(list (make-element 'roman "]")))))
- (define/kw (BNF-group #:body s)
+ (define (BNF-group . s)
(make-element #f (append (list (make-element 'roman "{"))
(list (apply BNF-seq (decode-content s)))
(list (make-element 'roman "}")))))
- (define/kw (kleenestar #:body s)
+ (define (kleenestar . s)
(make-element #f (append (decode-content s) (list (make-element 'roman "*")))))
- (define/kw (kleeneplus #:body s)
+ (define (kleeneplus . s)
(make-element #f (append (decode-content s) (list (make-element 'superscript (list "+"))))))
- (define/kw (kleenerange a b #:body s)
+ (define (kleenerange a b . s)
(make-element #f (append (decode-content s)
(list (make-element 'roman
(make-element 'superscript