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