src/method-impl.lisp, etc.: Add a `readonly' message property.
[sod] / doc / parsing.tex
index 1c4c3cd..22960ee 100644 (file)
@@ -7,7 +7,7 @@
 
 %%%----- Licensing notice ---------------------------------------------------
 %%%
 
 %%%----- 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
 %%%
 %%% 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,208 @@ 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.
 
 \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{Streams} \label{sec:parsing.streams}
+
+\begin{describe*}
+    {\dhead{cls}{position-aware-stream \&key :file :line :column}
+     \dhead{gf}{position-aware-stream-file @<stream> @> @<pathname>}
+     \dhead{gf}{setf (position-aware-stream-file @<stream>) @<pathname>}
+     \dhead{gf}{position-aware-stream-line @<stream> @> @<fixnum>}
+     \dhead{gf}{setf (position-aware-stream-line @<stream>) @<fixnum>}
+     \dhead{gf}{position-aware-stream-column @<stream> @> @<fixnum>}
+     \dhead{gf}{setf (position-aware-stream-column @<stream>) @<fixnum>}}
+\end{describe*}
+
+\begin{describe*}
+    {\dhead{cls}{position-aware-input-stream \&key :file :line :column}
+     \dhead{cls}{position-aware-output-stream \&key :file :line :column}}
+\end{describe*}
+
+\begin{describe}{gf}{stream-pathname @<stream> @> @<pathname-or-nil>}
+  \begin{describe}{meth}{stream}
+      {stream-pathname (@<stream> stream) @> nil}
+  \end{describe}
+  \begin{describe}{meth}{file-stream}
+      {stream-pathname (@<stream> file-stream) @> @<pathname>}
+  \end{describe}
+  \begin{describe}{meth}{position-aware-stream}
+      {stream-pathname (@<stream> position-aware-stream) @> @<pathname>}
+  \end{describe}
+\end{describe}
+
+\begin{describe}{gf}{stream-line-and-column @<stream> @> @<line> @<column>}
+  \begin{describe}{meth}{stream}
+      {stream-line-and-column (@<stream> stream) @> nil nil}
+  \end{describe}
+  \begin{describe}{meth}{position-aware-stream}
+      {stream-line-and-column (@<stream> position-aware-stream)
+        \nlret @<line> @<column>}
+  \end{describe}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\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}
+      {file-location (@<floc> file-location) @> @<floc>}
+  \end{describe}
+  \begin{describe}{meth}{stream}
+      {file-location (@<stream> stream) @> @<floc>}
+  \end{describe}
+  \begin{describe}{meth}{t}
+      {file-location (@<any> t) @> @<floc>}
+  \end{describe}
+\end{describe}
+
+\begin{describe}{cls}{condition-with-location (condition) \&key :location}
+\end{describe}
+
+\begin{describe}{meth}{condition-with-location}
+    {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-condition-with-location (condition)           \\ \>
+         \&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>}
+     \dhead{fun}{info-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}{error}
+         {classify-condition (@<condition> error) @> @<string>}
+       \dhead{meth}{warning}
+         {classify-condition (@<condition> warning) @> @<string>}
+       \dhead{meth}{information}
+         {classify-condition (@<condition> information)
+             @> @<string>}
+       \dhead{meth}{base-lexer-error}
+         {classify-condition (@<condition> base-lexer-error)
+             @> @<string>}
+       \dhead{meth}{base-syntax-error}
+         {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}
 
 %%%--------------------------------------------------------------------------
 \section{Scanners} \label{sec:parsing.scanner}
@@ -61,6 +261,7 @@ Some scanners support an additional \emph{place-capture} protocol which
 allows rewinding the scanner to an earlier point in the input so that it can
 be scanned again.
 
 allows rewinding the scanner to an earlier point in the input so that it can
 be scanned again.
 
+
 \subsection{Basic scanner protocol} \label{sec:parsing.scanner.basic}
 
 The basic protocol supports stepping the scanner forward through its input
 \subsection{Basic scanner protocol} \label{sec:parsing.scanner.basic}
 
 The basic protocol supports stepping the scanner forward through its input
@@ -81,6 +282,7 @@ sequence, and detecting the end of the sequence.
   step the scanner.
 \end{describe}
 
   step the scanner.
 \end{describe}
 
+
 \subsection{Place-capture scanner protocol} \label{sec:parsing.scanner.place}
 
 The place-capture protocol allows rewinding to an earlier point in the
 \subsection{Place-capture scanner protocol} \label{sec:parsing.scanner.place}
 
 The place-capture protocol allows rewinding to an earlier point in the
@@ -93,7 +295,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
 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
 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 +322,21 @@ the scanner and read that data again.  Therefore it's possible to
 \end{describe}
 
 \begin{describe}{mac}
 \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}
 
 \end{describe}
 
+
 \subsection{Scanner file-location protocol} \label{sec:parsing.scanner.floc}
 
 \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
 
 \begin{describe}{fun}{scanner-file-location @<scanner> @> @<file-location>}
   Return a @|file-location| object describing the current position of the
@@ -147,32 +352,18 @@ information using scanner-specific functions described here.
   specialized methods on @|file-location|.
 \end{describe}
 
   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*}
+    {\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}{meth}{scanner-filename (@<scanner> t) @> @<string>}
-  Returns nil.
-\end{describe}
+  There are default methods on all three generic functions which simply
+  return 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}{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}
 
 \subsection{Character scanners} \label{sec:parsing.scanner.char}
 
 
 \subsection{Character scanners} \label{sec:parsing.scanner.char}
 
@@ -192,7 +383,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
 \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}
 
   stepped; or @<character> was not the previous current character.
 \end{describe}
 
@@ -234,6 +425,7 @@ operations to the sequence of characters held by a character scanner.
   character scanner protocols is suitable.  See @|make-scanner-stream|.
 \end{describe}
 
   character scanner protocols is suitable.  See @|make-scanner-stream|.
 \end{describe}
 
+
 \subsection{String scanners} \label{sec:parsing.scanner.string}
 
 A \emph{string scanner} is a simple kind of character scanner which reads
 \subsection{String scanners} \label{sec:parsing.scanner.string}
 
 A \emph{string scanner} is a simple kind of character scanner which reads
@@ -258,6 +450,7 @@ and place-capture protocols.
   to the end of the @<string>).
 \end{describe}
 
   to the end of the @<string>).
 \end{describe}
 
+
 \subsection{Character buffer scanners} \label{sec:parsing.scanner.charbuf}
 
 A \emph{character buffer scanner}, or \emph{charbuf scanner} for short, is an
 \subsection{Character buffer scanners} \label{sec:parsing.scanner.charbuf}
 
 A \emph{character buffer scanner}, or \emph{charbuf scanner} for short, is an
@@ -274,6 +467,10 @@ file-location protocols.
   the scanner will update the location as it reads its input.
 \end{describe}
 
   the scanner will update the location as it reads its input.
 \end{describe}
 
+\begin{describe}{cls}
+    {charbuf-scanner-stream (character-scanner-stream) \&key :scanner}
+\end{describe}
+
 \begin{describe}{cls}{charbuf-scanner-place}
   The class of place objects captured by a charbuf scanner.
 \end{describe}
 \begin{describe}{cls}{charbuf-scanner-place}
   The class of place objects captured by a charbuf scanner.
 \end{describe}
@@ -286,15 +483,15 @@ file-location protocols.
 
 \begin{describe}{gf}
     {charbuf-scanner-map @<scanner> @<func> \&optional @<fail>
 
 \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}
   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
       \textrm\ldots)
   \end{prog}
   The argument @<buf> is a simple string; @<start> and @<end> are two
@@ -302,7 +499,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
   @<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.
 
   @<used> \le @<end>$: the function has consumed the buffer as far as @<used>
   (exclusive) and has completed successfully.
 
@@ -310,8 +507,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}
   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
   \end{prog}
 
   The @|charbuf-scanner-map| function returns three values.  The first value
@@ -322,12 +519,18 @@ file-location protocols.
   at least once, or with $@<used> > @<start>$.
 \end{describe}
 
   at least once, or with $@<used> > @<start>$.
 \end{describe}
 
+
 \subsection{Token scanners} \label{sec:parsing.scanner.token}
 
 \begin{describe}{cls}
     {token-scanner () \&key :filename (:line 1) (:column 0)}
 \end{describe}
 
 \subsection{Token scanners} \label{sec:parsing.scanner.token}
 
 \begin{describe}{cls}
     {token-scanner () \&key :filename (:line 1) (:column 0)}
 \end{describe}
 
+\begin{describe*}
+    {\dhead{gf}{setf (scanner-line @<scanner>) @<fixnum>}
+     \dhead{gf}{setf (scanner-column @<scanner>) @<fixnum>}}
+\end{describe*}
+
 \begin{describe}{gf}{token-type @<scanner> @> @<type>}
 \end{describe}
 
 \begin{describe}{gf}{token-type @<scanner> @> @<type>}
 \end{describe}
 
@@ -344,6 +547,7 @@ file-location protocols.
     {token-scanner-place-p @<value> @> @<generalized-boolean>}
 \end{describe}
 
     {token-scanner-place-p @<value> @> @<generalized-boolean>}
 \end{describe}
 
+
 \subsection{List scanners}
 
 \begin{describe}{ty}{list-scanner}
 \subsection{List scanners}
 
 \begin{describe}{ty}{list-scanner}
@@ -356,10 +560,373 @@ file-location protocols.
 \end{describe}
 
 %%%--------------------------------------------------------------------------
 \end{describe}
 
 %%%--------------------------------------------------------------------------
-\section{Parsing macros}
+\section{Parser contexts and parser syntax} \label{sec:parsing.syntax}
 
 
-%%%--------------------------------------------------------------------------
-\section{Lexical analyser}
+
+\subsection{Parser contexts} \label{sec:parsing.syntax.contexts}
+
+\begin{describe}{mac}
+    {with-parser-context
+        (@<context-class> @{ @<init-keyword> @<value> @}^*)     \\ \ind
+      @<declaration>^*                                          \\
+      @<form>^*
+     \-\nlret @<value>^*}
+\end{describe}
+
+\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}{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}{cls}{list-parser () \&key :var}
+\end{describe}
+
+
+\subsection{Basic parser syntax} \label{sec:parsing.syntax.basic}
+
+\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}
+
+
+\subsection{Place-capture protocol} \label{sec:parsing.syntax.place}
+
+\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}
+
+
+\subsection{Character parsers} \label{sec:parsing.syntax.character}
+
+\begin{describe}{cls}{character-parser-context () \&key}
+\end{describe}
+
+\begin{describe}{gf}{parser-current-char @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{cls}
+    {string-parser (character-parser-context) \&key :string :index :length}
+\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}
+
+
+\subsection{Scanner contexts} \label{sec:parsing.syntax.scanner}
+
+\begin{describe}{cls}{scanner-context () \&key :scanner}
+\end{describe}
+
+\begin{describe}{gf}{parser-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}
+
+
+\subsection{Expression parsing} \label{sec:parsing.syntax.expression}
+
+\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}{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} \label{sec:parsing.lexical}
+
+\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 --------------------------------------------------
 
 
 %%%----- That's all, folks --------------------------------------------------