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