[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 5/5] c++: shorten the assertions that check whether tokens are co
From: |
Akim Demaille |
Subject: |
[PATCH 5/5] c++: shorten the assertions that check whether tokens are correct |
Date: |
Wed, 11 Nov 2020 16:39:51 +0100 |
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.
---
NEWS | 4 +++
data/skeletons/variant.hh | 68 +++++++++++++++++++++++++++++++++++----
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($@)[);
]])[}
]])])
--
2.29.2
- [PATCH 0/5] maint: c++: fix several issues with assertions, Akim Demaille, 2020/11/11
- [PATCH 1/5] c++: style: use more regular m4 quoting patterns, Akim Demaille, 2020/11/11
- [PATCH 0/5] maint: c++: fix several issues with assertions, Akim Demaille, 2020/11/11
- [PATCH 2/5] c++: don't use YY_ASSERT at all if parse.assert is disabled, Akim Demaille, 2020/11/11
- [PATCH 3/5] lalr1.cc: YY_ASSERT should use api.prefix, Akim Demaille, 2020/11/11
- [PATCH 4/5] c++: don't glue functions together, Akim Demaille, 2020/11/11
- [PATCH 5/5] c++: shorten the assertions that check whether tokens are correct,
Akim Demaille <=