xref: /aosp_15_r20/prebuilts/build-tools/common/bison/skeletons/variant.hh (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1 # C++ 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 
19 ## --------- ##
20 ## variant.  ##
21 ## --------- ##
22 
23 # b4_assert
24 # ---------
25 # The name of YY_ASSERT.
26 m4_define([b4_assert],
27           [b4_api_PREFIX[]_ASSERT])
28 
29 
30 # b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS])
31 # ------------------------------------------------
32 # Run some ACTION ("build", or "destroy") on YYVAL of symbol type
33 # YYTYPE.
34 m4_define([b4_symbol_variant],
35 [m4_pushdef([b4_dollar_dollar],
36             [$2.$3< $][3 > (m4_shift3($@))])dnl
37 switch ($1)
38     {
39 b4_type_foreach([_b4_type_action])[]dnl
40       default:
41         break;
42     }
43 m4_popdef([b4_dollar_dollar])dnl
44 ])
45 
46 
47 # _b4_char_sizeof_counter
48 # -----------------------
49 # A counter used by _b4_char_sizeof_dummy to create fresh symbols.
50 m4_define([_b4_char_sizeof_counter],
51 [0])
52 
53 # _b4_char_sizeof_dummy
54 # ---------------------
55 # At each call return a new C++ identifier.
56 m4_define([_b4_char_sizeof_dummy],
57 [m4_define([_b4_char_sizeof_counter], m4_incr(_b4_char_sizeof_counter))dnl
58 dummy[]_b4_char_sizeof_counter])
59 
60 
61 # b4_char_sizeof(SYMBOL-NUMS)
62 # ---------------------------
63 # To be mapped on the list of type names to produce:
64 #
65 #    char dummy1[sizeof (type_name_1)];
66 #    char dummy2[sizeof (type_name_2)];
67 #
68 # for defined type names.
69 m4_define([b4_char_sizeof],
70 [b4_symbol_if([$1], [has_type],
71 [
72 m4_map([      b4_symbol_tag_comment], [$@])dnl
73       char _b4_char_sizeof_dummy@{sizeof (b4_symbol([$1], [type]))@};
74 ])])
75 
76 
77 # b4_variant_includes
78 # -------------------
79 # The needed includes for variants support.
80 m4_define([b4_variant_includes],
81 [b4_parse_assert_if([[#include <typeinfo>
82 #ifndef ]b4_assert[
83 # include <cassert>
84 # define ]b4_assert[ assert
85 #endif
86 ]])])
87 
88 
89 
90 ## -------------------------- ##
91 ## Adjustments for variants.  ##
92 ## -------------------------- ##
93 
94 
95 # b4_value_type_declare
96 # ---------------------
97 # Define value_type.
98 m4_define([b4_value_type_declare],
99 [[  /// A buffer to store and retrieve objects.
100   ///
101   /// Sort of a variant, but does not keep track of the nature
102   /// of the stored data, since that knowledge is available
103   /// via the current parser state.
104   class value_type
105   {
106   public:
107     /// Type of *this.
108     typedef value_type self_type;
109 
110     /// Empty construction.
111     value_type () YY_NOEXCEPT
112       : yyraw_ ()]b4_parse_assert_if([
113       , yytypeid_ (YY_NULLPTR)])[
114     {}
115 
116     /// Construct and fill.
117     template <typename T>
118     value_type (YY_RVREF (T) t)]b4_parse_assert_if([
119       : yytypeid_ (&typeid (T))])[
120     {]b4_parse_assert_if([[
121       ]b4_assert[ (sizeof (T) <= size);]])[
122       new (yyas_<T> ()) T (YY_MOVE (t));
123     }
124 
125 #if 201103L <= YY_CPLUSPLUS
126     /// Non copyable.
127     value_type (const self_type&) = delete;
128     /// Non copyable.
129     self_type& operator= (const self_type&) = delete;
130 #endif
131 
132     /// Destruction, allowed only if empty.
133     ~value_type () YY_NOEXCEPT
134     {]b4_parse_assert_if([
135       ]b4_assert[ (!yytypeid_);
136     ])[}
137 
138 # if 201103L <= YY_CPLUSPLUS
139     /// Instantiate a \a T in here from \a t.
140     template <typename T, typename... U>
141     T&
142     emplace (U&&... u)
143     {]b4_parse_assert_if([[
144       ]b4_assert[ (!yytypeid_);
145       ]b4_assert[ (sizeof (T) <= size);
146       yytypeid_ = & typeid (T);]])[
147       return *new (yyas_<T> ()) T (std::forward <U>(u)...);
148     }
149 # else
150     /// Instantiate an empty \a T in here.
151     template <typename T>
152     T&
153     emplace ()
154     {]b4_parse_assert_if([[
155       ]b4_assert[ (!yytypeid_);
156       ]b4_assert[ (sizeof (T) <= size);
157       yytypeid_ = & typeid (T);]])[
158       return *new (yyas_<T> ()) T ();
159     }
160 
161     /// Instantiate a \a T in here from \a t.
162     template <typename T>
163     T&
164     emplace (const T& t)
165     {]b4_parse_assert_if([[
166       ]b4_assert[ (!yytypeid_);
167       ]b4_assert[ (sizeof (T) <= size);
168       yytypeid_ = & typeid (T);]])[
169       return *new (yyas_<T> ()) T (t);
170     }
171 # endif
172 
173     /// Instantiate an empty \a T in here.
174     /// Obsolete, use emplace.
175     template <typename T>
176     T&
177     build ()
178     {
179       return emplace<T> ();
180     }
181 
182     /// Instantiate a \a T in here from \a t.
183     /// Obsolete, use emplace.
184     template <typename T>
185     T&
186     build (const T& t)
187     {
188       return emplace<T> (t);
189     }
190 
191     /// Accessor to a built \a T.
192     template <typename T>
193     T&
194     as () YY_NOEXCEPT
195     {]b4_parse_assert_if([[
196       ]b4_assert[ (yytypeid_);
197       ]b4_assert[ (*yytypeid_ == typeid (T));
198       ]b4_assert[ (sizeof (T) <= size);]])[
199       return *yyas_<T> ();
200     }
201 
202     /// Const accessor to a built \a T (for %printer).
203     template <typename T>
204     const T&
205     as () const YY_NOEXCEPT
206     {]b4_parse_assert_if([[
207       ]b4_assert[ (yytypeid_);
208       ]b4_assert[ (*yytypeid_ == typeid (T));
209       ]b4_assert[ (sizeof (T) <= size);]])[
210       return *yyas_<T> ();
211     }
212 
213     /// Swap the content with \a that, of same type.
214     ///
215     /// Both variants must be built beforehand, because swapping the actual
216     /// data requires reading it (with as()), and this is not possible on
217     /// unconstructed variants: it would require some dynamic testing, which
218     /// should not be the variant's responsibility.
219     /// Swapping between built and (possibly) non-built is done with
220     /// self_type::move ().
221     template <typename T>
222     void
223     swap (self_type& that) YY_NOEXCEPT
224     {]b4_parse_assert_if([[
225       ]b4_assert[ (yytypeid_);
226       ]b4_assert[ (*yytypeid_ == *that.yytypeid_);]])[
227       std::swap (as<T> (), that.as<T> ());
228     }
229 
230     /// Move the content of \a that to this.
231     ///
232     /// Destroys \a that.
233     template <typename T>
234     void
235     move (self_type& that)
236     {
237 # if 201103L <= YY_CPLUSPLUS
238       emplace<T> (std::move (that.as<T> ()));
239 # else
240       emplace<T> ();
241       swap<T> (that);
242 # endif
243       that.destroy<T> ();
244     }
245 
246 # if 201103L <= YY_CPLUSPLUS
247     /// Move the content of \a that to this.
248     template <typename T>
249     void
250     move (self_type&& that)
251     {
252       emplace<T> (std::move (that.as<T> ()));
253       that.destroy<T> ();
254     }
255 #endif
256 
257     /// Copy the content of \a that to this.
258     template <typename T>
259     void
260     copy (const self_type& that)
261     {
262       emplace<T> (that.as<T> ());
263     }
264 
265     /// Destroy the stored \a T.
266     template <typename T>
267     void
268     destroy ()
269     {
270       as<T> ().~T ();]b4_parse_assert_if([
271       yytypeid_ = YY_NULLPTR;])[
272     }
273 
274   private:
275 #if YY_CPLUSPLUS < 201103L
276     /// Non copyable.
277     value_type (const self_type&);
278     /// Non copyable.
279     self_type& operator= (const self_type&);
280 #endif
281 
282     /// Accessor to raw memory as \a T.
283     template <typename T>
284     T*
285     yyas_ () YY_NOEXCEPT
286     {
287       void *yyp = yyraw_;
288       return static_cast<T*> (yyp);
289      }
290 
291     /// Const accessor to raw memory as \a T.
292     template <typename T>
293     const T*
294     yyas_ () const YY_NOEXCEPT
295     {
296       const void *yyp = yyraw_;
297       return static_cast<const T*> (yyp);
298      }
299 
300     /// An auxiliary type to compute the largest semantic type.
301     union union_type
302     {]b4_type_foreach([b4_char_sizeof])[    };
303 
304     /// The size of the largest semantic type.
305     enum { size = sizeof (union_type) };
306 
307     /// A buffer to store semantic values.
308     union
309     {
310       /// Strongest alignment constraints.
311       long double yyalign_me_;
312       /// A buffer large enough to store any of the semantic values.
313       char yyraw_[size];
314     };]b4_parse_assert_if([
315 
316     /// Whether the content is built: if defined, the name of the stored type.
317     const std::type_info *yytypeid_;])[
318   };
319 ]])
320 
321 
322 # How the semantic value is extracted when using variants.
323 
324 # b4_symbol_value(VAL, SYMBOL-NUM, [TYPE])
325 # ----------------------------------------
326 # See README.
327 m4_define([b4_symbol_value],
328 [m4_ifval([$3],
329           [$1.as< $3 > ()],
330           [m4_ifval([$2],
331                     [b4_symbol_if([$2], [has_type],
332                                   [$1.as < b4_symbol([$2], [type]) > ()],
333                                   [$1])],
334                     [$1])])])
335 
336 # b4_symbol_value_template(VAL, SYMBOL-NUM, [TYPE])
337 # -------------------------------------------------
338 # Same as b4_symbol_value, but used in a template method.
339 m4_define([b4_symbol_value_template],
340 [m4_ifval([$3],
341           [$1.template as< $3 > ()],
342           [m4_ifval([$2],
343                     [b4_symbol_if([$2], [has_type],
344                                   [$1.template as < b4_symbol([$2], [type]) > ()],
345                                   [$1])],
346                     [$1])])])
347 
348 
349 
350 ## ------------- ##
351 ## make_SYMBOL.  ##
352 ## ------------- ##
353 
354 
355 # _b4_includes_tokens(SYMBOL-NUM...)
356 # ----------------------------------
357 # Expands to non-empty iff one of the SYMBOL-NUM denotes
358 # a token.
359 m4_define([_b4_is_token],
360           [b4_symbol_if([$1], [is_token], [1])])
361 m4_define([_b4_includes_tokens],
362           [m4_map([_b4_is_token], [$@])])
363 
364 
365 # _b4_token_maker_define(SYMBOL-NUM)
366 # ----------------------------------
367 # Declare make_SYMBOL for SYMBOL-NUM.  Use at class-level.
368 m4_define([_b4_token_maker_define],
369 [b4_token_visible_if([$1],
370 [#if 201103L <= YY_CPLUSPLUS
371       static
372       symbol_type
373       make_[]_b4_symbol([$1], [id]) (b4_join(
374                  b4_symbol_if([$1], [has_type],
375                  [b4_symbol([$1], [type]) v]),
376                  b4_locations_if([location_type l])))
377       {
378         return symbol_type (b4_join([token::b4_symbol([$1], [id])],
379                                     b4_symbol_if([$1], [has_type], [std::move (v)]),
380                                     b4_locations_if([std::move (l)])));
381       }
382 #else
383       static
384       symbol_type
385       make_[]_b4_symbol([$1], [id]) (b4_join(
386                  b4_symbol_if([$1], [has_type],
387                  [const b4_symbol([$1], [type])& v]),
388                  b4_locations_if([const location_type& l])))
389       {
390         return symbol_type (b4_join([token::b4_symbol([$1], [id])],
391                                     b4_symbol_if([$1], [has_type], [v]),
392                                     b4_locations_if([l])));
393       }
394 #endif
395 ])])
396 
397 
398 # b4_token_kind(SYMBOL-NUM)
399 # -------------------------
400 # Some tokens don't have an ID.
401 m4_define([b4_token_kind],
402 [b4_symbol_if([$1], [has_id],
403               [token::b4_symbol([$1], [id])],
404               [b4_symbol([$1], [code])])])
405 
406 
407 # _b4_tok_in(SYMBOL-NUM, ...)
408 # ---------------------------
409 # See b4_tok_in below.  The SYMBOL-NUMs... are tokens only.
410 #
411 # We iterate over the tokens to group them by "range" of token numbers (not
412 # symbols numbers!).
413 #
414 # b4_fst is the start of that range.
415 # b4_prev is the previous value.
416 # b4_val is the current value.
417 # If b4_val is the successor of b4_prev in token numbers, update the latter,
418 #   otherwise emit the code for range b4_fst .. b4_prev.
419 # $1 is also used as a terminator in the foreach, but it will not be printed.
420 #
421 m4_define([_b4_tok_in],
422 [m4_pushdef([b4_prev], [$1])dnl
423 m4_pushdef([b4_fst], [$1])dnl
424 m4_pushdef([b4_sep], [])dnl
425 m4_foreach([b4_val], m4_dquote(m4_shift($@, $1)),
426            [m4_if(b4_symbol(b4_val, [code]), m4_eval(b4_symbol(b4_prev, [code]) + 1), [],
427                   [b4_sep[]m4_if(b4_fst, b4_prev,
428                          [tok == b4_token_kind(b4_fst)],
429                          [(b4_token_kind(b4_fst) <= tok && tok <= b4_token_kind(b4_prev))])[]dnl
430 m4_define([b4_fst], b4_val)dnl
431 m4_define([b4_sep], [
432                    || ])])dnl
433 m4_define([b4_prev], b4_val)])dnl
434 m4_popdef([b4_sep])dnl
435 m4_popdef([b4_fst])dnl
436 m4_popdef([b4_prev])dnl
437 ])
438 
439 
440 # _b4_filter_tokens(SYMBOL-NUM, ...)
441 # ----------------------------------
442 # Expand as the list of tokens amongst SYMBOL-NUM.
443 m4_define([_b4_filter_tokens],
444 [m4_pushdef([b4_sep])dnl
445 m4_foreach([b4_val], [$@],
446            [b4_symbol_if(b4_val, [is_token], [b4_sep[]b4_val[]m4_define([b4_sep], [,])])])dnl
447 m4_popdef([b4_sep])dnl
448 ])
449 
450 
451 # b4_tok_in(SYMBOL-NUM, ...)
452 # ---------------------------
453 # A C++ conditional that checks that `tok` is a member of this list of symbol
454 # numbers.
455 m4_define([b4_tok_in],
456           [_$0(_b4_filter_tokens($@))])
457 
458 
459 
460 
461 # _b4_symbol_constructor_define(SYMBOL-NUM...)
462 # --------------------------------------------
463 # Define a symbol_type constructor common to all the SYMBOL-NUM (they
464 # have the same type).  Use at class-level.
465 m4_define([_b4_symbol_constructor_define],
466 [m4_ifval(_b4_includes_tokens($@),
467 [[#if 201103L <= YY_CPLUSPLUS
468       symbol_type (]b4_join(
469           [int tok],
470           b4_symbol_if([$1], [has_type],
471                        [b4_symbol([$1], [type]) v]),
472           b4_locations_if([location_type l]))[)
473         : super_type (]b4_join([token_kind_type (tok)],
474                                b4_symbol_if([$1], [has_type], [std::move (v)]),
475                                b4_locations_if([std::move (l)]))[)
476 #else
477       symbol_type (]b4_join(
478           [int tok],
479           b4_symbol_if([$1], [has_type],
480                        [const b4_symbol([$1], [type])& v]),
481           b4_locations_if([const location_type& l]))[)
482         : super_type (]b4_join([token_kind_type (tok)],
483                                b4_symbol_if([$1], [has_type], [v]),
484                                b4_locations_if([l]))[)
485 #endif
486       {]b4_parse_assert_if([[
487 #if !defined _MSC_VER || defined __clang__
488         ]b4_assert[ (]b4_tok_in($@)[);
489 #endif
490       ]])[}
491 ]])])
492 
493 
494 # b4_basic_symbol_constructor_define(SYMBOL-NUM)
495 # ----------------------------------------------
496 # Generate a constructor for basic_symbol from given type.
497 m4_define([b4_basic_symbol_constructor_define],
498 [[#if 201103L <= YY_CPLUSPLUS
499       basic_symbol (]b4_join(
500           [typename Base::kind_type t],
501           b4_symbol_if([$1], [has_type], [b4_symbol([$1], [type])&& v]),
502           b4_locations_if([location_type&& l]))[)
503         : Base (t)]b4_symbol_if([$1], [has_type], [
504         , value (std::move (v))])[]b4_locations_if([
505         , location (std::move (l))])[
506       {}
507 #else
508       basic_symbol (]b4_join(
509           [typename Base::kind_type t],
510           b4_symbol_if([$1], [has_type], [const b4_symbol([$1], [type])& v]),
511           b4_locations_if([const location_type& l]))[)
512         : Base (t)]b4_symbol_if([$1], [has_type], [
513         , value (v)])[]b4_locations_if([
514         , location (l)])[
515       {}
516 #endif
517 ]])
518 
519 
520 # b4_token_constructor_define
521 # ---------------------------
522 # Define the overloaded versions of make_FOO for all the token kinds.
523 m4_define([b4_token_constructor_define],
524 [    // Implementation of make_symbol for each token kind.
525 b4_symbol_foreach([_b4_token_maker_define])])
526