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