提高C ++ - 寻找精神符号表 [英] Boost C++ - Searching Spirit symbol table

查看:292
本文介绍了提高C ++ - 寻找精神符号表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在升压精神,如果我有一个符号表

 结构美孚:提振精神:: ::气::符号<焦炭,MyEnums :: FruitType>
{
    美孚(常量标准::字符串&放大器;名称=的std ::字符串(FooTable)
      :提振精神:: ::气::符号<焦炭,MyEnums :: FruitType>(名)
    {
        加(苹果,MyEnums ::苹果)
           (橙色,MyEnums ::橙色)
           (桃花源记,MyEnums ::桃);
    }
}

后来在我的code,如果我有数据类型,如何才能得到符号?例如:

 富fruitSymbolTable;
MyEnums :: FruitType水果= MyEnums ::苹果;标准::字符串fruitTypeString = ???? //希望它是等于苹果

我如何使用该表来获得苹果?

另外,我知道我能有这样一个表格:

 结构美孚:提振精神:: ::气::符号<焦炭,MyEnums :: FruitType>
{
    美孚(常量标准::字符串&放大器;名称=的std ::字符串(FooTable)
      :提振精神:: ::气::符号<焦炭,MyEnums :: FruitType>(名)
    {
        加(苹果,MyEnums ::苹果)
           (apple2,MyEnums ::苹果)
           (橙色,MyEnums ::橙色)
           (桃花源记,MyEnums ::桃);
    }
}

在哪里MyEnums ::苹果可以是苹果或在这种情况下,我preFER获得第一个匹配apple2。我怎样才能做到这一点?


解决方案

哦,看来你想有从变换气::符号解析器与人缘::符号发电机。

我会说这样的事情不存在。因为你可能已经找了它,我认为它是安全的假设它没有。

我可以看到它怎么会很有用,所以你可能会认为这有助于精神资源库。

我在这里度过了一段时间,编写一个简单的映射,从齐::符号转换人缘::符号

 模板< typename的字符,typename的T,typename的查找,类型名滤光器>
    因果报应::符号< T,性病:: basic_string的<&夏亚GT; >
    逆(气::符号<煤焦,T,查找,滤光器>&常量放大器;分析器)
{
    因果报应::符号< T,性病:: basic_string的<&夏亚GT; >发电机;    parser.for_each([安培;发电机(性病:: basic_string的<&夏亚GT;常量和放大器;符号,T V)
        {
            generator.add(ⅴ,符号);
        });    返回发生器;
}

修改在C ++ 03的风格:

 模板< typename的字符,typename的T,typename的查找,类型名滤光器>
    因果报应::符号< T,性病:: basic_string的<&夏亚GT; >
    逆(气::符号<煤焦,T,查找,滤光器>&常量放大器;分析器)
{
    结构_adder {
        因果报应::符号< T,性病:: basic_string的<&夏亚GT; >结果;        void运算符()(性病:: basic_string的<&夏亚GT;常量和放大器;符号,T V){
            result.add(ⅴ,符号);
        }
    }加法器;    parser.for_each(加法);
    返回adder.result;
}


  

注意:该做的不可以然而在解析符号表处理潜在的反复​​映射的值。


下面是一个简单的例子程序,说明它的工作原理: 的http:// liveworkspace.org/$c$c/3uzQKi

 的#include<升压/精神/有/ qi.hpp>
#包括LT&;升压/精神/有/ karma.hpp>命名空间补气=的boost ::精神::补气;
命名空间因缘=的boost ::精神::人缘;模板< typename的ItType>
结构解析器:公共补气::语法< ItType,INT()>
{
    解析器()语法分析器:: base_type(开始)
    {
        _sym.add(AAP,1)(NOOT,2)(密斯,3);
        开始= _sym;
    }
  // 私人的:
    齐::符号<焦炭,INT> _sym;
    齐::规则< ItType,INT()>开始;
};模板< typename的ItType>
结构发生器:公共因缘::语法< ItType,INT()>
{
    模板< typename的符号>
    发电机(符号&安培;&安培;符号):发电机:: base_type(开始)
    {
        // _sym.add(1,AAP)(2,NOOT)(3,密斯);
        _sym =的std ::移动(符号);
        开始= _sym;
    }
  私人的:
    因果报应::符号< INT,标准::字符串> _sym;
    因果报应::规则< ItType,INT()>开始;
};模板< typename的字符,typename的T,typename的查找,类型名滤光器>
    因果报应::符号< T,性病:: basic_string的<&夏亚GT; >
    逆(气::符号<煤焦,T,查找,滤光器>&常量放大器;分析器)
{
    因果报应::符号< T,性病:: basic_string的<&夏亚GT; >发电机;    parser.for_each([安培;发电机(性病:: basic_string的<&夏亚GT;常量和放大器;符号,T V)
        {
            generator.add(ⅴ,符号);
        });    返回发生器;
}无效测试用例(标准::字符串常量和放大器; STR)
{
    的typedef的std ::字符串::为const_iterator它;    它开始= str.cbegin();
    它结束= str.cend();    静态常量解析器<它>磷;    int的列;
    布尔OK =齐::解析(开始,结束,P出);
    性病::法院LT&;<的std :: boolalpha<< OK<<的'\\ n';
    性病::法院LT&;< 仍然是:'<<标准::字符串(开始,结束)LT;< '\\ n;
    如果(OK)
    {
        性病::法院LT&;< 经分析的价值:<<出<< \\ n;
        静态常量发生器<的boost ::精神:: ostream_iterator>克(倒数(p._sym));
        性病::法院LT&;< 发电机:<<因果报应::格式(克,出)LT;< \\ n;
    }}诠释的main()
{
    常量汽车V =的std ::矢量<标准::字符串> {AAP,NOOT,密斯};
    为(自动它= v.begin();!它= v.end(); ++吧)
        测试用例(*它);
}

输出:

 
仍然是:''
分析得到的值:1
发电机:AAP
真正
仍然是:''
分析得到的值:2
发电机:NOOT
真正
仍然是:''
分析得到的值:3
发电机:密斯

In Boost Spirit if I have a symbol table

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

Later on in my code, if I have the data type how can I get the symbol? For example:

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

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

How can I use the table to get "apple"?

Also, I understand that I can have a table like:

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

Where MyEnums::Apple can be either "apple" or "apple2" in which case I'd prefer to get the 'first' match. How can I do this?

解决方案

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

这篇关于提高C ++ - 寻找精神符号表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆