bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 4/4] api.value.type: use keyword/brace values


From: Akim Demaille
Subject: [PATCH 4/4] api.value.type: use keyword/brace values
Date: Tue, 9 Apr 2013 17:27:46 +0200

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
---
 NEWS           | 18 ++++++++--------
 data/bison.m4  | 22 ++++++++++++++++---
 data/c++.m4    | 14 ++++++------
 data/c.m4      | 67 ++++++++++++++++++++++++++++++++++++++++------------------
 doc/bison.texi | 16 +++++++-------
 tests/types.at | 21 ++++++++++++------
 6 files changed, 106 insertions(+), 52 deletions(-)

diff --git a/NEWS b/NEWS
index 60a62e1..406521b 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> INT "integer"
     %token <char *> STRING "string"
     %printer { fprintf (yyo, "%d", $$); } <int>
@@ -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> INT "integer"
     %token <std::string> 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 <u.ival> INT "integer"
     %token <u.sval> STRING "string"
     %printer { fprintf (yyo, "%d", $$); } <u.ival>
diff --git a/data/bison.m4 b/data/bison.m4
index e536ceb..dc12ad2 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 9c12e5c..e2c20fb 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 eb469cd..edf9991 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 198403f..250e94d 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -1555,7 +1555,7 @@ calculator.  As in C, comments are placed between 
@samp{/address@hidden/}.
 address@hidden
 @end group
 
-%define api.value.type double
+%define api.value.type @address@hidden
 %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
address@hidden, 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}.
address@hidden@address@hidden, 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}}.)
address@hidden@}}; @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 @address@hidden
 %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 @address@hidden
 @end example
 
 @noindent
 or
 
 @example
-%define api.value.type "struct semantic_type"
+%define api.value.type @{struct address@hidden
 @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 acd0e1c..6275903 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"],
-- 
1.8.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]