Commit 8f177a17 authored by POTTIER Francois's avatar POTTIER Francois

Introduce and document [endrule] and [midrule].

parent 9d90b054
# Changes
## 2018/06/08
* Add two new parameterized nonterminal symbols, `endrule(X)` and `midrule(X)`,
to the standard library. These symbols have been available since 2015/02/11
under the names `anonymous(X)` and `embedded(X)`, but were not yet documented.
`endrule(X)` and `midrule(X)` are now documented,
while `anonymous(X)` and `embedded(X)` remain present but are deprecated.
## 2018/05/30
* In `--coq` mode, Menhir now produces references to `MenhirLib.Grammar`
......
......@@ -134,9 +134,6 @@
* Produce well-chosen (predictable) names for anonymous rules?
* In the standard library, possibly rename "anonymous" and "embedded" and
document them. Document WHEN they were added.
* Add standard library support for specifying arithmetic-expression-levels?
Check connection with parsec (chainl1).
More generally, find inspiration in parsec combinators.
......
......@@ -1039,6 +1039,9 @@ recognized.
\begin{tabular}{lp{51mm}l@{}l}
Name & Recognizes & Produces & Comment \\
\hline\\
\nt{endrule}(\nt{X}) & \nt{X} & $\alpha$, if \nt{X} : $\alpha$ & (inlined) \\
\nt{midrule}(\nt{X}) & \nt{X} & $\alpha$, if \nt{X} : $\alpha$ \\
\\
\nt{option}(\nt{X}) & $\epsilon$ \barre \nt{X} & $\alpha$ \basic{option}, if \nt{X} : $\alpha$ \\
\nt{ioption}(\nt{X}) & $\epsilon$ \barre \nt{X} & $\alpha$ \basic{option}, if \nt{X} : $\alpha$ & (inlined) \\
\nt{boption}(\nt{X}) & $\epsilon$ \barre \nt{X} & \basic{bool} \\
......@@ -1062,7 +1065,7 @@ Name & Recognizes & Produces & Comment \\
& a possibly empty sequence of \nt{X}'s separated with \nt{sep}'s
& $\alpha$ \basic{list}, if \nt{X} : $\alpha$ \\
\nt{separated\_nonempty\_list}(\nt{sep}, \nt{X})
& a nonempty sequence of \nt{X}'s separated with \nt{sep}'s
& a nonempty sequence of \nt{X}'s \hspace{2mm} separated with \nt{sep}'s
& $\alpha$ \basic{list}, if \nt{X} : $\alpha$ \\
\end{tabular}
......@@ -1114,6 +1117,85 @@ command line switch \ostdlib.
The command line switch \onostdlib instructs \menhir to \emph{not} load the
standard library.
The meaning of the symbols defined in the standard library
(\fref{fig:standard}) should be clear in most cases. Yet, the
symbols \nt{endrule}(\nt{X}) and \nt{midrule}(\nt{X}) deserve an explanation.
Both take an argument \nt{X}, which typically will be instantiated with an
anonymous rule (\sref{sec:actual}). Both are defined as a synonym
for \nt{X}. In both cases, this allows placing an anonymous subrule in the
middle of a rule.
\newcommand{\AAA}{\nt{cat}}
\newcommand{\BBB}{\nt{dog}}
\newcommand{\CCC}{\nt{cow}}
\newcommand{\XXX}{\nt{xxx}}
For instance, the following is a well-formed production:
%
\[\begin{array}{l}
\AAA \quad
\nt{endrule}(\BBB \quad \dpaction{\nt{\ocaml code$_1$}}) \quad
\CCC \quad
\dpaction{\nt{\ocaml code$_2$}}
\end{array}\]
%
This production consists of three producers, namely
\AAA{} and
\nt{endrule}(\BBB$\;$\dpaction{\nt{\ocaml code$_1$}}) and
\CCC,
and a semantic action \dpaction{\nt{\ocaml code$_2$}}.
%
Because \nt{endrule}(\nt{X}) is declared as an \dinline synonym for \nt{X},
the expansion of anonymous rules (\sref{sec:actual}), followed with the
expansion of \dinline symbols (\sref{sec:inline}), transforms the above
production into the following:
%
\[\begin{array}{l}
\AAA \quad
\BBB \quad
\CCC \quad
\dpaction{\nt{\ocaml code$_1$; \ocaml code$_2$}}
\end{array}\]
%
Note that \nt{\ocaml code$_1$} moves to the end of the rule, which means that
this code is executed only after \AAA, \BBB{} and \CCC{} have
been recognized. In this example, the use of \nt{endrule} is rather pointless,
as the expanded code is more concise and clearer than the original code. Still,
\nt{endrule} can be useful when its actual argument is an anonymous rule with
multiple branches.
% Let me *not* show an example. See the comments in standard.mly.
\nt{midrule} is used in exactly the same way as \nt{endrule}, but its expansion
is different. For instance, the following is a well-formed production:
%
\[\begin{array}{l}
\AAA \quad
\nt{midrule}(\dpaction{\nt{\ocaml code$_1$}}) \quad
\CCC \quad
\dpaction{\nt{\ocaml code$_2$}}
\end{array}\]
%
(There is no \BBB{} in this example; this is intentional.)
Because \nt{midrule}(\nt{X}) is a synonym for \nt{X}, but is not declared
\dinline, the expansion of anonymous rules (\sref{sec:actual}), followed
with the expansion of \dinline symbols (\sref{sec:inline}), transforms the
above production into the following:
%
\[\begin{array}{l}
\AAA \quad
\XXX \quad
\CCC \quad
\dpaction{\nt{\ocaml code$_2$}}
\end{array}\]
%
where the fresh nonterminal symbol $\XXX$ is separately defined by the
rule $\XXX: \dpaction{\nt{\ocaml code$_1$}}$. Thus, $\XXX$ recognizes
the empty string, and as soon as it is recognized, \nt{\ocaml code$_1$}
is executed. This is known as a ``mid-rule action''.
% https://www.gnu.org/software/bison/manual/html_node/Mid_002dRule-Actions.html
% ------------------------------------------------------------------------------
\section{Conflicts}
......@@ -4121,6 +4203,9 @@ in \sref{sec:positions}. In short, the solution is to use \verb+$symbolstartpos+
\question{Can I pretty-print a grammar in ASCII, HTML, or \LaTeX{} format?}
Yes. Have a look at \texttt{obelisk} \cite{obelisk}.
\question{Does \menhir support mid-rule actions?} Yes.
See \nt{midrule} and its explanation in \sref{sec:library}.
% ------------------------------------------------------------------------------
\section{Technical background}
......
......@@ -20,64 +20,71 @@
(* ------------------------------------------------------------------------- *)
(* The identity. *)
(* [anonymous(X)] is the same as [X]. *)
(* [endrule(X)] is the same as [X]. *)
(* This allows placing an anonymous sub-rule in the middle of a rule, as in:
(* This allows placing an anonymous subrule in the middle of a rule, as in:
foo
anonymous(baz { action1 })
bar
cat
endrule(dog { action1 })
cow
{ action2 }
Because anonymous is marked %inline, everything is expanded away. So,
Because [endrule] is marked %inline, everything is expanded away. So,
this is equivalent to:
foo baz bar { action1; action2 }
cat dog cow { action1; action2 }
Note that [action1] moves to the end of the rule. The anonymous sub-rule
Note that [action1] moves to the end of the rule. The anonymous subrule
can even have several branches, as in:
foo
anonymous(baz { action1a } | quux { action1b })
bar
cat
endrule(dog { action1a } | fox { action1b })
cow
{ action2 }
This is expanded to:
foo baz bar { action1a; action2 }
| foo quux bar { action1b; action2 }
cat dog cow { action1a; action2 }
| cat fox cow { action1b; action2 }
*)
%public %inline endrule(X):
x = X
{ x }
(* [anonymous(X)] is a deprecated synonym for [endrule(X)].
It was never documented. *)
%public %inline anonymous(X):
x = X
{ x }
(* [embedded(X)] is the same as [X]. *)
(* [midrule(X)] is the same as [X]. *)
(* This allows placing an anonymous sub-rule in the middle of a rule, as in:
(* This allows placing an anonymous subrule in the middle of a rule, as in:
foo
embedded(baz { action1 })
bar
cat
midrule(dog { action1 })
cow
{ action2 }
Because [embedded] is not marked %inline, this is equivalent to:
Because [midrule] is not marked %inline, this is equivalent to:
foo xxx bar { action2 }
cat xxx cow { action2 }
where the fresh non-terminal symbol [xxx] is separately defined by:
where the fresh nonterminal symbol [xxx] is separately defined by:
xxx: baz { action1 }
xxx: dog { action1 }
In particular, if there is no [baz], what we get is a semantic action
In particular, if there is no [dog], what we get is a semantic action
embedded in the middle of a rule. For instance,
foo embedded({ action1 }) bar { action2 }
cat midrule({ action1 }) cow { action2 }
is equivalent to:
foo xxx bar { action2 }
cat xxx cow { action2 }
where [xxx] is separately defined by the rule:
......@@ -85,6 +92,13 @@ x = X
*)
%public midrule(X):
x = X
{ x }
(* [embedded(X)] is a deprecated synonym for [midrule(X)].
It was never documented. *)
%public embedded(X):
x = X
{ x }
......@@ -217,4 +231,3 @@ x = X
{ x :: xs }
%%
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment