编译错误,带有boost::spirit语法分析器
Compilation error with a boost::spirit parser
我有一个使用boost::spirit制作的计算器的奇怪问题。这个计算器应该以一个字符串作为参数,表示一系列用逗号分隔的算术表达式,如"a+4*5,77,(b-c)*4"。它还允许字符串"?",并在这种情况下返回包含-1的数组。计算器使用SymTable初始化,SymTable是一个模板类参数,用于描述任何提供[string]->int运算符(例如:映射)的类,以解析变量的值。
下面的代码适用于我的Ubuntu 10.4,包括gcc 4.6.2和gcc 4.4,以及boost 1.47和1.48。它过去也在一台带有gcc 4.5.3和boost 1.47的Cray Linux机器上工作。
#include <boost/bind.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
namespace sp = boost::spirit;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace Damaris {
template <typename Iterator, typename SymTable>
struct Calc : qi::grammar<Iterator, std::vector<int>(), ascii::space_type>
{
qi::rule<Iterator, std::vector<int>(), ascii::space_type> start;
qi::rule<Iterator, int(), ascii::space_type> expr;
qi::rule<Iterator, int(), ascii::space_type> qmark;
qi::rule<Iterator, int(), ascii::space_type> factor;
qi::rule<Iterator, int(), ascii::space_type> simple;
qi::rule<Iterator, std::string(), ascii::space_type> identifier;
qi::rule<Iterator, int(SymTable), ascii::space_type> value;
/**
* brief Constructor.
* param[in] sym : table of symboles.
*/
Calc(SymTable &sym) : Calc::base_type(start)
{
identifier = qi::lexeme[( qi::alpha | '_') >> *( qi::alnum | '_')];
value = identifier[qi::_val = qi::labels::_r1[qi::_1]];
simple = ('(' >> expr >> ')')
| qi::int_
| value(boost::phoenix::ref(sym));
factor %= (simple >> '*' >> factor)[qi::_val = qi::_1 * qi::_2]
| (simple >> '/' >> factor)[qi::_val = qi::_1 / qi::_2]
| (simple >> '%' >> factor)[qi::_val = qi::_1 % qi::_2]
| simple;
expr %= (factor >> '+' >> expr)[qi::_val = qi::_1 + qi::_2]
| (factor >> '-' >> expr)[qi::_val = qi::_1 - qi::_2]
| factor;
qmark = qi::char_('?')[qi::_val = -1];
start = qmark
| (expr % ',');
}
};
}
今天,我再次尝试在Cray机器上编译相同的代码(我想从那时起,它已经升级了),我尝试了gcc 4.6.2和gcc 4.5.2,以及boost 1.48和1.49,但我总是得到我不理解的相同编译错误:
/nics/b/home/mdorier/damaris-0.4/common/Calc.hpp:74:3: instantiated from 'Damaris::Calc<Iterator, SymTable>::Calc(SymTable&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, SymTable = Damaris::ParameterSet]'
/nics/b/home/mdorier/damaris-0.4/common/MetadataManager.cpp:45:79: instantiated from here
/nics/b/home/mdorier/deploy/include/boost/spirit/home/qi/detail/assign_to.hpp:123:13: error: invalid static_cast from type 'const boost::fusion::vector2<int, int>' to type 'int'
Calc.hpp中的第74行对应于"factor=…"行。指示的实例化行(MetadataManager.cpp:45)如下:
layoutInterp = new Calc<std::string::const_iterator,ParameterSet>(*parameters);
其中layoutInterp是Calc*类型并且参数是ParameterSet*类型。
知道这个错误是从哪里来的吗?感谢
我很确定您可能已经重新安排了规则中的内容。事实上,%=
自动规则表达式赋值不起作用,因为语法分析器表达式的合成类型与int
不相似。
基本上,你会改变
factor %= (simple >> '*' >> factor)[ _val = _1 * _2 ]
| (simple >> '/' >> factor)[ _val = _1 / _2 ]
| (simple >> '%' >> factor)[ _val = _1 % _2 ]
| simple;
expr %= (factor >> '+' >> expr)[ _val = _1 + _2 ]
| (factor >> '-' >> expr)[ _val = _1 - _2 ]
| factor;
进入
factor = (simple >> '*' >> factor)[ _val = _1 * _2 ]
| (simple >> '/' >> factor)[ _val = _1 / _2 ]
| (simple >> '%' >> factor)[ _val = _1 % _2 ]
| (simple) [_val = _1 ];
expr = (factor >> '+' >> expr)[ _val = _1 + _2 ]
| (factor >> '-' >> expr)[ _val = _1 - _2 ]
| (factor) [_val = _1 ];
我已经解决了一些小问题,并为你的帖子创建了一个SSCCE,据我所知,它是有效的:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace sp = boost::spirit;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
namespace Damaris {
template <typename Iterator, typename SymTable>
struct Calc : qi::grammar<Iterator, std::vector<int>(), ascii::space_type>
{
qi::rule<Iterator, std::vector<int>(), ascii::space_type> start;
qi::rule<Iterator, int(), ascii::space_type> expr;
qi::rule<Iterator, int(), ascii::space_type> qmark;
qi::rule<Iterator, int(), ascii::space_type> factor;
qi::rule<Iterator, int(), ascii::space_type> simple;
qi::rule<Iterator, std::string(), ascii::space_type> identifier;
qi::rule<Iterator, int(SymTable), ascii::space_type> value;
Calc(SymTable &sym) : Calc::base_type(start)
{
using namespace qi;
identifier = lexeme[( alpha | '_') >> *( alnum | '_')];
value = identifier[ _val = _r1[_1] ];
simple = ('(' >> expr >> ')')
| int_
| value(boost::phoenix::ref(sym));
factor = (simple >> '*' >> factor)[ _val = _1 * _2 ]
| (simple >> '/' >> factor)[ _val = _1 / _2 ]
| (simple >> '%' >> factor)[ _val = _1 % _2 ]
| (simple) [_val = _1 ];
expr = (factor >> '+' >> expr)[ _val = _1 + _2 ]
| (factor >> '-' >> expr)[ _val = _1 - _2 ]
| (factor) [_val = _1 ];
qmark = char_('?')[ _val = -1 ];
start = qmark
| (expr % ',');
BOOST_SPIRIT_DEBUG_NODE(start);
BOOST_SPIRIT_DEBUG_NODE(qmark);
BOOST_SPIRIT_DEBUG_NODE(expr);
BOOST_SPIRIT_DEBUG_NODE(factor);
BOOST_SPIRIT_DEBUG_NODE(simple);
BOOST_SPIRIT_DEBUG_NODE(value);
BOOST_SPIRIT_DEBUG_NODE(identifier);
}
};
}
int main(int argc, const char *argv[])
{
typedef std::map<std::string, int> SymTable;
SymTable symbols;
Damaris::Calc<std::string::const_iterator, SymTable> calc(symbols);
symbols["TheAnswerToLifeUniverse"] = 100;
symbols["Everything"] = -58;
std::string input = "3*4+5/4, TheAnswerToLifeUniverse + Everything";
std::string::const_iterator f(input.begin()), l(input.end());
std::vector<int> data;
if (qi::phrase_parse(f,l,calc,ascii::space,data))
std::cout << "output: " << karma::format(karma::int_ % ", " << karma::eol, data);
else
std::cout << "problem: '" << std::string(f,l) << "'n";
return 0;
}
输出:
output: 13, 42
1gcc 4.6.1,提升1_48
相关文章:
- Boost.Spirit.Qi 语法,用于 Boost.Fusion 自适应结构中的默认值
- n-ary布尔语法从中缀到前缀的Boost::Spirit转换?
- 使用复合语法解析时出现 Boost.spirit 分割错误
- 如何使用 Boost Spirit x3 编写具有两个后操作数语法的二进制运算符?
- boost :: Spirit :: Karma语法:逗号从结构上划定了带有选件属性的输出
- 无法让 Boost Spirit 语法使用 std::map 的已知键<>
- Boost :: Spirit :: Qi语法使用具有不同迭代剂类型的语法
- 扩展现有的 Spirit 语法(AST 和 skipper 的问题)
- boost :: Spirit :: Qi-与语法结构中的实例成员一起工作
- 为什么 'n boost::spirit 将 foo123 与 (+alpha | +alnum) 语法匹配?
- boostqi::语法不更新使用spirit/fenix的valuetype
- 使用boost::spirit解析Newick语法
- 尝试解析 Boost Spirit 语法时出现编译时错误
- Boost的属性.Spirit语法:Boost::variant的std:vector错误
- 编译错误,带有boost::spirit语法分析器
- 用Spirit语法解析:齐不及格
- 使用简单的Boost::Spirit语法
- Android上的简单boost::spirit语法SIGSEGV
- Boost Spirit语法用于识别从一行到向量的一系列数字
- 编译非常简单的boost::spirit语法错误