Created
March 6, 2020 12:19
-
-
Save cppljevans/86770e37767b38f3aa0cceaea06f4407 to your computer and use it in GitHub Desktop.
skipper in recursive context leads to infinite template instantiation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//OriginalCode: | |
// http://coliru.stacked-crooked.com/a/d149f05af81bf0cf | |
//WhichWasAnswerTo: | |
// https://stackoverflow.com/questions/45899090/recursive-rule-in-spirit-x3/45900983 | |
//DownloadedOn: | |
// 2020-03-06.0512CST | |
//Modifications: | |
// WHAT: | |
// * added macro, USE_TOP_LEVEL_SKIPPER | |
// * depending on defined(USE_TOP_LEVEL_SKIPPER) | |
// used skipper top level or at lower level | |
// WHY: | |
// to see if https://github.com/boostorg/spirit/pull/237 solves problem | |
// mentioned in the stackoverflow question. | |
//Conclusion: | |
// #if defined(USE_TOP_LEVEL_SKIPPER) | |
// runs OK | |
// #else | |
// fails at compile time with: | |
/* | |
/usr/include/boost/spirit/home/x3/support/traits/attribute_of.hpp:35:51: fatal error: recursive template instantiation exceeded | |
maximum depth of 200 | |
typename Component::attribute_type>::type> | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ | |
*/ | |
//============= | |
//#define USE_TOP_LEVEL_SKIPPER | |
//#define BOOST_SPIRIT_X3_DEBUG | |
#include <iostream> | |
#include <boost/fusion/adapted.hpp> | |
#include <boost/spirit/home/x3.hpp> | |
#include <string> | |
#include <vector> | |
#include <variant> | |
struct value: std::variant<int,float,std::vector<value>> | |
{ | |
using base_type = std::variant<int,float,std::vector<value>>; | |
using base_type::variant; | |
friend std::ostream& operator<<(std::ostream& os, base_type const& v) { | |
struct { | |
std::ostream& operator()(float const& f) const { return _os << "float:" << f; } | |
std::ostream& operator()(int const& i) const { return _os << "int:" << i; } | |
std::ostream& operator()(std::vector<value> const& v) const { | |
_os << "tuple: ["; | |
for (auto& el : v) _os << el << ","; | |
return _os << ']'; | |
} | |
std::ostream& _os; | |
} vis { os }; | |
return std::visit(vis, v); | |
} | |
}; | |
namespace parser { | |
namespace x3 = boost::spirit::x3; | |
x3::rule<struct value_class, value> const value_ = "value"; | |
x3::rule<struct o_tuple_class, std::vector<value> > o_tuple_ = "tuple"; | |
x3::real_parser<float, x3::strict_real_policies<float> > float_; | |
const auto o_tuple__def | |
= "tuple" >> x3::lit(':') >> | |
#ifndef USE_TOP_LEVEL_SKIPPER | |
x3::skip(x3::space) [ | |
#endif | |
("[" >> value_ % "," >> "]") | |
#ifndef USE_TOP_LEVEL_SKIPPER | |
] | |
#endif | |
; | |
const auto value__def | |
= "float" >> (':' >> float_) | |
| "int" >> (':' >> x3::int_) | |
| o_tuple_ | |
; | |
BOOST_SPIRIT_DEFINE(value_, o_tuple_) | |
const auto entry_point = | |
#ifdef USE_TOP_LEVEL_SKIPPER | |
x3::skip(x3::space) [ value_ ] | |
#else | |
value_ | |
#endif | |
; | |
} | |
int main() | |
{ | |
for (std::string const str : { | |
"", | |
"float: 3.14", | |
"int: 3.14", | |
"tuple: [float: 3.14,int: 3]", | |
// the following _should_ have compiled with the original skip() configuration: | |
"tuple: [ float: 3.14,\tint: 3 ]", | |
// the following would not have parsed with the original skip() configuration: | |
"float:3.14", | |
"int:3.14", | |
"tuple:[float: 3.14,int: 3]", | |
"tuple:[float:3.14,int:3]", | |
"tuple: [ float:3.14,\tint:3 ]", | |
// one final show case for good measure | |
R"( | |
tuple: [ | |
int : 4, | |
float: 7e9, | |
tuple: [float: -inf], | |
int: 42 | |
])" | |
}) { | |
std::cout << "============ '" << str << "'\n"; | |
//using boost::spirit::x3::parse; | |
auto first = str.begin(), last = str.end(); | |
value val; | |
if (parse(first, last, parser::entry_point, val)) | |
std::cout << "Parsed '" << val << "'\n"; | |
else | |
std::cout << "Parse failed\n"; | |
if (first != last) | |
std::cout << "Remaining input: '" << std::string(first, last) << "'\n"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment