C++ Boost spirit将整数解析为自定义列表模板
我无法使用boost spirit解析这样的文件:C++ Boost spirit将整数解析为自定义列表模板,c++,parsing,templates,boost-spirit,boost-fusion,C++,Parsing,Templates,Boost Spirit,Boost Fusion,我无法使用boost spirit解析这样的文件: int [int, int, int] [ int, int] ... 没有什么特别难的,下面的语法适用于此: template<typename Iterator> struct parser_expression : qi::grammar<Iterator,ascii::space_type> { parser_expression() : parser_expression::base_
int [int, int, int] [ int, int]
...
没有什么特别难的,下面的语法适用于此:
template<typename Iterator>
struct parser_expression : qi::grammar<Iterator,ascii::space_type>
{
parser_expression() : parser_expression::base_type(start) {
using qi::double_;
using qi::int_;
using boost::spirit::qi::char_;
using qi::alpha;
using qi::alnum;
using qi::digit;
using qi::eps;
using qi::_val;
using boost::phoenix::bind;
start = int_ >> list1 >> list2 >> char_('=');
list1 = ('[' >> int_ >> *(char_(',') >> int_ ) >> char_(']')) | (char_('[') >> char_(']'));
list2 = ('[' >> int_ >> *(char_(',') >> int_ ) >> char_(']')) | -(char_('[') >> char_(']'));
}
qi::rule<Iterator,ascii::space_type> start;
qi::rule<Iterator,ascii::space_type> list1;
qi::rule<Iterator,ascii::space_type> list2;
};
模板
结构解析器_表达式:qi::grammar
{
解析器_表达式():解析器_表达式::基本类型(开始){
使用qi::double;
使用qi::int_;
使用boost::spirit::qi::char;
使用qi::alpha;
使用qi::alnum;
使用qi::数字;
使用qi::eps;
使用qi:(u val);
使用boost::phoenix::bind;
start=int_>>list1>>list2>>char('=');
列表1=('['>>int_>>*(char_(',')>>int_>>char_(']'))(char_('[')>>char_(']'));
列表2=('['>>int.>>*(char.(',')>>int.>>char.(']'))-(char.('[')>>char.(']');
}
qi::规则开始;
qi::规则列表1;
qi::规则列表2;
};
我的问题是我需要保存解析的结果。
例如,我需要将int的list1和list2保存到自定义列表模板:
template <typename T>
class SimpleLinkList {
private:
ChainLink<T>* head;
...
}
模板
类单纯形列表{
私人:
链环*头;
...
}
其中ChainLink是:
template<typename T>
class ChainLink {
private:
T object;
ChainLink* next;
...
}
模板
类链环{
私人:
T对象;
链接*下一步;
...
}
我在SimpleLinkList中有一个方法pushback,就像vector一样,但我不知道如何解析int,将其保存到ChainLink并将其添加到SimpleLinkList
我已经了解了如何将模板结构调整到融合序列
我需要一个自定义链接列表,以便能够删除和添加项目,而在它上循环
我需要帮助来理解如何安排所有这些来成功解析我的文件
谢谢您的帮助。您可能正在寻找容器属性自定义点:
namespace boost { namespace spirit { namespace traits {
template <typename T>
struct container_value<SimpleLinkList<T>, void> {
typedef T type;
};
template <typename T>
struct push_back_container<SimpleLinkList<T>, T, void> {
static bool call(SimpleLinkList<T>& c, T const& val) {
c.push_back(val);
return true;
}
};
}}}
注
- 在可能的情况下,我用(隐式)
替换了qi::lit
,因为您实际上不想将标点符号解析到属性中(对吗?)qi::char
- 我使用了列表解析器操作符
,而不是详细的替代方法%
- 我使用解析器操作符
使元素列表成为可选的(允许零元素)-
- 类似地,使用
使第二个列表一起成为可选列表list>>-list
void test(const std::string input)
{
static const parser_expression<std::string::const_iterator> p;
AbstractDataType parsed;
auto f(input.begin()), l(input.end());
bool ok = qi::phrase_parse(f, l, p, qi::space, parsed);
if (ok)
std::cout << "Result: " << parsed.number << " " << parsed.list1 << parsed.list2 << "\n";
else
std::cout << "Parse failed\n";
if (f!=l)
std::cout << "Unparsed: '" << std::string(f,l) << "'\n";
}
int main()
{
test("1 [2, 3, 4] [5, 6] =");
test("2 [] [6, 7] =");
test("3 [4, 5, 6] [ ] =");
test("4 [5, 6, 7] =");
}
查看所有集成:。防止linkrot:
// #define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
template <typename T> struct ChainLink;
template <typename T>
class SimpleLinkList {
public:
void push_back(T const& v) { /* todo */ _for_debug.push_back(v); }
std::list<int> _for_debug;
friend std::ostream& operator<<(std::ostream& os, SimpleLinkList const& list) {
os << "["; std::copy(list._for_debug.begin(), list._for_debug.end(), std::ostream_iterator<T>(os, " ")); return os << "]";
}
private:
ChainLink<T>* head;
};
namespace boost { namespace spirit { namespace traits {
template <typename T>
struct container_value<SimpleLinkList<T>, void> {
typedef T type;
};
template <typename T>
struct push_back_container<SimpleLinkList<T>, T, void> {
static bool call(SimpleLinkList<T>& c, T const& val) {
c.push_back(val);
return true;
}
};
}}}
struct AbstractDataType
{
int number;
SimpleLinkList<int> list1, list2;
};
BOOST_FUSION_ADAPT_STRUCT(AbstractDataType, (int, number)(SimpleLinkList<int>, list1)(SimpleLinkList<int>, list2))
template<typename Iterator>
struct parser_expression : qi::grammar<Iterator, AbstractDataType(), qi::space_type>
{
parser_expression() : parser_expression::base_type(start)
{
list = '[' >> -(qi::int_ % ',') >> ']';
start = qi::int_ >> list >> -list >> '=';
BOOST_SPIRIT_DEBUG_NODES((list)(start))
}
qi::rule<Iterator, AbstractDataType(), qi::space_type> start;
qi::rule<Iterator, SimpleLinkList<int>(), qi::space_type> list;
};
void test(const std::string input)
{
static const parser_expression<std::string::const_iterator> p;
AbstractDataType parsed;
auto f(input.begin()), l(input.end());
bool ok = qi::phrase_parse(f, l, p, qi::space, parsed);
if (ok)
std::cout << "Result: " << parsed.number << " " << parsed.list1 << parsed.list2 << "\n";
else
std::cout << "Parse failed\n";
if (f!=l)
std::cout << "Unparsed: '" << std::string(f,l) << "'\n";
}
int main()
{
test("1 [2, 3, 4] [5, 6] =");
test("2 [] [6, 7] =");
test("3 [4, 5, 6] [ ] =");
test("4 [5, 6, 7] =");
}
/#定义BOOST_SPIRIT_调试
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
模板结构链接;
模板
类单纯形列表{
公众:
void push_back(T const&v){/*todo*/_for_debug.push_back(v);}
std::list_用于_调试;
friend std::ostream&运算符']';
start=qi::int_>>列表>>-列表>>'=';
BOOST_SPIRIT_DEBUG_节点((列表)(开始))
}
qi::规则开始;
qi::规则列表;
};
无效测试(常量标准::字符串输入)
{
静态常量解析器_表达式p;
解析的抽象数据类型;
自动f(input.begin()),l(input.end());
bool ok=qi::phrase_parse(f,l,p,qi::space,parsed);
如果(确定)
STD::是的,你的权利,我不想分析标点符号。我只有一个编译问题,它说:/home /BIL/Test.CPP:函数“空洞测试(STD::String)”:/HOL/BILB/Test.CPP:67:12:错误:ISO C++禁止声明“F”,没有类型[FPrime]。它是你使用关键字“Auto'”的地方。我不知道这个,它是精神分析的自动解析器。我需要包括其他东西吗?好吧,不,它不是精神分析器AutoI,而是C++中的AutoToC。我不明白为什么它不能确定这个好的类型,但是用“STD::Str::StristyIdActer”代替AUTO解决了这个问题。非常感谢!@user1680951很可能是您的编译器禁用了c++0x/c++11功能。对于gcc供应-std=c++0x
/-std=c++11
,请启用。干杯
Result: 1 [2 3 4 ][5 6 ]
Result: 2 [][6 7 ]
Result: 3 [4 5 6 ][]
Result: 4 [5 6 7 ][]
// #define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
template <typename T> struct ChainLink;
template <typename T>
class SimpleLinkList {
public:
void push_back(T const& v) { /* todo */ _for_debug.push_back(v); }
std::list<int> _for_debug;
friend std::ostream& operator<<(std::ostream& os, SimpleLinkList const& list) {
os << "["; std::copy(list._for_debug.begin(), list._for_debug.end(), std::ostream_iterator<T>(os, " ")); return os << "]";
}
private:
ChainLink<T>* head;
};
namespace boost { namespace spirit { namespace traits {
template <typename T>
struct container_value<SimpleLinkList<T>, void> {
typedef T type;
};
template <typename T>
struct push_back_container<SimpleLinkList<T>, T, void> {
static bool call(SimpleLinkList<T>& c, T const& val) {
c.push_back(val);
return true;
}
};
}}}
struct AbstractDataType
{
int number;
SimpleLinkList<int> list1, list2;
};
BOOST_FUSION_ADAPT_STRUCT(AbstractDataType, (int, number)(SimpleLinkList<int>, list1)(SimpleLinkList<int>, list2))
template<typename Iterator>
struct parser_expression : qi::grammar<Iterator, AbstractDataType(), qi::space_type>
{
parser_expression() : parser_expression::base_type(start)
{
list = '[' >> -(qi::int_ % ',') >> ']';
start = qi::int_ >> list >> -list >> '=';
BOOST_SPIRIT_DEBUG_NODES((list)(start))
}
qi::rule<Iterator, AbstractDataType(), qi::space_type> start;
qi::rule<Iterator, SimpleLinkList<int>(), qi::space_type> list;
};
void test(const std::string input)
{
static const parser_expression<std::string::const_iterator> p;
AbstractDataType parsed;
auto f(input.begin()), l(input.end());
bool ok = qi::phrase_parse(f, l, p, qi::space, parsed);
if (ok)
std::cout << "Result: " << parsed.number << " " << parsed.list1 << parsed.list2 << "\n";
else
std::cout << "Parse failed\n";
if (f!=l)
std::cout << "Unparsed: '" << std::string(f,l) << "'\n";
}
int main()
{
test("1 [2, 3, 4] [5, 6] =");
test("2 [] [6, 7] =");
test("3 [4, 5, 6] [ ] =");
test("4 [5, 6, 7] =");
}