La fonction boost::spirit::qi::parse()
s'attend à ce que deux itérateurs définissent la plage d'entrée. Cela fonctionne bien si j'essaye d'analyser std::string
ou std::istream
. Maintenant, je veux implémenter une interface plus générique pour mon analyseur. Une approche consistait à utiliser boost::any_range
pour définir l'entrée. Voici mon code de test qu'il compile mais lance une exception: "string iterator not dereferencable"
.Combine boost :: spirit et boost :: any_range?
Deuxième question. Comment puis-je combiner boost::any_range
avec boost::spirit::classic::position_iterator
pour détecter une position d'erreur possible?
#include <boost/range/any_range.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>
namespace qi = boost::spirit::qi;
typedef boost::any_range<
char,
boost::forward_traversal_tag,
char,
std::ptrdiff_t
> input_type;
template < typename _Iterator >
struct decode
: qi::grammar<_Iterator>
{
decode() : decode::base_type(m_rule)
{
m_rule = qi::int_;
BOOST_SPIRIT_DEBUG_NODES((m_rule))
}
qi::rule<_Iterator> m_rule;
};
bool parse(const input_type& in, int& out)
{
// We use a stream iterator to access the given stream:
typedef boost::spirit::multi_pass<
input_type::const_iterator
> stream_iterator;
// Create begin iterator for given stream:
stream_iterator sBegin = boost::spirit::make_default_multi_pass(input_type::const_iterator(in.begin()));
stream_iterator sEnd = boost::spirit::make_default_multi_pass(input_type::const_iterator());
// Create an instance of the used grammar:
decode<
stream_iterator
> gr;
// Try to decode the data stored within the stream according the grammar and store the result in the out variable:
bool r = boost::spirit::qi::parse(sBegin,
sEnd,
gr,
out);
return r && sBegin == sEnd;
}
void main()
{
std::string in = "12345"; int out;
parse(in, out);
}
Mise à jour
1.) Je suis d'accord qu'il ya une erreur dans la valeur par défaut construit sEnd
iterator. Par conséquent, j'ai simplifié mon exemple et je pense que j'ai mal compris comment utiliser l'itérateur multi_pass
. Dans ce cas c0
est false
(attendue) et c1
est true
(pas prévu). Alors, quelle est la bonne façon d'utiliser l'itérateur multi_pass
?
#include <boost/range/any_range.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>
namespace qi = boost::spirit::qi;
typedef boost::any_range<
char,
boost::forward_traversal_tag,
char,
std::ptrdiff_t
> input_type;
bool parse(const input_type& in, int& out)
{
//for(input_type::iterator i = in.begin(); i != in.end(); ++i)
//{
// std::cout << *i;
//}
// We use a stream iterator to access the given stream:
typedef boost::spirit::multi_pass<
input_type::const_iterator,
boost::spirit::iterator_policies::default_policy< // Defaults:
boost::spirit::iterator_policies::ref_counted, // OwnershipPolicy: ref_counted
boost::spirit::iterator_policies::buf_id_check, // CheckingPolicy : buf_id_check
boost::spirit::iterator_policies::buffering_input_iterator, // InputPolicy : buffering_input_iterator
boost::spirit::iterator_policies::split_std_deque // StoragePolicy : split_std_deque
>
> stream_iterator;
bool c0 = in.begin() == in.end();
// Create begin iterator for given stream:
stream_iterator sBegin(in.begin());
stream_iterator sEnd( in.end() );
bool c1 = sBegin == sEnd;
//for(stream_iterator i = sBegin; i != sEnd; ++i)
//{
// std::cout << *i;
//}
return false;
}
void main()
{
std::string in = "12345"; int out;
parse(in, out);
}
2.) Oui, je peux compiler une nouvelle instance de grammaire pour chaque type d'itérateur d'entrée. Mon idée était de cacher le détail de l'implémentation (= boost::spirit
) de l'utilisateur et de lui donner une interface générique. Par conséquent, je voudrais éviter une fonction de modèle.
3.) Oui j'ai oublié d'exposer l'attribut. Ce n'était qu'un exemple rapide. Merci pour l'indice.
Je vais ignorer "deuxième question". Une question à la fois. Les deux sont beaucoup compliqués par eux-mêmes. – sehe