1#lang scribble/doc
2@(require scribble/manual "utils.rkt" scribble/bnf
3          ;; "utils.rkt" provides scribble/bnf for-label
4          )
5
6@title[#:tag "bnf"]{BNF Grammars}
7
8@defmodule[scribble/bnf]{The @racket[scribble/bnf] library
9provides utilities for typesetting grammars.}
10
11For example,
12
13@verbatim[#:indent 2]|{
14@(let ([open @litchar{(}]
15       [close @litchar{)}])
16   @BNF[(list @nonterm{expr}
17              @nonterm{id}
18              @BNF-seq[open @kleeneplus[@nonterm{expr}] close]
19              @BNF-seq[open @litchar{lambda}
20                        open @kleenestar[@nonterm{id}] close
21                        @nonterm{expr} close]
22              @nonterm{val})
23        (list @nonterm{val}
24              @BNF-alt[@nonterm{number} @nonterm{primop}])
25        (list @nonterm{id}
26              @elem{any name except for @litchar{lambda}})])
27}|
28
29produces the output
30
31@(let ([open @litchar{(}]
32       [close @litchar{)}])
33   @BNF[(list @nonterm{expr}
34              @nonterm{id}
35              @BNF-seq[open @kleeneplus[@nonterm{expr}] close]
36              @BNF-seq[open @litchar{lambda}
37                        open @kleenestar[@nonterm{id}] close
38                        @nonterm{expr} close]
39            @nonterm{val})
40      (list @nonterm{val}
41            @BNF-alt[@nonterm{number} @nonterm{primop}])
42        (list @nonterm{id}
43              @elem{any name except for @litchar{lambda}})])
44
45See also @racket[racketgrammar].
46
47@defproc[(BNF [prod (cons/c (or/c block? content?)
48                            (non-empty-listof (or/c block? content?)))]
49              ...)
50         table?]{
51
52Typesets a grammar table. Each production starts with an element
53(typically constructed with @racket[nonterm]) for the non-terminal
54being defined, and then a list of possibilities (typically constructed
55with @racket[BNF-seq], etc.) to show on separate lines.}
56
57@defproc[(nonterm [pre-content pre-content?] ...) element?]{
58
59Typesets a non-terminal: italic in angle brackets.}
60
61@defproc[(BNF-seq [elem content?] ...) (or/c element? "")]{
62
63Typesets a sequence.}
64
65@defproc[(BNF-seq-lines [elems (listof content?)] ...) block?]{
66
67Typesets a sequence that is broken into multiple lines, where each
68@racket[elems] is one line.}
69
70@defproc[(BNF-group [pre-content pre-content?] ...) element?]{
71
72Typesets a group surrounded by curly braces (so the entire group can
73be repeated, for example).}
74
75@defproc[(optional [pre-content pre-content?] ...) element?]{
76
77Typesets an optional element: in square brackets.}
78
79@defproc[(kleenestar [pre-content pre-content?] ...) element?]{
80
81Typesets a 0-or-more repetition.}
82
83@defproc[(kleeneplus [pre-content pre-content?] ...) element?]{
84
85Typesets a 1-or-more repetition.}
86
87@defproc[(kleenerange [n any/c] [m any/c] [pre-content pre-content?] ...)
88         element?]{
89
90Typesets a @racket[n]-to-@racket[m] repetition. The @racket[n] and
91@racket[m] arguments are converted to a string using @racket[(format
92"~a" n)] and @racket[(format "~a" m)].}
93
94@defproc[(BNF-alt [elem element?] ...) element?]{
95
96Typesets alternatives for a production's right-hand side to appear on
97a single line. The result is normally used as a single possibility in
98a production list for @racket[BNF].}
99
100@; BNF-alt/close is exported but undocumented.
101@; It looks like it produces a more densely packed version of
102@; BNF-alt, but I haven't confirmed this.
103
104@defthing[BNF-etc element?]{
105
106An element to use for omitted productions or content.
107Renders as: @BNF-etc
108}
109
110
111