bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RFC: documentation for typed mid-rule actions


From: Akim Demaille
Subject: RFC: documentation for typed mid-rule actions
Date: Sun, 12 Aug 2018 11:33:43 +0200

Hi all,

I believe that typed mid-rule actions are ready, except for
the lack of documentation.  Please find below a proposal of
documentation, currently in the ad/typed-midrule branch and
in PDF currently here:

https://www.lrde.epita.fr/~akim/private/bison/bison.pdf

I would also like to enforce consistency in Bison which uses
both midrule and mid-rule.  I am in favor of ‘midrule'
(shorter, consistent with our move to lookahead instead of
look-ahead, more consistent between code and doc as there is
no conversion from dash to underscore, etc.), but I am not
a native!  To which one should we stick? (FWIW, neither
appear in the manual of YACC, only ‘An action appearing in the
middle of a rule […]’ does).

I must have gotten rotten in Texinfo, as both my @ref to
{Typed Mid-Rule Actions} appear as
‘See ⟨undefined⟩ [Typed Mid-Rule Actions], page ⟨undefined⟩’
in PDF, and I have no idea why.  It doesn’t appear in the
table of contents either.  Info and HTML are fine, latest
gnulib.


Thanks in advance!


commit 962317f490ee018fd6f6177495c356e9effc92a3
Author: Akim Demaille <address@hidden>
Date:   Sun Aug 12 10:49:29 2018 +0200

    doc: typed mid-rule actions
    
    * doc/bison.texi (Mid-Rule Actions): Restructure to insert...
    (Typed Mid-Rule Actions): this new section.
    Move the manual translation of mid-rule actions into regular actions
    to...
    (Mid-Rule Action Translation): here.

diff --git a/doc/bison.texi b/doc/bison.texi
index 74ad9e5d..bad88cdb 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -225,6 +225,7 @@ Defining Language Semantics
 Actions in Mid-Rule
 
 * Using Mid-Rule Actions::       Putting an action in the middle of a rule.
+* Typed Mid-Rule Actions::       Specifying the semantic type of their values.
 * Mid-Rule Action Translation::  How mid-rule actions are actually processed.
 * Mid-Rule Conflicts::           Mid-rule actions can cause conflicts.
 
@@ -4071,6 +4072,7 @@ are executed before the parser even recognizes the 
following components.
 
 @menu
 * Using Mid-Rule Actions::       Putting an action in the middle of a rule.
+* Typed Mid-Rule Actions::       Specifying the semantic type of their values.
 * Mid-Rule Action Translation::  How mid-rule actions are actually processed.
 * Mid-Rule Conflicts::           Mid-rule actions can cause conflicts.
 @end menu
@@ -4158,64 +4160,86 @@ earlier action is used to restore the prior list of 
variables.  This
 removes the temporary @code{let}-variable from the list so that it won't
 appear to exist while the rest of the program is parsed.
 
+Because the types of the semantic values of mid-rule actions are unknown to
+Bison, type-based features (e.g., @samp{%printer}, @samp{%destructor}) do
+not work, which could result in memory leaks.  They also forbid the use of
+the @code{variant} implementation of the @code{api.value.type} in C++
+(@pxref{C++ Variants}).
+
address@hidden Mid-Rule Actions}, for one way to address this issue, and
address@hidden Action Translation}, for another: turning mid-action actions
+into regular actions.
+
+
address@hidden Typed Mid-Rule Actions
address@hidden Typed Mid-Rule Actions
+
 @findex %destructor
 @cindex discarded symbols, mid-rule actions
 @cindex error recovery, mid-rule actions
 In the above example, if the parser initiates error recovery (@pxref{Error
 Recovery}) while parsing the tokens in the embedded statement @code{stmt},
 it might discard the previous semantic context @code{$<context>5} without
-restoring it.
-Thus, @code{$<context>5} needs a destructor (@pxref{Destructor Decl, , Freeing
-Discarded Symbols}).
-However, Bison currently provides no means to declare a destructor specific to
-a particular mid-rule action's semantic value.
-
-One solution is to bury the mid-rule action inside a nonterminal symbol and to
-declare a destructor for that symbol:
+restoring it.  Thus, @code{$<context>5} needs a destructor
+(@pxref{Destructor Decl, , Freeing Discarded Symbols}), and Bison needs the
+type of the semantic value (@code{context}) to select the right destructor.
 
address@hidden
address@hidden
-%type <context> let
-%destructor @{ pop_context ($$); @} let
address@hidden group
+As an extension to Yacc's mid-rule actions, Bison offers a means to type
+their semantic value: specify its type tag (@samp{<...>} before the mid-rule
+action.
 
-%%
+Consider the previous example, with an untyped mid-rule action:
 
address@hidden
 @group
 stmt:
-  let stmt
+  "let" '(' var ')'
     @{
-      $$ = $2;
-      pop_context ($let);
-    @};
+      $<context>$ = push_context (); // ***
+      declare_variable ($3);
+    @}
+  stmt
+    @{
+      $$ = $6;
+      pop_context ($<context>5);     // ***
+    @}
 @end group
address@hidden example
+
address@hidden
+If instead you write:
 
address@hidden
 @group
-let:
+stmt:
   "let" '(' var ')'
-    @{
-      $let = push_context ();
+    <context>@{                      // ***
+      $$ = push_context ();          // ***
       declare_variable ($3);
-    @};
-
+    @}
+  stmt
+    @{
+      $$ = $6;
+      pop_context ($5);              // ***
+    @}
 @end group
 @end example
 
 @noindent
-Note that the action is now at the end of its rule.
-Any mid-rule action can be converted to an end-of-rule action in this way, and
-this is what Bison actually does to implement mid-rule actions.
+then @code{%printer}, and @code{%destructor} work properly (no more leaks!),
+C++ @code{variant}s can be used, and redundancy is reduced (@code{<context>}
+is specified once).
+
 
 @node Mid-Rule Action Translation
 @subsubsection Mid-Rule Action Translation
 @vindex $@@@var{n}
 @vindex @@@var{n}
 
-As hinted earlier, mid-rule actions are actually transformed into regular
-rules and actions.  The various reports generated by Bison (textual,
-graphical, etc., see @ref{Understanding, , Understanding Your Parser})
-reveal this translation, best explained by means of an example.  The
-following rule:
+Mid-rule actions are actually transformed into regular rules and actions.
+The various reports generated by Bison (textual, graphical, etc., see
address@hidden, , Understanding Your Parser}) reveal this translation,
+best explained by means of an example.  The following rule:
 
 @example
 exp: @{ a(); @} "b" @{ c(); @} @{ d(); @} "e" @{ f(); @};
@@ -4273,6 +4297,45 @@ mid.y:2.19-31: warning: unused value: $3
 @end group
 @end example
 
address@hidden 1
+
+It is sometimes useful to turn mid-rule actions into regular actions, e.g.,
+to factor them, or to escape from their limitations.  For instance, as an
+alternative to @emph{typed} mid-rule action, you may bury the mid-rule
+action inside a nonterminal symbol and to declare a printer and a destructor
+for that symbol:
+
address@hidden
address@hidden
+%type <context> let
+%destructor @{ pop_context ($$); @} let
+%printer @{ print_context (yyo, $$); @} let
address@hidden group
+
+%%
+
address@hidden
+stmt:
+  let stmt
+    @{
+      $$ = $2;
+      pop_context ($let);
+    @};
address@hidden group
+
address@hidden
+let:
+  "let" '(' var ')'
+    @{
+      $let = push_context ();
+      declare_variable ($var);
+    @};
+
address@hidden group
address@hidden example
+
+
+
 
 @node Mid-Rule Conflicts
 @subsubsection Conflicts due to Mid-Rule Actions
@@ -10523,7 +10586,7 @@ To enable variant-based semantic values, set 
@code{%define} variable
 @code{%union} is ignored, and instead of using the name of the fields of the
 @code{%union} to ``type'' the symbols, use genuine types.
 
-For instance, instead of
+For instance, instead of:
 
 @example
 %union
@@ -10536,7 +10599,7 @@ For instance, instead of
 @end example
 
 @noindent
-write
+write:
 
 @example
 %token <int> NUMBER;
@@ -10555,7 +10618,10 @@ Variants are stricter than unions.  When based on 
unions, you may play any
 dirty game with @code{yylval}, say storing an @code{int}, reading a
 @code{char*}, and then storing a @code{double} in it.  This is no longer
 possible with variants: they must be initialized, then assigned to, and
-eventually, destroyed.
+eventually, destroyed.  As a matter of fact, Bison variants forbid the use
+of alternative types such as @samp{$<int>2} or @samp{$<std::string>$}, even
+in mid-rule actions.  It is mandatory to use typed mid-rule actions
+(@pxref{Typed Mid-Rule Actions}).
 
 @deftypemethod {semantic_type} {T&} build<T> ()
 Initialize, but leave empty.  Returns the address where the actual value may
@@ -10575,10 +10641,13 @@ Boost.Variant not only stores the value, but also a 
tag specifying its
 type.  But the parser already ``knows'' the type of the semantic value, so
 that would be duplicating the information.
 
+We do not use C++17's @code{std::variant} either: we want to support all the
+C++ standards, and of course @code{std::variant} also stores a tag to record
+the current type.
+
 Therefore we developed light-weight variants whose type tag is external (so
-they are really like @code{unions} for C++ actually).  But our code is much
-less mature that Boost.Variant.  So there is a number of limitations in
-(the current implementation of) variants:
+they are really like @code{unions} for C++ actually).  There is a number of
+limitations in (the current implementation of) variants:
 @itemize
 @item
 Alignment must be enforced: values should be aligned in memory according to
@@ -10588,6 +10657,9 @@ therefore, since, as far as we know, @code{double} is 
the most demanding
 type on all platforms, alignments are enforced for @code{double} whatever
 types are actually used.  This may waste space in some cases.
 
address@hidden
+Move semantics is not yet supported, but will soon be added.
+
 @item
 There might be portability issues we are not aware of.
 @end itemize




reply via email to

[Prev in Thread] Current Thread [Next in Thread]