키 - 값 문자열을 구조체로 파싱하려고합니다. 일부 키 - 값은 없거나 다른 순서 일 수 있습니다. 따라서 at_key<>
지시문을 사용하여 구조를 수정하고 구문을 분석하려면 boost::fusion
을 사용하고 싶습니다.부스트 스피리트와 퓨전을 사용하여 연관 구조로 구문 분석하기
#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/sequence.hpp>
using namespace std;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;
using boost::fusion::at_key;
typedef string::const_iterator iter_type;
struct Couple {
int a;
int b;
Couple() : a(0), b(0) {}
};
namespace keys {
struct first;
struct second;
}
BOOST_FUSION_ADAPT_ASSOC_STRUCT(
Couple,
(int, a, keys::first)
(int, b, keys::second)
)
struct G: qi::grammar< iter_type, Couple(), ascii::space_type >
{
G() : G::base_type(start_rule) {
using qi::_val;
using qi::_1;
using qi::_2;
start_rule =
("first" >> qi::int_
[ at_key<keys::first>(_val) = _1 ]
)
^
("second" >> qi::int_
[ at_key<keys::second>(_val) = _1 ]
);
}
qi::rule< iter_type, Couple(), ascii::space_type > start_rule;
};
int main() {
Couple couple;
string example = "second 2 first 1";
iter_type begin(example.begin());
iter_type end(example.end());
// test at_key -- compiles with no error
at_key<keys::second>(couple) = 5;
bool ok = qi::phrase_parse(begin, end, G(), ascii::space, couple);
if (ok)
cout << couple.a << " " << couple.b << endl;
else
cout << "Parse failed" << endl;
return 0;
}
문제는 코드가 컴파일되지 않는다는 것입니다 (부스트 1.50.0, g ++ 4.5.0이는 MinGW는) 분명히 at_key<>
규칙에 실패
In file included from D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:10:0,
from D:\projects\workspace\boost/boost/fusion/include/category_of.hpp:10,
from D:\projects\workspace\boost/boost/proto/fusion.hpp:20,
from D:\projects\workspace\boost/boost/proto/core.hpp:21,
from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/fusion/support/detail/category_of.hpp: In instantiation of 'boost::fusion::detail::fusion_category_of<const boost::phoenix::actor<boost::spirit::attribute<0> > >':
D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:44:58: instantiated from 'boost::fusion::extension::category_of_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:66:9: instantiated from 'boost::fusion::traits::category_of<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:73:9: instantiated from 'boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/mpl/if.hpp:67:11: instantiated from 'boost::mpl::if_<boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >, boost::fusion::result_of::key_of<mpl_::arg<1> >, boost::fusion::result_of::value_of<mpl_::arg<1> > >'
D:\projects\workspace\boost/boost/fusion/algorithm/query/find.hpp:45:9: instantiated from 'boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17: instantiated from 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9: instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp:54:35: instantiated from here
D:\projects\workspace\boost/boost/fusion/support/detail/category_of.hpp:15:38: error: no type named 'category' in 'const struct boost::phoenix::actor<boost::spirit::attribute<0> >'
In file included from D:\projects\workspace\boost/boost/proto/args.hpp:21:0,
from D:\projects\workspace\boost/boost/proto/core.hpp:14,
from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/mpl/if.hpp: In instantiation of 'boost::mpl::if_<boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >, boost::fusion::result_of::key_of<mpl_::arg<1> >, boost::fusion::result_of::value_of<mpl_::arg<1> > >':
D:\projects\workspace\boost/boost/fusion/algorithm/query/find.hpp:45:9: instantiated from 'boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17: instantiated from 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9: instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp:54:35: instantiated from here
D:\projects\workspace\boost/boost/mpl/if.hpp:67:11: error: 'value' is not a member of 'boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/mpl/if.hpp:70:41: error: 'value' is not a member of 'boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
In file included from D:\projects\workspace\boost/boost/fusion/sequence/intrinsic.hpp:20:0,
from D:\projects\workspace\boost/boost/fusion/include/intrinsic.hpp:10,
from D:\projects\workspace\boost/boost/proto/fusion.hpp:22,
from D:\projects\workspace\boost/boost/proto/core.hpp:21,
from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp: In instantiation of 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>':
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9: instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp:54:35: instantiated from here
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17: error: no type named 'type' in 'struct boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp: In constructor 'G::G()':
..\src\spirit02_test.cpp:54:35: error: no matching function for call to 'at_key(const boost::spirit::_val_type&)'
In file included from D:\projects\workspace\boost/boost/fusion/sequence/intrinsic.hpp:20:0,
from D:\projects\workspace\boost/boost/fusion/include/intrinsic.hpp:10,
from D:\projects\workspace\boost/boost/proto/fusion.hpp:22,
from D:\projects\workspace\boost/boost/proto/core.hpp:21,
from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp: At global scope:
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp: In instantiation of 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::second>':
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9: instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::second>'
..\src\spirit02_test.cpp:58:36: instantiated from here
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17: error: no type named 'type' in 'struct boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::second>'
..\src\spirit02_test.cpp: In constructor 'G::G()':
..\src\spirit02_test.cpp:58:36: error: no matching function for call to 'at_key(const boost::spirit::_val_type&)'
나는 간단한 규칙을 사용하는 경우 (연관성없이) 모든 컴파일 잘 작동하지만이 솔루션은 다소 약해 :
// A non-associative solution
//start_rule %= (("first" >> qi::int_)^("second" >> qi::int_));
가 왜 의미 행동에 at_key
을 사용할 수 없습니다? 비 연관 구조로 "연관"구문 분석을 수행하는 더 좋은 방법이 있습니까?
지금까지 at_key 또는 BOOST_FUSION_ADAPT_ASSOC_STRUCT를 사용한 적이 없습니다. 하지만 : std :: map <>으로 구문 분석하는 것이 가능한가? 어쩌면 문법을 변경하여 boost :: optional으로 해석 할 수도 있지만 가능하지 않을 수도 있습니다. – duselbaer
@duselbaer std :: map은 허용됩니다. 지역 변수를 사용하고 ref()로 액세스하는 것이 더 빠를 수도 있지만 여전히 추가 매핑이 필요하지 않았습니다. – Lyth