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.
49 m4_define([b4_locations_flag], [1])
50 m4_define([b4_pure_flag],      [1])
51 
52 # The header is mandatory.
53 b4_defines_if([],
54               [b4_fatal([b4_skeleton[: using %%defines is mandatory]])])
55 
56 m4_include(b4_pkgdatadir/[c++.m4])
57 b4_percent_define_ifdef([[api.location.type]], [],
58                         [m4_include(b4_pkgdatadir/[location.cc])])
59 
60 m4_define([b4_parser_class_name],
61           [b4_percent_define_get([[parser_class_name]])])
62 
63 # Save the parse parameters.
64 m4_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.
71 m4_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], [
96 m4_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.).
114 m4_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.
134 m4_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
219 b4_namespace_close])
220 
221 
222 # Let glr.c believe that the user arguments include the parser itself.
223 m4_ifset([b4_parse_param],
224 [m4_pushdef([b4_parse_param],
225             [[b4_namespace_ref::b4_parser_class_name[& yyparser], [[yyparser]]],]
226 m4_defn([b4_parse_param]))],
227 [m4_pushdef([b4_parse_param],
228             [[b4_namespace_ref::b4_parser_class_name[& yyparser], [[yyparser]]]])
229 ])
230 m4_include(b4_pkgdatadir/[glr.c])
231 m4_popdef([b4_parse_param])
232 
233 b4_output_begin([b4_spec_defines_file])
234 b4_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     {
260 b4_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.
333 b4_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