doc/sod.sty: Provide explicit description labelling and indexing commands.
[sod] / doc / parsing.tex
CommitLineData
1f7d590d
MW
1%%% -*-latex-*-
2%%%
3%%% Description of the parsing machinery
4%%%
5%%% (c) 2015 Straylight/Edgeware
6%%%
7
8%%%----- Licensing notice ---------------------------------------------------
9%%%
e0808c47 10%%% This file is part of the Sensible Object Design, an object system for C.
1f7d590d
MW
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
31For the purpose of Sod's parsing library, \emph{parsing} is the process of
32reading a sequence of input items, in order, and computing an output value.
33
34A \emph{parser} is an expression which consumes zero or more input items and
35returns three values: a \emph{result}, a \emph{success flag}, and a
36\emph{consumed flag}. The two flags are (generalized) booleans. If the
37success flag is non-nil, then the parser is said to have \emph{succeeded},
38and the result is the parser's output. If the success flag is nil then the
39parser 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
41consumed any input items.
42
fcb6c0fb
MW
43\begin{describe}{fun}{combine-parser-failures @<failures> @> @<list>}
44\end{describe}
45
da901cf2
MW
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
1f7d590d 53%%%--------------------------------------------------------------------------
d2f1db72
MW
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%%%--------------------------------------------------------------------------
fcb6c0fb
MW
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>}
87883222
MW
109 \begin{describe}{meth}{file-location}
110 {file-location (@<floc> file-location) @> @<floc>}
fcb6c0fb 111 \end{describe}
87883222
MW
112 \begin{describe}{meth}{stream}
113 {file-location (@<stream> stream) @> @<floc>}
fcb6c0fb 114 \end{describe}
87883222
MW
115 \begin{describe}{meth}{t}
116 {file-location (@<any> t) @> @<floc>}
fcb6c0fb
MW
117 \end{describe}
118\end{describe}
119
120\begin{describe}{cls}{condition-with-location (condition) \&key :location}
121\end{describe}
122
87883222 123\begin{describe}{meth}{condition-with-location}
fcb6c0fb
MW
124 {file-location (@<condition> condition-with-location) @> @<floc>}
125\end{describe}
126
127\begin{describe*}
128 {\quad\=\quad\=\kill
129 \dhead{cls}
020b9e2b 130 {error-with-location (condition-with-location error) \\ \>
acaf88ad 131 \&key :location}
fcb6c0fb 132 \dhead{cls}
acaf88ad
MW
133 {warning-with-location (condition-with-location warning) \\ \>
134 \&key :location}
fcb6c0fb 135 \dhead{cls}
db6c3279
MW
136 {information-with-location (condition-with-location information) \\ \>
137 \&key :location}
138 \dhead{cls}
acaf88ad 139 {enclosing-error-with-location
020b9e2b 140 (enclosing-error-with-location error) \\ \>
acaf88ad
MW
141 \&key :condition :location}
142 \dhead{cls}
143 {enclosing-warning-with-location
020b9e2b 144 (enclosing-condition-with-location warning) \\ \>
acaf88ad
MW
145 \&key :condition :location}
146 \dhead{cls}
db6c3279
MW
147 {enclosing-information-with-location
148 (enclosing-condition-with-location information) \\ \>
149 \&key :condition :location}
150 \dhead{cls}
acaf88ad 151 {simple-condition-with-location
020b9e2b 152 (condition-with-location simple-condition) \\ \>
acaf88ad
MW
153 \&key :format-control :format-arguments :location}
154 \dhead{cls}
155 {simple-error-with-location
020b9e2b 156 (error-with-location simple-error) \\ \>
acaf88ad
MW
157 \&key :format-control :format-arguments :location}
158 \dhead{cls}
159 {simple-warning-with-location
020b9e2b 160 (warning-with-location simple-warning) \\ \>
db6c3279
MW
161 \&key :format-control :format-arguments :location}
162 \dhead{cls}
163 {simple-information-with-location
164 (information-with-location simple-information) \\ \>
acaf88ad 165 \&key :format-control :format-arguments :location}}
fcb6c0fb
MW
166\end{describe*}
167
388ab382
MW
168\begin{describe}{gf}
169 {enclosing-condition-with-location-type @<condition> @> @<symbol>}
170\end{describe}
171
fcb6c0fb
MW
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
40d95de7
MW
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
fcb6c0fb 209\begin{describe}{mac}
cac85e0b
MW
210 {with-default-error-location (@<floc>) @<declaration>^* @<form>^*
211 @> @<value>^*}
fcb6c0fb
MW
212\end{describe}
213
40d95de7
MW
214\begin{describe}{gf}{classify-condition @<condition> @> @<string>}
215 \begin{describe*}
87883222
MW
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>}}
40d95de7
MW
229 \end{describe*}
230\end{describe}
231
fcb6c0fb 232\begin{describe}{mac}
cac85e0b 233 {count-and-report-errors () @<declaration>^* @<form>^*
fcb6c0fb
MW
234 @> @<value> @<n-errors> @<n-warnings>}
235\end{describe}
1f7d590d
MW
236
237%%%--------------------------------------------------------------------------
238\section{Scanners} \label{sec:parsing.scanner}
239
240A \emph{scanner} is an object which keeps track of a parser's progress as it
241works through its input. There's no common base class for scanners: a
242scanner is simply any object which implements the scanner protocol described
243here.
244
245A scanner maintains a sequence of items to read. It can step forwards
246through the items, one at a time, until it reaches the end (if, indeed, the
247sequence is finite, which it needn't be). Until that point, there is a
248current item, though there's no protocol for accessing it at this level
249because the nature of the items is left unspecified.
250
251Some scanners support an additional \emph{place-capture} protocol which
252allows rewinding the scanner to an earlier point in the input so that it can
253be scanned again.
254
255\subsection{Basic scanner protocol} \label{sec:parsing.scanner.basic}
256
257The basic protocol supports stepping the scanner forward through its input
258sequence, 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
277The place-capture protocol allows rewinding to an earlier point in the
278sequence. Not all scanners support the place-capture protocol.
279
280To rewind a scanner to a particular point, that point must be \emph{captured}
281as a \emph{place} when it's current -- so you must know in advance that this
282is an interesting place that's worth capturing. The type of place returned
283depends on the type of scanner. Given a captured place, the scanner can be
284rewound to the position held in it.
285
286Depending on how the scanner works, holding onto a captured place might
054e8f8f 287consume a lot of memory or cause poor performance. For example, if the
1f7d590d
MW
288scanner is reading from an input stream, having a captured place means that
289data from that point on must be buffered in case the program needs to rewind
290the 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}
cac85e0b
MW
314 {with-scanner-place (@<place> @<scanner>) @<declarations>^* @<form>^*
315 @> @<value>^*}
cd35a54e
MW
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>.
1f7d590d
MW
320\end{describe}
321
322\subsection{Scanner file-location protocol} \label{sec:parsing.scanner.floc}
323
fcb6c0fb
MW
324Some scanners participate in the file-location protocol
325(\xref{sec:parsing.floc}). They implement a method on @|file-location| which
326collects the necessary information using scanner-specific functions described
327here.
1f7d590d
MW
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
fcb6c0fb
MW
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.
1f7d590d 350
fcb6c0fb
MW
351 There are default methods on all three generic functions which simply
352 return nil.
353\end{describe*}
1f7d590d
MW
354
355\subsection{Character scanners} \label{sec:parsing.scanner.char}
356
357Character 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
054e8f8f 373 if: the @<scanner> has reached end-of-file; the @<scanner> has never been
1f7d590d
MW
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}
394Sometimes it can be useful to apply the standard Lisp character input
395operations 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
417A \emph{string scanner} is a simple kind of character scanner which reads
418input from a string object. String scanners implement the character scanner
419and 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
441A \emph{character buffer scanner}, or \emph{charbuf scanner} for short, is an
442efficient scanner for reading characters from an input stream. Charbuf
443scanners implements the basic scanner, character buffer, place-capture, and
444file-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>
054e8f8f 467 \nlret @<result> @<success-flag> @<consumed-flag>}
1f7d590d
MW
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}
020b9e2b
MW
474 (multiple-value-bind (@<donep> @<used>) \\ \ind\ind
475 (funcall @<func> @<buf> @<start> @<end>) \-\\
1f7d590d
MW
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
054e8f8f 483 @<donep> is non-nil, then @<used> must be a fixnum such that $@<start> \le
1f7d590d
MW
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}
020b9e2b
MW
491 (lambda () \\ \ind
492 (values nil nil))
1f7d590d
MW
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%%%--------------------------------------------------------------------------
fcb6c0fb 537\section{Parsing syntax}
1f7d590d 538
fcb6c0fb
MW
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>) @]]
020b9e2b
MW
551 @<destructuring-lambda-list-item>^*) \\ \ind
552 @[[ @<declaration>^* @! @<doc-string> @]] \\
553 @<form>^*
554 \-\nlret @<name>}
fcb6c0fb
MW
555\end{describe}
556
557\begin{describe}{mac}
558 {with-parser-context
020b9e2b
MW
559 (@<context-class> @{ @<init-keyword> @<value> @}^*) \\ \ind
560 @<declaration>^* \\
561 @<form>^*
562 \-\nlret @<value>^*}
fcb6c0fb
MW
563\end{describe}
564
565\begin{describe}{lmac}
566 {parse @<parser> @> @<result> @<success-flag> @<consumed-flag>}
567\end{describe}
568
3f921e3f
MW
569\begin{describe}{mac}
570 {parser @<lambda-list>
571 @[[ @<declaration>^* @! @<doc-string> @]]
572 @<parser>
573 @> @<function>}
574\end{describe}
575
fcb6c0fb
MW
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
fcb6c0fb
MW
582\begin{describe}{mac}
583 {if-parse (@[[ \=:result @<result-var> @!
020b9e2b
MW
584 :expected @<expected-var> @! \+\\
585 :consumedp @<consumed-var> @]]) \-\\ \ind\ind
586 @<parser> \-\\
587 @<consequent> \\
588 @[@<alternatve>@]
589 \-\nlret @<value>^*}
fcb6c0fb
MW
590\end{describe}
591
592\begin{describe}{mac}
020b9e2b
MW
593 {when-parse (@[@<result-var>@]) @<parser> \\ \ind
594 @<form>^*
595 \-\nlret @<value>^*}
fcb6c0fb
MW
596\end{describe}
597
598\begin{describe}{mac}
599 {cond-parse (@[[ \=:result @<result-var> @!
020b9e2b
MW
600 :expected @<expected-var> @! \+\\
601 :consumedp @<consumed-var> @]]) \-\\ \ind
602 @{ (@<parser> @<form>^*) @}^*
603 \-\nlret @<value>^*}
fcb6c0fb
MW
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}
020b9e2b
MW
631 {seq (@{ @<atomic-parser-spec> @!
632 (@[@<var>@] @<parser>) @}^*) \\ \ind
cd35a54e 633 @<form>^*}
fcb6c0fb
MW
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}
020b9e2b
MW
646 {many (\=@<accumulator-var> @<init-form> @<update-form> \+\\
647 @[[ \=:new @<new-var> @! :final @<final-form> @! \+\\
648 :min @<minimum> @! :max @<maximum> @! \\
649 :commitp @<commitp> @]]) \-\-\\ \ind
fcb6c0fb
MW
650 @<item-parser> @[@<sep-parser>@]}
651\end{describe}
652
653\begin{describe}{parseform}
654 {list (@[[ :min @<minimum> @! :max @<maximum> @!
020b9e2b 655 :commitp @<commitp> @]]) \\ \ind
fcb6c0fb
MW
656 @<item-parser> @[@<sep-parser>@]}
657\end{describe}
658
659\begin{describe}{parseform}
660 {skip-many (@[[ :min @<minimum> @! :max @<maximum> @!
020b9e2b 661 :commitp @<commitp> @]]) \\ \ind
fcb6c0fb
MW
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}
cac85e0b
MW
676 {define-pluggable-parser @<symbol> @<tag> @<lambda-list>
677 @[[ @<declaration>^* @! @<doc-string> @]]
678 @<form>^*}
fcb6c0fb
MW
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}
46a4727d 691 {parser-places-must-be-released-p @<context> @> @<generalized-boolean>}
fcb6c0fb
MW
692\end{describe}
693
694\begin{describe}{mac}
cac85e0b
MW
695 {with-parser-place (@<place-var> @<context>)
696 @[[ @<declaration>^* @! @<doc-string> @]]
697 @<form>^*}
fcb6c0fb
MW
698\end{describe}
699
700\begin{describe}{parseform}{peek @<parser>}
701\end{describe}
702
2b8759bf
MW
703\begin{describe}{parseform}{commit}
704\end{describe}
705
fcb6c0fb
MW
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
34042b35 719\begin{describe}{parse}[char]{@<character>}
fcb6c0fb
MW
720\end{describe}
721
34042b35 722\begin{describe}{parse}[string]{@<string>}
fcb6c0fb
MW
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
34042b35 752\begin{describe}{parse}[atom]{@<atom>}
fcb6c0fb
MW
753\end{describe}
754
fcb6c0fb
MW
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
2c7465ac
MW
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}
020b9e2b 784 {expr \=(@[[ :nestedp @<nestedp-var> @]]) \+\\
2c7465ac
MW
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
020b9e2b
MW
810 \dhead{cls}{simple-binary-operator (simple-operator) \\ \>
811 \&key :name :function
812 :lprec :rprec :associativity}
2c7465ac
MW
813 \dhead{cls}{simple-postfix-operator (simple-unary-operator) \\ \>
814 \&key :name :function :lprec :rprec}
815 \dhead{cls}{simple-prefix-operator
020b9e2b 816 (prefix-operator simple-unary-operator) \\ \>
2c7465ac
MW
817 \&key :name :function :rprec}}
818\end{describe*}
819
820\begin{describe*}
821 {\dhead{mac}{preop @<name> (@<operand-var> @<lprec>)
cac85e0b 822 @<declaration>^* @<form>^*
2c7465ac
MW
823 @> @<prefix-operator>}
824 \dhead{mac}{postop @<name>
825 (@<operand-var> @<lprec> @[[ :rprec @<rprec> @]])
cac85e0b
MW
826 @<declaration>^* @<form>^*
827 \nlret @<postfix-operator>}
2c7465ac 828 \dhead{mac}{binop @<name> (@<operand-var> @<lprec> @<rprec> @<assoc>)
cac85e0b 829 @<declaration>^*@<form>^*
2c7465ac
MW
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*}
fcb6c0fb
MW
843
844%%%-------------------------------------------------------------------------
1f7d590d
MW
845\section{Lexical analyser}
846
2c7465ac
MW
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
40d95de7
MW
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
d63df20a
MW
862\begin{describe}{fun}
863 {syntax-error @<scanner> @<expected> \&key :continuep :location}
2c7465ac
MW
864\end{describe}
865
866\begin{describe}{fun}
d63df20a 867 {lexer-error @<char-scanner> @<expected> \&key :location}
2c7465ac
MW
868\end{describe}
869
870\begin{describe}{parseform}
871 {skip-until (@[[ :keep-end @<keep-end-flag> @]]) @<token-type>^*}
872\end{describe}
873
5fa27d76 874\begin{describe}{parseform}
450a4be6 875 {error (@[[ :ignore-unconsumed @<flag> @!
b5911ce8
MW
876 :force-process @<flag> @]]) \\ \ind\ind
877 @<sub-parser> @<recover-parser> \-\\
878 @<declaration>^* \\
879 @<form>^*}
2c7465ac
MW
880\end{describe}
881
ae7a3c8f
MW
882\begin{describe}{parseform}{must @<sub-parser> @[@<default>@]}
883\end{describe}
884
2c7465ac
MW
885\begin{describe}{fun}
886 {scan-comment @<char-scanner>
887 @> @<result> @<success-flag> @<consumed-flag>}
888\end{describe}
889
1f7d590d
MW
890%%%----- That's all, folks --------------------------------------------------
891
892%%% Local variables:
893%%% mode: LaTeX
894%%% TeX-master: "sod.tex"
895%%% TeX-PDF-mode: t
896%%% End: