c++ - 我如何将 boost::spirit X3 与 QString 结合使用?

标签 c++ qt boost boost-spirit qstring

Boost 有一个名为 Spirit 的库,它大量使用 TMP 以便于在类似 BNF 的语法中轻松创建解析器。默认情况下,它旨在与标准库字符串一起使用。我在基于 Qt 的项目中使用它,其中 QString 是主要的字符串类型。如何将 boost::spiritQString 一起使用?

最佳答案

boost::spiritQString 的协作有两个部分;获取数据和获取数据。我们将从后者开始。就boost::spirit而言,QString是未知类型。我们必须给它一些容器特征,以便它知道如何交互:

#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();
    }
};

}}}}

根据您的特定用例,您可能还想从 QString 中解析。可能有一种方法可以教 boost::spirit 关于 QChar(QString 的可迭代类型),但我没有耐心为了那个原因。另一种方法是创建一个 iterator_adaptor,其值类型为 char16_t。虽然 uint32_tboost::spirit 用来表示 unicode 值的类型,但它不能明确地转换为 QCharchar16_t 可以。 QString 在 UTF16 基础上运行,所以这个类型足够宽。请注意,您需要打开 unicode 支持 (#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, char16_t, boost::forward_traversal_tag, char16_t>
{
public:
    using boost::iterator_adaptor<
        QStringSpiritUnicodeIteratorAdaptor<QStringIterator>,
        QStringIterator, char16_t, boost::forward_traversal_tag,
        char16_t>::iterator_adaptor;

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

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

用法如下:

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

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

关于c++ - 我如何将 boost::spirit X3 与 QString 结合使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57461106/

相关文章:

c++ - 交换两个 boost::adjacency_list 图,类似于 std::swap

c++ - 无法使用 boost::iostreams::file 打开文件

c++ - CMAKE指定不同的源目录

c++ - Boost-python 如何将 C++ 类实例传递给 Python 类

c++ - 递归的概念

c++ - 当设置 ItemIsMovable 标志时,子项在 QGraphicsView 中不可移动

c++ - QT-Creator : How to align center my QWidgets when in full screen?

c++ - OpenCV-C++ VideoCapture 无法打开视频文件

c++ - -D 选项从 g++ 命令行被错误地扩展

c++ qt未定义对`_imp的引用