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