Reputation: 1579
I'm trying to compile the following seemingly simple code using GCC 3.4.6 and Boost 1.43 and it's generating an internal compiler error:
#include <string>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/qi.hpp>
namespace lex = boost::spirit::lex;
namespace qi = boost::spirit::qi;
typedef lex::lexertl::token<std::string::iterator> TokenT;
typedef lex::lexertl::actor_lexer<TokenT> LexerT;
template <typename LexerT>
struct Tokens: public lex::lexer<LexerT>
{};
int main()
{
typedef Tokens<LexerT>::iterator_type IteratorT;
qi::rule<IteratorT, int> expression;
expression = (qi::int_ >> qi::int_) [ qi::_val = qi::_1 ];
}
The generated error:
.../boost/mpl/aux_/preprocessed/gcc/template_arity.hpp:83: internal compiler error: in lookup_member, at cp/search.c:1300
The last line in main()
is generating this error. This error goes away by either letting the expression
rule work on an std::string::iterator
instead of IteratorT
.
Any help with fixing the error while still working with a lexer is much appreciated.
Thanks!
Upvotes: 1
Views: 621
Reputation: 392833
You missed the parens:
qi::rule<IteratorT, int()> expression;
This might fix the compile error (allthough I can't check, since both gcc, clang and msvc happily compiled it)
You may want to reduce the compiler stress:
Possibly more in that region.
I did a simple
grep -EoRh '\<\w+_LIMIT\>' ~/custom/boost_1_50_0/boost/spirit/home/ -h | sort -u
to get a list of possible defines, and based a following change on it:
#ifdef LEAN
#define PHOENIX_ACTOR_LIMIT 3 // boost 1_50 default: 10
#define PHOENIX_ARG_LIMIT 5 // boost 1_50 default: 10
#define PHOENIX_CATCH_LIMIT 1 // boost 1_50 default: 9
#define PHOENIX_COMPOSITE_LIMIT 5 // boost 1_50 default: 10
#define PHOENIX_DYNAMIC_LIMIT 1 // boost 1_50 default: 10
#define PHOENIX_LIMIT 5 // boost 1_50 default: 10
#define PHOENIX_LOCAL_LIMIT 3 // boost 1_50 default: 10
#define PHOENIX_MEMBER_LIMIT 3 // boost 1_50 default: 8
#define SPIRIT_ARGUMENTS_LIMIT 5 // boost 1_50 default: 10
#define SPIRIT_ATTRIBUTES_LIMIT 5 // boost 1_50 default: 10
#endif
#include <string>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace lex = boost::spirit::lex;
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
struct funcImpl
{
template <typename T>
struct result { typedef int type; };
template <typename T>
int operator()(T& x) const {
return 0;
}
};
typedef lex::lexertl::token<std::string::iterator> TokenT;
typedef lex::lexertl::actor_lexer<TokenT> LexerT;
template <typename LexerT>
struct Tokens: public lex::lexer<LexerT>
{};
int main()
{
//typedef Tokens<LexerT>::iterator_type IteratorT;
typedef char* IteratorT;
qi::rule<IteratorT, int()> expression;
phx::function<funcImpl> func = funcImpl();
expression = (qi::int_ >> qi::int_) [ qi::_val = func(qi::_1) ];
std::cout << "#define PHOENIX_ACTOR_LIMIT " << PHOENIX_ACTOR_LIMIT << '\n';
std::cout << "#define PHOENIX_ARG_LIMIT " << PHOENIX_ARG_LIMIT << '\n';
std::cout << "#define PHOENIX_CATCH_LIMIT " << PHOENIX_CATCH_LIMIT << '\n';
std::cout << "#define PHOENIX_COMPOSITE_LIMIT " << PHOENIX_COMPOSITE_LIMIT << '\n';
std::cout << "#define PHOENIX_DYNAMIC_LIMIT " << PHOENIX_DYNAMIC_LIMIT << '\n';
std::cout << "#define PHOENIX_LIMIT " << PHOENIX_LIMIT << '\n';
std::cout << "#define PHOENIX_LOCAL_LIMIT " << PHOENIX_LOCAL_LIMIT << '\n';
std::cout << "#define PHOENIX_MEMBER_LIMIT " << PHOENIX_MEMBER_LIMIT << '\n';
std::cout << "#define SPIRIT_ARGUMENTS_LIMIT " << SPIRIT_ARGUMENTS_LIMIT << '\n';
std::cout << "#define SPIRIT_ATTRIBUTES_LIMIT " << SPIRIT_ATTRIBUTES_LIMIT << '\n';
//std::cout << "#define BOOST_PHOENIX_LIMIT " << BOOST_PHOENIX_LIMIT << '\n';
//std::cout << "#define BOOST_SPIRIT_CLOSURE_LIMIT " << BOOST_SPIRIT_CLOSURE_LIMIT << '\n';
//std::cout << "#define BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT " << BOOST_SPIRIT_GRAMMAR_STARTRULE_TYPE_LIMIT << '\n';
//std::cout << "#define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT " << BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT << '\n';
//std::cout << "#define BOOST_SPIRIT_SELECT_LIMIT " << BOOST_SPIRIT_SELECT_LIMIT << '\n';
//std::cout << "#define BOOST_SPIRIT_SWITCH_CASE_LIMIT " << BOOST_SPIRIT_SWITCH_CASE_LIMIT << '\n';
//std::cout << "#define PHOENIX_CONSTRUCT_LIMIT " << PHOENIX_CONSTRUCT_LIMIT << '\n';
//std::cout << "#define SPIRIT_CLOSURE_LIMIT " << SPIRIT_CLOSURE_LIMIT << '\n';
}
Now, the following size changes happen (in LoC preprocessed):
sehe@mint12:/tmp$ g++ -g0 -O0 -I /home/sehe/custom/boost_1_50_0/ test.cpp -E | wc -l
193011
sehe@mint12:/tmp$ g++ -g0 -O0 -I ./boost_1_43_0/ test.cpp -DLEAN -E | wc -l
168862
basically, a >10% reduction in code lines. It just might help.
Upvotes: 1