Boost C++ - Searching Spirit symbol table

前端 未结 1 877
天命终不由人
天命终不由人 2021-01-27 00:59

In Boost Spirit if I have a symbol table

struct Foo : boost::spirit::qi::symbols
{
    Foo(const std::string& name = std::str         


        
相关标签:
1条回答
  • 2021-01-27 01:25

    Well, it appears you would like to have a transformation from a qi::symbols parser to a karma::symbols generator.

    I'd say such a thing does not exist. And since you have likely looked for it, I think it is safe to assume it doesn't.

    I can see how it would be useful, so you might consider contributing it to Spirit Repository.

    I've spent some time here writing a simple mapper that converts from qi::symbols to karma::symbols:

    template <typename Char, typename T, typename Lookup, typename Filter>
        karma::symbols<T, std::basic_string<Char> > 
        inverse(qi::symbols<Char,T,Lookup,Filter> const& parser)
    {
        karma::symbols<T, std::basic_string<Char> > generator;
    
        parser.for_each([&generator](std::basic_string<Char> const& symbol, T v) 
            { 
                generator.add(v, symbol); 
            });
    
        return generator;
    }
    

    EDIT In C++03 style:

    template <typename Char, typename T, typename Lookup, typename Filter>
        karma::symbols<T, std::basic_string<Char> > 
        inverse(qi::symbols<Char,T,Lookup,Filter> const& parser)
    {
        struct _adder { 
            karma::symbols<T, std::basic_string<Char> > result;
    
            void operator()(std::basic_string<Char> const& symbol, T v) { 
                result.add(v, symbol); 
            }
        } adder;
    
        parser.for_each(adder);
        return adder.result;
    }
    

    Note This does not yet handle potentially repeatedly mapped values in the parse symbol table.

    Here is a simple example program that shows that it works: http://liveworkspace.org/code/3uzQKi

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/karma.hpp>
    
    namespace qi     = boost::spirit::qi;
    namespace karma  = boost::spirit::karma;
    
    template <typename ItType>
    struct parser : public qi::grammar<ItType, int()>
    {
        parser() : parser::base_type(start)
        {
            _sym.add("aap", 1)("noot", 2)("mies", 3);
            start = _sym;
        }
      // private:
        qi::symbols<char, int> _sym;
        qi::rule<ItType, int()> start;
    };
    
    template <typename ItType>
    struct generator : public karma::grammar<ItType, int()>
    {
        template<typename Sym>
        generator(Sym&& sym) : generator::base_type(start)
        {
            // _sym.add(1, "aap")(2, "noot")(3, "mies");
            _sym = std::move(sym);
            start = _sym;
        }
      private:
        karma::symbols<int, std::string> _sym;
        karma::rule<ItType, int()> start;
    };
    
    template <typename Char, typename T, typename Lookup, typename Filter>
        karma::symbols<T, std::basic_string<Char> > 
        inverse(qi::symbols<Char,T,Lookup,Filter> const& parser)
    {
        karma::symbols<T, std::basic_string<Char> > generator;
    
        parser.for_each([&generator](std::basic_string<Char> const& symbol, T v) 
            { 
                generator.add(v, symbol); 
            });
    
        return generator;
    }
    
    void testcase(std::string const& str)
    {
        typedef std::string::const_iterator It;
    
        It begin = str.cbegin();
        It end   = str.cend();
    
        static const parser<It> p;
    
        int out;
        bool ok = qi::parse(begin, end, p, out);
        std::cout << std::boolalpha << ok << '\n';
        std::cout << "remains: '" << std::string(begin, end) << "'\n";
        if (ok)
        {
            std::cout << "parsed value: " << out << "\n";
            static const generator<boost::spirit::ostream_iterator> g(inverse(p._sym));
            std::cout << "generator: " << karma::format(g, out) << "\n";
        }
    
    }
    
    int main()
    {
        const auto v = std::vector<std::string>{ "aap", "noot", "mies" };
        for (auto it=v.begin(); it!=v.end(); ++it)
            testcase(*it);
    }
    

    Output:

    true
    remains: ''
    parsed value: 1
    generator: aap
    true
    remains: ''
    parsed value: 2
    generator: noot
    true
    remains: ''
    parsed value: 3
    generator: mies
    
    0 讨论(0)
提交回复
热议问题