简体   繁体   中英

How can I use boost::spirit X3 in conjunction with QString?

Boost has a library named Spirit that makes heavy use of TMP in order to facilitate the easy creation of parsers in a BNF like syntax. By default it is intended to work with standard library strings. I'm using it in a Qt based project, where QString is the primary string type. How can I use boost::spirit with QString s?

There are two parts to making boost::spirit and QString cooperate; getting data in and getting data out. We'll start with the latter. As far as boost::spirit is concerned, QString is an unknown type. We must give it a few container traits so that it knows how to interact:

#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
#include <QString>

namespace boost { namespace spirit { namespace x3 { namespace traits {

template<>
struct push_back_container<QString>
{
    template<typename T>
    static bool call(QString& c, T&& val)
    {
        c.push_back(std::move(val));
        return true;
    }
};

template<>
struct append_container<QString>
{
    template<typename Iterator>
    static bool call(QString& c, Iterator first, Iterator last)
    {
        c.append(first, std::distance(first, last));
        return true;
    }
};

template<>
struct is_empty_container<QString>
{
    static bool call(QString const& c)
    {
        return c.isEmpty();
    }
};

}}}}

Depending on your particular use case, you may also want to parse from QString s. There is probably a way to teach boost::spirit about QChar (the iterable type of QString ), but I don't have the patience for that. The alternative is to create an iterator_adaptor whose value type is uint32_t , which is the type boost::spirit uses to represent unicode values. Note you'll need to turn unicode support on ( #define BOOST_SPIRIT_X3_UNICODE ).

#include <boost/iterator/iterator_adaptor.hpp>
#include <QString>

template<typename QStringIterator>
class QStringSpiritUnicodeIteratorAdaptor : public boost::iterator_adaptor<
    QStringSpiritUnicodeIteratorAdaptor<QStringIterator>,
    QStringIterator, uint32_t, boost::forward_traversal_tag, uint32_t>
{
public:
    using boost::iterator_adaptor<
        QStringSpiritUnicodeIteratorAdaptor<QStringIterator>,
        QStringIterator, uint32_t, boost::forward_traversal_tag,
        uint32_t>::iterator_adaptor;

private:
    friend class boost::iterator_core_access;
    uint32_t dereference() const
    {
        return static_cast<uint32_t>(this->base_reference()->unicode());
    }
};

using QStringSpiritUnicodeIterator =
    QStringSpiritUnicodeIteratorAdaptor<QString::iterator>;
using QStringSpiritUnicodeConstIterator =
    QStringSpiritUnicodeIteratorAdaptor<QString::const_iterator>;

This is used as follows:

QString text = "blah blah blah";
QStringSpiritUnicodeIterator begin(text.begin());    
QStringSpiritUnicodeIterator end(text.end());

...::x3::phrase_parse(begin, end, ...);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM