[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] Factor %FLAG at scan level.
From: |
Akim Demaille |
Subject: |
Re: [PATCH] Factor %FLAG at scan level. |
Date: |
Thu, 9 Apr 2009 22:48:13 +0200 |
Le 9 avr. 09 à 06:45, Joel E. Denny a écrit :
On Wed, 8 Apr 2009, Akim Demaille wrote:
Even though that approach is
not actually possible, the user still has an opportunity to share
code
between the two by specifying that %printer invoke operator<<
instead.
If we make the symbol_type object directly accessible in %printer,
the
user can even write a single %printer that invokes operator<< for
all
symbols, which are specified by <*> and <>.
This would be a significant change of interface: %printer and
%destructor work
on the semantic value only, after the dispatch on the type, while
symbol_type
is the triple.
%printer and %destructor have access to $$ and @$. The dispatch on
symbol
type effectively means they have access to the symbol type too. If
they
have access to all the parts, why not give them access to the whole as
well?
That would be fine, indeed, but I had the impression that you
suggested to have %printer use the symbol_type to perform the
printing, which is likely to be an endless recursion. What kind of
use of the symbol_type do you have in mind? I think I don't
understand what you mean :) In the example variant.yy, it looks like
this:
template <typename Exact>
void
parser::yy_print_ (std::ostream& yyo,
const symbol_base_type<Exact>&
yysym) const
{
int yytype = yysym.type_get ();
yyo << (yytype < yyntokens_ ? "token" : "nterm")
<< ' ' << yytname_[yytype] << " ("
<< yysym.location << ": ";
switch (yytype)
{
case 3: // TEXT
/* Line 564 of lalr1.cc */
#line 53 "examples/variant.yy"
{ debug_stream () << yysym.value.template as< ::std::string
>(); }
/* Line 564 of lalr1.cc */
#line 249 "examples/variant.cc"
break;
case 4: // NUMBER
/* Line 564 of lalr1.cc */
#line 53 "examples/variant.yy"
{ debug_stream () << yysym.value.template as< int >(); }
/* Line 564 of lalr1.cc */
#line 258 "examples/variant.cc"
break;
case 7: // list
/* Line 564 of lalr1.cc */
#line 53 "examples/variant.yy"
{ debug_stream () << yysym.value.template
as< ::std::list<std::string> >(); }
/* Line 564 of lalr1.cc */
#line 267 "examples/variant.cc"
break;
case 8: // item
/* Line 564 of lalr1.cc */
#line 53 "examples/variant.yy"
{ debug_stream () << yysym.value.template as< ::std::string
>(); }
/* Line 564 of lalr1.cc */
#line 276 "examples/variant.cc"
break;
default:
break;
}
yyo << ')';
}
#endif
symbol_base_type is the based from which symbol_type (external
symbols, the type is coded by the type number) and stack_symbol_type
(internal symbols, the type is coded by the state number).
And this is a nice feature IMHO, as it is modular: you don't
have to write a single %printer which must handle the dispatching,
so you
would have to concentrate the code there. Rather, it is scattered
along the
%type directives.
I'm not suggesting we change that. I'm just suggesting that
%printer also
have access to the symbol_type object as well. Otherwise, the user
will
have to put the parts together by constructing his own temporary
symbol_type object in order to invoke operator<< from within %printer.
I'm sorry, I don't understand here. Sure, we can provided access to
it, but to what end? operator<< of a symbol_type bounces to the
various %printer implementations, so these should not bounce back to it.
By the way, why "symbol_type"? Why not just "symbol"? Isn't the
symbol
type just one field of the triple? Maybe I'm misunderstanding
something
fundamental.
What I call a symbol (implemented as the type symbol_type) is the
tripple, value and location included. Here is what symbol_type looks
like:
/// External form of a symbol: its type and attributes.
struct symbol_type : symbol_base_type<symbol_type>
{
/// The parent class.
typedef symbol_base_type<symbol_type> super_type;
/// Default constructor.
inline symbol_type ();
/// Constructor.
inline symbol_type (int t, const semantic_type& v, const
location_type& l);
inline symbol_type (int t, const location_type& l);
/// The symbol type.
int type;
/// Return the type corresponding to this state.
inline int type_get_ () const;
/// Its token.
inline token_type token () const;
};
I'm using the Curiously Recurring Template/Pattern here to avoid
dynamic dispatch. The base "class" is:
/// A complete symbol, with its type.
template <typename Exact>
struct symbol_base_type
{
/// Default constructor.
inline symbol_base_type ();
/// Constructor.
inline symbol_base_type (const location_type& l);
inline symbol_base_type (const semantic_type& v, const
location_type& l);
/// Return this with its exact type.
const Exact& self () const;
Exact& self ();
/// Return the type of this symbol.
int type_get () const;
/// The semantic value.
semantic_type value;
/// The location.
location_type location;
};
One issue with the current interface for %printer is also that I
encourage users to output on debug_stream(). So of course we could
std::ostream&
operator<<(std::ostream& yyostream, const symbol_type& yysymbol)
{
# define debug_stream() yystream
// Paste the %printers together.
# undef debug_stream()
return yyostream;
}
but that's ugly. Also, what should it look like in C? There is
nothing said about debug_stream in C, we just let the user understand
stderr is the right place, but some yystream (or yyfile) would be
nicer too. Should we start play with new symbols? $stream? %stream?
%printer { %stream << $$; } <*>
?
Of course we could decide that Bison is responsible for the "yystream
<<" part and ask the user to write
%printer { $$; } <*>
but this is not very nice: in the case of pointers, you want to
derefence if nonnull, how would you write this here? In the case of
containers, you'd like to iterate etc. Each time the user can address
this issue by simply implementing her operator<< for that type, but
that's asking for too much in my opinion (maybe displaying in the
traces is not the same as elsewhere in the program etc.). Besides,
this approach does not extend well to other languages such as C.
- [PATCH] Factor %FLAG at scan level., Akim Demaille, 2009/04/03
- Re: [PATCH] Factor %FLAG at scan level., Akim Demaille, 2009/04/03
- Re: [PATCH] Factor %FLAG at scan level., Joel E. Denny, 2009/04/04
- Re: [PATCH] Factor %FLAG at scan level., Akim Demaille, 2009/04/06
- Re: [PATCH] Factor %FLAG at scan level., Joel E. Denny, 2009/04/08
- Re: [PATCH] Factor %FLAG at scan level., Akim Demaille, 2009/04/08
- Re: [PATCH] Factor %FLAG at scan level., Joel E. Denny, 2009/04/09
- Re: [PATCH] Factor %FLAG at scan level.,
Akim Demaille <=
- Re: [PATCH] Factor %FLAG at scan level., Joel E. Denny, 2009/04/10
- Re: [PATCH] Factor %FLAG at scan level., Akim Demaille, 2009/04/10
- Re: [PATCH] Factor %FLAG at scan level., Joel E. Denny, 2009/04/10
- Re: [PATCH] Factor %FLAG at scan level., Akim Demaille, 2009/04/14
- Re: [PATCH] Factor %FLAG at scan level., Joel E. Denny, 2009/04/14
- Re: [PATCH] Factor %FLAG at scan level., Akim Demaille, 2009/04/15
- Re: [PATCH] Factor %FLAG at scan level., Joel E. Denny, 2009/04/16
- Re: [PATCH] Factor %FLAG at scan level., Joel E. Denny, 2009/04/09
- Re: [PATCH] Factor %FLAG at scan level., Akim Demaille, 2009/04/10
- Re: [PATCH] Factor %FLAG at scan level., Joel E. Denny, 2009/04/10