chiark / gitweb /
src/parser/streams-{proto,impl}.lisp: Publish classes and generic functions.
[sod] / doc / parsing.tex
1 %%% -*-latex-*-
2 %%%
3 %%% Description of the parsing machinery
4 %%%
5 %%% (c) 2015 Straylight/Edgeware
6 %%%
7
8 %%%----- Licensing notice ---------------------------------------------------
9 %%%
10 %%% This file is part of the Sensible Object Design, an object system for C.
11 %%%
12 %%% SOD is free software; you can redistribute it and/or modify
13 %%% it under the terms of the GNU General Public License as published by
14 %%% the Free Software Foundation; either version 2 of the License, or
15 %%% (at your option) any later version.
16 %%%
17 %%% SOD is distributed in the hope that it will be useful,
18 %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
19 %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 %%% GNU General Public License for more details.
21 %%%
22 %%% You should have received a copy of the GNU General Public License
23 %%% along with SOD; if not, write to the Free Software Foundation,
24 %%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26 \chapter{Parsing} \label{ch:parsing}
27
28 %%%--------------------------------------------------------------------------
29 \section{The parser protocol} \label{sec:parsing.proto}
30
31 For the purpose of Sod's parsing library, \emph{parsing} is the process of
32 reading a sequence of input items, in order, and computing an output value.
33
34 A \emph{parser} is an expression which consumes zero or more input items and
35 returns three values: a \emph{result}, a \emph{success flag}, and a
36 \emph{consumed flag}.  The two flags are (generalized) booleans.  If the
37 success flag is non-nil, then the parser is said to have \emph{succeeded},
38 and the result is the parser's output.  If the success flag is nil then the
39 parser is said to have \emph{failed}, and the result is a list of
40 \emph{indicators}.  Finally, the consumed flag is non-nil if the parser
41 consumed any input items.
42
43 \begin{describe}{fun}{combine-parser-failures @<failures> @> @<list>}
44 \end{describe}
45
46 \begin{describe}{fun}{parse-empty \&optional @<value> @> @<function>}
47 \end{describe}
48
49 \begin{describe}{fun}
50     {parse-fail @<indicator> \&optional @<consumedp> @> @<function>}
51 \end{describe}
52
53 %%%--------------------------------------------------------------------------
54 \section{Streams} \label{sec:parsing.streams}
55
56 \begin{describe*}
57     {\dhead{cls}{position-aware-stream \&key :file :line :column}
58      \dhead{gf}{position-aware-stream-file @<stream> @> @<pathname>}
59      \dhead{gf}{setf (position-aware-stream-file @<stream>) @<pathname>}
60      \dhead{gf}{position-aware-stream-line @<stream> @> @<fixnum>}
61      \dhead{gf}{setf (position-aware-stream-line @<stream>) @<fixnum>}
62      \dhead{gf}{position-aware-stream-column @<stream> @> @<fixnum>}
63      \dhead{gf}{setf (position-aware-stream-column @<stream>) @<fixnum>}}
64 \end{describe*}
65
66 \begin{describe}{gf}{stream-pathname @<stream> @> @<pathname-or-nil>}
67   \begin{describe}{meth}{stream}
68       {stream-pathname (@<stream> stream) @> nil}
69   \end{describe}
70   \begin{describe}{meth}{file-stream}
71       {stream-pathname (@<stream> file-stream) @> @<pathname>}
72   \end{describe}
73   \begin{describe}{meth}{position-aware-stream}
74       {stream-pathname (@<stream> position-aware-stream) @> @<pathname>}
75   \end{describe}
76 \end{describe}
77
78 \begin{describe}{gf}{stream-line-and-column @<stream> @> @<line> @<column>}
79   \begin{describe}{meth}{stream}
80       {stream-line-and-column (@<stream> stream) @> nil nil}
81   \end{describe}
82   \begin{describe}{meth}{position-aware-stream}
83       {stream-line-and-column (@<stream> position-aware-stream)
84         \nlret @<line> @<column>}
85   \end{describe}
86 \end{describe}
87
88 %%%--------------------------------------------------------------------------
89 \section{File locations} \label{sec:parsing.floc}
90
91 \begin{describe}{cls}{file-location}
92 \end{describe}
93
94 \begin{describe}{fun}{file-location-p @<object> @> @<generalized-boolean>}
95 \end{describe}
96
97 \begin{describe}{fun}
98     {make-file-location @<filename> \&optional @<line> @<column>
99       @> @<file-location>}
100 \end{describe}
101
102 \begin{describe*}
103     {\dhead{fun}{file-location-filename @<floc> @> @<string-or-nil>}
104      \dhead{fun}{file-location-line @<floc> @> @<fixnum-or-nil>}
105      \dhead{fun}{file-location-column @<floc> @> @<fixnum-or-nil>}}
106 \end{describe*}
107
108 \begin{describe}{gf}{file-location @<object> @> @<floc>}
109   \begin{describe}{meth}{file-location}
110       {file-location (@<floc> file-location) @> @<floc>}
111   \end{describe}
112   \begin{describe}{meth}{stream}
113       {file-location (@<stream> stream) @> @<floc>}
114   \end{describe}
115   \begin{describe}{meth}{t}
116       {file-location (@<any> t) @> @<floc>}
117   \end{describe}
118 \end{describe}
119
120 \begin{describe}{cls}{condition-with-location (condition) \&key :location}
121 \end{describe}
122
123 \begin{describe}{meth}{condition-with-location}
124     {file-location (@<condition> condition-with-location) @> @<floc>}
125 \end{describe}
126
127 \begin{describe*}
128     {\quad\=\quad\=\kill
129      \dhead{cls}
130        {error-with-location (condition-with-location error)     \\ \>
131          \&key :location}
132      \dhead{cls}
133        {warning-with-location (condition-with-location warning) \\ \>
134          \&key :location}
135      \dhead{cls}
136        {information-with-location (condition-with-location information) \\ \>
137          \&key :location}
138      \dhead{cls}
139        {enclosing-error-with-location
140            (enclosing-error-with-location error)                \\ \>
141          \&key :condition :location}
142      \dhead{cls}
143        {enclosing-warning-with-location
144            (enclosing-condition-with-location warning)          \\ \>
145          \&key :condition :location}
146      \dhead{cls}
147        {enclosing-information-with-location
148            (enclosing-condition-with-location information)      \\ \>
149          \&key :condition :location}
150      \dhead{cls}
151        {simple-condition-with-location
152            (condition-with-location simple-condition)           \\ \>
153          \&key :format-control :format-arguments :location}
154      \dhead{cls}
155        {simple-error-with-location
156            (error-with-location simple-error)                   \\ \>
157          \&key :format-control :format-arguments :location}
158      \dhead{cls}
159        {simple-warning-with-location
160            (warning-with-location simple-warning)               \\ \>
161          \&key :format-control :format-arguments :location}
162      \dhead{cls}
163        {simple-information-with-location
164            (information-with-location simple-information)       \\ \>
165          \&key :format-control :format-arguments :location}}
166 \end{describe*}
167
168 \begin{describe}{gf}
169     {enclosing-condition-with-location-type @<condition> @> @<symbol>}
170 \end{describe}
171
172 \begin{describe}{fun}
173     {make-condition-with-location @<default-type> @<floc>
174                                   @<datum> \&rest @<arguments>
175        \nlret @<condition-with-location>}
176 \end{describe}
177
178 \begin{describe*}
179     {\dhead{fun}{error-with-location @<floc> @<datum> \&rest @<arguments>}
180      \dhead{fun}{cerror-with-location @<floc> @<continue-string>
181                                       @<datum> \&rest @<arguments>}
182      \dhead{fun}{cerror*-with-location @<floc> @<datum> \&rest @<arguments>}
183      \dhead{fun}{warn-with-location @<floc> @<datum> \&rest @<arguments>}}
184 \end{describe*}
185
186 \begin{describe*}
187     {\dhead{cls}{parser-error (error) \\ \ind
188                     \&key :expected :found \-}
189      \dhead{gf}{parser-error-expected @<condition> @> @<list>}
190      \dhead{gf}{parser-error-found @<condition> @> @<value>}}
191 \end{describe*}
192
193 \begin{describe}{fun}
194     {report-parser-error @<error> @<stream> @<show-expected> @<show-found>}
195 \end{describe}
196
197 \begin{describe*}
198     {\quad\=\kill
199      \dhead{cls}{base-lexer-error (error-with-location) \&key :location}
200      \dhead{cls}{simple-lexer-error
201                       (base-lexer-error simple-error-with-location) \\\>
202                     \&key :format-control :format-arguments :location}
203      \dhead{cls}{base-syntax-error (error-with-location) \&key :location}
204      \dhead{cls}{simple-syntax-error
205                       (base-syntax-error simple-error-with-location) \\\>
206                     \&key :format-control :format-arguments :location}}
207 \end{describe*}
208
209 \begin{describe}{mac}
210     {with-default-error-location (@<floc>) @<declaration>^* @<form>^*
211       @> @<value>^*}
212 \end{describe}
213
214 \begin{describe}{gf}{classify-condition @<condition> @> @<string>}
215   \begin{describe*}
216       {\dhead{meth}{error}
217          {classify-condition (@<condition> error) @> @<string>}
218        \dhead{meth}{warning}
219          {classify-condition (@<condition> warning) @> @<string>}
220        \dhead{meth}{information}
221          {classify-condition (@<condition> information)
222              @> @<string>}
223        \dhead{meth}{base-lexer-error}
224          {classify-condition (@<condition> base-lexer-error)
225              @> @<string>}
226        \dhead{meth}{base-syntax-error}
227          {classify-condition (@<condition> base-syntax-error)
228              @> @<string>}}
229   \end{describe*}
230 \end{describe}
231
232 \begin{describe}{mac}
233     {count-and-report-errors () @<declaration>^* @<form>^*
234       @> @<value> @<n-errors> @<n-warnings>}
235 \end{describe}
236
237 %%%--------------------------------------------------------------------------
238 \section{Scanners} \label{sec:parsing.scanner}
239
240 A \emph{scanner} is an object which keeps track of a parser's progress as it
241 works through its input.  There's no common base class for scanners: a
242 scanner is simply any object which implements the scanner protocol described
243 here.
244
245 A scanner maintains a sequence of items to read.  It can step forwards
246 through the items, one at a time, until it reaches the end (if, indeed, the
247 sequence is finite, which it needn't be).  Until that point, there is a
248 current item, though there's no protocol for accessing it at this level
249 because the nature of the items is left unspecified.
250
251 Some scanners support an additional \emph{place-capture} protocol which
252 allows rewinding the scanner to an earlier point in the input so that it can
253 be scanned again.
254
255 \subsection{Basic scanner protocol} \label{sec:parsing.scanner.basic}
256
257 The basic protocol supports stepping the scanner forward through its input
258 sequence, and detecting the end of the sequence.
259
260 \begin{describe}{gf}{scanner-step @<scanner>}
261   Advance the @<scanner> to the next item, which becomes current.
262
263   It is an error to step the scanner if the scanner is at end-of-file.
264 \end{describe}
265
266 \begin{describe}{gf}{scanner-at-eof-p @<scanner> @> @<generalized-boolean>}
267   Return non-nil if the scanner is at end-of-file, i.e., there are no more
268   items to read.
269
270   If nil is returned, there is a current item, and it is safe to step the
271   scanner again; otherwise, it is an error to query the current item or to
272   step the scanner.
273 \end{describe}
274
275 \subsection{Place-capture scanner protocol} \label{sec:parsing.scanner.place}
276
277 The place-capture protocol allows rewinding to an earlier point in the
278 sequence.  Not all scanners support the place-capture protocol.
279
280 To rewind a scanner to a particular point, that point must be \emph{captured}
281 as a \emph{place} when it's current -- so you must know in advance that this
282 is an interesting place that's worth capturing.  The type of place returned
283 depends on the type of scanner.  Given a captured place, the scanner can be
284 rewound to the position held in it.
285
286 Depending on how the scanner works, holding onto a captured place might
287 consume a lot of memory or cause poor performance.  For example, if the
288 scanner is reading from an input stream, having a captured place means that
289 data from that point on must be buffered in case the program needs to rewind
290 the scanner and read that data again.  Therefore it's possible to
291 \emph{release} a place when it turns out not to be needed any more.
292
293 \begin{describe}{gf}{scanner-capture-place @<scanner> @> @<place>}
294   Capture the @<scanner>'s current position as a place, and return the place.
295 \end{describe}
296
297 \begin{describe}{gf}{scanner-restore-place @<scanner> @<place>}
298   Rewind the @<scanner> to the state it was in when @<place> was captured.
299   In particular, the item that was current when the @<place> was captured
300   becomes current again.
301
302   It is an error to restore a @<place> that has been released, or if the
303   @<place> wasn't captured from the @<scanner>.
304 \end{describe}
305
306 \begin{describe}{gf}{scanner-release-place @<scanner> @<place>}
307   Release the @<place>, to avoid having to maintaining the ability to restore
308   it after it's not needed any more..
309
310   It is an error if the @<place> wasn't captured from the @<scanner>.
311 \end{describe}
312
313 \begin{describe}{mac}
314     {with-scanner-place (@<place> @<scanner>) @<declarations>^* @<form>^*
315       @> @<value>^*}
316   Capture the @<scanner>'s current position as a place, evaluate the @<form>s
317   as an implicit progn with the variable @<place> bound to the captured
318   place.  When control leaves the @<form>s, the place is released.  The
319   return values are the values of the final @<form>.
320 \end{describe}
321
322 \subsection{Scanner file-location protocol} \label{sec:parsing.scanner.floc}
323
324 Some scanners participate in the file-location protocol
325 (\xref{sec:parsing.floc}).  They implement a method on @|file-location| which
326 collects the necessary information using scanner-specific functions described
327 here.
328
329 \begin{describe}{fun}{scanner-file-location @<scanner> @> @<file-location>}
330   Return a @|file-location| object describing the current position of the
331   @<scanner>.
332
333   This calls the @|scanner-filename|, @|scanner-line| and @|scanner-column|
334   generic functions on the scanner, and uses these to fill in an appropriate
335   @|file-location|.
336
337   Since there are default methods on these generic functions, it is not an
338   error to call @|scanner-file-location| on any kind of value, but it might
339   not be very useful.  This function exists to do the work of appropriately
340   specialized methods on @|file-location|.
341 \end{describe}
342
343 \begin{describe*}
344     {\dhead{gf}{scanner-filename @<scanner> @> @<string>}
345      \dhead{gf}{scanner-line @<scanner> @> @<integer>}
346      \dhead{gf}{scanner-column @<scanner> @> @<integer>}}
347   Return the filename, line and column components of the @<scanner>'s current
348   position, for use in assembling a @<file-location>: see the
349   @|scanner-file-location| function.
350
351   There are default methods on all three generic functions which simply
352   return nil.
353 \end{describe*}
354
355 \subsection{Character scanners} \label{sec:parsing.scanner.char}
356
357 Character scanners are scanners which read sequences of characters.
358
359 \begin{describe}{cls}{character-scanner () \&key}
360   Base class for character scanners.  This provides some very basic
361   functionality.
362
363   Not all character scanners are subclasses of @|character-scanner|.
364 \end{describe}
365
366 \begin{describe}{gf}{scanner-current-char @<scanner> @> @<character>}
367   Returns the current character.
368 \end{describe}
369
370 \begin{describe}{gf}{scanner-unread @<scanner> @<character>}
371   Rewind the @<scanner> by one step.  The @<chararacter> must be the previous
372   current character, and becomes the current character again.  It is an error
373   if: the @<scanner> has reached end-of-file; the @<scanner> has never been
374   stepped; or @<character> was not the previous current character.
375 \end{describe}
376
377 \begin{describe}{gf}
378     {scanner-interval @<scanner> @<place-a> \&optional @<place-b>
379         @> @<string>}
380   Return the characters in the @<scanner>'s input from @<place-a> up to (but
381   not including) @<place-b>.
382
383   The characters are returned as a string.  If @<place-b> is omitted, return
384   the characters up to (but not including) the current position.  It is an
385   error if @<place-b> precedes @<place-a> or they are from different
386   scanners.
387
388   This function is a character-scanner-specific extension to the
389   place-capture protocol; not all character scanners implement the
390   place-capture protocol, and some that do may not implement this function.
391 \end{describe}
392
393 \subsubsection{Stream access to character scanners}
394 Sometimes it can be useful to apply the standard Lisp character input
395 operations to the sequence of characters held by a character scanner.
396
397 \begin{describe}{gf}{make-scanner-stream @<scanner> @> @<stream>}
398   Returns a fresh input @|stream| object which fetches input characters from
399   the character scanner object @<scanner>.  Reading characters from the
400   stream steps the scanner.  The stream will reach end-of-file when the
401   scanner reports end-of-file.  If the scanner implements the file-location
402   protocol then reading from the stream will change the file location in an
403   appropriate manner.
404
405   This is mostly useful for applying standard Lisp stream functions, most
406   particularly the @|read| function, in the middle of a parsing operation.
407 \end{describe}
408
409 \begin{describe}{cls}{character-scanner-stream (stream) \&key :scanner}
410   A Common Lisp input @|stream| object which works using the character
411   scanner protocol.  Any @<scanner> which implements the base scanner and
412   character scanner protocols is suitable.  See @|make-scanner-stream|.
413 \end{describe}
414
415 \subsection{String scanners} \label{sec:parsing.scanner.string}
416
417 A \emph{string scanner} is a simple kind of character scanner which reads
418 input from a string object.  String scanners implement the character scanner
419 and place-capture protocols.
420
421 \begin{describe}{cls}{string-scanner}
422   The class of string scanners.  The @|string-scanner| class is not a
423   subclass of @|character-scanner|.
424 \end{describe}
425
426 \begin{describe}{fun}{string-scanner-p @<value> @> @<generalized-boolean>}
427   Return non-nil if @<value> is a @|string-scanner| object; otherwise return
428   nil.
429 \end{describe}
430
431 \begin{describe}{fun}
432     {make-string-scanner @<string> \&key :start :end @> @<string-scanner>}
433   Construct and return a fresh @|string-scanner| object.  The new scanner
434   will read characters from @<string>, starting at index @<start> (which
435   defaults to zero), and continuing until it reaches index @<end> (defaults
436   to the end of the @<string>).
437 \end{describe}
438
439 \subsection{Character buffer scanners} \label{sec:parsing.scanner.charbuf}
440
441 A \emph{character buffer scanner}, or \emph{charbuf scanner} for short, is an
442 efficient scanner for reading characters from an input stream.  Charbuf
443 scanners implements the basic scanner, character buffer, place-capture, and
444 file-location protocols.
445
446 \begin{describe}{cls}
447     {charbuf-scanner (character-scanner)
448         \&key :stream :filename :line :column}
449   The class of charbuf scanners.  The scanner will read characters from
450   @<stream>.  Charbuf scanners implement the file-location protocol: the
451   initial location is set from the given @<filename>, @<line> and @<column>;
452   the scanner will update the location as it reads its input.
453 \end{describe}
454
455 \begin{describe}{cls}{charbuf-scanner-place}
456   The class of place objects captured by a charbuf scanner.
457 \end{describe}
458
459 \begin{describe}{fun}
460     {charbuf-scanner-place-p @<value> @> @<generalized-boolean>}
461   Type predicate for charbuf scanner places: returns non-nil if @<value> is a
462   place captured by a charbuf scanner, and nil otherwise.
463 \end{describe}
464
465 \begin{describe}{gf}
466     {charbuf-scanner-map @<scanner> @<func> \&optional @<fail>
467       \nlret @<result> @<success-flag> @<consumed-flag>}
468   Read characters from the @<scanner>'s buffers.
469
470   This is intended to be an efficient and versatile interface for reading
471   characters from a scanner in bulk.  The function @<func> is invoked
472   repeatedly, as if by
473   \begin{prog}
474     (multiple-value-bind (@<donep> @<used>)                     \\ \ind\ind
475         (funcall @<func> @<buf> @<start> @<end>)              \-\\
476       \textrm\ldots)
477   \end{prog}
478   The argument @<buf> is a simple string; @<start> and @<end> are two
479   nonnegative fixnums, indicating that the subsequence of @<buf> between
480   @<start> (inclusive) and @<end> (exclusive) should be processed.  If
481   @<func>'s return value @<donep> is nil then @<used> is ignored: the
482   function has consumed the entire buffer and wishes to read more.  If
483   @<donep> is non-nil, then @<used> must be a fixnum such that $@<start> \le
484   @<used> \le @<end>$: the function has consumed the buffer as far as @<used>
485   (exclusive) and has completed successfully.
486
487   If end-of-file is encountered before @<func> completes successfully then it
488   fails: the @<fail> function is called with no arguments, and is expected to
489   return two values.  If omitted, @<fail> defaults to
490   \begin{prog}
491     (lambda ()                                                  \\ \ind
492       (values nil nil))
493   \end{prog}
494
495   The @|charbuf-scanner-map| function returns three values.  The first value
496   is the non-nil @<donep> value returned by @<func> if @|charbuf-scanner-map|
497   succeeded, or the first value returned by @<fail>; the second value is @|t|
498   on success, or the second value returned by @<fail>; the third value is
499   non-nil if @<func> consumed any input, i.e., it returned with @<donep> nil
500   at least once, or with $@<used> > @<start>$.
501 \end{describe}
502
503 \subsection{Token scanners} \label{sec:parsing.scanner.token}
504
505 \begin{describe}{cls}
506     {token-scanner () \&key :filename (:line 1) (:column 0)}
507 \end{describe}
508
509 \begin{describe}{gf}{token-type @<scanner> @> @<type>}
510 \end{describe}
511
512 \begin{describe}{gf}{token-value @<scanner> @> @<value>}
513 \end{describe}
514
515 \begin{describe}{gf}{scanner-token @<scanner> @> @<type> @<value>}
516 \end{describe}
517
518 \begin{describe}{ty}{token-scanner-place}
519 \end{describe}
520
521 \begin{describe}{fun}
522     {token-scanner-place-p @<value> @> @<generalized-boolean>}
523 \end{describe}
524
525 \subsection{List scanners}
526
527 \begin{describe}{ty}{list-scanner}
528 \end{describe}
529
530 \begin{describe}{fun}{list-scanner-p @<value> @> @<generalized-boolean>}
531 \end{describe}
532
533 \begin{describe}{fun}{make-list-scanner @<list> @> @<list-scanner>}
534 \end{describe}
535
536 %%%--------------------------------------------------------------------------
537 \section{Parsing syntax}
538
539 \begin{describe}{gf}{expand-parser-spec @<context> @<spec> @> @<form>}
540 \end{describe}
541
542 \begin{describe}{gf}
543     {expand-parser-form @<context> @<head> @<tail> @> @<form>}
544 \end{describe}
545
546 \begin{describe}{gf}{wrap-parser @<context> @<form> @> @<wrapped-form>}
547 \end{describe}
548
549 \begin{describe}{mac}
550     {defparse @<name> (@[[ :context (@<var> @<context-class>) @]]
551                        @<destructuring-lambda-list-item>^*)     \\ \ind
552       @[[ @<declaration>^* @! @<doc-string> @]]                 \\
553       @<form>^*
554      \-\nlret @<name>}
555 \end{describe}
556
557 \begin{describe}{mac}
558     {with-parser-context
559         (@<context-class> @{ @<init-keyword> @<value> @}^*)     \\ \ind
560       @<declaration>^*                                          \\
561       @<form>^*
562      \-\nlret @<value>^*}
563 \end{describe}
564
565 \begin{describe}{lmac}
566     {parse @<parser> @> @<result> @<success-flag> @<consumed-flag>}
567 \end{describe}
568
569 \begin{describe}{mac}
570     {parser @<lambda-list>
571       @[[ @<declaration>^* @! @<doc-string> @]]
572       @<parser>
573       @> @<function>}
574 \end{describe}
575
576 \begin{describe}{gf}{parser-at-eof-p @<context> @> @<form>}
577 \end{describe}
578
579 \begin{describe}{gf}{parser-step @<context> @> @<form>}
580 \end{describe}
581
582 \begin{describe}{mac}
583     {if-parse (@[[ \=:result @<result-var> @!
584                      :expected @<expected-var> @!             \+\\
585                      :consumedp @<consumed-var> @]])          \-\\ \ind\ind
586         @<parser>                                             \-\\
587       @<consequent>                                             \\
588       @[@<alternatve>@]
589      \-\nlret @<value>^*}
590 \end{describe}
591
592 \begin{describe}{mac}
593     {when-parse (@[@<result-var>@]) @<parser>                   \\ \ind
594       @<form>^*
595      \-\nlret @<value>^*}
596 \end{describe}
597
598 \begin{describe}{mac}
599     {cond-parse (@[[ \=:result @<result-var> @!
600                        :expected @<expected-var> @!           \+\\
601                        :consumedp @<consumed-var> @]])        \-\\ \ind
602       @{ (@<parser> @<form>^*) @}^*
603      \-\nlret @<value>^*}
604 \end{describe}
605
606 \begin{describe}{parse}{:eof}
607 \end{describe}
608
609 \begin{describe}{parseform}{lisp @<form>^*}
610 \end{describe}
611
612 \begin{describe}{parseform}{label @<parser>}
613 \end{describe}
614
615 \begin{describe}{parse}{t}
616 \end{describe}
617
618 \begin{describe}{parseform}{t @<value>}
619 \end{describe}
620
621 \begin{describe}{parse}{nil}
622 \end{describe}
623
624 \begin{describe}{parseform}{nil @<indicator>}
625 \end{describe}
626
627 \begin{describe}{parseform}{when @<cond> @<parser>}
628 \end{describe}
629
630 \begin{describe}{parseform}
631     {seq (@{ @<atomic-parser-spec> @!
632              (@[@<var>@] @<parser>) @}^*)                       \\ \ind
633       @<form>^*}
634 \end{describe}
635
636 \begin{describe}{parseform}{and @<parser>^*}
637 \end{describe}
638
639 \begin{describe}{parseform}{or @<parser>^*}
640 \end{describe}
641
642 \begin{describe}{parseform}{? @<parser> @[@<default>@]}
643 \end{describe}
644
645 \begin{describe}{parseform}
646     {many (\=@<accumulator-var> @<init-form> @<update-form>   \+\\
647            @[[ \=:new @<new-var> @! :final @<final-form> @!   \+\\
648                  :min @<minimum> @! :max @<maximum> @!          \\
649                  :commitp @<commitp> @]])                   \-\-\\ \ind
650       @<item-parser> @[@<sep-parser>@]}
651 \end{describe}
652
653 \begin{describe}{parseform}
654     {list (@[[ :min @<minimum> @! :max @<maximum> @!
655                :commitp @<commitp> @]])                         \\ \ind
656       @<item-parser> @[@<sep-parser>@]}
657 \end{describe}
658
659 \begin{describe}{parseform}
660     {skip-many (@[[ :min @<minimum> @! :max @<maximum> @!
661                     :commitp @<commitp> @]])                    \\ \ind
662       @<item-parser> @[@<sep-parser>@]}
663 \end{describe}
664
665 \begin{describe}{fun}{call-pluggable-parser @<symbol> \&rest @<args>}
666 \end{describe}
667
668 \begin{describe}{parseform}{plug @<symbol> @<arg>^*}
669 \end{describe}
670
671 \begin{describe}{fun}
672     {pluggable-parser-add @<symbol> @<tag> @<parser-function>}
673 \end{describe}
674
675 \begin{describe}{mac}
676     {define-pluggable-parser @<symbol> @<tag> @<lambda-list>
677       @[[ @<declaration>^* @! @<doc-string> @]]
678       @<form>^*}
679 \end{describe}
680
681 \begin{describe}{gf}{parser-capture-place @<context> @> @<form>}
682 \end{describe}
683
684 \begin{describe}{gf}{parser-restore-place @<context> @<place> @> @<form>}
685 \end{describe}
686
687 \begin{describe}{gf}{parser-release-place @<context> @<place> @> @<form>}
688 \end{describe}
689
690 \begin{describe}{gf}
691     {parser-places-must-be-released-p @<context> @> @<generalized-boolean>}
692 \end{describe}
693
694 \begin{describe}{mac}
695     {with-parser-place (@<place-var> @<context>)
696       @[[ @<declaration>^* @! @<doc-string> @]]
697       @<form>^*}
698 \end{describe}
699
700 \begin{describe}{parseform}{peek @<parser>}
701 \end{describe}
702
703 \begin{describe}{parseform}{commit}
704 \end{describe}
705
706 \begin{describe}{cls}{character-parser-context () \&key}
707 \end{describe}
708
709 \begin{describe}{gf}{parser-current-char @<context> @> @<form>}
710 \end{describe}
711
712 \begin{describe}{parseform}
713     {if-char (@[@<result-var>@]) @<condition> @<consequent> @<alternative>}
714 \end{describe}
715
716 \begin{describe}{parseform}{char @<character>}
717 \end{describe}
718
719 \begin{describe}{parse}[char]{@<character>}
720 \end{describe}
721
722 \begin{describe}{parse}[string]{@<string>}
723 \end{describe}
724
725 \begin{describe}{parse}{:any}
726 \end{describe}
727
728 \begin{describe}{parseform}{satisfies @<predicate>}
729 \end{describe}
730
731 \begin{describe}{parseform}{not @<character>}
732 \end{describe}
733
734 \begin{describe}{parseform}{filter @<predicate>}
735 \end{describe}
736
737 \begin{describe}{parse}{:whitespace}
738 \end{describe}
739
740 \begin{describe}{cls}{token-parser-context () \&key}
741 \end{describe}
742
743 \begin{describe}{gf}{parser-token-type @<context> @> @<form>}
744 \end{describe}
745
746 \begin{describe}{gf}{parser-token-value @<context> @> @<form>}
747 \end{describe}
748
749 \begin{describe}{parseform}{token @<type> @[@<value>@] @[:peekp @<peek>@]}
750 \end{describe}
751
752 \begin{describe}{parse}[atom]{@<atom>}
753 \end{describe}
754
755 \begin{describe}{cls}{scanner-context () \&key :scanner}
756 \end{describe}
757
758 \begin{describe}{gf}{parse-scanner @<context> @> @<symbol>}
759 \end{describe}
760
761 \begin{describe}{cls}
762     {character-scanner-context (scanner-context character-parser-context)
763       \&key :scanner}
764 \end{describe}
765
766 \begin{describe}{cls}
767     {token-scanner-context (scanner-context token-parser-context)
768       \&key :scanner}
769 \end{describe}
770
771 \begin{describe}{gf}{push-operator @<operator> @<state>}
772 \end{describe}
773
774 \begin{describe}{gf}{push-value @<value> @<state>}
775 \end{describe}
776
777 \begin{describe}{gf}{apply-operator @<operator> @<state>}
778 \end{describe}
779
780 \begin{describe}{gf}{operator-push-action @<left> @<right>}
781 \end{describe}
782
783 \begin{describe}{parseform}
784     {expr \=(@[[ :nestedp @<nestedp-var> @]])                 \+\\
785             @<operand-parser> @<binop-parser>
786             @<preop-parser> @<postop-parser>}
787 \end{describe}
788
789 \begin{describe}{gf}{operator-left-precedence @<operator> @> @<prec>}
790 \end{describe}
791
792 \begin{describe}{gf}{operator-right-precedence @<operator> @> @<prec>}
793 \end{describe}
794
795 \begin{describe}{gf}{operator-associativity @<operator> @> @<assoc>}
796 \end{describe}
797
798 \begin{describe}{cls}{prefix-operator () \&key}
799 \end{describe}
800
801 \begin{describe}{cls}{simple-operator () \&key :name :function}
802 \end{describe}
803
804 \begin{describe}{cls}
805     {simple-unary-operator (simple-operator) \&key :name :function}
806 \end{describe}
807
808 \begin{describe*}
809     {\quad\=\kill
810      \dhead{cls}{simple-binary-operator (simple-operator)       \\ \>
811                   \&key :name :function
812                         :lprec :rprec :associativity}
813      \dhead{cls}{simple-postfix-operator (simple-unary-operator) \\ \>
814                   \&key :name :function :lprec :rprec}
815      \dhead{cls}{simple-prefix-operator
816                     (prefix-operator simple-unary-operator)     \\ \>
817                   \&key :name :function :rprec}}
818 \end{describe*}
819
820 \begin{describe*}
821     {\dhead{mac}{preop @<name> (@<operand-var> @<lprec>)
822                   @<declaration>^* @<form>^*
823                   @> @<prefix-operator>}
824      \dhead{mac}{postop @<name>
825                      (@<operand-var> @<lprec> @[[ :rprec @<rprec> @]])
826                   @<declaration>^* @<form>^*
827                   \nlret @<postfix-operator>}
828      \dhead{mac}{binop @<name> (@<operand-var> @<lprec> @<rprec> @<assoc>)
829                   @<declaration>^*@<form>^*
830                   @> @<binary-operator>}}
831 \end{describe*}
832
833 \begin{describe*}
834     {\dhead{cls}{parenthesis () \&key :tag}
835      \dhead{cls}{open-parenthesis (parenthesis prefix-operator) \&key :tag}
836      \dhead{cls}{close-parenthesis (parenthesis) \&key :tag}}
837 \end{describe*}
838
839 \begin{describe*}
840     {\dhead{fun}{lparen @<tag> @> @<open-paren>}
841      \dhead{fun}{rparen @<tag> @> @<close-paren>}}
842 \end{describe*}
843
844 %%%-------------------------------------------------------------------------
845 \section{Lexical analyser}
846
847 \begin{describe}{cls}
848     {sod-token-scanner (token-scanner)
849       \&key :filename (:line 1) (:column 0) :char-scanner}
850 \end{describe}
851
852 \begin{describe}{fun}{define-indicator @<indicator> @<description>}
853 \end{describe}
854
855 \begin{describe*}
856     {\dhead{cls}{lexer-error (parser-error base-lexer-error) \\ \ind
857                     \&key :expected :found :location \-}
858      \dhead{cls}{syntax-error (parser-error base-syntax-error) \\ \ind
859                     \&key :expected :found :location \-}}
860 \end{describe*}
861
862 \begin{describe}{fun}
863     {syntax-error @<scanner> @<expected> \&key :continuep :location}
864 \end{describe}
865
866 \begin{describe}{fun}
867     {lexer-error @<char-scanner> @<expected> \&key :location}
868 \end{describe}
869
870 \begin{describe}{parseform}
871     {skip-until (@[[ :keep-end @<keep-end-flag> @]]) @<token-type>^*}
872 \end{describe}
873
874 \begin{describe}{parseform}
875     {error (@[[ :ignore-unconsumed @<flag> @!
876                 :force-process @<flag> @]])                     \\ \ind\ind
877         @<sub-parser> @<recover-parser>                       \-\\
878       @<declaration>^*                                          \\
879       @<form>^*}
880 \end{describe}
881
882 \begin{describe}{parseform}{must @<sub-parser> @[@<default>@]}
883 \end{describe}
884
885 \begin{describe}{fun}
886     {scan-comment @<char-scanner>
887       @> @<result> @<success-flag> @<consumed-flag>}
888 \end{describe}
889
890 %%%----- That's all, folks --------------------------------------------------
891
892 %%% Local variables:
893 %%% mode: LaTeX
894 %%% TeX-master: "sod.tex"
895 %%% TeX-PDF-mode: t
896 %%% End: