mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
Reported by Rich Wilson. * data/c.m4 (b4_symbol_type_register): Append to b4_union_members, not b4_user_union_members. The latter invokes the former, but it is the former which is reinitialized to empty by b4_value_type_setup_union. * tests/types.at: Check it. This reveals another bug, this time in the case of glr.c parsers. * data/glr.c: Generate the header file before the implementation file, to be sure that the setup is run before what depends on it.
252 lines
7.2 KiB
Plaintext
252 lines
7.2 KiB
Plaintext
# Value type. -*- Autotest -*-
|
|
|
|
# Copyright (C) 2013-2014 Free Software Foundation, Inc.
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
AT_BANNER([[Value type tests.]])
|
|
|
|
|
|
## ----------------------------------- ##
|
|
## %union vs. %define api.value.type. ##
|
|
## ----------------------------------- ##
|
|
|
|
AT_SETUP([[%union vs. %define api.value.type]])
|
|
|
|
AT_DATA([[input.y]],
|
|
[[%union { int ival; }
|
|
%define api.value.type union-directive
|
|
%%
|
|
exp: %empty;
|
|
]])
|
|
|
|
AT_BISON_CHECK([[input.y]], [[1]], [[]],
|
|
[[input.y:2.9-22: error: '%union' and '%define api.value.type' cannot be used together
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## ---------------------------------------- ##
|
|
## %yacc vs. %define api.value.type union. ##
|
|
## ---------------------------------------- ##
|
|
|
|
AT_SETUP([[%yacc vs. %define api.value.type union]])
|
|
|
|
AT_DATA([[input.y]],
|
|
[[%yacc
|
|
%define api.value.type union
|
|
%%
|
|
exp: %empty;
|
|
]])
|
|
|
|
AT_BISON_CHECK([[input.y]], [[1]], [[]],
|
|
[[input.y:2.9-22: error: '%yacc' and '%define api.value.type "union"' cannot be used together
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------------- ##
|
|
## api.value.type. ##
|
|
## ---------------- ##
|
|
|
|
# _AT_TEST($1: BISON-DIRECTIVES,
|
|
# $2: MORE-BISON-DIRECTIVES,
|
|
# $3: PARSER-ACTION,
|
|
# $4: INPUT,
|
|
# $5: SCANNER-ACTION,
|
|
# $6: RESULT)
|
|
# --------------------------------------
|
|
# Compile the grammar and check the expected result.
|
|
# BISON-DIRECTIVES are passed to AT_SETUP, contrary to MORE-BISON-DIRECTIVES.
|
|
m4_pushdef([_AT_TEST],
|
|
[
|
|
AT_SETUP([$1])
|
|
AT_KEYWORDS([api.value.type])
|
|
AT_BISON_OPTION_PUSHDEFS([%debug $1 $2])
|
|
AT_DATA_GRAMMAR([test.y],
|
|
[[%debug
|
|
|
|
%code
|
|
{
|
|
# include <stdio.h>
|
|
# include <stdlib.h>
|
|
]AT_YYERROR_DECLARE[
|
|
]AT_YYLEX_DECLARE[
|
|
}
|
|
|
|
]$1[
|
|
]$2[
|
|
|
|
%%
|
|
|
|
start: $3;
|
|
|
|
%%
|
|
]AT_YYERROR_DEFINE[
|
|
]AT_YYLEX_DEFINE([$4], [$5])[
|
|
]AT_MAIN_DEFINE[
|
|
]])
|
|
|
|
AT_FULL_COMPILE([[test]])
|
|
AT_PARSER_CHECK([./test], 0, [$6
|
|
], [stderr])
|
|
AT_BISON_OPTION_POPDEFS
|
|
AT_CLEANUP
|
|
])
|
|
|
|
# AT_TEST($1: BISON-DIRECTIVES,
|
|
# $2: MORE-BISON-DIRECTIVES,
|
|
# $3: PARSER-ACTION,
|
|
# $4: INPUT,
|
|
# $5: SCANNER-ACTION,
|
|
# $6: RESULT)
|
|
# --------------------------------------
|
|
# Check with and without %defines, to avoid regressions. It turns out
|
|
# that in that case yacc.c calls the set-up of the %union twice,
|
|
# because YYSTYPE is defined once in the header, and once in the
|
|
# implementation file (eventually it'd be better to include the header
|
|
# file, but that's another story). Unfortunately running these macros
|
|
# a second time doubled the side-effects and resulted in a double
|
|
# definition of the union members.
|
|
m4_pushdef([AT_TEST],
|
|
[_AT_TEST([$1], [$2], [$3], [$4], [$5], [$6])
|
|
_AT_TEST([$1 %defines], [$2], [$3], [$4], [$5], [$6])
|
|
])
|
|
|
|
m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]],
|
|
[# A built-in type.
|
|
AT_TEST([%skeleton "]b4_skel["
|
|
%define api.value.type {double}],
|
|
[],
|
|
['1' '2' { printf ("%2.1f\n", $1 + $2); }],
|
|
["12"],
|
|
[AT_VAL = (res - '0') / 10.0],
|
|
[0.3])
|
|
|
|
# A typedef which looks like a Bison keyword, but it's using braces.
|
|
AT_TEST([%skeleton "]b4_skel["
|
|
%define api.value.type {variant}],
|
|
[%code requires { typedef double variant; }],
|
|
['1' '2' { printf ("%2.1f\n", $1 + $2); }],
|
|
["12"],
|
|
[AT_VAL = (res - '0') / 10.0],
|
|
[0.3])
|
|
|
|
# A user defined struct.
|
|
AT_TEST([%skeleton "]b4_skel["
|
|
%define api.value.type {struct foo}],
|
|
[%code requires { struct foo { float fval; int ival; }; }],
|
|
['1' '2'
|
|
{ printf ("%d %2.1f\n", $1.ival + $2.ival, $1.fval + $2.fval); }],
|
|
["12"],
|
|
[AT_VAL.ival = (res - '0') * 10;
|
|
AT_VAL.fval = (res - '0') / 10.f],
|
|
[30 0.3])
|
|
|
|
# A user defined struct that uses pointers.
|
|
AT_TEST([%skeleton "]b4_skel["
|
|
%define api.value.type {struct bar}],
|
|
[%code requires
|
|
{
|
|
struct u
|
|
{
|
|
int ival;
|
|
};
|
|
struct bar
|
|
{
|
|
struct u *up;
|
|
};
|
|
}
|
|
%token <up->ival> '1' '2'
|
|
%printer { ]AT_SKEL_CC_IF([[yyoutput << $$]],
|
|
[[fprintf (yyo, "%d", $$)]])[; } <up->ival>
|
|
],
|
|
['1' '2'
|
|
{
|
|
printf ("%d %d\n", $1, $<up->ival>2);
|
|
free ($<up>1);
|
|
free ($<up>2);
|
|
}],
|
|
["12"],
|
|
[AT_VAL.up = (struct u *) malloc (sizeof *AT_VAL.up);
|
|
assert (AT_VAL.up);
|
|
AT_VAL.up->ival = res - '0';],
|
|
[1 2])
|
|
|
|
# A user defined union.
|
|
AT_TEST([%skeleton "]b4_skel["
|
|
%define api.value.type {union foo}],
|
|
[%code requires { union foo { float fval; int ival; }; }],
|
|
['1' '2' { printf ("%d %2.1f\n", $1.ival, $2.fval); }],
|
|
["12"],
|
|
[if (res == '1')
|
|
AT_VAL.ival = 10;
|
|
else
|
|
AT_VAL.fval = .2f],
|
|
[10 0.2])
|
|
|
|
# A %union.
|
|
AT_TEST([%skeleton "]b4_skel["
|
|
%union { float fval; int ival; };],
|
|
[%token <ival> '1';
|
|
%token <fval> '2';],
|
|
['1' '2' { printf ("%d %2.1f\n", $1, $2); }],
|
|
["12"],
|
|
[if (res == '1')
|
|
AT_VAL.ival = 10;
|
|
else
|
|
AT_VAL.fval = 0.2f],
|
|
[10 0.2])
|
|
|
|
# A Bison-defined union.
|
|
# The tokens names are not available directly in C++, we use their
|
|
# user number to keep it simple between C and C++.
|
|
AT_TEST([%skeleton "]b4_skel["
|
|
%define api.value.type union],
|
|
[%token <int> ONE 101;
|
|
%token <float> TWO 102 THREE 103;
|
|
%printer { ]AT_SKEL_CC_IF([[yyoutput << $$]],
|
|
[[fprintf (yyo, "%d", $$)]])[; } <int>
|
|
%printer { ]AT_SKEL_CC_IF([[yyoutput << $$]],
|
|
[[fprintf (yyo, "%f", $$)]])[; } <float>
|
|
],
|
|
[ONE TWO THREE { printf ("%d %2.1f %2.1f\n", $1, $2, $3); }],
|
|
[{ 101, 102, 103, EOF }],
|
|
[if (res == 101)
|
|
AT_VAL.ONE = 10;
|
|
else if (res == 102)
|
|
AT_VAL.TWO = .2f;
|
|
else if (res == 103)
|
|
AT_VAL.THREE = 3.3f],
|
|
[10 0.2 3.3])
|
|
|
|
# A Bison-defined variant, for lalr1.cc only.
|
|
m4_if(b4_skel, [lalr1.cc], [
|
|
AT_TEST([%skeleton "]b4_skel["
|
|
%define api.value.type variant],
|
|
[%token <int> '1';
|
|
%token <std::string> '2';],
|
|
['1' '2' { std::cout << $1 << ", " << $2 << std::endl; }],
|
|
["12"],
|
|
[if (res == '1')
|
|
AT_VAL.build(10);
|
|
else
|
|
AT_VAL.build<std::string>("two");],
|
|
[10, two])])
|
|
])
|
|
|
|
m4_popdef([AT_TEST])
|
|
m4_popdef([_AT_TEST])
|