Boost Spirit X3如何使用u8_to_u32_iterator?

How to use u8_to_u32_iterator in Boost Spirit X3?

我正在使用 Boost Spirit X3 创建编程语言,但是当我尝试支持 Unicode 时,出现错误!
这是该程序的简化版本示例。

#define BOOST_SPIRIT_X3_UNICODE
#include <boost/spirit/home/x3.hpp>

namespace x3 = boost::spirit::x3;

struct sample : x3::symbols<unsigned> {
    sample()
    {
        add("48", 10);
    }
};

int main()
{
  const std::string s("");

  boost::u8_to_u32_iterator<std::string::const_iterator> first{cbegin(s)},
    last{cend(s)};

  x3::parse(first, last, sample{});
}

Live on wandbox

我该怎么办?

如您所见,char_encoding::unicode 在内部采用了 char32_t

因此,首先相应地更改 symbols

template <typename T>
using symbols = x3::symbols_parser<boost::spirit::char_encoding::unicode, T>;

struct sample : symbols<unsigned> {
    sample() { add(U"48", 10); }
};

现在代码无法调用 case_compare:

/home/sehe/custom/boost_1_78_0/boost/spirit/home/x3/string/detail/tst.hpp|74 col 33| error: no match for call to ‘(boost::spirit::x3::case_compare<boost::spirit::char_encoding::unicode>) (reference, char32_t&)’

如您所见,它需要一个 char32_t 引用,但是 u8_to_u32_iterator returns unsigned ints (std::uint32_t).

仅用于比较/完整性检查:https://godbolt.org/z/1zozxq96W

幸运的是,您可以指示 u8_to_u32_iterator 使用另一个 co-domain 类型:

Live On Compiler Explorer

#define BOOST_SPIRIT_X3_UNICODE
#include <boost/spirit/home/x3.hpp>
#include <iomanip>
#include <iostream>

namespace x3 = boost::spirit::x3;

template <typename T>
using symbols = x3::symbols_parser<boost::spirit::char_encoding::unicode, T>;

struct sample : symbols<unsigned> {
    sample() { add(U"48", 10)(U"", 11); }
};

int main() {
    auto test = [](auto const& s) {
        boost::u8_to_u32_iterator<decltype(cbegin(s)), char32_t> first{
            cbegin(s)},
            last{cend(s)};

        unsigned parsed_value;
        if (x3::parse(first, last, sample{}, parsed_value)) {
            std::cout << s << " -> " << parsed_value << "\n";
        } else {
            std::cout << s << " FAIL\n";
        }
    };

    for (std::string s : {"", "48", ""})
        test(s);
}

版画

 -> 11
48 -> 10
 FAIL