1 #C++ GLR skeleton for Bison 2 3 #Copyright(C) 2002 - 2015, 2018 - 2021 Free Software Foundation, Inc. 4 5 #This program is free software : you can redistribute it and / or modify 6 #it under the terms of the GNU General Public License as published by 7 #the Free Software Foundation, either version 3 of the License, or 8 #(at your option) any later version. 9 # 10 #This program is distributed in the hope that it will be useful, 11 #but WITHOUT ANY WARRANTY; without even the implied warranty of 12 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 13 #GNU General Public License for more details. 14 # 15 #You should have received a copy of the GNU General Public License 16 #along with this program.If not, see < https: // www.gnu.org/licenses/>. 17 18 #This skeleton produces a C++ class that encapsulates a C glr parser. 19 #This is in order to reduce the maintenance burden.The glr.c 20 #skeleton is clean and pure enough so that there are no real 21 #problems.The C++ interface is the same as that of lalr1.cc.In 22 #fact, glr.c can replace yacc.c without the user noticing any 23 #difference, and similarly for glr.cc replacing lalr1.cc. 24 # 25 #The passing of parse - params 26 # 27 #The additional arguments are stored as members of the parser 28 #object, yyparser.The C routines need to carry yyparser 29 #throughout the C parser; that's easy: make yyparser an 30 #additional parse - param.But because the C++ skeleton needs to 31 #know the "real" original parse - param, we save them 32 #(b4_parse_param_orig).Note that b4_parse_param is overquoted 33 #(and c.m4 strips one level of quotes).This is a PITA, and 34 #explains why there are so many levels of quotes. 35 # 36 #The locations 37 # 38 #We use location.cc just like lalr1.cc, but because glr.c stores 39 #the locations in a union, the position and location classes 40 #must not have a constructor.Therefore, contrary to lalr1.cc, we 41 #must not define "b4_location_constructors".As a consequence the 42 #user must initialize the first positions(in particular the 43 #filename member). 44 45 #We require a pure interface. 46 m4_define([b4_pure_flag], [1]) 47 48 m4_include(b4_skeletonsdir/[c++.m4]) 49 b4_bison_locations_if([m4_include(b4_skeletonsdir/[location.cc])]) 50 51 m4_define([b4_parser_class], 52 [b4_percent_define_get([[api.parser.class]])]) 53 54 #Save the parse parameters. 55 m4_define([b4_parse_param_orig], m4_defn([b4_parse_param])) 56 57 #b4_parse_param_wrap 58 #-- -- -- -- -- -- -- -- -- - 59 #New ones. 60 m4_ifset([b4_parse_param], 61 [m4_define([b4_parse_param_wrap], 62 [[b4_namespace_ref::b4_parser_class[& yyparser], [[yyparser]]],] 63 m4_defn([b4_parse_param]))], 64 [m4_define([b4_parse_param_wrap], 65 [[b4_namespace_ref::b4_parser_class[& yyparser], [[yyparser]]]]) 66 ]) 67 68 #b4_yy_symbol_print_define 69 #-- -- -- -- -- -- -- -- -- -- -- -- - 70 #Bypass the default implementation to generate the "yy_symbol_print" 71 # and "yy_symbol_value_print" functions. 72 m4_define([b4_yy_symbol_print_define], 73 [[/*--------------------. 74 | Print this symbol. | 75 `--------------------*/ 76 77 static void 78 yy_symbol_print (FILE *, ]b4_namespace_ref::b4_parser_class[::symbol_kind_type yytoken, 79 const ]b4_namespace_ref::b4_parser_class[::value_type *yyvaluep]b4_locations_if([[, 80 const ]b4_namespace_ref::b4_parser_class[::location_type *yylocationp]])[]b4_user_formals[) 81 { 82 ]b4_parse_param_use[]dnl 83 [ yyparser.yy_symbol_print_ (yytoken, yyvaluep]b4_locations_if([, yylocationp])[); 84 } 85 ]])[ 86 87 #Hijack the initial action to initialize the locations. 88 ]b4_bison_locations_if([m4_define([b4_initial_action], 89 [yylloc.initialize ();]m4_ifdef([b4_initial_action], [ 90 m4_defn([b4_initial_action])]))])[ 91 92 #Hijack the post prologue to declare yyerror. 93 ]m4_append([b4_post_prologue], 94 [b4_syncline([@oline@], [@ofile@])dnl 95 [static void 96 yyerror (]b4_locations_if([[const ]b4_namespace_ref::b4_parser_class[::location_type *yylocationp, 97 ]])[]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param), 98 ])[const char* msg);]])[ 99 100 #Inserted before the epilogue to define implementations(yyerror, parser member 101 #functions etc.). 102 ]m4_define([b4_glr_cc_pre_epilogue], 103 [b4_syncline([@oline@], [@ofile@])dnl 104 [ 105 /*------------------. 106 | Report an error. | 107 `------------------*/ 108 109 static void 110 yyerror (]b4_locations_if([[const ]b4_namespace_ref::b4_parser_class[::location_type *yylocationp, 111 ]])[]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param), 112 ])[const char* msg) 113 { 114 ]b4_parse_param_use[]dnl 115 [ yyparser.error (]b4_locations_if([[*yylocationp, ]])[msg); 116 } 117 118 119 ]b4_namespace_open[ 120 ]dnl In this section, the parse params are the original parse_params. 121 m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl 122 [ /// Build a parser object. 123 ]b4_parser_class::b4_parser_class[ (]b4_parse_param_decl[)]m4_ifset([b4_parse_param], [ 124 :])[ 125 #if] b4_api_PREFIX[DEBUG 126 ]m4_ifset([b4_parse_param], [ ], [ :])[yycdebug_ (&std::cerr)]m4_ifset([b4_parse_param], [,])[ 127 #endif] b4_parse_param_cons[ 128 {} 129 130 ]b4_parser_class::~b4_parser_class[ () 131 {} 132 133 ]b4_parser_class[::syntax_error::~syntax_error () YY_NOEXCEPT YY_NOTHROW 134 {} 135 136 int 137 ]b4_parser_class[::operator() () 138 { 139 return parse(); 140 } 141 142 int 143 ]b4_parser_class[::parse () 144 { 145 return ::yy_parse_impl (*this]b4_user_args[); 146 } 147 148 #if] b4_api_PREFIX[DEBUG 149 /*--------------------. 150 | Print this symbol. | 151 `--------------------*/ 152 153 void 154 ]b4_parser_class[::yy_symbol_value_print_ (symbol_kind_type yykind, 155 const value_type* yyvaluep]b4_locations_if([[, 156 const location_type* yylocationp]])[) const 157 {]b4_locations_if([[ 158 YY_USE (yylocationp);]])[ 159 YY_USE (yyvaluep); 160 std::ostream& yyo = debug_stream (); 161 std::ostream& yyoutput = yyo; 162 YY_USE (yyoutput); 163 ]b4_symbol_actions([printer])[ 164 } 165 166 167 void 168 ]b4_parser_class[::yy_symbol_print_ (symbol_kind_type yykind, 169 const value_type* yyvaluep]b4_locations_if([[, 170 const location_type* yylocationp]])[) const 171 { 172 *yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm") 173 << ' ' << yysymbol_name (yykind) << " ("]b4_locations_if([[ 174 << *yylocationp << ": "]])[; 175 yy_symbol_value_print_ (yykind, yyvaluep]b4_locations_if([[, yylocationp]])[); 176 *yycdebug_ << ')'; 177 } 178 179 std::ostream& 180 ]b4_parser_class[::debug_stream () const 181 { 182 return *yycdebug_; 183 } 184 185 void 186 ]b4_parser_class[::set_debug_stream (std::ostream& o) 187 { 188 yycdebug_ = &o; 189 } 190 191 192 ]b4_parser_class[::debug_level_type 193 ]b4_parser_class[::debug_level () const 194 { 195 return yydebug; 196 } 197 198 void 199 ]b4_parser_class[::set_debug_level (debug_level_type l) 200 { 201 // Actually, it is yydebug which is really used. 202 yydebug = l; 203 } 204 205 #endif 206 ]m4_popdef([b4_parse_param])dnl 207 b4_namespace_close[]dnl 208 ]) 209 210 211 m4_define([b4_define_symbol_kind], 212 [m4_format([#define %-15s %s], 213 b4_symbol($][1, kind_base), 214 b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol($1, kind_base)) 215 ]) 216 217 #b4_glr_cc_setup 218 #-- -- -- -- -- -- -- - 219 #Setup redirections for glr.c : Map the names used in c.m4 to the ones used 220 #in c++.m4. 221 m4_define([b4_glr_cc_setup], 222 [[]b4_attribute_define[ 223 ]b4_null_define[ 224 225 // This skeleton is based on C, yet compiles it as C++. 226 // So expect warnings about C style casts. 227 #if defined __clang__ && 306 <= __clang_major__ * 100 + __clang_minor__ 228 # pragma clang diagnostic ignored "-Wold-style-cast" 229 #elif defined __GNUC__ && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ 230 # pragma GCC diagnostic ignored "-Wold-style-cast" 231 #endif 232 233 // On MacOS, PTRDIFF_MAX is defined as long long, which Clang's 234 // -pedantic reports as being a C++11 extension. 235 #if defined __APPLE__ && YY_CPLUSPLUS < 201103L && defined __clang__ && 4 <= __clang_major__ 236 # pragma clang diagnostic ignored "-Wc++11-long-long" 237 #endif 238 239 #undef] b4_symbol(empty, [id])[ 240 #define] b4_symbol(empty, [id])[] b4_namespace_ref[::] b4_parser_class[::token::] b4_symbol( \ 241 empty, [id])[ 242 #undef] b4_symbol(eof, [id])[ 243 #define] b4_symbol(eof, [id])[] b4_namespace_ref[::] b4_parser_class[::token::] b4_symbol( \ 244 eof, [id])[ 245 #undef] b4_symbol(error, [id])[ 246 #define] b4_symbol(error, [id])[] b4_namespace_ref[::] b4_parser_class[::token::] b4_symbol( \ 247 error, [id])[ 248 249 #ifndef] b4_api_PREFIX[STYPE 250 # define] b4_api_PREFIX[STYPE] b4_namespace_ref[::] b4_parser_class[::value_type 251 #endif 252 #ifndef] b4_api_PREFIX[LTYPE 253 # define] b4_api_PREFIX[LTYPE] b4_namespace_ref[::] b4_parser_class[::location_type 254 #endif 255 256 typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind_type yysymbol_kind_t; 257 258 // Expose C++ symbol kinds to C. 259 ]b4_define_symbol_kind(-2)dnl 260 b4_symbol_foreach([b4_define_symbol_kind])])[ 261 ]]) 262 263 264 m4_define([b4_undef_symbol_kind], 265 [[#undef ]b4_symbol($1, kind_base)[ 266 ]]) 267 268 #b4_glr_cc_cleanup 269 #-- -- -- -- -- -- -- -- - 270 #Remove redirections for glr.c. 271 m4_define([b4_glr_cc_cleanup], 272 [[#undef ]b4_symbol(empty, [id])[ 273 #undef] b4_symbol(eof, [id])[ 274 #undef] b4_symbol(error, [id])[ 275 276 ]b4_undef_symbol_kind(-2)dnl 277 b4_symbol_foreach([b4_undef_symbol_kind])dnl 278 ]) 279 280 #b4_shared_declarations(hh | cc) 281 #-- -- -- -- -- -- -- -- -- -- -- -- -- -- - 282 #Declaration that might either go into the header(if --header, $1 = hh) 283 # or in the implementation file. 284 m4_define([b4_shared_declarations], 285 [m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl 286 b4_percent_code_get([[requires]])[ 287 #include <iostream> 288 #include <stdexcept> 289 #include <string> 290 291 ]b4_cxx_portability[ 292 ]m4_ifdef([b4_location_include], 293 [[# include ]b4_location_include])[ 294 ]b4_variant_if([b4_variant_includes])[ 295 296 // Whether we are compiled with exception support. 297 #ifndef YY_EXCEPTIONS 298 # if defined __GNUC__ && !defined __EXCEPTIONS 299 # define YY_EXCEPTIONS 0 300 # else 301 # define YY_EXCEPTIONS 1 302 # endif 303 #endif 304 305 ]b4_YYDEBUG_define[ 306 307 ]b4_namespace_open[ 308 309 ]b4_bison_locations_if([m4_ifndef([b4_location_file], 310 [b4_location_define])])[ 311 312 /// A Bison parser. 313 class ]b4_parser_class[ 314 { 315 public: 316 ]b4_public_types_declare[ 317 318 /// Build a parser object. 319 ]b4_parser_class[ (]b4_parse_param_decl[); 320 virtual ~]b4_parser_class[ (); 321 322 /// Parse. An alias for parse (). 323 /// \returns 0 iff parsing succeeded. 324 int operator() (); 325 326 /// Parse. 327 /// \returns 0 iff parsing succeeded. 328 virtual int parse (); 329 330 #if] b4_api_PREFIX[DEBUG 331 /// The current debugging stream. 332 std::ostream& debug_stream () const; 333 /// Set the current debugging stream. 334 void set_debug_stream (std::ostream &); 335 336 /// Type for debugging levels. 337 typedef int debug_level_type; 338 /// The current debugging level. 339 debug_level_type debug_level () const; 340 /// Set the current debugging level. 341 void set_debug_level (debug_level_type l); 342 #endif 343 344 /// Report a syntax error.]b4_locations_if([[ 345 /// \param loc where the syntax error is found.]])[ 346 /// \param msg a description of the syntax error. 347 virtual void error (]b4_locations_if([[const location_type& loc, ]])[const std::string& msg); 348 349 #if] b4_api_PREFIX[DEBUG 350 public: 351 /// \brief Report a symbol value on the debug stream. 352 /// \param yykind The symbol kind. 353 /// \param yyvaluep Its semantic value.]b4_locations_if([[ 354 /// \param yylocationp Its location.]])[ 355 virtual void yy_symbol_value_print_ (symbol_kind_type yykind, 356 const value_type* yyvaluep]b4_locations_if([[, 357 const location_type* yylocationp]])[) const; 358 /// \brief Report a symbol on the debug stream. 359 /// \param yykind The symbol kind. 360 /// \param yyvaluep Its semantic value.]b4_locations_if([[ 361 /// \param yylocationp Its location.]])[ 362 virtual void yy_symbol_print_ (symbol_kind_type yykind, 363 const value_type* yyvaluep]b4_locations_if([[, 364 const location_type* yylocationp]])[) const; 365 private: 366 /// Debug stream. 367 std::ostream* yycdebug_; 368 #endif 369 370 ]b4_parse_param_vars[ 371 }; 372 373 ]b4_namespace_close[ 374 375 ]b4_percent_code_get([[provides]])[ 376 ]m4_popdef([b4_parse_param])dnl 377 ])[ 378 379 ]b4_header_if( 380 [b4_output_begin([b4_spec_header_file]) 381 b4_copyright([Skeleton interface for Bison GLR parsers in C++], 382 [2002-2015, 2018-2021])[ 383 // C++ GLR parser skeleton written by Akim Demaille. 384 385 ]b4_disclaimer[ 386 ]b4_cpp_guard_open([b4_spec_mapped_header_file])[ 387 ]b4_shared_declarations[ 388 ]b4_cpp_guard_close([b4_spec_mapped_header_file])[ 389 ]b4_output_end]) 390 391 #Let glr.c(and b4_shared_declarations) believe that the user 392 #arguments include the parser itself. 393 m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_wrap])) 394 m4_include(b4_skeletonsdir/[glr.c]) 395 m4_popdef([b4_parse_param]) 396