Closed goblin-rulez closed 2 years ago
I found two reasons why annotate fails.
x3/support/utility/annotate_on_success.hpp
struct annotate_on_success
{
template <typename Iterator, typename Context, typename... Types>
inline void on_success(Iterator const& first, Iterator const& last
, variant<Types...>& ast, Context const& context)
{
ast.apply_visitor(x3::make_lambda_visitor<void>([&](auto& node)
{
this->on_success(first, last, node, context);
}));
}
template <typename T, typename Iterator, typename Context>
inline void on_success(Iterator const& first, Iterator const& last
, T& ast, Context const& context)
{
auto& error_handler = x3::get<error_handler_tag>(context).get();
error_handler.tag(ast, first, last);
}
};
x3/support/ast/position_tagged.hpp
// This will catch all nodes except those inheriting from position_tagged
template <typename AST>
void annotate(AST& /* ast */, iterator_type /* first */, iterator_type /* last */, mpl::false_)
{
// (no-op) no need for tags
}
// This will catch all nodes inheriting from position_tagged
void annotate(position_tagged& ast, iterator_type first, iterator_type last, mpl::true_)
{
ast.id_first = int(positions.size());
positions.push_back(first);
ast.id_last = int(positions.size());
positions.push_back(last);
}
template <typename AST>
void annotate(AST& ast, iterator_type first, iterator_type last)
{
annotate(ast, first, last, is_base_of<position_tagged, AST>());
}
I modified the annotate_on_success as follows, and it seems the issue is fixed.
#include <boost/spirit/home/x3/support/traits/is_variant.hpp>
struct annotate_on_success
{
template <typename Iterator, typename Context, typename... Types>
inline void on_success(Iterator const& first, Iterator const& last
, variant<Types...>& ast, Context const& context)
{
ast.apply_visitor(x3::make_lambda_visitor<void>([&](auto& node)
{
this->on_success(first, last, node, context);
}));
}
template <typename T, typename Iterator, typename Context>
inline void on_success(Iterator const& first, Iterator const& last
, forward_ast<T>& ast, Context const& context)
{
this->on_success(first, last, ast.get(), context);
}
template <typename T, typename Iterator, typename Context>
inline typename disable_if<traits::is_variant<T>>::type on_success(Iterator const& first, Iterator const& last
, T& ast, Context const& context)
{
auto& error_handler = x3::get<error_handler_tag>(context).get();
error_handler.tag(ast, first, last);
}
};
Now, the sample output looks like this.
-------------------------
Parsing succeeded
expression found. pos_ids{-1, -1}
In line 1:
expression found. pos_ids{14, 15}
(a * (-b))
~~~~~~~~~~ <<-- Here
In line 1:
variable "a" found. pos_ids{2, 3}
(a * (-b))
~ <<-- Here
operation "*" found. pos_ids{-1, -1}
In line 1:
expression found. pos_ids{10, 11}
(a * (-b))
~~~~ <<-- Here
In line 1:
unary "-" found. pos_ids{6, 7}
(a * (-b))
~~ <<-- Here
-------------------------
annotate_on_success(x3/support/utility/annotate_on_success.hpp) doesn't annotate when the type of ast is either
struct operand : x3::variant<...>;
orhere is the sample that reproduce the issue. This is basically simplified version of calc example. I added pos_printer that tries to print annotated information for parsed ast elements.
And this is the output. No position is annotated.