From: Akim Demaille Date: Fri, 5 Apr 2013 12:40:25 +0000 (+0200) Subject: api.value.type: use keyword/brace values X-Git-Tag: v2.7.90~38 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/435575cb5e28bfc20263413e837c24a95373b3d4?hp=--cc 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 --- 435575cb5e28bfc20263413e837c24a95373b3d4 diff --git a/NEWS b/NEWS index 60a62e1d..406521b9 100644 --- a/NEWS +++ b/NEWS @@ -295,11 +295,11 @@ GNU Bison NEWS yylval.sval = "42"; return STRING; The %define variable api.value.type supports several special values. The - value "union" means that the user provides genuine types, not union member - names such as "ival" and "sval" above (WARNING: will fail if + keyword value 'union' means that the user provides genuine types, not + union member names such as "ival" and "sval" above (WARNING: will fail if -y/--yacc/%yacc is enabled). - %define api.value.type "union" + %define api.value.type union %token INT "integer" %token STRING "string" %printer { fprintf (yyo, "%d", $$); } @@ -309,15 +309,15 @@ GNU Bison NEWS yylval.INT = 42; return INT; yylval.STRING = "42"; return STRING; - The value "variant" is somewhat equivalent, but for C++ special provision - is made to allow classes to be used (more about this below). + The keyword value variant is somewhat equivalent, but for C++ special + 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 "integer" %token STRING "string" - Any other name is a user type to use. This is where YYSTYPE used to be - used. + Values between braces denote user defined types. This is where YYSTYPE + used to be used. %code requires { @@ -334,7 +334,7 @@ GNU Bison NEWS } u; }; } - %define api.value.type "struct my_value" + %define api.value.type {struct my_value} %token INT "integer" %token STRING "string" %printer { fprintf (yyo, "%d", $$); } diff --git a/data/bison.m4 b/data/bison.m4 index e536ceb3..dc12ad2b 100644 --- a/data/bison.m4 +++ b/data/bison.m4 @@ -707,6 +707,20 @@ b4_loc[]dnl m4_popdef([b4_loc])], [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) # ---------------------------------------- # 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_percent_define_if_define([variant]) -m4_case(b4_percent_define_get([[api.value.type]]), - [variant], [m4_define([b4_variant_flag], [[1]])], - [m4_define([b4_variant_flag], [[0]])]) +m4_define([b4_variant_flag], [[0]]) +b4_percent_define_ifdef([[api.value.type]], + [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]) diff --git a/data/c++.m4 b/data/c++.m4 index 9c12e5cf..e2c20fbd 100644 --- a/data/c++.m4 +++ b/data/c++.m4 @@ -120,14 +120,16 @@ m4_define([b4_token_enums], m4_define([b4_value_type_declare], [b4_value_type_setup[]dnl [ /// Symbol semantic values. -]m4_bmatch(b4_percent_define_get([api.value.type]), -[^%union\|union$], +]m4_bmatch(b4_percent_define_get_kind([[api.value.type]]), +[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 { -]b4_user_union_members[ - };]], -[^$], [], -[[ typedef ]b4_percent_define_get([api.value.type])[ semantic_type;]])]) + ]b4_user_union_members[ + };]])])dnl +]) # b4_public_types_declare diff --git a/data/c.m4 b/data/c.m4 index eb469cdf..edf9991f 100644 --- a/data/c.m4 +++ b/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 # by other skeletons. 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']], [b4_skeleton], [%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 # ------------------- # Check if api.value.type is properly defined, and possibly prepare # its use. -m4_define([b4_value_type_setup], -[b4_percent_define_default([[api.value.type]], -[m4_ifdef([b4_union_members], [%union], - [m4_if(b4_tag_seen_flag, 0, [int], - [])])])dnl -m4_case(b4_percent_define_get([api.value.type]), - [union], [b4_value_type_setup_union], - [variant], [b4_value_type_setup_variant])]) - +b4_define_silent([b4_value_type_setup], +[# Define default value. +b4_percent_define_ifdef([[api.value.type]], [], +[# %union => api.value.type=union-directive +m4_ifdef([b4_union_members], +[m4_define([b4_percent_define_kind(api.value.type)], [keyword]) +m4_define([b4_percent_define(api.value.type)], [union-directive])], +[# 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,25 +620,26 @@ m4_case(b4_percent_define_get([api.value.type]), m4_define([b4_value_type_define], [b4_value_type_setup[]dnl /* Value type. */ -m4_bmatch(b4_percent_define_get([api.value.type]), -[^%?union$], +m4_bmatch(b4_percent_define_get_kind([[api.value.type]]), +[code], [[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED -typedef union ]b4_union_name[ ]b4_api_PREFIX[STYPE; -union ]b4_union_name[ -{ -]b4_user_union_members[ -}; +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 -typedef ]b4_percent_define_get([api.value.type])[ ]b4_api_PREFIX[STYPE; +typedef union ]b4_union_name[ ]b4_api_PREFIX[STYPE; +union ]b4_union_name[ +{ +]b4_user_union_members[ +}; # define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1 # define ]b4_api_PREFIX[STYPE_IS_DECLARED 1 #endif -]])]) +]])])]) # b4_location_type_define diff --git a/doc/bison.texi b/doc/bison.texi index 198403fe..250e94d8 100644 --- a/doc/bison.texi +++ b/doc/bison.texi @@ -1555,7 +1555,7 @@ calculator. As in C, comments are placed between @samp{/*@dots{}*/}. %@} @end group -%define api.value.type double +%define api.value.type @{double@} %token NUM %% /* 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 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 -@code{double}, each token and each expression has an associated value, which -is a floating point number. C code can use @code{YYSTYPE} to refer to the -value @code{api.value.type}. +@samp{@{double@}}, each token and each expression has an associated value, +which is a floating point number. C code can use @code{YYSTYPE} to refer to +the value @code{api.value.type}. Each terminal symbol that is not a single-character literal must be 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 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 -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. (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 /* Bison declarations. */ -%define api.value.type double +%define api.value.type @{double@} %token NUM %left '-' '+' %left '*' '/' @@ -3670,14 +3670,14 @@ specify some other type, define the @code{%define} variable @code{api.value.type} like this: @example -%define api.value.type double +%define api.value.type @{double@} @end example @noindent or @example -%define api.value.type "struct semantic_type" +%define api.value.type @{struct semantic_type@} @end example The value of @code{api.value.type} should be a type name that does not diff --git a/tests/types.at b/tests/types.at index acd0e1c4..6275903c 100644 --- a/tests/types.at +++ b/tests/types.at @@ -26,7 +26,7 @@ AT_SETUP([[%union vs. %define api.value.type]]) AT_DATA([[input.y]], [[%union { int ival; } -%define api.value.type "%union" +%define api.value.type union-directive %% exp: %empty; ]]) @@ -45,7 +45,7 @@ AT_SETUP([[%yacc vs. %define api.value.type union]]) AT_DATA([[input.y]], [[%yacc -%define api.value.type "union" +%define api.value.type union %% exp: %empty; ]]) @@ -108,16 +108,25 @@ AT_CLEANUP 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], + %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"], + %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); }], @@ -128,7 +137,7 @@ m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]], # A user defined struct that uses pointers. AT_TEST([%skeleton "]b4_skel[" - %define api.value.type "struct bar"], + %define api.value.type {struct bar}], [%code requires { struct u @@ -158,7 +167,7 @@ m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]], # A user defined union. 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; }; }], ['1' '2' { printf ("%d %2.1f\n", $1.ival, $2.fval); }], ["12"],