X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/1f7d590d9c7b87442c8d8b6424ed4f769d377692..34042b3558b28b85fa7155f7c7cd171239cbbaa3:/doc/parsing.tex

diff --git a/doc/parsing.tex b/doc/parsing.tex
index 1c4c3cd..4cb6ef1 100644
--- a/doc/parsing.tex
+++ b/doc/parsing.tex
@@ -7,7 +7,7 @@
 
 %%%----- Licensing notice ---------------------------------------------------
 %%%
-%%% This file is part of the Sensble Object Design, an object system for C.
+%%% This file is part of the Sensible Object Design, an object system for C.
 %%%
 %%% SOD is free software; you can redistribute it and/or modify
 %%% it under the terms of the GNU General Public License as published by
@@ -40,8 +40,156 @@ parser is said to have \emph{failed}, and the result is a list of
 \emph{indicators}.  Finally, the consumed flag is non-nil if the parser
 consumed any input items.
 
+\begin{describe}{fun}{combine-parser-failures @<failures> @> @<list>}
+\end{describe}
+
+\begin{describe}{fun}{parse-empty \&optional @<value> @> @<function>}
+\end{describe}
+
+\begin{describe}{fun}
+    {parse-fail @<indicator> \&optional @<consumedp> @> @<function>}
+\end{describe}
+
 %%%--------------------------------------------------------------------------
-\section{File locations}
+\section{File locations} \label{sec:parsing.floc}
+
+\begin{describe}{cls}{file-location}
+\end{describe}
+
+\begin{describe}{fun}{file-location-p @<object> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{fun}
+    {make-file-location @<filename> \&optional @<line> @<column>
+      @> @<file-location>}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{fun}{file-location-filename @<floc> @> @<string-or-nil>}
+     \dhead{fun}{file-location-line @<floc> @> @<fixnum-or-nil>}
+     \dhead{fun}{file-location-column @<floc> @> @<fixnum-or-nil>}}
+\end{describe*}
+
+\begin{describe}{gf}{file-location @<object> @> @<floc>}
+  \begin{describe}{meth}{file-location (@<floc> file-location) @> @<floc>}
+  \end{describe}
+  \begin{describe}{meth}{file-location (@<stream> stream) @> @<floc>}
+  \end{describe}
+  \begin{describe}{meth}{file-location (@<any> t) @> @<floc>}
+  \end{describe}
+\end{describe}
+
+\begin{describe}{cls}{condition-with-location (condition) \&key :location}
+\end{describe}
+
+\begin{describe}{meth}
+    {file-location (@<condition> condition-with-location) @> @<floc>}
+\end{describe}
+
+\begin{describe*}
+    {\quad\=\quad\=\kill
+     \dhead{cls}
+       {error-with-location (condition-with-location error)     \\ \>
+         \&key :location}
+     \dhead{cls}
+       {warning-with-location (condition-with-location warning) \\ \>
+         \&key :location}
+     \dhead{cls}
+       {information-with-location (condition-with-location information) \\ \>
+         \&key :location}
+     \dhead{cls}
+       {enclosing-error-with-location
+           (enclosing-error-with-location error)                \\ \>
+         \&key :condition :location}
+     \dhead{cls}
+       {enclosing-warning-with-location
+           (enclosing-condition-with-location warning)          \\ \>
+         \&key :condition :location}
+     \dhead{cls}
+       {enclosing-information-with-location
+           (enclosing-condition-with-location information)      \\ \>
+         \&key :condition :location}
+     \dhead{cls}
+       {simple-condition-with-location
+           (condition-with-location simple-condition)           \\ \>
+         \&key :format-control :format-arguments :location}
+     \dhead{cls}
+       {simple-error-with-location
+           (error-with-location simple-error)                   \\ \>
+         \&key :format-control :format-arguments :location}
+     \dhead{cls}
+       {simple-warning-with-location
+           (warning-with-location simple-warning)               \\ \>
+         \&key :format-control :format-arguments :location}
+     \dhead{cls}
+       {simple-information-with-location
+           (information-with-location simple-information)       \\ \>
+         \&key :format-control :format-arguments :location}}
+\end{describe*}
+
+\begin{describe}{gf}
+    {enclosing-condition-with-location-type @<condition> @> @<symbol>}
+\end{describe}
+
+\begin{describe}{fun}
+    {make-condition-with-location @<default-type> @<floc>
+                                  @<datum> \&rest @<arguments>
+       \nlret @<condition-with-location>}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{fun}{error-with-location @<floc> @<datum> \&rest @<arguments>}
+     \dhead{fun}{cerror-with-location @<floc> @<continue-string>
+                                      @<datum> \&rest @<arguments>}
+     \dhead{fun}{cerror*-with-location @<floc> @<datum> \&rest @<arguments>}
+     \dhead{fun}{warn-with-location @<floc> @<datum> \&rest @<arguments>}}
+\end{describe*}
+
+\begin{describe*}
+    {\dhead{cls}{parser-error (error) \\ \ind
+                    \&key :expected :found \-}
+     \dhead{gf}{parser-error-expected @<condition> @> @<list>}
+     \dhead{gf}{parser-error-found @<condition> @> @<value>}}
+\end{describe*}
+
+\begin{describe}{fun}
+    {report-parser-error @<error> @<stream> @<show-expected> @<show-found>}
+\end{describe}
+
+\begin{describe*}
+    {\quad\=\kill
+     \dhead{cls}{base-lexer-error (error-with-location) \&key :location}
+     \dhead{cls}{simple-lexer-error
+                      (base-lexer-error simple-error-with-location) \\\>
+                    \&key :format-control :format-arguments :location}
+     \dhead{cls}{base-syntax-error (error-with-location) \&key :location}
+     \dhead{cls}{simple-syntax-error
+                      (base-syntax-error simple-error-with-location) \\\>
+                    \&key :format-control :format-arguments :location}}
+\end{describe*}
+
+\begin{describe}{mac}
+    {with-default-error-location (@<floc>) @<declaration>^* @<form>^*
+      @> @<value>^*}
+\end{describe}
+
+\begin{describe}{gf}{classify-condition @<condition> @> @<string>}
+  \begin{describe*}
+      {\dhead{meth}{classify-condition (@<condition> error) @> @<string>}
+       \dhead{meth}{classify-condition (@<condition> warning) @> @<string>}
+       \dhead{meth}{classify-condition (@<condition> information)
+                       @> @<string>}
+       \dhead{meth}{classify-condition (@<condition> base-lexer-error)
+                       @> @<string>}
+       \dhead{meth}{classify-condition (@<condition> base-syntax-error)
+                       @> @<string>}}
+  \end{describe*}
+\end{describe}
+
+\begin{describe}{mac}
+    {count-and-report-errors () @<declaration>^* @<form>^*
+      @> @<value> @<n-errors> @<n-warnings>}
+\end{describe}
 
 %%%--------------------------------------------------------------------------
 \section{Scanners} \label{sec:parsing.scanner}
@@ -93,7 +241,7 @@ depends on the type of scanner.  Given a captured place, the scanner can be
 rewound to the position held in it.
 
 Depending on how the scanner works, holding onto a captured place might
-consume a lot of memory or case poor performance.  For example, if the
+consume a lot of memory or cause poor performance.  For example, if the
 scanner is reading from an input stream, having a captured place means that
 data from that point on must be buffered in case the program needs to rewind
 the scanner and read that data again.  Therefore it's possible to
@@ -120,18 +268,20 @@ the scanner and read that data again.  Therefore it's possible to
 \end{describe}
 
 \begin{describe}{mac}
-    {with-scanner-place (@<place> @<scanner>) @<body-form>^* @> @<value>^*}
-  Capture the @<scanner>'s current position as a place, evaluate the
-  @<body-form>s as an implicit progn with the variable @<place> bound to the captured
-  place.  When control leaves the @<body-form>s, the place is released.  The return
-  values are the values of the final @<body-form>.
+    {with-scanner-place (@<place> @<scanner>) @<declarations>^* @<form>^*
+      @> @<value>^*}
+  Capture the @<scanner>'s current position as a place, evaluate the @<form>s
+  as an implicit progn with the variable @<place> bound to the captured
+  place.  When control leaves the @<form>s, the place is released.  The
+  return values are the values of the final @<form>.
 \end{describe}
 
 \subsection{Scanner file-location protocol} \label{sec:parsing.scanner.floc}
 
-Some scanners participate in the file-location protocol (\xref{sec:floc}).
-They implement a method on @|file-location| which collects the necessary
-information using scanner-specific functions described here.
+Some scanners participate in the file-location protocol
+(\xref{sec:parsing.floc}).  They implement a method on @|file-location| which
+collects the necessary information using scanner-specific functions described
+here.
 
 \begin{describe}{fun}{scanner-file-location @<scanner> @> @<file-location>}
   Return a @|file-location| object describing the current position of the
@@ -147,32 +297,17 @@ information using scanner-specific functions described here.
   specialized methods on @|file-location|.
 \end{describe}
 
-\begin{describe}{gf}{scanner-filename @<scanner> @> @<string>}
-  Return the name of the file the scanner is currently processing, as a
-  string, or nil if the filename is not known.
-\end{describe}
-
-\begin{describe}{meth}{scanner-filename (@<scanner> t) @> @<string>}
-  Returns nil.
-\end{describe}
-
-\begin{describe}{gf}{scanner-line @<scanner> @> @<integer>}
-  Return the line number of the @<scanner>'s current position, as an integer,
-  or nil if the line number is not known.
-\end{describe}
-
-\begin{describe}{meth}{scanner-line (@<scanner> t) @> @<integer>}
-  Returns nil.
-\end{describe}
+\begin{describe*}
+    {\dhead{gf}{scanner-filename @<scanner> @> @<string>}
+     \dhead{gf}{scanner-line @<scanner> @> @<integer>}
+     \dhead{gf}{scanner-column @<scanner> @> @<integer>}}
+  Return the filename, line and column components of the @<scanner>'s current
+  position, for use in assembling a @<file-location>: see the
+  @|scanner-file-location| function.
 
-\begin{describe}{gf}{scanner-column @<scanner> @> @<integer>}
-  Return the column number of the @<scanner>'s current position, as an
-  integer, or nil if the column number is not known.
-\end{describe}
-
-\begin{describe}{meth}{scanner-column (@<scanner> t) @> @<integer>}
-  Returns nil.
-\end{describe}
+  There are default methods on all three generic functions which simply
+  return nil.
+\end{describe*}
 
 \subsection{Character scanners} \label{sec:parsing.scanner.char}
 
@@ -192,7 +327,7 @@ Character scanners are scanners which read sequences of characters.
 \begin{describe}{gf}{scanner-unread @<scanner> @<character>}
   Rewind the @<scanner> by one step.  The @<chararacter> must be the previous
   current character, and becomes the current character again.  It is an error
-  if: the @<scanner> has reached end-of-file; the @<scanner> is never been
+  if: the @<scanner> has reached end-of-file; the @<scanner> has never been
   stepped; or @<character> was not the previous current character.
 \end{describe}
 
@@ -286,15 +421,15 @@ file-location protocols.
 
 \begin{describe}{gf}
     {charbuf-scanner-map @<scanner> @<func> \&optional @<fail>
-      \nlret @<result> @<successp> @<consumedp>}
+      \nlret @<result> @<success-flag> @<consumed-flag>}
   Read characters from the @<scanner>'s buffers.
 
   This is intended to be an efficient and versatile interface for reading
   characters from a scanner in bulk.  The function @<func> is invoked
   repeatedly, as if by
   \begin{prog}
-    (multiple-value-bind (@<donep> @<used>) \\ \ind\ind
-        (funcall @<func> @<buf> @<start> @<end>) \- \\
+    (multiple-value-bind (@<donep> @<used>)                     \\ \ind\ind
+        (funcall @<func> @<buf> @<start> @<end>)              \-\\
       \textrm\ldots)
   \end{prog}
   The argument @<buf> is a simple string; @<start> and @<end> are two
@@ -302,7 +437,7 @@ file-location protocols.
   @<start> (inclusive) and @<end> (exclusive) should be processed.  If
   @<func>'s return value @<donep> is nil then @<used> is ignored: the
   function has consumed the entire buffer and wishes to read more.  If
-  @<donep> is non-nil, then it must be a fixnum such that $@<start> \le
+  @<donep> is non-nil, then @<used> must be a fixnum such that $@<start> \le
   @<used> \le @<end>$: the function has consumed the buffer as far as @<used>
   (exclusive) and has completed successfully.
 
@@ -310,8 +445,8 @@ file-location protocols.
   fails: the @<fail> function is called with no arguments, and is expected to
   return two values.  If omitted, @<fail> defaults to
   \begin{prog}
-    (lambda () \\ \ind
-      (values nil nil))%
+    (lambda ()                                                  \\ \ind
+      (values nil nil))
   \end{prog}
 
   The @|charbuf-scanner-map| function returns three values.  The first value
@@ -356,11 +491,359 @@ file-location protocols.
 \end{describe}
 
 %%%--------------------------------------------------------------------------
-\section{Parsing macros}
+\section{Parsing syntax}
 
-%%%--------------------------------------------------------------------------
+\begin{describe}{gf}{expand-parser-spec @<context> @<spec> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}
+    {expand-parser-form @<context> @<head> @<tail> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{wrap-parser @<context> @<form> @> @<wrapped-form>}
+\end{describe}
+
+\begin{describe}{mac}
+    {defparse @<name> (@[[ :context (@<var> @<context-class>) @]]
+                       @<destructuring-lambda-list-item>^*)     \\ \ind
+      @[[ @<declaration>^* @! @<doc-string> @]]                 \\
+      @<form>^*
+     \-\nlret @<name>}
+\end{describe}
+
+\begin{describe}{mac}
+    {with-parser-context
+        (@<context-class> @{ @<init-keyword> @<value> @}^*)     \\ \ind
+      @<declaration>^*                                          \\
+      @<form>^*
+     \-\nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{lmac}
+    {parse @<parser> @> @<result> @<success-flag> @<consumed-flag>}
+\end{describe}
+
+\begin{describe}{mac}
+    {parser @<lambda-list>
+      @[[ @<declaration>^* @! @<doc-string> @]]
+      @<parser>
+      @> @<function>}
+\end{describe}
+
+\begin{describe}{gf}{parser-at-eof-p @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-step @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{mac}
+    {if-parse (@[[ \=:result @<result-var> @!
+                     :expected @<expected-var> @!             \+\\
+                     :consumedp @<consumed-var> @]])          \-\\ \ind\ind
+        @<parser>                                             \-\\
+      @<consequent>                                             \\
+      @[@<alternatve>@]
+     \-\nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {when-parse (@[@<result-var>@]) @<parser>                   \\ \ind
+      @<form>^*
+     \-\nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {cond-parse (@[[ \=:result @<result-var> @!
+                       :expected @<expected-var> @!           \+\\
+                       :consumedp @<consumed-var> @]])        \-\\ \ind
+      @{ (@<parser> @<form>^*) @}^*
+     \-\nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{parse}{:eof}
+\end{describe}
+
+\begin{describe}{parseform}{lisp @<form>^*}
+\end{describe}
+
+\begin{describe}{parseform}{label @<parser>}
+\end{describe}
+
+\begin{describe}{parse}{t}
+\end{describe}
+
+\begin{describe}{parseform}{t @<value>}
+\end{describe}
+
+\begin{describe}{parse}{nil}
+\end{describe}
+
+\begin{describe}{parseform}{nil @<indicator>}
+\end{describe}
+
+\begin{describe}{parseform}{when @<cond> @<parser>}
+\end{describe}
+
+\begin{describe}{parseform}
+    {seq (@{ @<atomic-parser-spec> @!
+             (@[@<var>@] @<parser>) @}^*)                       \\ \ind
+      @<form>^*}
+\end{describe}
+
+\begin{describe}{parseform}{and @<parser>^*}
+\end{describe}
+
+\begin{describe}{parseform}{or @<parser>^*}
+\end{describe}
+
+\begin{describe}{parseform}{? @<parser> @[@<default>@]}
+\end{describe}
+
+\begin{describe}{parseform}
+    {many (\=@<accumulator-var> @<init-form> @<update-form>   \+\\
+           @[[ \=:new @<new-var> @! :final @<final-form> @!   \+\\
+                 :min @<minimum> @! :max @<maximum> @!          \\
+                 :commitp @<commitp> @]])                   \-\-\\ \ind
+      @<item-parser> @[@<sep-parser>@]}
+\end{describe}
+
+\begin{describe}{parseform}
+    {list (@[[ :min @<minimum> @! :max @<maximum> @!
+               :commitp @<commitp> @]])                         \\ \ind
+      @<item-parser> @[@<sep-parser>@]}
+\end{describe}
+
+\begin{describe}{parseform}
+    {skip-many (@[[ :min @<minimum> @! :max @<maximum> @!
+                    :commitp @<commitp> @]])                    \\ \ind
+      @<item-parser> @[@<sep-parser>@]}
+\end{describe}
+
+\begin{describe}{fun}{call-pluggable-parser @<symbol> \&rest @<args>}
+\end{describe}
+
+\begin{describe}{parseform}{plug @<symbol> @<arg>^*}
+\end{describe}
+
+\begin{describe}{fun}
+    {pluggable-parser-add @<symbol> @<tag> @<parser-function>}
+\end{describe}
+
+\begin{describe}{mac}
+    {define-pluggable-parser @<symbol> @<tag> @<lambda-list>
+      @[[ @<declaration>^* @! @<doc-string> @]]
+      @<form>^*}
+\end{describe}
+
+\begin{describe}{gf}{parser-capture-place @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-restore-place @<context> @<place> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-release-place @<context> @<place> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}
+    {parser-places-must-be-released-p @<context> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{mac}
+    {with-parser-place (@<place-var> @<context>)
+      @[[ @<declaration>^* @! @<doc-string> @]]
+      @<form>^*}
+\end{describe}
+
+\begin{describe}{parseform}{peek @<parser>}
+\end{describe}
+
+\begin{describe}{parseform}{commit}
+\end{describe}
+
+\begin{describe}{cls}{character-parser-context () \&key}
+\end{describe}
+
+\begin{describe}{gf}{parser-current-char @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{parseform}
+    {if-char (@[@<result-var>@]) @<condition> @<consequent> @<alternative>}
+\end{describe}
+
+\begin{describe}{parseform}{char @<character>}
+\end{describe}
+
+\begin{describe}{parse}[char]{@<character>}
+\end{describe}
+
+\begin{describe}{parse}[string]{@<string>}
+\end{describe}
+
+\begin{describe}{parse}{:any}
+\end{describe}
+
+\begin{describe}{parseform}{satisfies @<predicate>}
+\end{describe}
+
+\begin{describe}{parseform}{not @<character>}
+\end{describe}
+
+\begin{describe}{parseform}{filter @<predicate>}
+\end{describe}
+
+\begin{describe}{parse}{:whitespace}
+\end{describe}
+
+\begin{describe}{cls}{token-parser-context () \&key}
+\end{describe}
+
+\begin{describe}{gf}{parser-token-type @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-token-value @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{parseform}{token @<type> @[@<value>@] @[:peekp @<peek>@]}
+\end{describe}
+
+\begin{describe}{parse}[atom]{@<atom>}
+\end{describe}
+
+\begin{describe}{cls}{scanner-context () \&key :scanner}
+\end{describe}
+
+\begin{describe}{gf}{parse-scanner @<context> @> @<symbol>}
+\end{describe}
+
+\begin{describe}{cls}
+    {character-scanner-context (scanner-context character-parser-context)
+      \&key :scanner}
+\end{describe}
+
+\begin{describe}{cls}
+    {token-scanner-context (scanner-context token-parser-context)
+      \&key :scanner}
+\end{describe}
+
+\begin{describe}{gf}{push-operator @<operator> @<state>}
+\end{describe}
+
+\begin{describe}{gf}{push-value @<value> @<state>}
+\end{describe}
+
+\begin{describe}{gf}{apply-operator @<operator> @<state>}
+\end{describe}
+
+\begin{describe}{gf}{operator-push-action @<left> @<right>}
+\end{describe}
+
+\begin{describe}{parseform}
+    {expr \=(@[[ :nestedp @<nestedp-var> @]])                 \+\\
+            @<operand-parser> @<binop-parser>
+            @<preop-parser> @<postop-parser>}
+\end{describe}
+
+\begin{describe}{gf}{operator-left-precedence @<operator> @> @<prec>}
+\end{describe}
+
+\begin{describe}{gf}{operator-right-precedence @<operator> @> @<prec>}
+\end{describe}
+
+\begin{describe}{gf}{operator-associativity @<operator> @> @<assoc>}
+\end{describe}
+
+\begin{describe}{cls}{prefix-operator () \&key}
+\end{describe}
+
+\begin{describe}{cls}{simple-operator () \&key :name :function}
+\end{describe}
+
+\begin{describe}{cls}
+    {simple-unary-operator (simple-operator) \&key :name :function}
+\end{describe}
+
+\begin{describe*}
+    {\quad\=\kill
+     \dhead{cls}{simple-binary-operator (simple-operator)       \\ \>
+                  \&key :name :function
+                        :lprec :rprec :associativity}
+     \dhead{cls}{simple-postfix-operator (simple-unary-operator) \\ \>
+                  \&key :name :function :lprec :rprec}
+     \dhead{cls}{simple-prefix-operator
+                    (prefix-operator simple-unary-operator)     \\ \>
+                  \&key :name :function :rprec}}
+\end{describe*}
+
+\begin{describe*}
+    {\dhead{mac}{preop @<name> (@<operand-var> @<lprec>)
+                  @<declaration>^* @<form>^*
+                  @> @<prefix-operator>}
+     \dhead{mac}{postop @<name>
+                     (@<operand-var> @<lprec> @[[ :rprec @<rprec> @]])
+                  @<declaration>^* @<form>^*
+                  \nlret @<postfix-operator>}
+     \dhead{mac}{binop @<name> (@<operand-var> @<lprec> @<rprec> @<assoc>)
+                  @<declaration>^*@<form>^*
+                  @> @<binary-operator>}}
+\end{describe*}
+
+\begin{describe*}
+    {\dhead{cls}{parenthesis () \&key :tag}
+     \dhead{cls}{open-parenthesis (parenthesis prefix-operator) \&key :tag}
+     \dhead{cls}{close-parenthesis (parenthesis) \&key :tag}}
+\end{describe*}
+
+\begin{describe*}
+    {\dhead{fun}{lparen @<tag> @> @<open-paren>}
+     \dhead{fun}{rparen @<tag> @> @<close-paren>}}
+\end{describe*}
+
+%%%-------------------------------------------------------------------------
 \section{Lexical analyser}
 
+\begin{describe}{cls}
+    {sod-token-scanner (token-scanner)
+      \&key :filename (:line 1) (:column 0) :char-scanner}
+\end{describe}
+
+\begin{describe}{fun}{define-indicator @<indicator> @<description>}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{cls}{lexer-error (parser-error base-lexer-error) \\ \ind
+                    \&key :expected :found :location \-}
+     \dhead{cls}{syntax-error (parser-error base-syntax-error) \\ \ind
+                    \&key :expected :found :location \-}}
+\end{describe*}
+
+\begin{describe}{fun}
+    {syntax-error @<scanner> @<expected> \&key :continuep :location}
+\end{describe}
+
+\begin{describe}{fun}
+    {lexer-error @<char-scanner> @<expected> \&key :location}
+\end{describe}
+
+\begin{describe}{parseform}
+    {skip-until (@[[ :keep-end @<keep-end-flag> @]]) @<token-type>^*}
+\end{describe}
+
+\begin{describe}{parseform}
+    {error (@[[ :ignore-unconsumed @<flag> @!
+                :force-process @<flag> @]])                     \\ \ind\ind
+        @<sub-parser> @<recover-parser>                       \-\\
+      @<declaration>^*                                          \\
+      @<form>^*}
+\end{describe}
+
+\begin{describe}{parseform}{must @<sub-parser> @[@<default>@]}
+\end{describe}
+
+\begin{describe}{fun}
+    {scan-comment @<char-scanner>
+      @> @<result> @<success-flag> @<consumed-flag>}
+\end{describe}
+
 %%%----- That's all, folks --------------------------------------------------
 
 %%% Local variables:
