summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkim Demaille <akim.demaille@gmail.com>2020-11-11 13:29:47 +0100
committerAkim Demaille <akim.demaille@gmail.com>2020-11-13 06:17:52 +0100
commitd8cc6b073e2802d871a16dc62418a7eb62ed2216 (patch)
tree328311ed5f70335bbb707908fc761c3f860f7101
parent0264b4bca071cfac10a8909f30e0e5aa422b35d6 (diff)
downloadbison-d8cc6b073e2802d871a16dc62418a7eb62ed2216.tar.gz
c++: shorten the assertions that check whether tokens are correct
Before: YY_ASSERT (tok == token::YYEOF || tok == token::YYerror || tok == token::YYUNDEF || tok == 120 || tok == 49 || tok == 50 || tok == 51 || tok == 52 || tok == 53 || tok == 54 || tok == 55 || tok == 56 || tok == 57 || tok == 97 || tok == 98); After: YY_ASSERT (tok == token::YYEOF || (token::YYerror <= tok && tok <= token::YYUNDEF) || tok == 120 || (49 <= tok && tok <= 57) || (97 <= tok && tok <= 98)); Clauses are now also wrapped on several lines. This is nicer to read and diff, but also avoids pushing Visual C++ to its arbitrary limits (640K and lines of 16380 bytes ought to be enough for anybody, otherwise make an C2026 error). The useless parens are there for the dummy warnings about precedence (in the future, will we also have to put parens in `1+2*3`?). * data/skeletons/variant.hh (_b4_filter_tokens, b4_tok_in, b4_tok_in): New. (_b4_token_constructor_define): Use them.
-rw-r--r--NEWS4
-rw-r--r--data/skeletons/variant.hh68
2 files changed, 66 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index 8bdad6a6..27076634 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,10 @@ GNU Bison NEWS
The private internal macro YY_ASSERT now obeys the `api.prefix` %define
variable.
+ When there is a very large number of tokens, some assertions could be long
+ enough to hit arbitrary limits in Visual C++. They have been rewritten to
+ work around this limitation.
+
** Changes
The YYBISON macro in generated "regular C parsers" (from the "yacc.c"
diff --git a/data/skeletons/variant.hh b/data/skeletons/variant.hh
index 4734079b..2887ba61 100644
--- a/data/skeletons/variant.hh
+++ b/data/skeletons/variant.hh
@@ -395,11 +395,67 @@ m4_define([_b4_token_maker_define],
])])
-m4_define([_b4_type_clause],
-[b4_symbol_if([$1], [is_token],
- [b4_symbol_if([$1], [has_id],
- [tok == token::b4_symbol([$1], [id])],
- [tok == b4_symbol([$1], [code])])])])
+# b4_token_kind(SYMBOL-NUM)
+# -------------------------
+# Some tokens don't have an ID.
+m4_define([b4_token_kind],
+[b4_symbol_if([$1], [has_id],
+ [token::b4_symbol([$1], [id])],
+ [b4_symbol([$1], [code])])])
+
+
+# _b4_tok_in(SYMBOL-NUM, ...)
+# ---------------------------
+# See b4_tok_in below. The SYMBOL-NUMs... are tokens only.
+#
+# We iterate over the tokens to group them by "range" of token numbers (not
+# symbols numbers!).
+#
+# b4_fst is the start of that range.
+# b4_prev is the previous value.
+# b4_val is the current value.
+# If b4_val is the successor of b4_prev in token numbers, update the latter,
+# otherwise emit the code for range b4_fst .. b4_prev.
+# $1 is also used as a terminator in the foreach, but it will not be printed.
+#
+m4_define([_b4_tok_in],
+[m4_pushdef([b4_prev], [$1])dnl
+m4_pushdef([b4_fst], [$1])dnl
+m4_pushdef([b4_sep], [])dnl
+m4_foreach([b4_val], m4_dquote(m4_shift($@, $1)),
+ [m4_if(b4_symbol(b4_val, [code]), m4_eval(b4_symbol(b4_prev, [code]) + 1), [],
+ [b4_sep[]m4_if(b4_fst, b4_prev,
+ [tok == b4_token_kind(b4_fst)],
+ [(b4_token_kind(b4_fst) <= tok && tok <= b4_token_kind(b4_prev))])[]dnl
+m4_define([b4_fst], b4_val)dnl
+m4_define([b4_sep], [
+ || ])])dnl
+m4_define([b4_prev], b4_val)])dnl
+m4_popdef([b4_sep])dnl
+m4_popdef([b4_fst])dnl
+m4_popdef([b4_prev])dnl
+])
+
+
+# _b4_filter_tokens(SYMBOL-NUM, ...)
+# ----------------------------------
+# Expand as the list of tokens amongst SYMBOL-NUM.
+m4_define([_b4_filter_tokens],
+[m4_pushdef([b4_sep])dnl
+m4_foreach([b4_val], [$@],
+ [b4_symbol_if(b4_val, [is_token], [b4_sep[]b4_val[]m4_define([b4_sep], [,])])])dnl
+m4_popdef([b4_sep])dnl
+])
+
+
+# b4_tok_in(SYMBOL-NUM, ...)
+# ---------------------------
+# A C++ conditional that checks that `tok` is a member of this list of symbol
+# numbers.
+m4_define([b4_tok_in],
+ [_$0(_b4_filter_tokens($@))])
+
+
# _b4_token_constructor_define(SYMBOL-NUM...)
@@ -428,7 +484,7 @@ m4_define([_b4_token_constructor_define],
b4_locations_if([l]))[)
#endif
{]b4_parse_assert_if([[
- ]b4_assert[ (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[);
+ ]b4_assert[ (]b4_tok_in($@)[);
]])[}
]])])