1

If we ignore the attribute, this test::char_ will do the work.

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{};
}

But what if we want to get the attribute from test::char_? I don't know how to set attribute_type correctly because this attribute_type should be

typename std::iterator_traits<Iterator>::value_type

This is not a problem in spirit qi because qi parser has a template attribute struct where we can get the char type from Iterator.

Edit: Thank sehe for answering this. Automatic attribute propagation works for test::char_, but it still cannot propagate correct attribute for compound attribute say +test::char_.

Edit2: I would like to use this test::char_ to replace various char_encoding::char_ in x3. For example I have a simple parser function foo. The input string could be ascii encoded string or wide char encoded string. Therefore I can use this test::char_ instead of x3::char_ and x3::standard_wide::char_ with a #IFDEF everywhere.

#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: Setting attribute_type to void or x3::unused_type will make the test::char_ propagate correct attribute.

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: Probably http://coliru.stacked-crooked.com/a/0a487591fbaedef4 from sehe is a better idea compared to this test::char_. Thanks.

wanghan02
  • 1,227
  • 7
  • 14
  • To edit 2: I see no reason to implement anything at all, just alias/reference what you need: http://coliru.stacked-crooked.com/a/0a487591fbaedef4. I would probably prefer just defining the `spirit_encoding` in the single #ifdef: http://coliru.stacked-crooked.com/a/0a487591fbaedef4. That said, I'd always advise against making schizophrenic codebases like this these days. Just commit to UTF8 or UTF16 internally, and do conversions only when required for I/O – sehe Mar 22 '17 at 10:29

1 Answers1

4

Automatic attribute propagation already takes care of it:

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

Prints

Parsed: H
Parsed: W
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks! But it still doesn't work for compound attribute generation say +test::char_. – wanghan02 Mar 21 '17 at 15:15
  • On closer look it looks like you are using `any_char` wrong (it's not a CRTP base-class). What are you trying to achieve? – sehe Mar 21 '17 at 17:22
  • 1
    PS. If you're "just" trying to propagate the input sequence, look at http://coliru.stacked-crooked.com/a/e73403995f064529 (`Attr&` becomes the _actual_ attribute type). – sehe Mar 21 '17 at 17:38
  • I'm trying to use test::char_ as the replacement of all char_encoding::char_ to make the parser work for different input format. – wanghan02 Mar 21 '17 at 19:22
  • "different"? Different from what? What is a format? Do you mean different... grammars? Can you just show an example of what you like to do, and why it doesn't work. – sehe Mar 21 '17 at 22:01
  • I have updated why I want this test::char_ in Edit2. Thanks. x3::char_parser is indeed a CRTP base class in x3/char/char_parser.hpp. The reason why I prefer to derive from x3::char_parser is that I want to modify less code and just provide a test method like other parser implemented in x3. – wanghan02 Mar 22 '17 at 08:17