c++ - Boost C++ - 搜索 spirit 符号表

标签 c++ boost boost-spirit

如果我有一个符号表,在 Boost Spirit 中

struct Foo : boost::spirit::qi::symbols<char, MyEnums::FruitType>
{
    Foo(const std::string& name = std::string("FooTable")
      : boost::spirit::qi::symbols<char, MyEnums::FruitType>(name)
    {
        add("apple", MyEnums::Apple)
           ("orange", MyEnums::Orange)
           ("peach", MyEnums::Peach);
    }
}

稍后在我的代码中,如果我有数据类型,我该如何获取符号?例如:

Foo fruitSymbolTable;
MyEnums::FruitType fruit = MyEnums::Apple;

std::string fruitTypeString = ???? // want it to be equal to "apple"

如何使用表格获取“苹果”?

另外,我知道我可以有一个像这样的表:

struct Foo : boost::spirit::qi::symbols<char, MyEnums::FruitType>
{
    Foo(const std::string& name = std::string("FooTable")
      : boost::spirit::qi::symbols<char, MyEnums::FruitType>(name)
    {
        add("apple", MyEnums::Apple)
           ("apple2", MyEnums::Apple)
           ("orange", MyEnums::Orange)
           ("peach", MyEnums::Peach);
    }
}

MyEnums::Apple 可以是“apple”或“apple2”,在这种情况下我更愿意获得“第一个”匹配项。我怎样才能做到这一点?

最佳答案

好吧,看来您希望将 qi::symbols 解析器转换为 karma::symbols 生成器。

我会说这样的事情不存在。由于您可能已经寻找过它,我认为可以安全地假设它没有。

我知道它会有多大用处,所以你可以考虑将它贡献给 Spirit Repository。

我在这里花了一些时间编写一个简单的映射器,将 qi::symbols 转换为 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;
}

编辑 C++03 风格:

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.

这是一个简单的示例程序,表明它可以正常工作: 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);
}

输出:

true
remains: ''
parsed value: 1
generator: aap
true
remains: ''
parsed value: 2
generator: noot
true
remains: ''
parsed value: 3
generator: mies

关于c++ - Boost C++ - 搜索 spirit 符号表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26968485/

相关文章:

c++ - Spirit X3解析器启动状态?

c++ - boost::bool 可选,在 boost::spirit::qi 语法中

尝试访问对象的方法时出现 C++ Qt 段错误

c++ - 如何在使用 c++ 中的 sdl、opengl 移动相机时修复奇怪的相机旋转

C++ Boost 图库 : outputting custom vertex properties

c++ - Boost::Spirit 表达式解析器

c++ - Spirit.X3 中的递归规则

c++ - 错误 C2664 : 'errno_t wcstombs_s(size_t *,char *,size_t,const wchar_t *,size_t)' : cannot convert parameter 4

c++ - 从同一目录读取图像?

c++ - 使用 Boost 序列化双端队列 vector 的问题