X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/1818107e8198734df843841a51bca3713bd37596..00d59354c311fb28730b7c9b117b0d91aac092cc:/doc/parsing.tex diff --git a/doc/parsing.tex b/doc/parsing.tex index 58959c0..22960ee 100644 --- a/doc/parsing.tex +++ b/doc/parsing.tex @@ -7,7 +7,7 @@ %%%----- Licensing notice --------------------------------------------------- %%% -%%% This file is part of the Sensble Object Design, an object system for C. +%%% This file is part of the Sensible Object Design, an object system for C. %%% %%% SOD is free software; you can redistribute it and/or modify %%% it under the terms of the GNU General Public License as published by @@ -43,6 +43,53 @@ consumed any input items. \begin{describe}{fun}{combine-parser-failures @ @> @} \end{describe} +\begin{describe}{fun}{parse-empty \&optional @ @> @} +\end{describe} + +\begin{describe}{fun} + {parse-fail @ \&optional @ @> @} +\end{describe} + +%%%-------------------------------------------------------------------------- +\section{Streams} \label{sec:parsing.streams} + +\begin{describe*} + {\dhead{cls}{position-aware-stream \&key :file :line :column} + \dhead{gf}{position-aware-stream-file @ @> @} + \dhead{gf}{setf (position-aware-stream-file @) @} + \dhead{gf}{position-aware-stream-line @ @> @} + \dhead{gf}{setf (position-aware-stream-line @) @} + \dhead{gf}{position-aware-stream-column @ @> @} + \dhead{gf}{setf (position-aware-stream-column @) @}} +\end{describe*} + +\begin{describe*} + {\dhead{cls}{position-aware-input-stream \&key :file :line :column} + \dhead{cls}{position-aware-output-stream \&key :file :line :column}} +\end{describe*} + +\begin{describe}{gf}{stream-pathname @ @> @} + \begin{describe}{meth}{stream} + {stream-pathname (@ stream) @> nil} + \end{describe} + \begin{describe}{meth}{file-stream} + {stream-pathname (@ file-stream) @> @} + \end{describe} + \begin{describe}{meth}{position-aware-stream} + {stream-pathname (@ position-aware-stream) @> @} + \end{describe} +\end{describe} + +\begin{describe}{gf}{stream-line-and-column @ @> @ @} + \begin{describe}{meth}{stream} + {stream-line-and-column (@ stream) @> nil nil} + \end{describe} + \begin{describe}{meth}{position-aware-stream} + {stream-line-and-column (@ position-aware-stream) + \nlret @ @} + \end{describe} +\end{describe} + %%%-------------------------------------------------------------------------- \section{File locations} \label{sec:parsing.floc} @@ -64,51 +111,72 @@ consumed any input items. \end{describe*} \begin{describe}{gf}{file-location @ @> @} - \begin{describe}{meth}{file-location (@ file-location) @> @} + \begin{describe}{meth}{file-location} + {file-location (@ file-location) @> @} \end{describe} - \begin{describe}{meth}{file-location (@ stream) @> @} + \begin{describe}{meth}{stream} + {file-location (@ stream) @> @} \end{describe} - \begin{describe}{meth}{file-location (@ t) @> @} + \begin{describe}{meth}{t} + {file-location (@ t) @> @} \end{describe} \end{describe} \begin{describe}{cls}{condition-with-location (condition) \&key :location} \end{describe} -\begin{describe}{meth} +\begin{describe}{meth}{condition-with-location} {file-location (@ condition-with-location) @> @} \end{describe} \begin{describe*} {\quad\=\quad\=\kill \dhead{cls} - {error-with-location (condition-with-location error) \\ \> - \&key :location} - \dhead{cls} - {warning-with-location (condition-with-location warning) \\ \> - \&key :location} - \dhead{cls} - {enclosing-error-with-location - (enclosing-error-with-location error) \\ \> - \&key :condition :location} - \dhead{cls} - {enclosing-warning-with-location - (enclosing-condition-with-location warning) \\ \> - \&key :condition :location} + {error-with-location (condition-with-location error) \\ \> + \&key :location} + \dhead{cls} + {warning-with-location (condition-with-location warning) \\ \> + \&key :location} + \dhead{cls} + {information-with-location (condition-with-location information) \\ \> + \&key :location} + \dhead{cls} + {enclosing-condition-with-location (condition) \\ \> + \&key :location} \dhead{cls} - {simple-condition-with-location - (condition-with-location simple-condition) \\ \> - \&key :format-control :format-arguments :location} + {enclosing-error-with-location + (enclosing-error-with-location error) \\ \> + \&key :condition :location} \dhead{cls} - {simple-error-with-location - (error-with-location simple-error) \\ \> - \&key :format-control :format-arguments :location} - \dhead{cls} - {simple-warning-with-location - (warning-with-location simple-warning) \\ \> - \&key :format-control :format-arguments :location}} + {enclosing-warning-with-location + (enclosing-condition-with-location warning) \\ \> + \&key :condition :location} + \dhead{cls} + {enclosing-information-with-location + (enclosing-condition-with-location information) \\ \> + \&key :condition :location} + \dhead{cls} + {simple-condition-with-location + (condition-with-location simple-condition) \\ \> + \&key :format-control :format-arguments :location} + \dhead{cls} + {simple-error-with-location + (error-with-location simple-error) \\ \> + \&key :format-control :format-arguments :location} + \dhead{cls} + {simple-warning-with-location + (warning-with-location simple-warning) \\ \> + \&key :format-control :format-arguments :location} + \dhead{cls} + {simple-information-with-location + (information-with-location simple-information) \\ \> + \&key :format-control :format-arguments :location}} \end{describe*} +\begin{describe}{gf} + {enclosing-condition-with-location-type @ @> @} +\end{describe} + \begin{describe}{fun} {make-condition-with-location @ @ @ \&rest @ @@ -120,15 +188,58 @@ consumed any input items. \dhead{fun}{cerror-with-location @ @ @ \&rest @} \dhead{fun}{cerror*-with-location @ @ \&rest @} - \dhead{fun}{warn-with-location @ @ \&rest @}} + \dhead{fun}{warn-with-location @ @ \&rest @} + \dhead{fun}{info-with-location @ @ \&rest @}} +\end{describe*} + +\begin{describe*} + {\dhead{cls}{parser-error (error) \\ \ind + \&key :expected :found \-} + \dhead{gf}{parser-error-expected @ @> @} + \dhead{gf}{parser-error-found @ @> @}} +\end{describe*} + +\begin{describe}{fun} + {report-parser-error @ @ @ @} +\end{describe} + +\begin{describe*} + {\quad\=\kill + \dhead{cls}{base-lexer-error (error-with-location) \&key :location} + \dhead{cls}{simple-lexer-error + (base-lexer-error simple-error-with-location) \\\> + \&key :format-control :format-arguments :location} + \dhead{cls}{base-syntax-error (error-with-location) \&key :location} + \dhead{cls}{simple-syntax-error + (base-syntax-error simple-error-with-location) \\\> + \&key :format-control :format-arguments :location}} \end{describe*} \begin{describe}{mac} - {with-default-error-location (@) @^* @> @^*} + {with-default-error-location (@) @^* @
^* + @> @^*} +\end{describe} + +\begin{describe}{gf}{classify-condition @ @> @} + \begin{describe*} + {\dhead{meth}{error} + {classify-condition (@ error) @> @} + \dhead{meth}{warning} + {classify-condition (@ warning) @> @} + \dhead{meth}{information} + {classify-condition (@ information) + @> @} + \dhead{meth}{base-lexer-error} + {classify-condition (@ base-lexer-error) + @> @} + \dhead{meth}{base-syntax-error} + {classify-condition (@ base-syntax-error) + @> @}} + \end{describe*} \end{describe} \begin{describe}{mac} - {count-and-report-errors () @^* + {count-and-report-errors () @^* @^* @> @ @ @} \end{describe} @@ -150,6 +261,7 @@ Some scanners support an additional \emph{place-capture} protocol which allows rewinding the scanner to an earlier point in the input so that it can be scanned again. + \subsection{Basic scanner protocol} \label{sec:parsing.scanner.basic} The basic protocol supports stepping the scanner forward through its input @@ -170,6 +282,7 @@ sequence, and detecting the end of the sequence. step the scanner. \end{describe} + \subsection{Place-capture scanner protocol} \label{sec:parsing.scanner.place} The place-capture protocol allows rewinding to an earlier point in the @@ -182,7 +295,7 @@ depends on the type of scanner. Given a captured place, the scanner can be rewound to the position held in it. Depending on how the scanner works, holding onto a captured place might -consume a lot of memory or case poor performance. For example, if the +consume a lot of memory or cause poor performance. For example, if the scanner is reading from an input stream, having a captured place means that data from that point on must be buffered in case the program needs to rewind the scanner and read that data again. Therefore it's possible to @@ -209,13 +322,15 @@ the scanner and read that data again. Therefore it's possible to \end{describe} \begin{describe}{mac} - {with-scanner-place (@ @) @^* @> @^*} - Capture the @'s current position as a place, evaluate the - @s as an implicit progn with the variable @ bound to the captured - place. When control leaves the @s, the place is released. The return - values are the values of the final @. + {with-scanner-place (@ @) @^* @^* + @> @^*} + Capture the @'s current position as a place, evaluate the @s + as an implicit progn with the variable @ bound to the captured + place. When control leaves the @s, the place is released. The + return values are the values of the final @. \end{describe} + \subsection{Scanner file-location protocol} \label{sec:parsing.scanner.floc} Some scanners participate in the file-location protocol @@ -249,6 +364,7 @@ here. return nil. \end{describe*} + \subsection{Character scanners} \label{sec:parsing.scanner.char} Character scanners are scanners which read sequences of characters. @@ -267,7 +383,7 @@ Character scanners are scanners which read sequences of characters. \begin{describe}{gf}{scanner-unread @ @} Rewind the @ by one step. The @ must be the previous current character, and becomes the current character again. It is an error - if: the @ has reached end-of-file; the @ is never been + if: the @ has reached end-of-file; the @ has never been stepped; or @ was not the previous current character. \end{describe} @@ -309,6 +425,7 @@ operations to the sequence of characters held by a character scanner. character scanner protocols is suitable. See @|make-scanner-stream|. \end{describe} + \subsection{String scanners} \label{sec:parsing.scanner.string} A \emph{string scanner} is a simple kind of character scanner which reads @@ -333,6 +450,7 @@ and place-capture protocols. to the end of the @). \end{describe} + \subsection{Character buffer scanners} \label{sec:parsing.scanner.charbuf} A \emph{character buffer scanner}, or \emph{charbuf scanner} for short, is an @@ -349,6 +467,10 @@ file-location protocols. the scanner will update the location as it reads its input. \end{describe} +\begin{describe}{cls} + {charbuf-scanner-stream (character-scanner-stream) \&key :scanner} +\end{describe} + \begin{describe}{cls}{charbuf-scanner-place} The class of place objects captured by a charbuf scanner. \end{describe} @@ -361,15 +483,15 @@ file-location protocols. \begin{describe}{gf} {charbuf-scanner-map @ @ \&optional @ - \nlret @ @ @} + \nlret @ @ @} Read characters from the @'s buffers. This is intended to be an efficient and versatile interface for reading characters from a scanner in bulk. The function @ is invoked repeatedly, as if by \begin{prog} - (multiple-value-bind (@ @) \\ \ind\ind - (funcall @ @ @ @) \- \\ + (multiple-value-bind (@ @) \\ \ind\ind + (funcall @ @ @ @) \-\\ \textrm\ldots) \end{prog} The argument @ is a simple string; @ and @ are two @@ -377,7 +499,7 @@ file-location protocols. @ (inclusive) and @ (exclusive) should be processed. If @'s return value @ is nil then @ is ignored: the function has consumed the entire buffer and wishes to read more. If - @ is non-nil, then it must be a fixnum such that $@ \le + @ is non-nil, then @ must be a fixnum such that $@ \le @ \le @$: the function has consumed the buffer as far as @ (exclusive) and has completed successfully. @@ -385,8 +507,8 @@ file-location protocols. fails: the @ function is called with no arguments, and is expected to return two values. If omitted, @ defaults to \begin{prog} - (lambda () \\ \ind - (values nil nil))% + (lambda () \\ \ind + (values nil nil)) \end{prog} The @|charbuf-scanner-map| function returns three values. The first value @@ -397,12 +519,18 @@ file-location protocols. at least once, or with $@ > @$. \end{describe} + \subsection{Token scanners} \label{sec:parsing.scanner.token} \begin{describe}{cls} {token-scanner () \&key :filename (:line 1) (:column 0)} \end{describe} +\begin{describe*} + {\dhead{gf}{setf (scanner-line @) @} + \dhead{gf}{setf (scanner-column @) @}} +\end{describe*} + \begin{describe}{gf}{token-type @ @> @} \end{describe} @@ -419,6 +547,7 @@ file-location protocols. {token-scanner-place-p @ @> @} \end{describe} + \subsection{List scanners} \begin{describe}{ty}{list-scanner} @@ -431,7 +560,18 @@ file-location protocols. \end{describe} %%%-------------------------------------------------------------------------- -\section{Parsing syntax} +\section{Parser contexts and parser syntax} \label{sec:parsing.syntax} + + +\subsection{Parser contexts} \label{sec:parsing.syntax.contexts} + +\begin{describe}{mac} + {with-parser-context + (@ @{ @ @ @}^*) \\ \ind + @^* \\ + @^* + \-\nlret @^*} +\end{describe} \begin{describe}{gf}{expand-parser-spec @ @ @> @} \end{describe} @@ -445,55 +585,59 @@ file-location protocols. \begin{describe}{mac} {defparse @ (@[[ :context (@ @) @]] - @^*) \\ \ind - @^* \- - \nlret @} -\end{describe} - -\begin{describe}{mac} - {with-parser-context - (@ @{ @ @ @}^*) \\ \ind - @^* \- - \nlret @^*} + @^*) \\ \ind + @[[ @^* @! @ @]] \\ + @^* + \-\nlret @} \end{describe} \begin{describe}{lmac} {parse @ @> @ @ @} \end{describe} -\begin{describe}{gf}{parser-at-eof-p @ @> @} +\begin{describe}{mac} + {parser @ + @[[ @^* @! @ @]] + @ + @> @} \end{describe} -\begin{describe}{gf}{parser-step @ @> @} +\begin{describe}{gf}{parser-at-eof-p @ @> @} \end{describe} -\begin{describe}{sym}{it} +\begin{describe}{gf}{parser-step @ @> @} \end{describe} \begin{describe}{mac} {if-parse (@[[ \=:result @ @! - :expected @ @! \+ \\ - :consumedp @ @]]) \- \\ \ind\ind - @ \- \\ - @ \\ - @[@@] \- - \nlret @^*} + :expected @ @! \+\\ + :consumedp @ @]]) \-\\ \ind\ind + @ \-\\ + @ \\ + @[@@] + \-\nlret @^*} \end{describe} \begin{describe}{mac} - {when-parse (@[@@]) @ \\ \ind - @^* \- - \nlret @^*} + {when-parse (@[@@]) @ \\ \ind + @^* + \-\nlret @^*} \end{describe} \begin{describe}{mac} {cond-parse (@[[ \=:result @ @! - :expected @ @! \+ \\ - :consumedp @ @]]) \- \\ \ind - @{ (@ @^*) @}^* \- - \nlret @^*} + :expected @ @! \+\\ + :consumedp @ @]]) \-\\ \ind + @{ (@ @^*) @}^* + \-\nlret @^*} +\end{describe} + +\begin{describe}{cls}{list-parser () \&key :var} \end{describe} + +\subsection{Basic parser syntax} \label{sec:parsing.syntax.basic} + \begin{describe}{parse}{:eof} \end{describe} @@ -519,8 +663,9 @@ file-location protocols. \end{describe} \begin{describe}{parseform} - {seq (@{ @ @! (@[@@] @) @}^*) \\ \ind - @^*} + {seq (@{ @ @! + (@[@@] @) @}^*) \\ \ind + @^*} \end{describe} \begin{describe}{parseform}{and @^*} @@ -533,22 +678,22 @@ file-location protocols. \end{describe} \begin{describe}{parseform} - {many (\=@ @ @ \+ \\ - @[[ \=:new @ @! :final @ @! \+ \\ - :min @ @! :max @ @! \\ - :commitp @ @]]) \-\- \\ \ind + {many (\=@ @ @ \+\\ + @[[ \=:new @ @! :final @ @! \+\\ + :min @ @! :max @ @! \\ + :commitp @ @]]) \-\-\\ \ind @ @[@@]} \end{describe} \begin{describe}{parseform} {list (@[[ :min @ @! :max @ @! - :commitp @ @]])\\ \ind + :commitp @ @]]) \\ \ind @ @[@@]} \end{describe} \begin{describe}{parseform} {skip-many (@[[ :min @ @! :max @ @! - :commitp @ @]])\\ \ind + :commitp @ @]]) \\ \ind @ @[@@]} \end{describe} @@ -563,9 +708,14 @@ file-location protocols. \end{describe} \begin{describe}{mac} - {define-pluggable-parser @ @ @ @^*} + {define-pluggable-parser @ @ @ + @[[ @^* @! @ @]] + @^*} \end{describe} + +\subsection{Place-capture protocol} \label{sec:parsing.syntax.place} + \begin{describe}{gf}{parser-capture-place @ @> @} \end{describe} @@ -576,22 +726,34 @@ file-location protocols. \end{describe} \begin{describe}{gf} - {parser-places-must-be-released-p @ @> @>} + {parser-places-must-be-released-p @ @> @} \end{describe} \begin{describe}{mac} - {with-parser-place (@ @) @^*} + {with-parser-place (@ @) + @[[ @^* @! @ @]] + @^*} \end{describe} \begin{describe}{parseform}{peek @} \end{describe} +\begin{describe}{parseform}{commit} +\end{describe} + + +\subsection{Character parsers} \label{sec:parsing.syntax.character} + \begin{describe}{cls}{character-parser-context () \&key} \end{describe} \begin{describe}{gf}{parser-current-char @ @> @} \end{describe} +\begin{describe}{cls} + {string-parser (character-parser-context) \&key :string :index :length} +\end{describe} + \begin{describe}{parseform} {if-char (@[@@]) @ @ @} \end{describe} @@ -599,10 +761,10 @@ file-location protocols. \begin{describe}{parseform}{char @} \end{describe} -\begin{describe}[char]{parse}{@} +\begin{describe}{parse}[char]{@} \end{describe} -\begin{describe}[string]{parse}{@} +\begin{describe}{parse}[string]{@} \end{describe} \begin{describe}{parse}{:any} @@ -632,16 +794,16 @@ file-location protocols. \begin{describe}{parseform}{token @ @[@@] @[:peekp @@]} \end{describe} -\begin{describe}[atom]{parse}{@} +\begin{describe}{parse}[atom]{@} \end{describe} -\begin{describe}[string]{parse}{@} -\end{describe} + +\subsection{Scanner contexts} \label{sec:parsing.syntax.scanner} \begin{describe}{cls}{scanner-context () \&key :scanner} \end{describe} -\begin{describe}{gf}{parse-scanner @ @> @} +\begin{describe}{gf}{parser-scanner @ @> @} \end{describe} \begin{describe}{cls} @@ -654,20 +816,14 @@ file-location protocols. \&key :scanner} \end{describe} -\begin{describe}{gf}{push-operator @ @} -\end{describe} - -\begin{describe}{gf}{push-value @ @} -\end{describe} -\begin{describe}{gf}{apply-operator @ @} -\end{describe} +\subsection{Expression parsing} \label{sec:parsing.syntax.expression} \begin{describe}{gf}{operator-push-action @ @} \end{describe} \begin{describe}{parseform} - {expr \=(@[[ :nestedp @ @]]) \+ \\ + {expr \=(@[[ :nestedp @ @]]) \+\\ @ @ @ @} \end{describe} @@ -693,31 +849,31 @@ file-location protocols. \begin{describe*} {\quad\=\kill - \dhead{cls}{simple-binary-operator (simple-operator) \\ \> - \&key :name :function :lprec :rprec :associativity} + \dhead{cls}{simple-binary-operator (simple-operator) \\ \> + \&key :name :function + :lprec :rprec :associativity} \dhead{cls}{simple-postfix-operator (simple-unary-operator) \\ \> \&key :name :function :lprec :rprec} \dhead{cls}{simple-prefix-operator - (prefix-operator simple-unary-operator) \\ \> + (prefix-operator simple-unary-operator) \\ \> \&key :name :function :rprec}} \end{describe*} \begin{describe*} {\dhead{mac}{preop @ (@ @) - @^* + @^* @^* @> @} \dhead{mac}{postop @ (@ @ @[[ :rprec @ @]]) - @^* - @> @} + @^* @^* + \nlret @} \dhead{mac}{binop @ (@ @ @ @) - @^* + @^*@^* @> @}} \end{describe*} \begin{describe*} - {\dhead{cls}{parenthesis () \&key :tag} - \dhead{cls}{open-parenthesis (parenthesis prefix-operator) \&key :tag} + {\dhead{cls}{open-parenthesis (parenthesis prefix-operator) \&key :tag} \dhead{cls}{close-parenthesis (parenthesis) \&key :tag}} \end{describe*} @@ -727,7 +883,7 @@ file-location protocols. \end{describe*} %%%------------------------------------------------------------------------- -\section{Lexical analyser} +\section{Lexical analyser} \label{sec:parsing.lexical} \begin{describe}{cls} {sod-token-scanner (token-scanner) @@ -737,18 +893,34 @@ file-location protocols. \begin{describe}{fun}{define-indicator @ @} \end{describe} -\begin{describe}{fun}{syntax-error @ @ \&key :continuep} +\begin{describe*} + {\dhead{cls}{lexer-error (parser-error base-lexer-error) \\ \ind + \&key :expected :found :location \-} + \dhead{cls}{syntax-error (parser-error base-syntax-error) \\ \ind + \&key :expected :found :location \-}} +\end{describe*} + +\begin{describe}{fun} + {syntax-error @ @ \&key :continuep :location} \end{describe} \begin{describe}{fun} - {lexer-error @ @ @} + {lexer-error @ @ \&key :location} \end{describe} \begin{describe}{parseform} {skip-until (@[[ :keep-end @ @]]) @^*} \end{describe} -\begin{describe}{parseform}{error () @ @} +\begin{describe}{parseform} + {error (@[[ :ignore-unconsumed @ @! + :force-process @ @]]) \\ \ind\ind + @ @ \-\\ + @^* \\ + @^*} +\end{describe} + +\begin{describe}{parseform}{must @ @[@@]} \end{describe} \begin{describe}{fun}