- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想解析如下内容:
1;2
=1200
3;4
5;6
行可以以任何顺序出现。以 = 符号开头的行可以不止一行,只有最后一行重要;包含 ; 的行代表我想存储在 map 中的一对值。阅读 this question 的答案我想出了一些应该足够好的代码(抱歉,但我仍然是 Spirit 的菜鸟)并且应该完成我想要实现的目标。这是代码:
#define BOOST_SPIRIT_USE_PHOENIX_V3
#define DATAPAIR_PAIR
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/mpl/bool.hpp>
#include <map>
#if !defined(DATAPAIR_PAIR)
#include <vector>
#endif
static const char g_data[] = "1;2\n=1200\n3;4\n5;6\n";
typedef std::string DataTypeFirst;
#if defined(DATAPAIR_PAIR)
typedef std::string DataTypeSecond;
typedef std::pair<DataTypeFirst, DataTypeSecond> DataPair;
typedef std::map<DataTypeFirst, DataTypeSecond> DataMap;
#else
typedef std::vector<DataTypeFirst> DataPair;
typedef std::map<DataTypeFirst, DataTypeFirst> DataMap;
#endif
struct MyContainer {
DataMap data;
double number;
};
namespace boost { namespace spirit { namespace traits {
template<> struct is_container<MyContainer> : boost::mpl::true_ {};
template<>
struct container_value<MyContainer> {
typedef boost::variant<double, DataPair> type;
};
template <>
struct push_back_container<MyContainer, double> {
static bool call ( MyContainer& parContainer, double parValue ) {
parContainer.number = parValue;
return true;
}
};
template <>
struct push_back_container<MyContainer, DataPair> {
static bool call ( MyContainer& parContainer, const DataPair& parValue ) {
#if defined(DATAPAIR_PAIR)
parContainer.data[parValue.first] = parValue.second;
#else
parContainer.data[parValue[0]] = parValue[1];
#endif
return true;
}
};
} } }
template <typename Iterator>
struct TestGrammar : boost::spirit::qi::grammar<Iterator, MyContainer()> {
TestGrammar ( void );
boost::spirit::qi::rule<Iterator, MyContainer()> start;
boost::spirit::qi::rule<Iterator, DataPair()> data;
boost::spirit::qi::rule<Iterator, double()> num;
};
template <typename Iterator>
TestGrammar<Iterator>::TestGrammar() :
TestGrammar::base_type(start)
{
using boost::spirit::qi::alnum;
using boost::spirit::qi::lit;
using boost::spirit::ascii::char_;;
using boost::spirit::qi::double_;
using boost::spirit::qi::eol;
using boost::spirit::qi::eoi;
start %= *((num | data) >> (eol | eoi));
data = +alnum >> lit(";") >> +alnum;
num = '=' >> double_;
}
int main() {
std::cout << "Parsing data:\n" << g_data << "\n";
TestGrammar<const char*> gramm;
MyContainer result;
boost::spirit::qi::parse(static_cast<const char*>(g_data),
g_data + sizeof(g_data) / sizeof(g_data[0]) - 1,
gramm,
result
);
std::cout << "Parsed data:\n";
std::cout << "Result: " << result.number << "\n";
for (const auto& p : result.data) {
std::cout << p.first << " = " << p.second << '\n';
}
return 0;
}
我正在 Gentoo Linux 上开发这个,使用 dev-libs/boost-1.55.0-r2:0/1.55.0 和 gcc (Gentoo 4.8.3 p1.1, pie-0.5.9) 4.8.3 .编译上面的代码我得到一个错误
/usr/include/boost/spirit/home/support/container.hpp:278:13: 错误:“struct MyContainer”没有名为“insert”的成员
作为解决方法,我想出了您通过注释“#define DATAPAIR_PAIR”行获得的替代代码。在那种情况下,代码可以编译并运行,但我真正想要的是一对,例如我可以在其中混合 std::string 和 int 值。为什么使用 std::pair 作为我的数据规则的属性会导致编译器错过 push_back_container 的正确特化?是否可以使用 std::pair 或任何等效方法修复代码并使其正常工作?
最佳答案
我会通过/just/不同时将事物视为容器和非容器来简化这一点。因此,对于这种特殊情况,我可能会偏离我通常的口头禅(avoid semantic actions)并使用它们¹:
template <typename It, typename Skipper = qi::blank_type>
struct grammar : qi::grammar<It, MyContainer(), Skipper> {
grammar() : grammar::base_type(start) {
update_number = '=' > qi::double_ [ qi::_r1 = qi::_1 ];
map_entry = qi::int_ > ';' > qi::int_;
auto number = phx::bind(&MyContainer::number, qi::_val);
auto data = phx::bind(&MyContainer::data, qi::_val);
start = *(
( update_number(number)
| map_entry [ phx::insert(data, phx::end(data), qi::_1) ]
)
>> qi::eol);
}
private:
qi::rule<It, void(double&), Skipper> update_number;
qi::rule<It, MyContainer::Pair(), Skipper> map_entry;
qi::rule<It, MyContainer(), Skipper> start;
};
如果您负担得起 map 中的 (0;0)
条目,您甚至可以省去语法:
std::map<int, int> data;
double number;
bool ok = qi::phrase_parse(f, l,
*(
(qi::omit['=' > qi::double_ [phx::ref(number)=qi::_1]]
| (qi::int_ > ';' > qi::int_)
) >> qi::eol)
, qi::blank, data);
我也可以尝试让你的“先进精神”方法奏效,但这可能需要一段时间:)
¹ 我使用 auto
来提高可读性,但当然你不需要使用它;只需重复内联子表达式或使用 BOOST_AUTO。请注意,对于有状态解析器表达式,这通常不是好的建议(请参阅 BOOST_SPIRIT_AUTO)
关于c++ - 为提升精神编译自定义容器时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27092735/
我正在使用此代码将“k1 = v1; k2 = v2; k3 = v3; kn = vn”字符串解析为映射。 qi::phrase_parse( begin,end,
我不理解以下示例中 x3 的行为(取自更大的语法)。 当然,语法有点奇怪,但大致实现了 (lal)?()? .当第二组不存在时,默认为 .我不明白为什么要输入 "lal"我得到 defaultcha
所以我的问题很简单,在我的词法分析器类(扩展 lex::lexer )中,我有以下内容; this->self.add ... ("&&", AND_AND) ("||", O
我正在尝试修改以下示例:http://www.boost.org/doc/libs/1_57_0/libs/spirit/example/qi/employee.cpp 我想在 employee 结构
我正在为当前分支为多个版本的应用程序寻找版本编号方案/模式/系统 shell game样式发布日期。这使得版本控制成为一场噩梦。我想只使用典型的 Major.Minor.Revision 但是这会很快
是的,我开始做这个测试了! 但是我不知道该用什么=/ Rspec + 应该吗? Rspec + 牛排? 迷你测试? cucumber ? capybara ? 可以吗? ( cucumber 与 Sh
我是一名优秀的程序员,十分优秀!