1                                                                    -*- C -*-
2
3# C++ GLR skeleton for Bison
4
5# Copyright (C) 2002-2012 Free Software Foundation, Inc.
6
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20
21# This skeleton produces a C++ class that encapsulates a C glr parser.
22# This is in order to reduce the maintenance burden.  The glr.c
23# skeleton is clean and pure enough so that there are no real
24# problems.  The C++ interface is the same as that of lalr1.cc.  In
25# fact, glr.c can replace yacc.c without the user noticing any
26# difference, and similarly for glr.cc replacing lalr1.cc.
27#
28# The passing of parse-params
29#
30#   The additional arguments are stored as members of the parser
31#   object, yyparser.  The C routines need to carry yyparser
32#   throughout the C parser; that easy: just let yyparser become an
33#   additional parse-param.  But because the C++ skeleton needs to
34#   know the "real" original parse-param, we save them
35#   (b4_parse_param_orig).  Note that b4_parse_param is overquoted
36#   (and c.m4 strips one level of quotes).  This is a PITA, and
37#   explains why there are so many levels of quotes.
38#
39# The locations
40#
41#   We use location.cc just like lalr1.cc, but because glr.c stores
42#   the locations in a (C++) union, the position and location classes
43#   must not have a constructor.  Therefore, contrary to lalr1.cc, we
44#   must not define "b4_location_constructors".  As a consequence the
45#   user must initialize the first positions (in particular the
46#   filename member).
47
48# We require a pure interface using locations.
49m4_define([b4_locations_flag], [1])
50m4_define([b4_pure_flag],      [1])
51
52# The header is mandatory.
53b4_defines_if([],
54              [b4_fatal([b4_skeleton[: using %%defines is mandatory]])])
55
56m4_include(b4_pkgdatadir/[c++.m4])
57b4_percent_define_ifdef([[api.location.type]], [],
58                        [m4_include(b4_pkgdatadir/[location.cc])])
59
60m4_define([b4_parser_class_name],
61          [b4_percent_define_get([[parser_class_name]])])
62
63# Save the parse parameters.
64m4_define([b4_parse_param_orig], m4_defn([b4_parse_param]))
65
66
67# b4_yy_symbol_print_generate
68# ---------------------------
69# Bypass the default implementation to generate the "yy_symbol_print"
70# and "yy_symbol_value_print" functions.
71m4_define([b4_yy_symbol_print_generate],
72[[
73/*--------------------.
74| Print this symbol.  |
75`--------------------*/
76
77]b4_c_ansi_function_def([yy_symbol_print],
78    [static void],
79    [[FILE *],               []],
80    [[int yytype],           [yytype]],
81    [[const ]b4_namespace_ref::b4_parser_class_name[::semantic_type *yyvaluep],
82                             [yyvaluep]],
83    [[const ]b4_namespace_ref::b4_parser_class_name[::location_type *yylocationp],
84                             [yylocationp]],
85    b4_parse_param)[
86{
87]b4_parse_param_use[]dnl
88[  yyparser.yy_symbol_print_ (yytype, yyvaluep]b4_locations_if([, yylocationp])[);
89}
90]])[
91
92# Hijack the initial action to initialize the locations.
93]b4_locations_if([b4_percent_define_ifdef([[api.location.type]], [],
94[m4_define([b4_initial_action],
95[yylloc.initialize ();]m4_ifdef([b4_initial_action], [
96m4_defn([b4_initial_action])]))])])[
97
98# Hijack the post prologue to insert early definition of YYLLOC_DEFAULT
99# and declaration of yyerror.
100]m4_append([b4_post_prologue],
101[b4_syncline([@oline@], [@ofile@])[
102]b4_yylloc_default_define[
103#define YYRHSLOC(Rhs, K) ((Rhs)[K].yystate.yyloc)
104]b4_c_ansi_function_decl([yyerror],
105    [static void],
106    [[const ]b4_namespace_ref::b4_parser_class_name[::location_type *yylocationp],
107                        [yylocationp]],
108    b4_parse_param,
109    [[const char* msg], [msg]])])
110
111
112# Hijack the epilogue to define implementations (yyerror, parser member
113# functions etc.).
114m4_append([b4_epilogue],
115[b4_syncline([@oline@], [@ofile@])[
116/*------------------.
117| Report an error.  |
118`------------------*/
119
120]b4_c_ansi_function_def([yyerror],
121    [static void],
122    [[const ]b4_namespace_ref::b4_parser_class_name[::location_type *yylocationp],
123                        [yylocationp]],
124    b4_parse_param,
125    [[const char* msg], [msg]])[
126{
127]b4_parse_param_use[]dnl
128[  yyparser.error (*yylocationp, msg);
129}
130
131
132]b4_namespace_open[
133]dnl In this section, the parse param are the original parse_params.
134m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl
135[  /// Build a parser object.
136  ]b4_parser_class_name::b4_parser_class_name[ (]b4_parse_param_decl[)]m4_ifset([b4_parse_param], [
137    :])[
138#if ]b4_api_PREFIX[DEBUG
139    ]m4_ifset([b4_parse_param], [  ], [ :])[
140      yycdebug_ (&std::cerr)]m4_ifset([b4_parse_param], [,])[
141#endif]b4_parse_param_cons[
142  {
143  }
144
145  ]b4_parser_class_name::~b4_parser_class_name[ ()
146  {
147  }
148
149  int
150  ]b4_parser_class_name[::parse ()
151  {
152    return ::yyparse (*this]b4_user_args[);
153  }
154
155#if ]b4_api_PREFIX[DEBUG
156  /*--------------------.
157  | Print this symbol.  |
158  `--------------------*/
159
160  inline void
161  ]b4_parser_class_name[::yy_symbol_value_print_ (int yytype,
162                           const semantic_type* yyvaluep,
163                           const location_type* yylocationp)
164  {
165    YYUSE (yylocationp);
166    YYUSE (yyvaluep);
167    std::ostream& yyoutput = debug_stream ();
168    std::ostream& yyo = yyoutput;
169    YYUSE (yyo);
170    switch (yytype)
171      {
172  ]m4_map([b4_symbol_actions], m4_defn([b4_symbol_printers]))dnl
173[        default:
174          break;
175      }
176  }
177
178
179  void
180  ]b4_parser_class_name[::yy_symbol_print_ (int yytype,
181                           const semantic_type* yyvaluep,
182                           const location_type* yylocationp)
183  {
184    *yycdebug_ << (yytype < YYNTOKENS ? "token" : "nterm")
185               << ' ' << yytname[yytype] << " ("
186               << *yylocationp << ": ";
187    yy_symbol_value_print_ (yytype, yyvaluep, yylocationp);
188    *yycdebug_ << ')';
189  }
190
191  std::ostream&
192  ]b4_parser_class_name[::debug_stream () const
193  {
194    return *yycdebug_;
195  }
196
197  void
198  ]b4_parser_class_name[::set_debug_stream (std::ostream& o)
199  {
200    yycdebug_ = &o;
201  }
202
203
204  ]b4_parser_class_name[::debug_level_type
205  ]b4_parser_class_name[::debug_level () const
206  {
207    return yydebug;
208  }
209
210  void
211  ]b4_parser_class_name[::set_debug_level (debug_level_type l)
212  {
213    // Actually, it is yydebug which is really used.
214    yydebug = l;
215  }
216
217#endif
218]m4_popdef([b4_parse_param])dnl
219b4_namespace_close])
220
221
222# Let glr.c believe that the user arguments include the parser itself.
223m4_ifset([b4_parse_param],
224[m4_pushdef([b4_parse_param],
225            [[b4_namespace_ref::b4_parser_class_name[& yyparser], [[yyparser]]],]
226m4_defn([b4_parse_param]))],
227[m4_pushdef([b4_parse_param],
228            [[b4_namespace_ref::b4_parser_class_name[& yyparser], [[yyparser]]]])
229])
230m4_include(b4_pkgdatadir/[glr.c])
231m4_popdef([b4_parse_param])
232
233b4_output_begin([b4_spec_defines_file])
234b4_copyright([Skeleton interface for Bison GLR parsers in C++],
235             [2002-2006, 2009-2012])[
236
237/* C++ GLR parser skeleton written by Akim Demaille.  */
238
239]b4_cpp_guard_open([b4_spec_defines_file])[
240
241]b4_percent_code_get([[requires]])[
242
243# include <string>
244# include <iostream>
245]b4_percent_define_ifdef([[api.location.type]], [],
246                         [[# include "location.hh"]])[
247
248]b4_YYDEBUG_define[
249
250]b4_namespace_open[
251  /// A Bison parser.
252  class ]b4_parser_class_name[
253  {
254  public:
255    /// Symbol semantic values.
256# ifndef ]b4_api_PREFIX[STYPE
257]m4_ifdef([b4_stype],
258[    union semantic_type
259    {
260b4_user_stype
261    };],
262[m4_if(b4_tag_seen_flag, 0,
263[[    typedef int semantic_type;]],
264[[    typedef ]b4_api_PREFIX[STYPE semantic_type;]])])[
265# else
266    typedef ]b4_api_PREFIX[STYPE semantic_type;
267# endif
268    /// Symbol locations.
269    typedef ]b4_percent_define_get([[api.location.type]],
270                                   [[location]])[ location_type;
271    /// Tokens.
272    struct token
273    {
274      ]b4_token_enums(b4_tokens)[
275    };
276    /// Token type.
277    typedef token::yytokentype token_type;
278
279    /// Build a parser object.
280    ]b4_parser_class_name[ (]b4_parse_param_decl[);
281    virtual ~]b4_parser_class_name[ ();
282
283    /// Parse.
284    /// \returns  0 iff parsing succeeded.
285    virtual int parse ();
286
287    /// The current debugging stream.
288    std::ostream& debug_stream () const;
289    /// Set the current debugging stream.
290    void set_debug_stream (std::ostream &);
291
292    /// Type for debugging levels.
293    typedef int debug_level_type;
294    /// The current debugging level.
295    debug_level_type debug_level () const;
296    /// Set the current debugging level.
297    void set_debug_level (debug_level_type l);
298
299  private:
300
301  public:
302    /// Report a syntax error.
303    /// \param loc    where the syntax error is found.
304    /// \param msg    a description of the syntax error.
305    virtual void error (const location_type& loc, const std::string& msg);
306  private:
307
308# if ]b4_api_PREFIX[DEBUG
309  public:
310    /// \brief Report a symbol value on the debug stream.
311    /// \param yytype       The token type.
312    /// \param yyvaluep     Its semantic value.
313    /// \param yylocationp  Its location.
314    virtual void yy_symbol_value_print_ (int yytype,
315                                         const semantic_type* yyvaluep,
316                                         const location_type* yylocationp);
317    /// \brief Report a symbol on the debug stream.
318    /// \param yytype       The token type.
319    /// \param yyvaluep     Its semantic value.
320    /// \param yylocationp  Its location.
321    virtual void yy_symbol_print_ (int yytype,
322                                   const semantic_type* yyvaluep,
323                                   const location_type* yylocationp);
324  private:
325    /* Debugging.  */
326    std::ostream* yycdebug_;
327# endif
328
329]b4_parse_param_vars[
330  };
331
332]dnl Redirections for glr.c.
333b4_percent_define_flag_if([[global_tokens_and_yystype]],
334[b4_token_defines(b4_tokens)])
335[
336#ifndef ]b4_api_PREFIX[STYPE
337# define ]b4_api_PREFIX[STYPE ]b4_namespace_ref[::]b4_parser_class_name[::semantic_type
338#endif
339#ifndef ]b4_api_PREFIX[LTYPE
340# define ]b4_api_PREFIX[LTYPE ]b4_namespace_ref[::]b4_parser_class_name[::location_type
341#endif
342
343]b4_namespace_close[
344]b4_percent_code_get([[provides]])[
345]b4_cpp_guard_close([b4_spec_defines_file])[
346]b4_output_end()
347