我遇到了一个Boost Spirit Qi语法的问题,它正在发出一个不需要的类型,导致这个编译错误:
error C2664: 'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::insert(unsigned int,const std::basic_string<_Elem,_Traits,_Ax> &)' : cannot convert parameter 1 from 'std::_String_iterator<_Elem,_Traits,_Alloc>' to 'unsigned int'
以下是导致此问题的语法:
qi::rule<Iterator, qi::unused_type()> gr_newline;
// asmast::label() just contains an identifier struct that is properly emitted from gr_identifier
qi::rule<Iterator, asmast::label(), skipper<Iterator> > gr_label;
gr_newline = +( char_('\r')
|char_('\n')
);
这失败了:
gr_label = gr_identifier
>> ':'
> gr_newline;
但以下 所有的工作:
// This parses OK
gr_label = gr_identifier
> gr_newline;
// This also parses OK
gr_label = gr_identifier
> ':'
> gr_newline;
// This also parses OK
// **Why does this work when parenthesized?**
gr_label = gr_identifier
>> (':'
> skip_grammar.gr_newline
);
// This also parses OK
gr_label = gr_identifier
>> omit[':'
> gr_newline];
我不明白为什么删除字符文字或省略[]它“修复”问题,但我不希望语法混乱。
根据&gt;&gt;的复合属性规则和&gt;找到here和字符解析器属性here,gr_label应该只发出asmast :: label
a: A, b: B --> (a >> b): tuple<A, B>
a: A, b: Unused --> (a >> b): A <---- This one here is the one that should match so far as I understand
a: Unused, b: B --> (a >> b): B
a: Unused, b: Unused --> (a >> b): Unused
Expression Attribute
c unused or if c is a Lazy Argument, the character type returned by invoking it.
但是,某些东西会污染目标属性,并导致编译器错误。
所以我的问题是这个语法发出了一个不受欢迎的属性,以及如何摆脱它。
答案 0 :(得分:2)
问题似乎是因为你在这里混合搭配>
和>>
。
虽然您正确地观察了记录的属性生成规则,但真正似乎发生的是Unused
方更像fusion::vector1<qi::unused_type>
(而不是qi::unused_type
)。
旁注:
这也解释了“为什么在括号时才能正常工作?” - 您
正在改变表达式评估的顺序(推翻运算符优先级)
并获得另一种类型。
您可以使用诸如此类技术来确定我的预感是否正确Detecting the parameter types in a Spirit semantic action
所以,简短回答是:这是它的工作原理。这是否是一个错误,文档中的遗漏或只是一个功能在SO上讨论真的没有建设性。我指的是[spirit-general]邮件列表(注意他们也有一个活跃的#IRC频道)。
略长的答案是: 我认为您还没有显示 。
两件事:
错误消息非常清楚地表明它正在尝试insert
字符串迭代器 * ,其中包含字符(或可兑换)。我没有看到你发布的任何代码的连接,但我可以猜到
我可以编译你的“有问题”的规则标本就好嵌入我的“模拟”语法中,我根据你在previous question中暴露的一点点来猜测。
我想也许您应该尝试发布另一个问题,同时显示Short Self Contained Correct Example,表明您真正拥有的问题。
请务必提及编译器版本和使用的boost版本。
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
namespace asmast
{
typedef std::string label;
}
template <typename It, typename Skipper = qi::blank_type>
struct parser : qi::grammar<It, Skipper>
{
parser() : parser::base_type(start)
{
using namespace qi;
start = lexeme["Func" >> !(alnum | '_')] > function;
function = gr_identifier
>> "{"
>> -(
gr_instruction
| gr_label
//| gr_vardecl
//| gr_paramdecl
) % eol
> "}";
gr_instruction_names.add("Mov", unused);
gr_instruction_names.add("Push", unused);
gr_instruction_names.add("Exit", unused);
gr_instruction = lexeme [ gr_instruction_names >> !(alnum|"_") ] > gr_operands;
gr_operands = -(gr_operand % ',');
gr_identifier = lexeme [ alpha >> *(alnum | '_') ];
gr_operand = gr_identifier | gr_string;
gr_string = lexeme [ '"' >> *("\"\"" | ~char_("\"")) >> '"' ];
gr_newline = +( char_('\r')
|char_('\n')
);
gr_label = gr_identifier >> ':' > gr_newline;
BOOST_SPIRIT_DEBUG_NODES((start)(function)(gr_instruction)(gr_operands)(gr_identifier)(gr_operand)(gr_string));
}
private:
qi::symbols<char, qi::unused_type> gr_instruction_names;
qi::rule<It, Skipper> start, function, gr_instruction, gr_operands, gr_operand, gr_string;
qi::rule<It, qi::unused_type()> gr_newline;
qi::rule<It, asmast::label(), Skipper> gr_label, gr_identifier;
};
int main()
{
typedef boost::spirit::istream_iterator It;
std::cin.unsetf(std::ios::skipws);
It f(std::cin), l;
parser<It, qi::blank_type> p;
try
{
bool ok = qi::phrase_parse(f,l,p,qi::blank);
if (ok) std::cout << "parse success\n";
else std::cerr << "parse failed: '" << std::string(f,l) << "'\n";
if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
return ok;
} catch(const qi::expectation_failure<It>& e)
{
std::string frag(e.first, e.last);
std::cerr << e.what() << "'" << frag << "'\n";
}
return false;
}