mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-21 10:13:03 +00:00
api.value.type: use keyword/brace values
Suggested by Joel E. Denny. http://lists.gnu.org/archive/html/bison-patches/2013-03/msg00016.html * data/bison.m4 (b4_percent_define_get_kind): New. (b4_variant_flag): Check that api.value.type is defined as the 'variant' keyword value. * data/c.m4 (_b4_value_type_setup_keyword): New. (b4_value_type_setup): Use it to simplify reading. Use b4_define_silent. Decode api.value.type, including its type. (b4_value_type_define): Likewise. * data/c++.m4 (b4_value_type_declare): Adjust the decoding of api.value.type, taking its kind into account. * doc/bison.texi: Adjust all the examples to the new syntax. * NEWS: Ditto. * tests/types.at: Adjust
This commit is contained in:
18
NEWS
18
NEWS
@@ -295,11 +295,11 @@ GNU Bison NEWS
|
|||||||
yylval.sval = "42"; return STRING;
|
yylval.sval = "42"; return STRING;
|
||||||
|
|
||||||
The %define variable api.value.type supports several special values. The
|
The %define variable api.value.type supports several special values. The
|
||||||
value "union" means that the user provides genuine types, not union member
|
keyword value 'union' means that the user provides genuine types, not
|
||||||
names such as "ival" and "sval" above (WARNING: will fail if
|
union member names such as "ival" and "sval" above (WARNING: will fail if
|
||||||
-y/--yacc/%yacc is enabled).
|
-y/--yacc/%yacc is enabled).
|
||||||
|
|
||||||
%define api.value.type "union"
|
%define api.value.type union
|
||||||
%token <int> INT "integer"
|
%token <int> INT "integer"
|
||||||
%token <char *> STRING "string"
|
%token <char *> STRING "string"
|
||||||
%printer { fprintf (yyo, "%d", $$); } <int>
|
%printer { fprintf (yyo, "%d", $$); } <int>
|
||||||
@@ -309,15 +309,15 @@ GNU Bison NEWS
|
|||||||
yylval.INT = 42; return INT;
|
yylval.INT = 42; return INT;
|
||||||
yylval.STRING = "42"; return STRING;
|
yylval.STRING = "42"; return STRING;
|
||||||
|
|
||||||
The value "variant" is somewhat equivalent, but for C++ special provision
|
The keyword value variant is somewhat equivalent, but for C++ special
|
||||||
is made to allow classes to be used (more about this below).
|
provision is made to allow classes to be used (more about this below).
|
||||||
|
|
||||||
%define api.value.type "variant"
|
%define api.value.type variant
|
||||||
%token <int> INT "integer"
|
%token <int> INT "integer"
|
||||||
%token <std::string> STRING "string"
|
%token <std::string> STRING "string"
|
||||||
|
|
||||||
Any other name is a user type to use. This is where YYSTYPE used to be
|
Values between braces denote user defined types. This is where YYSTYPE
|
||||||
used.
|
used to be used.
|
||||||
|
|
||||||
%code requires
|
%code requires
|
||||||
{
|
{
|
||||||
@@ -334,7 +334,7 @@ GNU Bison NEWS
|
|||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
%define api.value.type "struct my_value"
|
%define api.value.type {struct my_value}
|
||||||
%token <u.ival> INT "integer"
|
%token <u.ival> INT "integer"
|
||||||
%token <u.sval> STRING "string"
|
%token <u.sval> STRING "string"
|
||||||
%printer { fprintf (yyo, "%d", $$); } <u.ival>
|
%printer { fprintf (yyo, "%d", $$); } <u.ival>
|
||||||
|
|||||||
@@ -707,6 +707,20 @@ b4_loc[]dnl
|
|||||||
m4_popdef([b4_loc])],
|
m4_popdef([b4_loc])],
|
||||||
[b4_fatal([[$0: undefined %%define variable '%s']], [$1])])])
|
[b4_fatal([[$0: undefined %%define variable '%s']], [$1])])])
|
||||||
|
|
||||||
|
# b4_percent_define_get_kind(VARIABLE)
|
||||||
|
# ------------------------------------
|
||||||
|
# Get the kind (code, keyword, string) of VARIABLE, i.e., how its
|
||||||
|
# value was defined (braces, not delimiters, quotes).
|
||||||
|
#
|
||||||
|
# If the %define variable VARIABLE is undefined, complain fatally
|
||||||
|
# since that's a Bison or skeleton error. Don't record this as a
|
||||||
|
# Bison usage of VARIABLE as there's no reason to suspect that the
|
||||||
|
# user-supplied value has yet influenced the output.
|
||||||
|
m4_define([b4_percent_define_get_kind],
|
||||||
|
[m4_ifdef([b4_percent_define_kind(]$1[)],
|
||||||
|
[m4_indir([b4_percent_define_kind(]$1[)])],
|
||||||
|
[b4_fatal([[$0: undefined %%define variable '%s']], [$1])])])
|
||||||
|
|
||||||
# b4_percent_define_get_syncline(VARIABLE)
|
# b4_percent_define_get_syncline(VARIABLE)
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
# Mimic muscle_percent_define_get_syncline in ../src/muscle-tab.h exactly.
|
# Mimic muscle_percent_define_get_syncline in ../src/muscle-tab.h exactly.
|
||||||
@@ -923,9 +937,11 @@ b4_error_verbose_if([m4_define([b4_token_table_flag], [1])])
|
|||||||
# b4_variant_if([IF-VARIANT-ARE-USED], [IF-NOT])
|
# b4_variant_if([IF-VARIANT-ARE-USED], [IF-NOT])
|
||||||
# ----------------------------------------------
|
# ----------------------------------------------
|
||||||
b4_percent_define_if_define([variant])
|
b4_percent_define_if_define([variant])
|
||||||
m4_case(b4_percent_define_get([[api.value.type]]),
|
m4_define([b4_variant_flag], [[0]])
|
||||||
[variant], [m4_define([b4_variant_flag], [[1]])],
|
b4_percent_define_ifdef([[api.value.type]],
|
||||||
[m4_define([b4_variant_flag], [[0]])])
|
[m4_case(b4_percent_define_get_kind([[api.value.type]]), [keyword],
|
||||||
|
[m4_case(b4_percent_define_get([[api.value.type]]), [variant],
|
||||||
|
[m4_define([b4_variant_flag], [[1]])])])])
|
||||||
b4_define_flag_if([variant])
|
b4_define_flag_if([variant])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
14
data/c++.m4
14
data/c++.m4
@@ -120,14 +120,16 @@ m4_define([b4_token_enums],
|
|||||||
m4_define([b4_value_type_declare],
|
m4_define([b4_value_type_declare],
|
||||||
[b4_value_type_setup[]dnl
|
[b4_value_type_setup[]dnl
|
||||||
[ /// Symbol semantic values.
|
[ /// Symbol semantic values.
|
||||||
]m4_bmatch(b4_percent_define_get([api.value.type]),
|
]m4_bmatch(b4_percent_define_get_kind([[api.value.type]]),
|
||||||
[^%union\|union$],
|
[code],
|
||||||
|
[[ typedef ]b4_percent_define_get([[api.value.type]])[ semantic_type;]],
|
||||||
|
[m4_bmatch(b4_percent_define_get([[api.value.type]]),
|
||||||
|
[union\|union-directive],
|
||||||
[[ union semantic_type
|
[[ union semantic_type
|
||||||
{
|
{
|
||||||
]b4_user_union_members[
|
]b4_user_union_members[
|
||||||
};]],
|
};]])])dnl
|
||||||
[^$], [],
|
])
|
||||||
[[ typedef ]b4_percent_define_get([api.value.type])[ semantic_type;]])])
|
|
||||||
|
|
||||||
|
|
||||||
# b4_public_types_declare
|
# b4_public_types_declare
|
||||||
|
|||||||
65
data/c.m4
65
data/c.m4
@@ -563,25 +563,51 @@ m4_copy_force([b4_symbol_value_union], [b4_symbol_value])
|
|||||||
# Setup support for api.value.type=variant. By default, fail, specialized
|
# Setup support for api.value.type=variant. By default, fail, specialized
|
||||||
# by other skeletons.
|
# by other skeletons.
|
||||||
m4_define([b4_value_type_setup_variant],
|
m4_define([b4_value_type_setup_variant],
|
||||||
[b4_complain_at(b4_percent_define_get_loc([api.value.type]),
|
[b4_complain_at(b4_percent_define_get_loc([[api.value.type]]),
|
||||||
[['%s' does not support '%s']],
|
[['%s' does not support '%s']],
|
||||||
[b4_skeleton],
|
[b4_skeleton],
|
||||||
[%define api.value.type variant])])
|
[%define api.value.type variant])])
|
||||||
|
|
||||||
|
|
||||||
|
# _b4_value_type_setup_keyword
|
||||||
|
# ----------------------------
|
||||||
|
# api.value.type is defined with a keyword/string syntax. Check if
|
||||||
|
# that is properly defined, and prepare its use.
|
||||||
|
m4_define([_b4_value_type_setup_keyword],
|
||||||
|
[b4_percent_define_check_values([[[[api.value.type]],
|
||||||
|
[[none]],
|
||||||
|
[[union]],
|
||||||
|
[[union-directive]],
|
||||||
|
[[variant]],
|
||||||
|
[[yystype]]]])dnl
|
||||||
|
m4_case(b4_percent_define_get([[api.value.type]]),
|
||||||
|
[union], [b4_value_type_setup_union],
|
||||||
|
[variant], [b4_value_type_setup_variant])])
|
||||||
|
|
||||||
|
|
||||||
# b4_value_type_setup
|
# b4_value_type_setup
|
||||||
# -------------------
|
# -------------------
|
||||||
# Check if api.value.type is properly defined, and possibly prepare
|
# Check if api.value.type is properly defined, and possibly prepare
|
||||||
# its use.
|
# its use.
|
||||||
m4_define([b4_value_type_setup],
|
b4_define_silent([b4_value_type_setup],
|
||||||
[b4_percent_define_default([[api.value.type]],
|
[# Define default value.
|
||||||
[m4_ifdef([b4_union_members], [%union],
|
b4_percent_define_ifdef([[api.value.type]], [],
|
||||||
[m4_if(b4_tag_seen_flag, 0, [int],
|
[# %union => api.value.type=union-directive
|
||||||
[])])])dnl
|
m4_ifdef([b4_union_members],
|
||||||
m4_case(b4_percent_define_get([api.value.type]),
|
[m4_define([b4_percent_define_kind(api.value.type)], [keyword])
|
||||||
[union], [b4_value_type_setup_union],
|
m4_define([b4_percent_define(api.value.type)], [union-directive])],
|
||||||
[variant], [b4_value_type_setup_variant])])
|
[# no tag seen => api.value.type={int}
|
||||||
|
m4_if(b4_tag_seen_flag, 0,
|
||||||
|
[m4_define([b4_percent_define_kind(api.value.type)], [code])
|
||||||
|
m4_define([b4_percent_define(api.value.type)], [int])],
|
||||||
|
[# otherwise api.value.type=yystype
|
||||||
|
m4_define([b4_percent_define_kind(api.value.type)], [keyword])
|
||||||
|
m4_define([b4_percent_define(api.value.type)], [yystype])])])])
|
||||||
|
|
||||||
|
# Set up.
|
||||||
|
m4_bmatch(b4_percent_define_get_kind([[api.value.type]]),
|
||||||
|
[keyword\|string], [_b4_value_type_setup_keyword])
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
## -------------- ##
|
## -------------- ##
|
||||||
@@ -594,8 +620,16 @@ m4_case(b4_percent_define_get([api.value.type]),
|
|||||||
m4_define([b4_value_type_define],
|
m4_define([b4_value_type_define],
|
||||||
[b4_value_type_setup[]dnl
|
[b4_value_type_setup[]dnl
|
||||||
/* Value type. */
|
/* Value type. */
|
||||||
m4_bmatch(b4_percent_define_get([api.value.type]),
|
m4_bmatch(b4_percent_define_get_kind([[api.value.type]]),
|
||||||
[^%?union$],
|
[code],
|
||||||
|
[[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
|
||||||
|
typedef ]b4_percent_define_get([[api.value.type]])[ ]b4_api_PREFIX[STYPE;
|
||||||
|
# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
|
||||||
|
# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
|
||||||
|
#endif
|
||||||
|
]],
|
||||||
|
[m4_bmatch(b4_percent_define_get([[api.value.type]]),
|
||||||
|
[union\|union-directive],
|
||||||
[[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
|
[[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
|
||||||
typedef union ]b4_union_name[ ]b4_api_PREFIX[STYPE;
|
typedef union ]b4_union_name[ ]b4_api_PREFIX[STYPE;
|
||||||
union ]b4_union_name[
|
union ]b4_union_name[
|
||||||
@@ -605,14 +639,7 @@ union ]b4_union_name[
|
|||||||
# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
|
# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
|
||||||
# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
|
# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
|
||||||
#endif
|
#endif
|
||||||
]],
|
]])])])
|
||||||
[^$], [],
|
|
||||||
[[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
|
|
||||||
typedef ]b4_percent_define_get([api.value.type])[ ]b4_api_PREFIX[STYPE;
|
|
||||||
# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
|
|
||||||
# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
|
|
||||||
#endif
|
|
||||||
]])])
|
|
||||||
|
|
||||||
|
|
||||||
# b4_location_type_define
|
# b4_location_type_define
|
||||||
|
|||||||
@@ -1555,7 +1555,7 @@ calculator. As in C, comments are placed between @samp{/*@dots{}*/}.
|
|||||||
%@}
|
%@}
|
||||||
@end group
|
@end group
|
||||||
|
|
||||||
%define api.value.type double
|
%define api.value.type @{double@}
|
||||||
%token NUM
|
%token NUM
|
||||||
|
|
||||||
%% /* Grammar rules and actions follow. */
|
%% /* Grammar rules and actions follow. */
|
||||||
@@ -1582,9 +1582,9 @@ thus specifying the C data type for semantic values of both tokens and
|
|||||||
groupings (@pxref{Value Type, ,Data Types of Semantic Values}). The Bison
|
groupings (@pxref{Value Type, ,Data Types of Semantic Values}). The Bison
|
||||||
parser will use whatever type @code{api.value.type} is defined as; if you
|
parser will use whatever type @code{api.value.type} is defined as; if you
|
||||||
don't define it, @code{int} is the default. Because we specify
|
don't define it, @code{int} is the default. Because we specify
|
||||||
@code{double}, each token and each expression has an associated value, which
|
@samp{@{double@}}, each token and each expression has an associated value,
|
||||||
is a floating point number. C code can use @code{YYSTYPE} to refer to the
|
which is a floating point number. C code can use @code{YYSTYPE} to refer to
|
||||||
value @code{api.value.type}.
|
the value @code{api.value.type}.
|
||||||
|
|
||||||
Each terminal symbol that is not a single-character literal must be
|
Each terminal symbol that is not a single-character literal must be
|
||||||
declared. (Single-character literals normally don't need to be declared.)
|
declared. (Single-character literals normally don't need to be declared.)
|
||||||
@@ -1806,7 +1806,7 @@ The semantic value of the token (if it has one) is stored into the
|
|||||||
global variable @code{yylval}, which is where the Bison parser will look
|
global variable @code{yylval}, which is where the Bison parser will look
|
||||||
for it. (The C data type of @code{yylval} is @code{YYSTYPE}, whose value
|
for it. (The C data type of @code{yylval} is @code{YYSTYPE}, whose value
|
||||||
was defined at the beginning of the grammar via @samp{%define api.value.type
|
was defined at the beginning of the grammar via @samp{%define api.value.type
|
||||||
double}; @pxref{Rpcalc Declarations,,Declarations for @code{rpcalc}}.)
|
@{double@}}; @pxref{Rpcalc Declarations,,Declarations for @code{rpcalc}}.)
|
||||||
|
|
||||||
A token type code of zero is returned if the end-of-input is encountered.
|
A token type code of zero is returned if the end-of-input is encountered.
|
||||||
(Bison recognizes any nonpositive value as indicating end-of-input.)
|
(Bison recognizes any nonpositive value as indicating end-of-input.)
|
||||||
@@ -2004,7 +2004,7 @@ parentheses nested to arbitrary depth. Here is the Bison code for
|
|||||||
|
|
||||||
@group
|
@group
|
||||||
/* Bison declarations. */
|
/* Bison declarations. */
|
||||||
%define api.value.type double
|
%define api.value.type @{double@}
|
||||||
%token NUM
|
%token NUM
|
||||||
%left '-' '+'
|
%left '-' '+'
|
||||||
%left '*' '/'
|
%left '*' '/'
|
||||||
@@ -3670,14 +3670,14 @@ specify some other type, define the @code{%define} variable
|
|||||||
@code{api.value.type} like this:
|
@code{api.value.type} like this:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
%define api.value.type double
|
%define api.value.type @{double@}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
or
|
or
|
||||||
|
|
||||||
@example
|
@example
|
||||||
%define api.value.type "struct semantic_type"
|
%define api.value.type @{struct semantic_type@}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
The value of @code{api.value.type} should be a type name that does not
|
The value of @code{api.value.type} should be a type name that does not
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ AT_SETUP([[%union vs. %define api.value.type]])
|
|||||||
|
|
||||||
AT_DATA([[input.y]],
|
AT_DATA([[input.y]],
|
||||||
[[%union { int ival; }
|
[[%union { int ival; }
|
||||||
%define api.value.type "%union"
|
%define api.value.type union-directive
|
||||||
%%
|
%%
|
||||||
exp: %empty;
|
exp: %empty;
|
||||||
]])
|
]])
|
||||||
@@ -45,7 +45,7 @@ AT_SETUP([[%yacc vs. %define api.value.type union]])
|
|||||||
|
|
||||||
AT_DATA([[input.y]],
|
AT_DATA([[input.y]],
|
||||||
[[%yacc
|
[[%yacc
|
||||||
%define api.value.type "union"
|
%define api.value.type union
|
||||||
%%
|
%%
|
||||||
exp: %empty;
|
exp: %empty;
|
||||||
]])
|
]])
|
||||||
@@ -108,16 +108,25 @@ AT_CLEANUP
|
|||||||
m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]],
|
m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]],
|
||||||
[# A built-in type.
|
[# A built-in type.
|
||||||
AT_TEST([%skeleton "]b4_skel["
|
AT_TEST([%skeleton "]b4_skel["
|
||||||
%define api.value.type double],
|
%define api.value.type {double}],
|
||||||
[],
|
[],
|
||||||
['1' '2' { printf ("%2.1f\n", $1 + $2); }],
|
['1' '2' { printf ("%2.1f\n", $1 + $2); }],
|
||||||
["12"],
|
["12"],
|
||||||
[AT_VAL = (res - '0') / 10.0],
|
[AT_VAL = (res - '0') / 10.0],
|
||||||
[0.3])
|
[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.
|
# A user defined struct.
|
||||||
AT_TEST([%skeleton "]b4_skel["
|
AT_TEST([%skeleton "]b4_skel["
|
||||||
%define api.value.type "struct foo"],
|
%define api.value.type {struct foo}],
|
||||||
[%code requires { struct foo { float fval; int ival; }; }],
|
[%code requires { struct foo { float fval; int ival; }; }],
|
||||||
['1' '2'
|
['1' '2'
|
||||||
{ printf ("%d %2.1f\n", $1.ival + $2.ival, $1.fval + $2.fval); }],
|
{ printf ("%d %2.1f\n", $1.ival + $2.ival, $1.fval + $2.fval); }],
|
||||||
@@ -128,7 +137,7 @@ m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]],
|
|||||||
|
|
||||||
# A user defined struct that uses pointers.
|
# A user defined struct that uses pointers.
|
||||||
AT_TEST([%skeleton "]b4_skel["
|
AT_TEST([%skeleton "]b4_skel["
|
||||||
%define api.value.type "struct bar"],
|
%define api.value.type {struct bar}],
|
||||||
[%code requires
|
[%code requires
|
||||||
{
|
{
|
||||||
struct u
|
struct u
|
||||||
@@ -158,7 +167,7 @@ m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]],
|
|||||||
|
|
||||||
# A user defined union.
|
# A user defined union.
|
||||||
AT_TEST([%skeleton "]b4_skel["
|
AT_TEST([%skeleton "]b4_skel["
|
||||||
%define api.value.type "union foo"],
|
%define api.value.type {union foo}],
|
||||||
[%code requires { union foo { float fval; int ival; }; }],
|
[%code requires { union foo { float fval; int ival; }; }],
|
||||||
['1' '2' { printf ("%d %2.1f\n", $1.ival, $2.fval); }],
|
['1' '2' { printf ("%d %2.1f\n", $1.ival, $2.fval); }],
|
||||||
["12"],
|
["12"],
|
||||||
|
|||||||
Reference in New Issue
Block a user