Last active
June 6, 2018 14:35
-
-
Save cppljevans/0f4351f127c2e651d8094877a9510e5a to your computer and use it in GitHub Desktop.
x3 employees using alternative to position_tagged
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
/*============================================================================= | |
Copyright (c) 2002-2015 Joel de Guzman | |
Distributed under the Boost Software License, Version 1.0. (See accompanying | |
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
=============================================================================*/ | |
/////////////////////////////////////////////////////////////////////////////// | |
// | |
// A parser for arbitrary tuples. This example presents a parser | |
// for an employee structure. | |
// | |
// [ JDG May 9, 2007 ] | |
// [ JDG May 13, 2015 ] spirit X3 | |
// [ LJE June 2, 2018] | |
// Illustrate how to satisfy [email protected]'s requirement | |
// "to get the two iterators of a rule match" as he expressed in | |
// expressed in posts: | |
// https://sourceforge.net/p/spirit/mailman/message/36332995/ | |
// https://sourceforge.net/p/spirit/mailman/message/36333543/ | |
// using annotated attributes as in: | |
// https://github.com/boostorg/spirit/blob/develop/example/x3/annotation.cpp | |
// | |
/////////////////////////////////////////////////////////////////////////////// | |
#include <boost/config/warning_disable.hpp> | |
//#define BOOST_SPIRIT_X3_DEBUG | |
#include <boost/spirit/home/x3.hpp> | |
#include <boost/spirit/home/x3/support/ast/position_tagged.hpp> | |
#include <boost/fusion/include/adapt_struct.hpp> | |
#include <boost/fusion/include/io.hpp> | |
#include <iostream> | |
#include <string> | |
namespace client { namespace ast | |
{ | |
namespace x3 = boost::spirit::x3; | |
struct employee : x3::position_tagged | |
{ | |
//#define EMPTY_TAGGED | |
#ifndef EMPTY_TAGGED | |
int age; | |
std::string first_name; | |
std::string last_name; | |
double salary; | |
friend std::ostream& operator<<(std::ostream& sout, employee const& x) | |
{ | |
sout | |
<<"{ age="<<x.age<<"\n" | |
<<", first_name="<<x.first_name<<"\n" | |
<<", last_name="<<x.last_name<<"\n" | |
<<", salary="<<x.salary<<"\n" | |
<<"}\n"; | |
return sout; | |
} | |
#endif | |
}; | |
}} | |
// We need to tell fusion about our employee struct | |
// to make it a first-class fusion citizen. This has to | |
// be in global scope. | |
#ifndef EMPTY_TAGGED | |
BOOST_FUSION_ADAPT_STRUCT(client::ast::employee | |
, age, first_name, last_name, salary | |
) | |
#else | |
BOOST_FUSION_ADAPT_STRUCT(client::ast::employee | |
) | |
#endif | |
namespace client | |
{ | |
namespace parser | |
{ | |
namespace x3 = boost::spirit::x3; | |
namespace ascii = boost::spirit::x3::ascii; | |
/////////////////////////////////////////////////////////////////////// | |
// Our annotation handler | |
/////////////////////////////////////////////////////////////////////// | |
// tag used to get the position cache from the context | |
struct position_cache_tag; | |
struct annotate_position | |
{ | |
template <typename T, typename Iterator, typename Context> | |
inline void on_success(Iterator const& first, Iterator const& last | |
, T& ast, Context const& context) | |
{ | |
auto& position_cache = x3::get<position_cache_tag>(context).get(); | |
position_cache.annotate(ast, first, last); | |
} | |
}; | |
/////////////////////////////////////////////////////////////////////// | |
// Our annotated rule_id's | |
/////////////////////////////////////////////////////////////////////// | |
struct employee_class : annotate_position {}; | |
/////////////////////////////////////////////////////////////////////// | |
// Our employee parser | |
/////////////////////////////////////////////////////////////////////// | |
using x3::int_; | |
using x3::double_; | |
using x3::lexeme; | |
using ascii::char_; | |
namespace x3 = boost::spirit::x3; | |
namespace ascii = boost::spirit::x3::ascii; | |
using x3::int_; | |
using x3::lit; | |
using x3::double_; | |
using x3::lexeme; | |
using ascii::char_; | |
x3::rule<employee_class, ast::employee> const employee = "employee"; | |
auto const quoted_string = lexeme['"' >> +(char_ - '"') >> '"']; | |
auto const employee_def = employee | |
= '{' >> int_ | |
>> ',' >> quoted_string | |
>> ',' >> quoted_string | |
>> ',' >> double_ | |
>> '}' | |
; | |
auto const employees = employee_def >> *(',' >> employee_def); | |
} | |
} | |
// Sample input: | |
std::string input = R"( | |
{ | |
23, | |
"Amanda", | |
"Stefanski", | |
1000.99 | |
}, | |
{ | |
35, | |
"Angie", | |
"Chilcote", | |
2000.99 | |
}, | |
{ | |
43, | |
"Dannie", | |
"Dillinger", | |
3000.99 | |
}, | |
{ | |
22, | |
"Dorene", | |
"Dole", | |
2500.99 | |
}, | |
{ | |
38, | |
"Rossana", | |
"Rafferty", | |
5000.99 | |
} | |
)"; | |
//////////////////////////////////////////////////////////////////////////// | |
// Main program | |
//////////////////////////////////////////////////////////////////////////// | |
int | |
main() | |
{ | |
std::cout << "/////////////////////////////////////////////////////////\n\n"; | |
std::cout << "\t\tAn employee parser for Spirit...\n\n"; | |
std::cout << "/////////////////////////////////////////////////////////\n\n"; | |
using boost::spirit::x3::ascii::space; | |
using iterator_type = std::string::const_iterator; | |
using position_cache = boost::spirit::x3::position_cache<std::vector<iterator_type>>; | |
using client::parser::employees; | |
iterator_type iter = input.begin(); | |
iterator_type const end = input.end(); | |
std::vector<client::ast::employee> emps; | |
using boost::spirit::x3::with; | |
// Our parser | |
using client::parser::employees; | |
using client::parser::position_cache_tag; | |
position_cache positions{iter, end}; | |
auto const parser = | |
// we pass our position_cache to the parser so we can access | |
// it later in our on_sucess handlers | |
with<position_cache_tag>(std::ref(positions)) | |
[ | |
employees | |
]; | |
bool r = phrase_parse(iter, end, parser, space, emps); | |
if (r && iter == end) | |
{ | |
std::cout << "-------------------------\n"; | |
std::cout << "Parsing succeeded\n"; | |
std::cout << "got:\n"; | |
for(auto emp:emps) | |
{ | |
#ifndef EMPTY_TAGGED | |
std::cout << "***struct output***\n"; | |
std::cout<<emp; | |
#endif | |
auto pos = positions.position_of(emp); | |
std::cout << "***string output***\n"; | |
std::cout << std::string(pos.begin(), pos.end()) << std::endl; | |
std::cout << "-------------------------\n"; | |
} | |
std::cout << ".\n"; | |
std::cout << "\n-------------------------\n"; | |
} | |
else | |
{ | |
std::cout << "-------------------------\n"; | |
std::cout << "Parsing failed\n"; | |
std::cout << "-------------------------\n"; | |
} | |
return 0; | |
} |
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
/*============================================================================= | |
Copyright (c) 2002-2015 Joel de Guzman | |
Distributed under the Boost Software License, Version 1.0. (See accompanying | |
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
=============================================================================*/ | |
/////////////////////////////////////////////////////////////////////////////// | |
// | |
// A parser for arbitrary tuples. This example presents a parser | |
// for an employee structure. | |
// | |
// [ JDG May 9, 2007 ] | |
// [ JDG May 13, 2015 ] spirit X3 | |
// [ LJE June 2, 2018] | |
// Illustrate how to satisfy [email protected]'s requirement | |
// "to get the two iterators of a rule match" as he expressed in | |
// posts: | |
// https://sourceforge.net/p/spirit/mailman/message/36332995/ | |
// https://sourceforge.net/p/spirit/mailman/message/36333543/ | |
// | |
/////////////////////////////////////////////////////////////////////////////// | |
#include <boost/config/warning_disable.hpp> | |
//#define BOOST_SPIRIT_X3_DEBUG | |
#include <boost/spirit/home/x3.hpp> | |
#include <iostream> | |
#include <string> | |
namespace client | |
{ | |
/////////////////////////////////////////////////////////////////////////////// | |
// Our employee parser | |
/////////////////////////////////////////////////////////////////////////////// | |
namespace parser | |
{ | |
using iterator_type=std::string::const_iterator; | |
} | |
} | |
namespace client { namespace ast | |
{ | |
/////////////////////////////////////////////////////////////////////////// | |
// Our employee struct | |
/////////////////////////////////////////////////////////////////////////// | |
struct employee | |
{ | |
client::parser::iterator_type beg; | |
client::parser::iterator_type end; | |
friend std::ostream& operator<<(std::ostream& sout, employee const& x) | |
{ | |
return sout << std::string(x.beg,x.end); | |
} | |
}; | |
}} | |
namespace client | |
{ | |
/////////////////////////////////////////////////////////////////////////////// | |
// Our employee parser | |
/////////////////////////////////////////////////////////////////////////////// | |
namespace parser | |
{ | |
namespace x3 = boost::spirit::x3; | |
namespace ascii = boost::spirit::x3::ascii; | |
using x3::int_; | |
using x3::lit; | |
using x3::double_; | |
using x3::eps; | |
using x3::lexeme; | |
using ascii::char_; | |
using x3::_val; | |
using x3::_where; | |
auto employee_act_beg = [](auto& ctx) | |
{ | |
auto iter=_where(ctx).begin(); | |
_val(ctx).beg=iter; | |
}; | |
auto employee_act_end = [](auto& ctx) | |
{ | |
auto iter=_where(ctx).begin(); | |
_val(ctx).end=iter; | |
std::cout<<"employee_act_end:iter_beg..iter_end=\n"; | |
std::cout<<_val(ctx); | |
std::cout<<".\n"; | |
}; | |
x3::rule<class employee, ast::employee> const employee = "employee"; | |
auto const quoted_string = lexeme['"' >> +(char_ - '"') >> '"']; | |
auto const employee_def = employee | |
= eps[employee_act_beg] | |
>> '{' >> int_ | |
>> ',' >> quoted_string | |
>> ',' >> quoted_string | |
>> ',' >> double_ | |
>> '}' | |
>> eps[employee_act_end] | |
; | |
auto const employees = employee_def >> *(',' >> employee_def); | |
} | |
} | |
// Sample input: | |
std::string input = R"( | |
{ | |
23, | |
"Amanda", | |
"Stefanski", | |
1000.99 | |
}, | |
{ | |
35, | |
"Angie", | |
"Chilcote", | |
2000.99 | |
}, | |
{ | |
43, | |
"Dannie", | |
"Dillinger", | |
3000.99 | |
}, | |
{ | |
22, | |
"Dorene", | |
"Dole", | |
2500.99 | |
}, | |
{ | |
38, | |
"Rossana", | |
"Rafferty", | |
5000.99 | |
} | |
)"; | |
//////////////////////////////////////////////////////////////////////////// | |
// Main program | |
//////////////////////////////////////////////////////////////////////////// | |
int | |
main() | |
{ | |
std::cout << "/////////////////////////////////////////////////////////\n\n"; | |
std::cout << "\t\tAn employee parser for Spirit...\n\n"; | |
std::cout << "/////////////////////////////////////////////////////////\n\n"; | |
using boost::spirit::x3::ascii::space; | |
using client::parser::iterator_type; | |
using client::parser::employees; | |
iterator_type iter = input.begin(); | |
iterator_type const end = input.end(); | |
std::vector<client::ast::employee> emps; | |
bool r = phrase_parse(iter, end, employees, space, emps); | |
if (r && iter == end) | |
{ | |
std::cout << "-------------------------\n"; | |
std::cout << "Parsing succeeded\n"; | |
std::cout << "got:\n"; | |
for(auto emp:emps) | |
{ | |
std::cout << emp << ";\n"; | |
} | |
std::cout << ".\n"; | |
std::cout << "\n-------------------------\n"; | |
} | |
else | |
{ | |
std::cout << "-------------------------\n"; | |
std::cout << "Parsing failed\n"; | |
std::cout << "-------------------------\n"; | |
} | |
return 0; | |
} |
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
/*============================================================================= | |
Copyright (c) 2002-2015 Joel de Guzman | |
Distributed under the Boost Software License, Version 1.0. (See accompanying | |
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
=============================================================================*/ | |
/////////////////////////////////////////////////////////////////////////////// | |
// | |
// A parser for arbitrary tuples. This example presents a parser | |
// for an employee structure. | |
// | |
// [ JDG May 9, 2007 ] | |
// [ JDG May 13, 2015 ] spirit X3 | |
// [ LJE June 2, 2018] | |
// Illustrate how to satisfy [email protected]'s requirement | |
// "to get the two iterators of a rule match" as he expressed in | |
// using raw directive. | |
// | |
/////////////////////////////////////////////////////////////////////////////// | |
#include <boost/config/warning_disable.hpp> | |
//#define BOOST_SPIRIT_X3_DEBUG | |
#include <boost/spirit/home/x3.hpp> | |
#include <iostream> | |
#include <string> | |
namespace client { namespace ast | |
{ | |
/////////////////////////////////////////////////////////////////////////// | |
// Our employee attribute | |
// (== raw directive attribute, converted to std::string) | |
/////////////////////////////////////////////////////////////////////////// | |
using employee=std::string; | |
}} | |
namespace client | |
{ | |
/////////////////////////////////////////////////////////////////////////////// | |
// Our employee parser | |
/////////////////////////////////////////////////////////////////////////////// | |
namespace parser | |
{ | |
namespace x3 = boost::spirit::x3; | |
using x3::int_; | |
using x3::double_; | |
using x3::lexeme; | |
using x3::ascii::char_; | |
x3::rule<class employee, ast::employee> const employee = "employee"; | |
auto const quoted_string = lexeme['"' >> +(char_ - '"') >> '"']; | |
auto const employee_def = employee = x3::raw | |
[ '{' >> int_ | |
>> ',' >> quoted_string | |
>> ',' >> quoted_string | |
>> ',' >> double_ | |
>> '}' | |
] | |
; | |
auto const employees = employee_def >> *(',' >> employee_def); | |
} | |
} | |
// Sample input: | |
std::string input = R"( | |
{ | |
23, | |
"Amanda", | |
"Stefanski", | |
1000.99 | |
}, | |
{ | |
35, | |
"Angie", | |
"Chilcote", | |
2000.99 | |
}, | |
{ | |
43, | |
"Dannie", | |
"Dillinger", | |
3000.99 | |
}, | |
{ | |
22, | |
"Dorene", | |
"Dole", | |
2500.99 | |
}, | |
{ | |
38, | |
"Rossana", | |
"Rafferty", | |
5000.99 | |
} | |
)"; | |
//////////////////////////////////////////////////////////////////////////// | |
// Main program | |
//////////////////////////////////////////////////////////////////////////// | |
int | |
main() | |
{ | |
std::cout << "/////////////////////////////////////////////////////////\n\n"; | |
std::cout << "\t\tAn employee parser for Spirit...\n\n"; | |
std::cout << "/////////////////////////////////////////////////////////\n\n"; | |
using boost::spirit::x3::ascii::space; | |
using iterator_type=std::string::const_iterator; | |
using client::parser::employees; | |
iterator_type iter = input.begin(); | |
iterator_type const end = input.end(); | |
std::vector<client::ast::employee> emps; | |
bool r = phrase_parse(iter, end, employees, space, emps); | |
if (r && iter == end) | |
{ | |
std::cout << "-------------------------\n"; | |
std::cout << "Parsing succeeded\n"; | |
std::cout << "got:\n"; | |
for(auto emp:emps) | |
{ | |
//std::cout << std::string(emp.begin(),emp.end()) << ";\n"; | |
std::cout << emp << ";\n"; | |
} | |
std::cout << ".\n"; | |
std::cout << "\n-------------------------\n"; | |
} | |
else | |
{ | |
std::cout << "-------------------------\n"; | |
std::cout << "Parsing failed\n"; | |
std::cout << "-------------------------\n"; | |
} | |
return 0; | |
} |
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
///////////////////////////////////////////////////////// | |
An employee parser for Spirit... | |
///////////////////////////////////////////////////////// | |
------------------------- | |
Parsing succeeded | |
got: | |
{ | |
23, | |
"Amanda", | |
"Stefanski", | |
1000.99 | |
}; | |
{ | |
35, | |
"Angie", | |
"Chilcote", | |
2000.99 | |
}; | |
{ | |
43, | |
"Dannie", | |
"Dillinger", | |
3000.99 | |
}; | |
{ | |
22, | |
"Dorene", | |
"Dole", | |
2500.99 | |
}; | |
{ | |
38, | |
"Rossana", | |
"Rafferty", | |
5000.99 | |
}; | |
. | |
------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment