bug-bison
[Top][All Lists]
Advanced

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

Re: Bison C++ mid-rule value lost with variants


From: Akim Demaille
Subject: Re: Bison C++ mid-rule value lost with variants
Date: Mon, 18 Jun 2018 20:44:35 +0200


> Le 18 juin 2018 à 15:26, Frank Heckenbach <address@hidden> a écrit :
> 
> Akim Demaille wrote:

Hi Frank,

>> Piotr's grammar file includes:
>> 
>> %token <int> NUM
>> %%
>> expr:
>>  NUM
>> | expr { $<int>$ = 42; } '+' NUM { std::cout << $<int>2 << '\n'; };
>> 
>> and one can see that when run, $<int>2 is not 42, but 0.
>> 
>> My opinion on this is somewhat different from the ones that
>> have been expressed so far.  IMHO, it has no good reason
>> to work.
>> 
>> Yes, it works with plain old unions.  But that's unsafe, and
>> that's because you hide things from your tool (Bison).
> 
> AFAIK, that's the only purpose of the $<> syntax in Bison which has
> been around for I don't know how long. So claiming it has no reason
> to work now seems a bit odd to me.

Well, you can use $<> wherever you want, in regular actions
too.  And some people are doing nasty things with it in C,
which forced, for backward compatibility with YACC, to keep
weird code.

And as you know, YACC does not support C++, and obviously
not (Bison) variants.  So to expect a « feature » from C to
naturally work for C++ is not so straightforward.

>> I personally see these typed accesses to the semantical
>> values ($<int>2) are no different from a cast (and actually,
>> that's exactly what they are with unions).
> 
> I don't think so. C unions involve a hidden cast only when accessing
> a different member than was set, but that's not the case here.

Yes, I agree.  But the code does not know that.  And I mean
_statically_, not at runtime.

We tried to eliminate these runtime problems and make them
compile-time as much as possible.  A typical example
is the symbol constructors in C++, which forbid that in the
scanner you declare an INT and set yylval->float_val.

Here, it’s just another instance of the same class of issues.


> Apparently (and reasonably) this case is not supposed to work with
> $<>, so WRT whether or not to support $<> at all, I see no
> fundamental difference between C and C++, so if dropping support in
> C++, it would only be consequent to do it in C as well, and that
> might be nearly impossible due to backward-compatibility (or perhaps
> even Yacc compatibility, I don't know).

We are bound to POSIX for YACC, and POSIX forces us to accept

%union {
  int ival;
  float fval;
  char* sval;
}
%token <val> NUM
foo: NUM NUM NUM { $1; $<fval>2; $<sval>3; }

which completely breaks the typing system of Bison.  If I were
to chose, I would forbid this and force the user to

foo: NUM NUM NUM { $1; (float)$2; (const char*)$3; }

but the decision to allow this was made decades ago :)
At a time C functions were not even typed.

Since then people tend to be rigorous with types.


>> Sure, using std::variant or std::any we avoid the first three issues,
>> but that's still by hiding things from Bison and relying on
>> magic on the language side.  And obviously that works only for
>> C++, and actually modern C++.
> 
> As I wrote sometime before, I currently don't use any
> semantic-valued mid-rule actions, so I'm basically neutral on this
> proposal. In principle, I think a properly declared type for them
> seems reasonable, I just think this proposal is a few decades late.

I agree.



> What's more important for me, and the reason I worked on this, are
> other features, most importantly move semantics. Of course, they
> also require modern C++ (i.e., C++11 or newer), so if that's a
> problem, I'll have to keep my own fork anyway.

I’m sorry if I gave the impression I would not provide support
for modern C++, that’s definitely not my point.  I want to
avoid _requiring_ it, but, if __cplusplus__ is modern enough,
we absolutely should support move semantics!  I’m focus on this
issue now just because I’m trying to catch up!  And it seems to
me that it shows we don’t need to require std::variant.


reply via email to

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