如何定义从任何编码空间解析单个char的精灵x3解析器?

时间:2017-03-21 14:47:33

标签: c++ boost boost-spirit boost-spirit-qi boost-spirit-x3

如果我们忽略该属性,则此test::char_将完成工作。

namespace test {
    struct any_char: x3::char_parser<any_char> {
        static bool const has_attribute = false;
        template <typename Char, typename Context>
        bool test(Char ch_, Context const&) const {
            return true;
        }
    };

    auto const char_ = any_char{};
}

但是如果我们想要从test::char_获取属性呢?我不知道如何正确设置attribute_type,因为这个attribute_type应该是

typename std::iterator_traits<Iterator>::value_type

这在精神qi中不是问题,因为qi解析器有一个模板属性struct,我们可以从Iterator获取char类型。

编辑:感谢sehe回答此问题。自动属性传播适用于test::char_,但它仍然无法传播复合属性的正确属性,如+test::char_

Edit2:我想使用此test :: char_来替换x3中的各种char_encoding :: char_。例如,我有一个简单的解析器函数foo。输入字符串可以是ascii编码的字符串或宽字符编码的字符串。因此,我可以使用此test :: char_而不是x3 :: char_和x3 :: standard_wide :: char_,#IFDEF无处不在。

#ifdef NARROW_CHAR
    using _char = char;
    #define _STR(str) str
#else
    using _char = wchar_t;
    #define _STR(str) L ## str
#endif

bool foo(std::basic_string<_char> const& input, std::basic_string<_char>& attr) {
    return x3::parse(
        input.begin(),
        input.end(), 
        +(test::char_ - _STR('X')),
        attr);
}

Edit3:将attribute_type设置为void或x3 :: unused_type将使test :: char_传播正确的属性。

namespace test {
    struct any_char: x3::char_parser<any_char> {
        using attribute_type = void; // or x3::unused_type
        static bool const has_attribute = true;
        template <typename Char, typename Context>
        bool test(Char ch_, Context const&) const {
            return true;
        }
    };

    auto const char_ = any_char{};
}

Edit4:与此测试:: char_相比,来自sehe的http://coliru.stacked-crooked.com/a/0a487591fbaedef4可能是一个更好的主意。谢谢。

1 个答案:

答案 0 :(得分:4)

自动属性传播已经完成了它:

<强> Live On Coliru

#include <boost/spirit/home/x3.hpp>
#include <string>
#include <iostream>
#include <iostream>
using namespace std::string_literals;
namespace x3 = boost::spirit::x3;

namespace test {
    struct any_char: x3::char_parser<any_char> {
        static bool const has_attribute = false;
        template <typename Char, typename Context>
        bool test(Char /*ch_*/, Context const&) const {
            return true;
        }
    };

    auto const char_ = any_char{};
}

template <typename S>
void doTest(S const& s) {

    typename S::value_type ch;

    if (x3::parse(s.begin(), s.end(), test::char_, ch)) {
        std::wcout << L"Parsed: " << std::wcout.widen(ch) << std::endl;
    } else {
        std::wcout << L"Not parsed\n";
    }

}

int main() {
    doTest("Hello"s);
    doTest(L"World"s);
}

打印

Parsed: H
Parsed: W
相关问题