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