bison-patches
[Top][All Lists]
Advanced

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

Re: prologue alternatives


From: Joel E. Denny
Subject: Re: prologue alternatives
Date: Sat, 16 Sep 2006 23:12:22 -0400 (EDT)

On Sat, 16 Sep 2006, Paul Eggert wrote:

> "Joel E. Denny" <address@hidden> writes:
> 
> > Let's say I have multiple B's:
> >
> >   %{ #include "type1.h" %}
> >   %union { type1 field1; }
> >   %destructor { type1_destroy ($$); } <field1>
> >   %printer { type1_print (yyoutput, $$); } <field1>
> >
> >   %{ #include "type2.h" %}
> >   %union { type2 field2; }
> >   %destructor { type2_destroy ($$); } <field2>
> >   %printer { type2_print (yyoutput, $$); } <field2>
> >
> > The above code does not compile.
> 
> It's easy to see why it doesn't compile, once you look at the
> generated C code, and it's easy to fix once you see the problem.

All of these easy problems are adding up to a lot of frustration.  I think 
Bison grammar files ought to be easily understood without reading the 
generated source code.  The above has a nice modular organization, so I'd 
like it to compile fine (after renaming %{...%} to %type-code{...} of 
course).

> YYSTYPE's implementation as a single union is inherent to this
> problem; it's what's driving a lot of the issues here.  If we stick to
> that implementation, there will be silly limitations (silly, from the
> point of the grammar, anyway) no matter how we gussy things up in
> Bison input.

I don't follow.  Are you suggesting YYSTYPE shouldn't be a single union?  
I'm not sure what that means.

> >   1. Type code goes in %type-code {...}
> >   2. Other header code goes in %header-code {...}
> >   3. Other code goes in %code {...}
> >
> > That is, the user tells Bison what each piece of code is for, and Bison 
> > handles the gory details.
> 
> That's a good principle, but I want it to be simpler if possible.
> It's simpler if we have just two categories: header code, and
> non-header code.  Users can easily see why we need to have these two
> categories, because they understand the difference between
> header/interface and code/implementation.  It's not so easy to see why
> Bison needs _three_ categories.

There's def before use and there's interface vs. implementation.  I think 
that's easy enough to see.

In my mind, def before use is the more important issue in this case and 
requires only two directives: %code and %type-code.  I believe 
%header-code would be convenient but less often used.

> > Does calling them %type-code/%header-code help?  %type-code is like A and 
> > %code is like C... both regardless of whether there's a B.  %header-code 
> > is a new feature.  Ignore it if you like.
> 
> How about if we have two categories: %{ ... %}, which puts the code
> into the implementation, and %header-code{ ... }, which puts it into
> the interface?  Plus, we have special strings $declare{YYSTYPE} and
> $declare{YYLTYPE} that can be put in the "..." part of the directives,
> and which expand to declarations for YYSTYPE and YYLTYPE, so that the
> user can specify exactly where the Bison-generated declarations go.
> Code would generated in the order the user specifies.
>
> This is a lower-level mechanism than what you're proposing, but it
> specifies the problem space clearly and it gives the expert user
> finer-grained control over where things go.

So, if I put things like this in my grammar section:

  %{ #include "Preamble.h" %}
  %union { Preamble *preamble; }
  %destructor { Preamble__destroy ($$); } preamble
  preamble:
    paragraph_list { $$ = Preamble__new ($1); }
    ;

I'd have to put this at the end of my grammar:

  %{ $declare{YYSTYPE} %}

so that it would appear after all the YYSTYPE dependencies in other 
%{...%}'s.  If I had any static global variables or other types (the kinds 
of things that normally go in the definitions section) but they depended 
on the semantic type, they'd need to go after this as well.  In other 
words, if I strived to modularize parts of my grammar file in this way, 
I'd have to scatter other parts.  Yes, as I believe Akim once argued, 
these def before use problems are inherent limitations in C.  However, I 
see the Bison grammar file language as something of a meta language that 
can do better than C... and %type-code{...} seems to make that possible.

If I suddenly realized that I needed to add a header that contained 
YYSTYPE, I'd have to rewrite all those %{...%}'s as %header{...}'s.  That 
wouldn't be a problem if I had told Bison that this was type-code to begin 
with via %type-code{...}.  Whether a header is generated seems like it 
ought to be an orthogonal issue.

The advantage I see of your proposal is that it means I can tell Bison not 
to put YYSTYPE or YYLTYPE in the header file.  However, I'm not sure why 
the user would need to do that.  The YY namespace protects them.

IMHO, your proposal offers more low-level flexibility than I at least have 
found reason for, and it seems to worsen grammar organization flexibility.

However, if we're going for maximum flexibility in all areas, we could 
take your proposal and extend your $declare{YYSTYPE} to a general variable 
language.  Where "stype-code" is a user variable and "YYSTYPE" is a Bison 
variable:

  %header {
    $var{stype-code}
    $var{YYSTYPE}
  }
  %{
    static int my_global = 0;
  %}

  %var-append "stype-code" { #include "type1.h" }
  %union { type1 field1; }
  %destructor { type1_destroy ($$); } <field1>
  %printer { type1_print (yyoutput, $$); } <field1>

  %var-append "stype-code" { #include "type2.h" }
  %union { type2 field2; }
  %destructor { type2_destroy ($$); } <field2>
  %printer { type2_print (yyoutput, $$); } <field2>

  %%

  /* Long well-organized grammar here.  */

  %var-append "stype-code" { #include "Preamble.h" }
  %union { Preamble *preamble; }
  %destructor { Preamble__destroy ($$); } preamble
  preamble:
    paragraph_list { $$ = Preamble__new ($1); }
    ;

I suppose %header would imply %defines.  Moreover, because of the variable 
language, a single %header would probably be sufficient in any grammar 
file.




reply via email to

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