glr.cc 12 KB

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