2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-19 04:22:13 +00:00

Provide failover empty symbol table tries for use inside of skippers, since

nothing prevents using a symbol_parser in a skipper, and the previous commit
introduced nullptr skipper data tables in some cases.

Related to #245
This commit is contained in:
Zach Laine
2025-10-13 18:43:08 -05:00
parent 1f5303c756
commit d873d7ea80
2 changed files with 92 additions and 3 deletions

View File

@@ -330,7 +330,7 @@ the input they match unless otherwise stated in the table below.]
[[ _symbols_t_ ]
[ _symbols_ is an associative container of key, value pairs. Each key is a _std_str_ and each value has type `T`. In the Unicode parsing path, the strings are considered to be UTF-8 encoded; in the non-Unicode path, no encoding is assumed. _symbols_ matches the longest prefix `pre` of the input that is equal to one of the keys `k`. If the length `len` of `pre` is zero, and there is no zero-length key, it does not match the input. If `len` is positive, the generated attribute is the value associated with `k`.]
[ `T` ]
[ Unlike the other entries in this table, _symbols_ is a type, not an object. ]]
[ Unlike the other entries in this table, _symbols_ is a type, not an object. Inside of skippers, all _symbols_ will appear empty. ]]
[[ _quot_str_ ]
[ Matches `'"'`, followed by zero or more characters, followed by `'"'`. ]

View File

@@ -472,6 +472,37 @@ namespace boost { namespace parser {
nope_or_pointer_t<Where, true> where_{};
int no_case_depth_ = 0;
// These exist in order to provide an address, if requested, for
// either kind of symbol table struct. The nonstatic member
// pointers for these will be null if this context was created
// inside of detail::skip(), but nothing prevents the user from
// trying to use a symbol_parser anyway. So, we have these.
static std::optional<symbol_table_tries_t>
empty_symbol_table_tries_;
static std::optional<pending_symbol_table_operations_t>
empty_pending_symbol_table_operations_;
symbol_table_tries_t & get_symbol_table_tries() const
{
if (symbol_table_tries_)
return *symbol_table_tries_;
if (!empty_symbol_table_tries_)
empty_symbol_table_tries_ = symbol_table_tries_t();
return *empty_symbol_table_tries_;
}
pending_symbol_table_operations_t &
get_pending_symbol_table_operations() const
{
if (pending_symbol_table_operations_)
return *pending_symbol_table_operations_;
if (!empty_pending_symbol_table_operations_) {
empty_pending_symbol_table_operations_ =
pending_symbol_table_operations_t();
}
return *empty_pending_symbol_table_operations_;
}
template<typename T>
static auto nope_or_address(T & x)
{
@@ -648,6 +679,64 @@ namespace boost { namespace parser {
{}
};
template<
bool DoTrace,
bool UseCallbacks,
typename I,
typename S,
typename ErrorHandler,
typename GlobalState,
typename Callbacks,
typename Attr,
typename Val,
typename RuleTag,
typename RuleLocals,
typename RuleParams,
typename Where>
std::optional<symbol_table_tries_t> parse_context<
DoTrace,
UseCallbacks,
I,
S,
ErrorHandler,
GlobalState,
Callbacks,
Attr,
Val,
RuleTag,
RuleLocals,
RuleParams,
Where>::empty_symbol_table_tries_;
template<
bool DoTrace,
bool UseCallbacks,
typename I,
typename S,
typename ErrorHandler,
typename GlobalState,
typename Callbacks,
typename Attr,
typename Val,
typename RuleTag,
typename RuleLocals,
typename RuleParams,
typename Where>
std::optional<pending_symbol_table_operations_t> parse_context<
DoTrace,
UseCallbacks,
I,
S,
ErrorHandler,
GlobalState,
Callbacks,
Attr,
Val,
RuleTag,
RuleLocals,
RuleParams,
Where>::empty_pending_symbol_table_operations_;
template<
bool DoTrace,
bool UseCallbacks,
@@ -1734,7 +1823,7 @@ namespace boost { namespace parser {
using trie_t = text::trie_map<std::vector<char32_t>, T>;
using result_type = std::pair<trie_t &, bool>;
symbol_table_tries_t & symbol_table_tries =
*context.symbol_table_tries_;
context.get_symbol_table_tries();
auto & [any, has_case_folded] =
symbol_table_tries[(void *)&sym_parser.ref()];
@@ -1773,7 +1862,7 @@ namespace boost { namespace parser {
Context const & context, symbol_parser<T> const & sym_parser)
{
void const * ptr = static_cast<void const *>(&sym_parser);
auto & entry = (*context.pending_symbol_table_operations_)[ptr];
auto & entry = (context.get_pending_symbol_table_operations())[ptr];
std::vector<detail::symbol_table_operation<T>> * retval = nullptr;
if (entry.visit_) {
retval = std::any_cast<