我尝试了各种方法来解决这个问题,使用地图和强制转换,将解析分成不同的子部分,直接使用std :: vector并尝试_r1等,但我似乎未能掌握使用的基本内容属性。
我想解析一行,例如:
DEFMACRO macroname param1 param2 param3 ... paramN
并将macroname与其params列表一起添加到qi :: symbols解析器中。
匹配
lit("DEFMACRO") >> (+char_) >> predicate_
并且放入defmacro结构工作正常,但是当我尝试使用结果或将其整体存储为符号解析器的数据元素时,我得到了表单的错误
无法从'const boost :: phoenix :: actor'转换为'const client :: defmacro'
下面是代码片段,然后是针对我的问题的这个变体的编译器输出。
我对未能掌握一些重要概念的任何解释都非常欢迎。
将VC ++ 2008与Spirit 1.42一起使用。
由于 瑞克
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_int.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <string>
#include <vector>
namespace client
{
namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
typedef std::vector<std::string> predicate;
struct defmacro
{
std::string name; // identifier for macro
predicate params; // parameters for macro
};
}
BOOST_FUSION_ADAPT_STRUCT(
client::defmacro,
(std::string, name)
(client::predicate, params)
)
namespace client
{
template <typename Iterator>
struct awe_grammar
: qi::grammar<Iterator, awe(), qi::locals<std::string>, ascii::space_type>
{
awe_grammar()
: awe_grammar::base_type(x, "x")
{
using qi::lit;
using qi::eol;
using qi::int_;
using ascii::char_;
using namespace qi::labels;
using phoenix::at_c;
long line_no=1;
qi::symbols<std::string, defmacro> macros;
eol_ = eol[ref(line_no)++];
predicate_ %= *(+char_);
defmacro_line_ %= (lit("DEFMACRO") >> (+char_) >> predicate_ >> eol_);
// ******** This line will not compile *************************
defmacro_ = defmacro_line_[macros.add(at_c<0>(_1),_1)];
// *************************************************************
}
qi::rule<Iterator, defmacro(), ascii::space_type> defmacro_line_;
qi::rule<Iterator, void(), ascii::space_type> defmacro_;
qi::rule<Iterator, predicate(), ascii::space_type> predicate_;
};
}
2>v:\awe\parser\parser\spirit\spirit_eg.cpp(XXX) : error C2664: 'const boost::spirit::qi::symbols<Char,T>::adder &boost::spirit::qi::symbols<Char,T>::adder::operator ()<boost::phoenix::actor<Eval>>(const Str &,const T &) const' : cannot convert parameter 2 from 'const boost::phoenix::actor<Eval>' to 'const client::defmacro &'
2> with
2> [
2> Char=std::string,
2> T=client::defmacro,
2> Eval=boost::phoenix::composite<boost::phoenix::at_eval<0>,boost::fusion::vector<boost::spirit::argument<0>,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_>>,
2> Str=boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::at_eval<0>,boost::fusion::vector<boost::spirit::argument<0>,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_>>>
2> ]
2> and
2> [
2> Eval=boost::spirit::argument<0>
2> ]
2> Reason: cannot convert from 'const boost::phoenix::actor<Eval>' to 'const client::defmacro'
2> with
2> [
2> Eval=boost::spirit::argument<0>
2> ]
2> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
2> v:\awe\parser\parser\spirit\spirit_eg.cpp(351) : while compiling class template member function 'client::awe_grammar<Iterator>::awe_grammar(void)'
2> with
2> [
2> Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>
2> ]
2> v:\awe\parser\parser\spirit\spirit_eg.cpp(622) : see reference to class template instantiation 'client::awe_grammar<Iterator>' being compiled
2> with
2> [
2> Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>
2> ]
答案 0 :(得分:1)
您可以在语法之外的符号中添加值,如下所示:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_int.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <string>
#include <vector>
namespace client
{
namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
typedef std::vector<std::string> predicate;
struct defmacro
{
std::string name; // identifier for macro
predicate params; // parameters for macro
};
typedef std::vector<defmacro> awe;
}
BOOST_FUSION_ADAPT_STRUCT(
client::defmacro,
(std::string, name)
(client::predicate, params)
)
namespace client
{
template <typename Iterator>
struct awe_grammar
: qi::grammar<Iterator, awe()>
{
awe_grammar()
: awe_grammar::base_type(start_)
{
using qi::lit;
using qi::eol;
using ascii::char_;
using ascii::blank;
using ascii::space;
using namespace qi::labels;
using phoenix::ref;
using phoenix::at_c;
line_no = 0;
eol_ = eol[++ref(line_no)];
identifier_ %= qi::lexeme[+(char_ - space)];
predicate_ %= (identifier_ % blank) >> eol_;
defmacro_line_ %=
lit("DEFMACRO ")
>> identifier_ >> ' '
>> predicate_
;
start_ %= +defmacro_line_;
}
long line_no;
qi::rule<Iterator, void() > eol_;
qi::rule<Iterator, defmacro() > defmacro_line_;
qi::rule<Iterator, awe() > start_;
qi::rule<Iterator, std::string()> identifier_;
qi::rule<Iterator, predicate() > predicate_;
};
}
和
#include <cstdlib>
#include <iostream>
#include "awe_grammar.h"
template <typename P, typename T>
void test_parser_attr(
char const* input, P const& p, T& attr, bool full_match = true)
{
using boost::spirit::qi::parse;
char const* f(input);
char const* l(f + strlen(f));
if (parse(f, l, p, attr) && (!full_match || (f == l)))
std::cout << "ok" << std::endl;
else
std::cout << "fail" << std::endl;
}
int main( /*int _argc, char * _argv[]*/ )
{
typedef client::awe_grammar<char const *> my_grammar;
my_grammar g;
client::awe result;
test_parser_attr(
"DEFMACRO macroname param1 param2 param3\n"
"DEFMACRO macro2 param1 param2\n",
g,
result,
true
);
////////////////////
// adding
////////////////////
boost::spirit::qi::symbols<char, client::defmacro> macros;
for (size_t i = 0; i < result.size(); i++)
{
macros.add(result[i].name, result[i]);
}
return EXIT_SUCCESS;
}
之后,您可以使用macros
所需的内容(例如,将其传递给另一种语法)。
答案 1 :(得分:0)
试试这个:
// ******** This line will not compile *************************
using qi::_val;
defmacro_ = defmacro_line_[macros.add(at_c<0>(_val),_1)];
// *************************************************************