commit 916eaca8fa2a1077411036d3a03100626a967441
parent 31a7a10dc39d7f4bec287f3372953368c34c5e02
Author: Eli Barzilay <eli@racket-lang.org>
Date: Fri, 12 Sep 2008 13:22:31 +0000
improved reader documentation
svn: r11673
original commit: a3930ea08846d9eef84bb3763b7a78f8c0341195
Diffstat:
1 file changed, 150 insertions(+), 46 deletions(-)
diff --git a/collects/scribblings/scribble/reader.scrbl b/collects/scribblings/scribble/reader.scrbl
@@ -20,20 +20,28 @@ You can use the reader via MzScheme's @schemefont{#reader} form:
@schemeblock[
#, @schemefont|{
- #reader(lib "reader.ss" "scribble")@{This is free-form text!}
+ #reader scribble/reader @foo{This is free-form text!}
}|]
-Note that the reader will only read @"@"-forms as S-expressions. The
-meaning of these S-expressions depends on the rest of your own code.
+Note that the Scribble reader reads @"@"-forms as S-expressions. This
+means that it is up to you to give meanings for these expressions in
+the usual way: use Scheme functions, define your functions, or require
+functions. For example, typing the above into MzScheme is likely
+going to produce a ``reference to undefined identifier'' error --- you
+can use @scheme[string-append] instead, or you can define @scheme[foo]
+as a function (with variable arity).
-A PLT Scheme manual more likely starts with
+A common use of the Scribble @"@"-reader is when using Scribble as a
+documentation system for producing manuals. In this case, the manual
+text is likely to start with
@schememod[scribble/doc]
-which installs a reader, wraps the file content afterward into a
-MzScheme module, and parses the body into a document using
-@schememodname[scribble/decode]. See @secref["docreader"] for more
-information.
+which installs the @"@" reader starting in ``text mode'', wraps the
+file content afterward into a MzScheme module where many useful Scheme
+and documentation related functions are available, and parses the body
+into a document using @schememodname[scribble/decode]. See
+@secref["docreader"] for more information.
Another way to use the reader is to use the @scheme[use-at-readtable]
function to switch the current readtable to a readtable that parses
@@ -44,6 +52,8 @@ function to switch the current readtable to a readtable that parses
@;--------------------------------------------------------------------
@section{Concrete Syntax}
+@subsection{The Scribble Syntax at a Glance}
+
Informally, the concrete syntax of @"@"-forms is
@schemeblock[
@@ -55,50 +65,136 @@ Informally, the concrete syntax of @"@"-forms is
where all three parts after @litchar["@"] are optional, but at least
one should be present. (Note that spaces are not allowed between the
-three parts.) @litchar["@"] is set as a non-terminating reader macro,
-so it can be used as usual in Scheme identifiers unless you want to
-use it as a first character of an identifier; in this case you need to
-quote with a backslash (@schemefont["\\@foo"]) or quote the whole
-identifier with bars (@schemefont["|@foo|"]).
+three parts.) Roughly, a form matching the above grammar is read as
@schemeblock[
- #, @schemefont|!{
- (define |@foo| '\@bar@baz)
-}!|]
-
-Of course, @litchar["@"] is not treated specially in Scheme strings,
-character constants, etc.
-
-Roughly, a form matching the above grammar is read as
-
-@schemeblock[
- (#, @nonterm{cmd}
- #, @kleenestar{@nonterm{datum}}
- #, @kleenestar{@nonterm{parsed-body}})
+ (#, @nonterm{cmd} #, @kleenestar{@nonterm{datum}} #, @kleenestar{@nonterm{parsed-body}})
]
where @nonterm{parsed-body} is the translation of each
@nonterm{text-body} in the input. Thus, the initial @nonterm{cmd}
determines the Scheme code that the input is translated into. The
-common case is when @nonterm{cmd} is a Scheme identifier, which
-generates a plain Scheme form.
+common case is when @nonterm{cmd} is a Scheme identifier, which reads
+as a plain Scheme form, with datum arguments and/or string arguments.
-A @nonterm{text-body} is made of text, newlines, and nested
-@"@"-forms. Note that the syntax for @"@"-forms is the same in a
-@nonterm{text-body} context as in a Scheme context. A
+@scribble-examples|==={
+ @foo{blah blah blah}
+ @foo{blah "blah" (`blah'?)}
+ @foo[1 2]{3 4}
+ @foo[1 2 3 4]
+ @foo[#:width 2]{blah blah}
+ @foo{blah blah
+ yada yada}
+ @foo{
+ blah blah
+ yada yada
+ }
+}===|
+
+(Note that these examples show how an input syntax is read as Scheme
+syntax, not what it evaluates to.)
+
+As seen in the last example, multiple lines and the newlines that
+separate them are parsed to multiple Scheme strings. More generally,
+a @nonterm{text-body} is made of text, newlines, and nested
+@"@"-forms, where the syntax for @"@"-forms is the same whether it's
+in a @nonterm{text-body} context as in a Scheme context. A
@nonterm{text-body} that isn't an @"@"-form is converted to a string
-expression for its @nonterm{parsed-body}, and newlines are converted
-to @scheme["\n"] expressions.
+expression for its @nonterm{parsed-body}; newlines and following
+indentations are converted to @scheme["\n"] and all-space string
+expressions.
@scribble-examples|==={
- @foo{bar baz
- blah}
- @foo{bar @baz[3]
- blah}
@foo{bar @baz{3}
blah}
- @foo{bar @baz[2 3]{4 5}
+ @foo{@b{@u[3] @u{4}}
blah}
+ @C{while (*(p++))
+ *p = '\n';}
+}===|
+
+The command part of an @"@"-form is optional as well, which is read as
+a list, usually a function application, but also useful when quoted
+with the usual Scheme @scheme[quote]:
+
+@scribble-examples|==={
+ @{blah blah}
+ @{blah @[3]}
+ '@{foo
+ bar
+ baz}
+}===|
+
+But we can also drop the datum and text parts, which leaves us with
+only the command --- which is read as is, not within a parenthesized
+form. This is not useful when reading Scheme code, but it can be used
+inside a text block to escape a Scheme identifier. A vertical bar
+(@litchar{|}) can be used to delimit the escaped identifier when
+needed.
+
+@scribble-examples|==={
+ @foo
+ @{blah @foo blah}
+ @{blah @foo: blah}
+ @{blah @|foo|: blah}
+}===|
+
+Actually, the command part can be any Scheme expression, which is
+particularly useful with such escapes since they can be used with any
+expression.
+
+@scribble-examples|==={
+ @foo{(+ 1 2) -> @(+ 1 2)!}
+ @foo{A @"string" escape}
+}===|
+
+Note that an escaped Scheme string is merged with the surrounding text
+as a special case. This is useful if you want to use the special
+characters in your string (but note that escaping braces is not
+necessary if they are balanced).
+
+@scribble-examples|==={
+ @foo{eli@"@"barzilay.org}
+ @foo{A @"{" begins a block}
+ @C{while (*(p++)) {
+ *p = '\n';
+ }}
+}===|
+
+In some cases a @"@"-rich text can become cumbersome to quote. For
+this, the braces have an alternative syntax --- a block of text can
+begin with a ``@litchar["|{"]'' and terminated accordingly with a
+``@litchar["}|"]''. Furthermore, any nested @"@" forms must begin
+with a ``@litchar["|@"]''.
+
+@scribble-examples|==={
+ @foo|{bar}@{baz}|
+ @foo|{bar |@x{X} baz}|
+ @foo|{bar |@x|{@}| baz}|
+}===|
+
+In cases when even this is not convenient enough, punctuation
+characters can be added between the @litchar{|} and the braces and the
+@"@" in nested forms. (The punctuation is mirrored for parentheses
+and @litchar{<>}s.) With this, the Scribble syntax can be used as a
+here-string replacement.
+
+@scribble-examples|==={
+ @foo|--{bar}@|{baz}--|
+ @foo|<<{bar}@|{baz}>>|
+}===|
+
+The flip side of this is: how can an @"@" sign be used in Scheme code?
+This is almost never an issue, because Scheme strings and characters
+are still read the same, and because @litchar["@"] is set as a
+non-terminating reader macro so it can be used in Scheme identifiers
+as usual except when it is the first character of an identifier. In
+the last case, you need to quote the identifier like other
+non-standard characters --- with a backslash or with vertical bars:
+
+@scribble-examples|==={
+ (define \@email "foo@bar.com")
+ (define |@atchar| #\@)
}===|
Note that spaces are not allowed before a @litchar{[} or a
@@ -109,9 +205,13 @@ code). (More on using braces in body texts below.)
@foo{bar @baz[2 3] {4 5}}
}===|
-When the above @"@"-forms appear in a Scheme expression context, the
-lexical environment must provide bindings for @scheme[foo] (as a procedure or
-a macro).
+Finally, remember that the Scribble is just an alternate for
+S-expressions --- identifiers still get their meaning, as in any
+Scheme code, through the lexical context in which they appear.
+Specifically, when the above @"@"-form appears in a Scheme expression
+context, the lexical environment must provide bindings for
+@scheme[foo] as a procedure or a macro; it can be defined, required,
+or bound locally (with @scheme[let], for example).
@; FIXME: unfortunate code duplication
@interaction[
@@ -132,12 +232,16 @@ a macro).
@text{@it{Note}: @bf{This is @ul{not} a pipe}.}))
]
-If you want to see the expression that is actually being read, you can
-use Scheme's @scheme[quote].
+When you first experiment with the Scribble syntax, it is often useful
+to use Scheme's @scheme[quote] to inspect how some concrete syntax is
+being read.
-@scribble-examples|==={
- '@foo{bar}
-}===|
+@; FIXME: unfortunate code duplication
+@interaction[
+(eval:alts
+ #,(tt "'@foo{bar}")
+ '@foo{bar})
+]
@;--------------------------------------------------------------------
@subsection{The Command Part}