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