]>
Commit | Line | Data |
---|---|---|
6574576c AD |
1 | # Value type. -*- Autotest -*- |
2 | ||
3209eb1c | 3 | # Copyright (C) 2013-2015 Free Software Foundation, Inc. |
6574576c AD |
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 <http://www.gnu.org/licenses/>. | |
17 | ||
18 | AT_BANNER([[Value type tests.]]) | |
19 | ||
20 | ||
21 | ## ----------------------------------- ## | |
22 | ## %union vs. %define api.value.type. ## | |
23 | ## ----------------------------------- ## | |
24 | ||
25 | AT_SETUP([[%union vs. %define api.value.type]]) | |
26 | ||
27 | AT_DATA([[input.y]], | |
28 | [[%union { int ival; } | |
435575cb | 29 | %define api.value.type union-directive |
6574576c AD |
30 | %% |
31 | exp: %empty; | |
32 | ]]) | |
33 | ||
34 | AT_BISON_CHECK([[input.y]], [[1]], [[]], | |
35 | [[input.y:2.9-22: error: '%union' and '%define api.value.type' cannot be used together | |
36 | ]]) | |
37 | ||
38 | AT_CLEANUP | |
39 | ||
1fa19a76 AD |
40 | ## ---------------------------------------- ## |
41 | ## %yacc vs. %define api.value.type union. ## | |
42 | ## ---------------------------------------- ## | |
43 | ||
44 | AT_SETUP([[%yacc vs. %define api.value.type union]]) | |
45 | ||
46 | AT_DATA([[input.y]], | |
47 | [[%yacc | |
435575cb | 48 | %define api.value.type union |
1fa19a76 AD |
49 | %% |
50 | exp: %empty; | |
51 | ]]) | |
52 | ||
53 | AT_BISON_CHECK([[input.y]], [[1]], [[]], | |
54 | [[input.y:2.9-22: error: '%yacc' and '%define api.value.type "union"' cannot be used together | |
55 | ]]) | |
56 | ||
57 | AT_CLEANUP | |
58 | ||
59 | ||
6574576c AD |
60 | ## ---------------- ## |
61 | ## api.value.type. ## | |
62 | ## ---------------- ## | |
63 | ||
8d4dc896 AD |
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) | |
6574576c AD |
70 | # -------------------------------------- |
71 | # Compile the grammar and check the expected result. | |
72 | # BISON-DIRECTIVES are passed to AT_SETUP, contrary to MORE-BISON-DIRECTIVES. | |
8d4dc896 | 73 | m4_pushdef([_AT_TEST], |
6574576c AD |
74 | [ |
75 | AT_SETUP([$1]) | |
76 | AT_KEYWORDS([api.value.type]) | |
cb8d8bb9 | 77 | AT_BISON_OPTION_PUSHDEFS([%debug $1 $2]) |
6574576c AD |
78 | AT_DATA_GRAMMAR([test.y], |
79 | [[%debug | |
80 | ||
81 | %code | |
82 | { | |
83 | # include <stdio.h> | |
84 | # include <stdlib.h> | |
85 | ]AT_YYERROR_DECLARE[ | |
86 | ]AT_YYLEX_DECLARE[ | |
87 | } | |
88 | ||
89 | ]$1[ | |
90 | ]$2[ | |
91 | ||
92 | %% | |
93 | ||
94 | start: $3; | |
95 | ||
96 | %% | |
97 | ]AT_YYERROR_DEFINE[ | |
98 | ]AT_YYLEX_DEFINE([$4], [$5])[ | |
99 | ]AT_MAIN_DEFINE[ | |
100 | ]]) | |
101 | ||
102 | AT_FULL_COMPILE([[test]]) | |
103 | AT_PARSER_CHECK([./test], 0, [$6 | |
104 | ], [stderr]) | |
105 | AT_BISON_OPTION_POPDEFS | |
106 | AT_CLEANUP | |
107 | ]) | |
108 | ||
8d4dc896 AD |
109 | # AT_TEST($1: BISON-DIRECTIVES, |
110 | # $2: MORE-BISON-DIRECTIVES, | |
111 | # $3: PARSER-ACTION, | |
112 | # $4: INPUT, | |
113 | # $5: SCANNER-ACTION, | |
114 | # $6: RESULT) | |
115 | # -------------------------------------- | |
116 | # Check with and without %defines, to avoid regressions. It turns out | |
117 | # that in that case yacc.c calls the set-up of the %union twice, | |
118 | # because YYSTYPE is defined once in the header, and once in the | |
119 | # implementation file (eventually it'd be better to include the header | |
120 | # file, but that's another story). Unfortunately running these macros | |
121 | # a second time doubled the side-effects and resulted in a double | |
122 | # definition of the union members. | |
123 | m4_pushdef([AT_TEST], | |
124 | [_AT_TEST([$1], [$2], [$3], [$4], [$5], [$6]) | |
125 | _AT_TEST([$1 %defines], [$2], [$3], [$4], [$5], [$6]) | |
126 | ]) | |
127 | ||
6574576c AD |
128 | m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]], |
129 | [# A built-in type. | |
130 | AT_TEST([%skeleton "]b4_skel[" | |
435575cb | 131 | %define api.value.type {double}], |
6574576c AD |
132 | [], |
133 | ['1' '2' { printf ("%2.1f\n", $1 + $2); }], | |
134 | ["12"], | |
135 | [AT_VAL = (res - '0') / 10.0], | |
136 | [0.3]) | |
137 | ||
435575cb AD |
138 | # A typedef which looks like a Bison keyword, but it's using braces. |
139 | AT_TEST([%skeleton "]b4_skel[" | |
140 | %define api.value.type {variant}], | |
141 | [%code requires { typedef double variant; }], | |
142 | ['1' '2' { printf ("%2.1f\n", $1 + $2); }], | |
143 | ["12"], | |
144 | [AT_VAL = (res - '0') / 10.0], | |
145 | [0.3]) | |
146 | ||
6574576c AD |
147 | # A user defined struct. |
148 | AT_TEST([%skeleton "]b4_skel[" | |
435575cb | 149 | %define api.value.type {struct foo}], |
6574576c AD |
150 | [%code requires { struct foo { float fval; int ival; }; }], |
151 | ['1' '2' | |
152 | { printf ("%d %2.1f\n", $1.ival + $2.ival, $1.fval + $2.fval); }], | |
153 | ["12"], | |
154 | [AT_VAL.ival = (res - '0') * 10; | |
155 | AT_VAL.fval = (res - '0') / 10.f], | |
156 | [30 0.3]) | |
157 | ||
cb8d8bb9 AD |
158 | # A user defined struct that uses pointers. |
159 | AT_TEST([%skeleton "]b4_skel[" | |
435575cb | 160 | %define api.value.type {struct bar}], |
cb8d8bb9 AD |
161 | [%code requires |
162 | { | |
163 | struct u | |
164 | { | |
165 | int ival; | |
166 | }; | |
167 | struct bar | |
168 | { | |
169 | struct u *up; | |
170 | }; | |
171 | } | |
172 | %token <up->ival> '1' '2' | |
173 | %printer { ]AT_SKEL_CC_IF([[yyoutput << $$]], | |
174 | [[fprintf (yyo, "%d", $$)]])[; } <up->ival> | |
175 | ], | |
176 | ['1' '2' | |
177 | { | |
178 | printf ("%d %d\n", $1, $<up->ival>2); | |
179 | free ($<up>1); | |
180 | free ($<up>2); | |
181 | }], | |
182 | ["12"], | |
183 | [AT_VAL.up = (struct u *) malloc (sizeof *AT_VAL.up); | |
184 | assert (AT_VAL.up); | |
185 | AT_VAL.up->ival = res - '0';], | |
186 | [1 2]) | |
187 | ||
6574576c AD |
188 | # A user defined union. |
189 | AT_TEST([%skeleton "]b4_skel[" | |
435575cb | 190 | %define api.value.type {union foo}], |
6574576c AD |
191 | [%code requires { union foo { float fval; int ival; }; }], |
192 | ['1' '2' { printf ("%d %2.1f\n", $1.ival, $2.fval); }], | |
193 | ["12"], | |
194 | [if (res == '1') | |
195 | AT_VAL.ival = 10; | |
196 | else | |
197 | AT_VAL.fval = .2f], | |
198 | [10 0.2]) | |
199 | ||
827bc59c AD |
200 | # A %union and a named %union. In C++ named %union is an error. |
201 | m4_foreach([b4_union], | |
202 | [m4_bmatch(b4_skel, [\.cc$], | |
203 | [[%union]], | |
204 | [[%union], [%union foo], | |
205 | [%define api.value.union.name foo; %union]])], | |
206 | [AT_TEST([%skeleton "]b4_skel[" | |
207 | ]b4_union[ { float fval; int ival; };], | |
208 | [%token <ival> '1'; | |
209 | %token <fval> '2';], | |
210 | ['1' '2' { printf ("%d %2.1f\n", $1, $2); }], | |
211 | ["12"], | |
212 | [if (res == '1') | |
213 | AT_VAL.ival = 10; | |
214 | else | |
215 | AT_VAL.fval = 0.2f], | |
216 | [10 0.2])]) | |
6574576c AD |
217 | |
218 | # A Bison-defined union. | |
219 | # The tokens names are not available directly in C++, we use their | |
220 | # user number to keep it simple between C and C++. | |
221 | AT_TEST([%skeleton "]b4_skel[" | |
222 | %define api.value.type union], | |
223 | [%token <int> ONE 101; | |
224 | %token <float> TWO 102 THREE 103; | |
225 | %printer { ]AT_SKEL_CC_IF([[yyoutput << $$]], | |
226 | [[fprintf (yyo, "%d", $$)]])[; } <int> | |
227 | %printer { ]AT_SKEL_CC_IF([[yyoutput << $$]], | |
228 | [[fprintf (yyo, "%f", $$)]])[; } <float> | |
229 | ], | |
230 | [ONE TWO THREE { printf ("%d %2.1f %2.1f\n", $1, $2, $3); }], | |
231 | [{ 101, 102, 103, EOF }], | |
232 | [if (res == 101) | |
233 | AT_VAL.ONE = 10; | |
234 | else if (res == 102) | |
235 | AT_VAL.TWO = .2f; | |
236 | else if (res == 103) | |
237 | AT_VAL.THREE = 3.3f], | |
238 | [10 0.2 3.3]) | |
239 | ||
240 | # A Bison-defined variant, for lalr1.cc only. | |
241 | m4_if(b4_skel, [lalr1.cc], [ | |
242 | AT_TEST([%skeleton "]b4_skel[" | |
243 | %define api.value.type variant], | |
244 | [%token <int> '1'; | |
245 | %token <std::string> '2';], | |
246 | ['1' '2' { std::cout << $1 << ", " << $2 << std::endl; }], | |
247 | ["12"], | |
248 | [if (res == '1') | |
249 | AT_VAL.build(10); | |
250 | else | |
251 | AT_VAL.build<std::string>("two");], | |
252 | [10, two])]) | |
253 | ]) | |
254 | ||
255 | m4_popdef([AT_TEST]) | |
8d4dc896 | 256 | m4_popdef([_AT_TEST]) |
827bc59c AD |
257 | |
258 | ||
259 | ## ------------------- ## | |
260 | ## C++: Named %union. ## | |
261 | ## ------------------- ## | |
262 | ||
263 | m4_foreach([b4_skel], [[lalr1.cc], [glr.cc]], | |
264 | [AT_SETUP([b4_skel: Named %union]) | |
265 | AT_DATA([input.y], | |
266 | [%skeleton "]b4_skel[" | |
267 | %union foo { float fval; int ival; }; | |
268 | %% | |
269 | exp: %empty; | |
270 | ]) | |
271 | AT_BISON_CHECK([input.y], 1, [], | |
272 | [[input.y:2.8-10: error: named %union is invalid in C++ | |
273 | ]]) | |
274 | AT_CLEANUP | |
275 | ]) |