news: update
[bison.git] / tests / types.at
blobdcdf3feb879e9505e465b2fd05a5448ece48bd33
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   AT_GLR2_CC_IF([AT_REQUIRE_CXX_STD(11, [echo "$at_std not supported"; continue])])
109   $7
110   AT_FULL_COMPILE([[test]])
111   AT_PARSER_CHECK([[test]], 0, [[$6
115 AT_BISON_OPTION_POPDEFS
116 AT_CLEANUP
119 # AT_TEST($1: BISON-DIRECTIVES,
120 #         $2: MORE-BISON-DIRECTIVES,
121 #         $3: PARSER-ACTION,
122 #         $4: INPUT,
123 #         $5: SCANNER-ACTION,
124 #         $6: RESULT,
125 #         $7: REQUIREMENT)
126 # --------------------------------------
127 # Check with and without %header, to avoid regressions.  It turns out
128 # that in that case yacc.c calls the set-up of the %union twice,
129 # because YYSTYPE is defined once in the header, and once in the
130 # implementation file (eventually it'd be better to include the header
131 # file, but that's another story).  Unfortunately running these macros
132 # a second time doubled the side-effects and resulted in a double
133 # definition of the union members.
134 m4_pushdef([AT_TEST],
135 [_AT_TEST([$1],         [$2], [$3], [$4], [$5], [$6], [$7])
136  _AT_TEST([$1 %header], [$2], [$3], [$4], [$5], [$6], [$7])
139 m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc], [glr2.cc]],
140  [# A built-in type.
141   AT_TEST([%skeleton "]b4_skel["
142            %define api.value.type {double}],
143           [],
144           ['1' '2' { printf ("%2.1f\n", $1 + $2); }],
145           ["12"],
146           [if (res)
147              AT_VAL = (res - '0') / 10.0],
148           [0.3])
150   # A typedef which looks like a Bison keyword, but it's using braces.
151   AT_TEST([%skeleton "]b4_skel["
152            %define api.value.type {variant}],
153           [%code requires { typedef double variant; }],
154           ['1' '2' { printf ("%2.1f\n", $1 + $2); }],
155           ["12"],
156           [if (res)
157              AT_VAL = (res - '0') / 10.0],
158           [0.3])
160   # A user defined struct.
161   AT_TEST([%skeleton "]b4_skel["
162            %define api.value.type {struct foo}],
163           [%code requires { struct foo { float fval; int ival; }; }],
164           ['1' '2'
165              { printf ("%d %2.1f\n", $1.ival + $2.ival, $1.fval + $2.fval); }],
166           ["12"],
167           [if (res)
168              {
169                AT_VAL.ival = (res - '0') * 10;
170                AT_VAL.fval = YY_CAST (float, res - '0') / 10.f;
171              }],
172           [30 0.3])
174   # A user defined struct that uses pointers.
175   AT_TEST([%skeleton "]b4_skel["
176            %define api.value.type {struct bar}],
177           [%code requires
178            {
179              struct u
180              {
181                int ival;
182              };
183              struct bar
184              {
185                struct u *up;
186              };
187            }
188            %token <up->ival> '1' '2'
189            %printer { ]AT_CXX_IF([[yyo << $$]],
190                                  [[fprintf (yyo, "%d", $$)]])[; } <up->ival>
191            ],
192           ['1' '2'
193            {
194              printf ("%d %d\n", $1, $<up->ival>2);
195              free ($<up>1);
196              free ($<up>2);
197            }],
198           ["12"],
199           [if (res)
200              {
201                AT_VAL.up = YY_CAST (struct u *, malloc (sizeof *AT_VAL.up));
202                assert (AT_VAL.up);
203                AT_VAL.up->ival = res - '0';
204              }
205           ],
206           [1 2])
208   # A user defined union.
209   AT_TEST([%skeleton "]b4_skel["
210            %define api.value.type {union foo}],
211           [%code requires { union foo { float fval; int ival; }; }],
212           ['1' '2' { printf ("%d %2.1f\n", $1.ival, $2.fval); }],
213           ["12"],
214           [if (res == '1')
215              AT_VAL.ival = 10;
216            else if (res == '2')
217              AT_VAL.fval = .2f],
218           [10 0.2])
220   # A %union and a named %union.  In C++ named %union is an error.
221   m4_foreach([b4_union],
222              [m4_bmatch(b4_skel, [\.cc$],
223                        [[%union]],
224                         [[%union], [%union foo],
225                          [%define api.value.union.name foo; %union]])],
226    [AT_TEST([%skeleton "]b4_skel["
227              ]b4_union[ { float fval; int ival; };],
228             [%token <ival> '1';
229              %token <fval> '2';],
230             ['1' '2' { printf ("%d %2.1f\n", $1, $2); }],
231             ["12"],
232             [if (res == '1')
233                AT_VAL.ival = 10;
234              else if (res == '2')
235                AT_VAL.fval = 0.2f],
236             [10 0.2])])
238   # A Bison-defined union.
239   # The token names are not available directly in C++, we use their
240   # codes to keep it simple between C and C++.
241   AT_TEST([%skeleton "]b4_skel["
242            %define api.value.type union],
243           [%token <int> ONE 101;
244            %token <float> TWO 102 THREE 103;
245            %printer { ]AT_CXX_IF([[yyo << $$]],
246                                  [[fprintf (yyo, "%d", $$)]])[; } <int>
247            %printer { ]AT_CXX_IF([[yyo << $$]],
248                                  [[fprintf (yyo, "%f", $$)]])[; } <float>
249           ],
250           [ONE TWO THREE { printf ("%d %2.1f %2.1f\n", $1, $2, $3); }],
251           [{ 101, 102, 103, EOF }],
252           [if (res == 101)
253              AT_VAL.ONE = 10;
254            else if (res == 102)
255              AT_VAL.TWO = .2f;
256            else if (res == 103)
257              AT_VAL.THREE = 3.3f],
258           [10 0.2 3.3])
260   # A Bison-defined variant, for lalr1.cc only.
261   m4_if(b4_skel, [lalr1.cc], [
262     AT_TEST([%skeleton "]b4_skel["
263              %define api.value.type variant],
264             [%token <int> '1';
265              %token <std::string> '2';],
266             ['1' '2' { std::cout << $1 << ", " << $2 << '\n'; }],
267             ["12"],
268             [if (res == '1')
269                AT_VAL.build (10);
270              else if (res == '2')
271                AT_VAL.build<std::string> ("two");],
272             [10, two])
274     # Test a regression where we passed user types (we can include
275     # commas) to a CPP macro.
276     AT_TEST([%skeleton "]b4_skel["
277              %define api.value.type variant],
278             [%token <std::pair<int, int>> '1';
279              %token <std::pair<std::string, std::string>> '2';],
280             ['1' '2'
281               {
282                 std::cout << $1.first << ':' << $1.second << ", "
283                           << $2.first << ':' << $2.second << '\n';
284               }],
285             ["12"],
286             [if (res == '1')
287                AT_VAL.build (std::make_pair (10, 11));
288              else if (res == '2')
289                AT_VAL.build (std::pair<std::string, std::string> ("two", "deux"));],
290             [10:11, two:deux])
292     # Type-based token constructors on move-only types, and types with commas.
293     AT_TEST([%skeleton "]b4_skel["
294              %define api.value.type variant
295              %define api.token.constructor],
296             [[%token <std::pair<int, int>> '1' '2';]],
297             ['1' '2'
298               {
299                 std::cout << $1.first << ':' << $1.second << ", "
300                           << $2.first << ':' << $2.second << '\n';
301               }],
302             ["12"],
303             [[typedef yy::parser::symbol_type symbol;
304              if (res)
305                return symbol (res, std::make_pair (res - '0', res - '0' + 1));
306              else
307                return symbol (res)]],
308             [1:2, 2:3])
310     # Move-only types, and variadic emplace.
311     AT_TEST([%skeleton "]b4_skel["
312              %code requires { #include <memory> }
313              %define api.value.type variant],
314             [[%token <std::unique_ptr<int>> '1';
315              %token <std::pair<int, int>> '2';]],
316             ['1' '2' { std::cout << *$1 << ", "
317                                  << $2.first << ':' << $2.second << '\n'; }],
318             ["12"],
319             [[if (res == '1')
320                ]AT_VAL[.emplace <std::unique_ptr<int>>
321                  (std::make_unique <int> (10));
322              else if (res == '2')
323                ]AT_VAL[.emplace <std::pair<int, int>> (21, 22);]],
324             [10, 21:22],
325             [AT_REQUIRE_CXX_STD(14, [echo "$at_std not supported"; continue])])
327     # Token constructors on move-only types, and types with commas.
328     AT_TEST([%skeleton "]b4_skel["
329              %code requires { #include <memory> }
330              %define api.value.type variant
331              %define api.token.constructor],
332             [[%token <std::unique_ptr<int>> ONE;
333              %token <std::pair<int, int>> TWO;
334              %token EOI 0;]],
335             [ONE TWO { std::cout << *$1 << ", "
336                                  << $2.first << ':' << $2.second << '\n'; }],
337             ["12"],
338             [[if (res == '1')
339                return yy::parser::make_ONE (std::make_unique<int> (10));
340              else if (res == '2')
341                return yy::parser::make_TWO (std::make_pair (21, 22));
342              else
343                return yy::parser::make_EOI ()]],
344             [10, 21:22],
345             [AT_REQUIRE_CXX_STD(14, [echo "$at_std not supported"; continue])])
347     # Type-based token constructors on move-only types, and types with commas.
348     AT_TEST([%skeleton "]b4_skel["
349              %code requires { #include <memory> }
350              %define api.value.type variant
351              %define api.token.constructor],
352             [[%token <std::unique_ptr<int>> '1';
353              %token <std::pair<int, int>> '2';]],
354             ['1' '2' { std::cout << *$1 << ", "
355                                  << $2.first << ':' << $2.second << '\n'; }],
356             ["12"],
357             [[if (res == '1')
358                return {res, std::make_unique<int> (10)};
359              else if (res == '2')
360                return {res, std::make_pair (21, 22)};
361              else
362                return res]],
363             [10, 21:22],
364             [AT_REQUIRE_CXX_STD(14, [echo "$at_std not supported"; continue])])
366   ])
369 m4_popdef([AT_TEST])
370 m4_popdef([_AT_TEST])
373 ## ------------------- ##
374 ## C++: Named %union.  ##
375 ## ------------------- ##
377 m4_foreach([b4_skel], [[lalr1.cc], [glr.cc]],
378 [AT_SETUP([b4_skel: Named %union])
379 AT_DATA([input.y],
380 [%skeleton "]b4_skel["
381 %union foo { float fval; int ival; };
383 exp: %empty;
385 AT_BISON_CHECK([input.y], 1, [],
386 [[input.y:2.8-10: error: named %union is invalid in C++
388 AT_CLEANUP