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