【问题标题】:How to define a spirit x3 parser that parses a single char from any encoding spaces?如何定义一个从任何编码空间解析单个字符的精神 x3 解析器?
【发布时间】:2017-03-21 14:47:32
【问题描述】:

如果我们忽略这个属性,这个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 解析器有一个模板属性结构,我们可以从 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: 与这个 test::char_ 相比,sehe 的 http://coliru.stacked-crooked.com/a/0a487591fbaedef4 可能是一个更好的主意。谢谢。

【问题讨论】:

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


【解决方案1】:

自动属性传播已经处理好了:

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

【讨论】:

  • 谢谢!但它仍然不适用于复合属性生成,比如 +test::char_。
  • 仔细观察,您似乎使用了 any_char 错误(它不是 CRTP 基类)。你想达到什么目的?
  • 附言。如果您“只是”尝试传播输入序列,请查看 coliru.stacked-crooked.com/a/e73403995f064529Attr&amp; 成为 actual 属性类型)。
  • 我正在尝试使用 test::char_ 作为所有 char_encoding::char_ 的替换,以使解析器适用于不同的输入格式。
  • “不同”?有什么不同?什么是格式?你的意思是不同的...语法?你能举个例子说明你喜欢做什么,以及为什么它不起作用。
猜你喜欢
  • 2016-11-26
  • 1970-01-01
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
  • 2011-05-01
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
相关资源
最近更新 更多