gnulib: update
[bison.git] / tests / types.at
blob02a7d6e3fa0d9b96353561c70567defa22f799ba
1 # Value type.                                     -*- Autotest -*-
3 # Copyright (C) 2013-2015, 2018-2021 Free Software Foundation, Inc.
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.
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.
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/>.
18 AT_BANNER([[Value type tests.]])
21 ## ----------------------------------- ##
22 ## %union vs. %define api.value.type.  ##
23 ## ----------------------------------- ##
25 AT_SETUP([[%union vs. %define api.value.type]])
27 AT_DATA([[input.y]],
28 [[%union { int ival; }
29 %define api.value.type union-directive
31 exp: %empty;
32 ]])
34 AT_BISON_CHECK([[input.y]], [[1]], [[]],
35 [[input.y:2.1-38: error: '%union' and '%define api.value.type' cannot be used together
36 ]])
38 AT_CLEANUP
40 ## ---------------------------------------- ##
41 ## %yacc vs. %define api.value.type union.  ##
42 ## ---------------------------------------- ##
44 AT_SETUP([[%yacc vs. %define api.value.type union]])
46 AT_DATA([[input.y]],
47 [[%yacc
48 %define api.value.type union
50 exp: %empty;
51 ]])
53 AT_BISON_CHECK([[input.y]], [[1]], [[]],
54 [[input.y:2.1-28: error: '%yacc' and '%define api.value.type "union"' cannot be used together
55 ]])
57 AT_CLEANUP
60 ## ---------------- ##
61 ## api.value.type.  ##
62 ## ---------------- ##
64 # _AT_TEST($1: BISON-DIRECTIVES,
65 #          $2: MORE-BISON-DIRECTIVES,
66 #          $3: PARSER-ACTION,
67 #          $4: INPUT,
68 #          $5: SCANNER-ACTION,
69 #          $6: RESULT,
70 #          $7: REQUIREMENT)
71 # --------------------------------------
72 # Compile the grammar and check the expected result.
73 # BISON-DIRECTIVES are passed to AT_SETUP, contrary to MORE-BISON-DIRECTIVES.
75 # Use REQUIREMENT e.g. skip the test if the compiler does not meet the
76 # requirements.
77 m4_pushdef([_AT_TEST],
79 AT_SETUP([$1])
80 AT_KEYWORDS([api.value.type])
82 AT_BISON_OPTION_PUSHDEFS([%debug $1 $2])
83 AT_DATA_GRAMMAR([test.y],
84 [[%debug
86 %code
88 # include <stdio.h>
89 # include <stdlib.h>
90 ]AT_YYERROR_DECLARE[
91 ]AT_YYLEX_DECLARE[
94 ]$1[
95 ]$2[
99 start: $3;
102 ]AT_YYERROR_DEFINE[
103 ]AT_YYLEX_DEFINE([$4], [$5])[
104 ]AT_MAIN_DEFINE[
107 AT_LANG_FOR_EACH_STD([
108   $7
109   AT_FULL_COMPILE([[test]])
110   AT_PARSER_CHECK([[test]], 0, [[$6
114 AT_BISON_OPTION_POPDEFS
115 AT_CLEANUP
118 # AT_TEST($1: BISON-DIRECTIVES,
119 #         $2: MORE-BISON-DIRECTIVES,
120 #         $3: PARSER-ACTION,
121 #         $4: INPUT,
122 #         $5: SCANNER-ACTION,
123 #         $6: RESULT,
124 #         $7: REQUIREMENT)
125 # --------------------------------------
126 # Check with and without %header, to avoid regressions.  It turns out
127 # that in that case yacc.c calls the set-up of the %union twice,
128 # because YYSTYPE is defined once in the header, and once in the
129 # implementation file (eventually it'd be better to include the header
130 # file, but that's another story).  Unfortunately running these macros
131 # a second time doubled the side-effects and resulted in a double
132 # definition of the union members.
133 m4_pushdef([AT_TEST],
134 [_AT_TEST([$1],         [$2], [$3], [$4], [$5], [$6], [$7])
135  _AT_TEST([$1 %header], [$2], [$3], [$4], [$5], [$6], [$7])
138 m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc], [glr2.cc]],
139  [# A built-in type.
140   AT_TEST([%skeleton "]b4_skel["
141            %define api.value.type {double}],
142           [],
143           ['1' '2' { printf ("%2.1f\n", $1 + $2); }],
144           ["12"],
145           [if (res)
146              AT_VAL = (res - '0') / 10.0],
147           [0.3])
149   # A typedef which looks like a Bison keyword, but it's using braces.
150   AT_TEST([%skeleton "]b4_skel["
151            %define api.value.type {variant}],
152           [%code requires { typedef double variant; }],
153           ['1' '2' { printf ("%2.1f\n", $1 + $2); }],
154           ["12"],
155           [if (res)
156              AT_VAL = (res - '0') / 10.0],
157           [0.3])
159   # A user defined struct.
160   AT_TEST([%skeleton "]b4_skel["
161            %define api.value.type {struct foo}],
162           [%code requires { struct foo { float fval; int ival; }; }],
163           ['1' '2'
164              { printf ("%d %2.1f\n", $1.ival + $2.ival, $1.fval + $2.fval); }],
165           ["12"],
166           [if (res)
167              {
168                AT_VAL.ival = (res - '0') * 10;
169                AT_VAL.fval = YY_CAST (float, res - '0') / 10.f;
170              }],
171           [30 0.3])
173   # A user defined struct that uses pointers.
174   AT_TEST([%skeleton "]b4_skel["
175            %define api.value.type {struct bar}],
176           [%code requires
177            {
178              struct u
179              {
180                int ival;
181              };
182              struct bar
183              {
184                struct u *up;
185              };
186            }
187            %token <up->ival> '1' '2'
188            %printer { ]AT_CXX_IF([[yyo << $$]],
189                                  [[fprintf (yyo, "%d", $$)]])[; } <up->ival>
190            ],
191           ['1' '2'
192            {
193              printf ("%d %d\n", $1, $<up->ival>2);
194              free ($<up>1);
195              free ($<up>2);
196            }],
197           ["12"],
198           [if (res)
199              {
200                AT_VAL.up = YY_CAST (struct u *, malloc (sizeof *AT_VAL.up));
201                assert (AT_VAL.up);
202                AT_VAL.up->ival = res - '0';
203              }
204           ],
205           [1 2])
207   # A user defined union.
208   AT_TEST([%skeleton "]b4_skel["
209            %define api.value.type {union foo}],
210           [%code requires { union foo { float fval; int ival; }; }],
211           ['1' '2' { printf ("%d %2.1f\n", $1.ival, $2.fval); }],
212           ["12"],
213           [if (res == '1')
214              AT_VAL.ival = 10;
215            else if (res == '2')
216              AT_VAL.fval = .2f],
217           [10 0.2])
219   # A %union and a named %union.  In C++ named %union is an error.
220   m4_foreach([b4_union],
221              [m4_bmatch(b4_skel, [\.cc$],
222                        [[%union]],
223                         [[%union], [%union foo],
224                          [%define api.value.union.name foo; %union]])],
225    [AT_TEST([%skeleton "]b4_skel["
226              ]b4_union[ { float fval; int ival; };],
227             [%token <ival> '1';
228              %token <fval> '2';],
229             ['1' '2' { printf ("%d %2.1f\n", $1, $2); }],
230             ["12"],
231             [if (res == '1')
232                AT_VAL.ival = 10;
233              else if (res == '2')
234                AT_VAL.fval = 0.2f],
235             [10 0.2])])
237   # A Bison-defined union.
238   # The token names are not available directly in C++, we use their
239   # codes to keep it simple between C and C++.
240   AT_TEST([%skeleton "]b4_skel["
241            %define api.value.type union],
242           [%token <int> ONE 101;
243            %token <float> TWO 102 THREE 103;
244            %printer { ]AT_CXX_IF([[yyo << $$]],
245                                  [[fprintf (yyo, "%d", $$)]])[; } <int>
246            %printer { ]AT_CXX_IF([[yyo << $$]],
247                                  [[fprintf (yyo, "%f", $$)]])[; } <float>
248           ],
249           [ONE TWO THREE { printf ("%d %2.1f %2.1f\n", $1, $2, $3); }],
250           [{ 101, 102, 103, EOF }],
251           [if (res == 101)
252              AT_VAL.ONE = 10;
253            else if (res == 102)
254              AT_VAL.TWO = .2f;
255            else if (res == 103)
256              AT_VAL.THREE = 3.3f],
257           [10 0.2 3.3])
259   # A Bison-defined variant, for lalr1.cc only.
260   m4_if(b4_skel, [lalr1.cc], [
261     AT_TEST([%skeleton "]b4_skel["
262              %define api.value.type variant],
263             [%token <int> '1';
264              %token <std::string> '2';],
265             ['1' '2' { std::cout << $1 << ", " << $2 << '\n'; }],
266             ["12"],
267             [if (res == '1')
268                AT_VAL.build (10);
269              else if (res == '2')
270                AT_VAL.build<std::string> ("two");],
271             [10, two])
273     # Test a regression where we passed user types (we can include
274     # commas) to a CPP macro.
275     AT_TEST([%skeleton "]b4_skel["
276              %define api.value.type variant],
277             [%token <std::pair<int, int>> '1';
278              %token <std::pair<std::string, std::string>> '2';],
279             ['1' '2'
280               {
281                 std::cout << $1.first << ':' << $1.second << ", "
282                           << $2.first << ':' << $2.second << '\n';
283               }],
284             ["12"],
285             [if (res == '1')
286                AT_VAL.build (std::make_pair (10, 11));
287              else if (res == '2')
288                AT_VAL.build (std::pair<std::string, std::string> ("two", "deux"));],
289             [10:11, two:deux])
291     # Type-based token constructors on move-only types, and types with commas.
292     AT_TEST([%skeleton "]b4_skel["
293              %define api.value.type variant
294              %define api.token.constructor],
295             [[%token <std::pair<int, int>> '1' '2';]],
296             ['1' '2'
297               {
298                 std::cout << $1.first << ':' << $1.second << ", "
299                           << $2.first << ':' << $2.second << '\n';
300               }],
301             ["12"],
302             [[typedef yy::parser::symbol_type symbol;
303              if (res)
304                return symbol (res, std::make_pair (res - '0', res - '0' + 1));
305              else
306                return symbol (res)]],
307             [1:2, 2:3])
309     # Move-only types, and variadic emplace.
310     AT_TEST([%skeleton "]b4_skel["
311              %code requires { #include <memory> }
312              %define api.value.type variant],
313             [[%token <std::unique_ptr<int>> '1';
314              %token <std::pair<int, int>> '2';]],
315             ['1' '2' { std::cout << *$1 << ", "
316                                  << $2.first << ':' << $2.second << '\n'; }],
317             ["12"],
318             [[if (res == '1')
319                ]AT_VAL[.emplace <std::unique_ptr<int>>
320                  (std::make_unique <int> (10));
321              else if (res == '2')
322                ]AT_VAL[.emplace <std::pair<int, int>> (21, 22);]],
323             [10, 21:22],
324             [AT_REQUIRE_CXX_STD(14, [echo "$at_std not supported"; continue])])
326     # Token constructors on move-only types, and types with commas.
327     AT_TEST([%skeleton "]b4_skel["
328              %code requires { #include <memory> }
329              %define api.value.type variant
330              %define api.token.constructor],
331             [[%token <std::unique_ptr<int>> ONE;
332              %token <std::pair<int, int>> TWO;
333              %token EOI 0;]],
334             [ONE TWO { std::cout << *$1 << ", "
335                                  << $2.first << ':' << $2.second << '\n'; }],
336             ["12"],
337             [[if (res == '1')
338                return yy::parser::make_ONE (std::make_unique<int> (10));
339              else if (res == '2')
340                return yy::parser::make_TWO (std::make_pair (21, 22));
341              else
342                return yy::parser::make_EOI ()]],
343             [10, 21:22],
344             [AT_REQUIRE_CXX_STD(14, [echo "$at_std not supported"; continue])])
346     # Type-based token constructors on move-only types, and types with commas.
347     AT_TEST([%skeleton "]b4_skel["
348              %code requires { #include <memory> }
349              %define api.value.type variant
350              %define api.token.constructor],
351             [[%token <std::unique_ptr<int>> '1';
352              %token <std::pair<int, int>> '2';]],
353             ['1' '2' { std::cout << *$1 << ", "
354                                  << $2.first << ':' << $2.second << '\n'; }],
355             ["12"],
356             [[if (res == '1')
357                return {res, std::make_unique<int> (10)};
358              else if (res == '2')
359                return {res, std::make_pair (21, 22)};
360              else
361                return res]],
362             [10, 21:22],
363             [AT_REQUIRE_CXX_STD(14, [echo "$at_std not supported"; continue])])
365   ])
368 m4_popdef([AT_TEST])
369 m4_popdef([_AT_TEST])
372 ## ------------------- ##
373 ## C++: Named %union.  ##
374 ## ------------------- ##
376 m4_foreach([b4_skel], [[lalr1.cc], [glr.cc]],
377 [AT_SETUP([b4_skel: Named %union])
378 AT_DATA([input.y],
379 [%skeleton "]b4_skel["
380 %union foo { float fval; int ival; };
382 exp: %empty;
384 AT_BISON_CHECK([input.y], 1, [],
385 [[input.y:2.8-10: error: named %union is invalid in C++
387 AT_CLEANUP