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