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