boostspirit:使用语义动作和phoenix时的参数类型
我使用 boost Spirit 来解析数学表达式,并遇到了一个问题,我将其提取到以下代码中。
有一个带有一个标记的简单词法分析器,具有一个保存匹配字符串的属性。解析器定义了一个规则,该规则旨在获取令牌的属性并用它调用函数。函数调用的结果应该是规则的属性值。
这无法编译(calc_something:无法将参数 1 从 const boost::spirit::_1_type 转换为 const std::string &) - 显然是因为 qi::_1 的类型未正确推断。但是,将操作更改为简单的“cout << qi::_1”是可行的。
我对提升精神还很陌生,但已经设法让我的语法表现得正确。现在我需要获取解析的值,我被困在这里,希望能得到任何帮助。
// spiritTest.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include <tchar.h>
#include <string>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
namespace qi = boost::spirit::qi;
namespace lex = boost::spirit::lex;
namespace phoenix = boost::phoenix;
template <typename Lexer>
class TestLexer : public lex::lexer<Lexer>
{
public:
TestLexer()
{
number = "(\\d*\\.)?\\d+([eE][-+]?\\d+)?";
self = number;
}
lex::token_def<std::string> number;
};
int calc_something(const std::string & s)
{
return 5;
}
template <typename Iterator>
class Parser : public qi::grammar<Iterator, int>
{
public:
template <typename TokenDef>
Parser(const TokenDef& tok) : Parser::base_type(value)
{
// the following line causes error C2664: 'calc_something' : cannot convert parameter 1 from 'const boost::spirit::_1_type' to 'const std::string &'
value = tok.number [qi::_val = calc_something(qi::_1)];
// the following line works as expected
//value = tok.number [std::cout << qi::_1 << std::endl];
}
qi::rule<Iterator, int> value;
};
int _tmain(int argc, _TCHAR* argv[])
{
typedef const char* base_iterator_type;
typedef lex::lexertl::token<base_iterator_type> token_type;
typedef lex::lexertl::lexer<token_type> lexer_type;
typedef TestLexer<lexer_type> TestLexer;
typedef TestLexer::iterator_type iterator_type;
typedef Parser<iterator_type> Parser;
TestLexer lexer;
Parser parser(lexer);
const char * formula = "530";
bool result = lex::tokenize_and_parse(formula, formula + strlen(formula), lexer, parser);
return 0;
}
I use boost spirit to parse mathematical expressions and have run into a problem that I extracted into the following code.
There is a simple lexer with one token, having an attribute holding the matched string. The parser defines a single rule which is meant to take the token's attribute and call a function with it. The result of the function call should be the attribute value of the rule.
This fails to compile (calc_something: cannot convert parameter 1 from const boost::spirit::_1_type to const std::string &) - clearly because the type of qi::_1 is not inferred correctly. However, changing the action to a simple "cout << qi::_1" works.
I am fairly new to boost spirit, but have managed to get my grammar to behave correctly. Now that I need to get at parsed values, I am stuck here and would appreciate any help I can get.
// spiritTest.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include <tchar.h>
#include <string>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
namespace qi = boost::spirit::qi;
namespace lex = boost::spirit::lex;
namespace phoenix = boost::phoenix;
template <typename Lexer>
class TestLexer : public lex::lexer<Lexer>
{
public:
TestLexer()
{
number = "(\\d*\\.)?\\d+([eE][-+]?\\d+)?";
self = number;
}
lex::token_def<std::string> number;
};
int calc_something(const std::string & s)
{
return 5;
}
template <typename Iterator>
class Parser : public qi::grammar<Iterator, int>
{
public:
template <typename TokenDef>
Parser(const TokenDef& tok) : Parser::base_type(value)
{
// the following line causes error C2664: 'calc_something' : cannot convert parameter 1 from 'const boost::spirit::_1_type' to 'const std::string &'
value = tok.number [qi::_val = calc_something(qi::_1)];
// the following line works as expected
//value = tok.number [std::cout << qi::_1 << std::endl];
}
qi::rule<Iterator, int> value;
};
int _tmain(int argc, _TCHAR* argv[])
{
typedef const char* base_iterator_type;
typedef lex::lexertl::token<base_iterator_type> token_type;
typedef lex::lexertl::lexer<token_type> lexer_type;
typedef TestLexer<lexer_type> TestLexer;
typedef TestLexer::iterator_type iterator_type;
typedef Parser<iterator_type> Parser;
TestLexer lexer;
Parser parser(lexer);
const char * formula = "530";
bool result = lex::tokenize_and_parse(formula, formula + strlen(formula), lexer, parser);
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我没有使用
spirit lex
的经验,但我认为它与qi
类似,因此您需要使用phoenix 函数
来这样做:I don't have experience with
spirit lex
, but I assume it's similar toqi
and so you'd want to use aphoenix function
to do that:eddi 已确定部分问题;我设法通过另外两个更改来实现此目的:
#define BOOST_SPIRIT_USE_PHOENIX_V3 1
eddi has identified part of the problem; I managed to get this working with another two changes:
<Iterator, int()>
#define BOOST_SPIRIT_USE_PHOENIX_V3 1