Re: X3 employee example with semantic actions
Larry Evans <[email protected]> Fri, 1 Jun 2018 22:19:30 -0500
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <[email protected]> |
On 06/01/2018 05:54 PM, Larry Evans wrote: > On 06/01/2018 05:09 PM, Larry Evans wrote: [snip] >> OOPS :( >> I failed to notice the printout of the attribute after parse >> did not reflect the input to the parse. >> >> I'm now trying to figure out why that's so. >> >> I guess that was your main concern. >> [snip] > > Specifying the rule default attribute, force_attribute=true, changed the > output so that it reflected the input for me. IOW: > > x3::rule<employee_id, ast::employee, true> const > employee = "employee"; > > See if that doesn't get you better results. > Although making force_attribute=true gets correct result, I don't understand why. In addition, when the semantic actions are removed, then it works when force_attribute=false. That seems very counter-intuitive. Is it a bug? Attached is a revised test.cpp with 2 macros: USE_ACTIONS FORCE_ATTRIBUTE to switch on and off the 2 changes. See if you get same results. -regards, Larry ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Spirit-general mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/spirit-general
test.cpp
(text/x-c++src, 5.9 KB)
//The following code was slightly modified from an attachment //to a post to the spirit-general mailing list. //That post's headers were: /* From: Maarten Verhage <[email protected]> Newsgroups: gmane.comp.parsers.spirit.general Subject: Re: X3 employee example with semantic actions Date: Fri, 1 Jun 2018 16:21:27 +0000 Lines: 231 Approved: [email protected] Message-ID: <AM5P192MB0131C2581427AF09905BE421BA620@AM5P192MB0131.EURP192.PROD.OUTLOOK.COM> */ //====================== /*============================================================================= 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 // /////////////////////////////////////////////////////////////////////////////// #include <boost/config/warning_disable.hpp> #include <boost/spirit/home/x3.hpp> #include <boost/fusion/include/adapt_struct.hpp> #include <boost/fusion/include/io.hpp> #include <iostream> #include <fstream> #include <string> namespace client { namespace ast { /////////////////////////////////////////////////////////////////////////// // Our employee struct /////////////////////////////////////////////////////////////////////////// struct employee { int age; std::string surname; std::string forename; double salary; }; using boost::fusion::operator<<; }} // We need to tell fusion about our employee struct // to make it a first-class fusion citizen. This has to // be in global scope. BOOST_FUSION_ADAPT_STRUCT(client::ast::employee, age, surname, forename, salary ) namespace client { /////////////////////////////////////////////////////////////////////////////// // Our employee parser /////////////////////////////////////////////////////////////////////////////// namespace x3 = boost::spirit::x3; struct print_string { static int calls; template <typename Context> void operator()(Context const& ctx) const { std::cout<<"call "<<calls<<"\n"; ++calls; auto attr =boost::spirit::x3::_attr(ctx); std::cout<<"attr="<<attr<<'\n'; auto input=x3::_where( ctx ); auto iter =input.begin(); auto end =input.end(); for ( ; iter != end; ++iter ) { std::cout << *iter; } std::cout<<'\n'; } }; int print_string::calls=1; namespace parser { 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 < class employee , ast::employee #define FORCE_ATTRIBUTE 0 #if FORCE_ATTRIBUTE //This works , true #else //This doesn't work, i.e. attribute //passed to phrase_parse below is //not changed by phrase_parse. #endif > const employee = "employee"; #define USE_ACTIONS 0 auto const quoted_string = lexeme['"' >> +(char_ - '"') >> '"'] #if USE_ACTIONS [client::print_string()] #endif ; auto const employee_def = lit("employee") >> '{' >> int_ >> ',' >> quoted_string >> ',' >> quoted_string >> ',' >> double_ >> '}' ; BOOST_SPIRIT_DEFINE(employee); } } //////////////////////////////////////////////////////////////////////////// // Main program //////////////////////////////////////////////////////////////////////////// int main( int argc, char **argv ) { std::cout << "/////////////////////////////////////////////////////////\n\n"; std::cout << "\t\tAn employee parser for Spirit...\n\n"; std::cout << "/////////////////////////////////////////////////////////\n\n"; char const* filename; if (argc > 1) { filename = argv[1]; } else { std::cerr << "Error: No input file provided." << std::endl; return 1; } std::ifstream in(filename, std::ios_base::in); if (!in) { std::cerr << "Error: Could not open input file: " << filename << std::endl; return 1; } std::string storage; // We will read the contents here. std::copy( std::istream_iterator<char>(in), std::istream_iterator<char>(), std::back_inserter(storage) ); std::cout<<"USE_ACTIONS="<<USE_ACTIONS<<"\n"; std::cout<<"FORCE_ATTRIBUTE="<<FORCE_ATTRIBUTE<<"\n"; std::cout<<"input=[\n"<<storage<<"\n]\n"; using boost::spirit::x3::ascii::space; typedef std::string::const_iterator iterator_type; using client::parser::employee; client::ast::employee emp; iterator_type iter = storage.begin(); iterator_type const end = storage.end(); bool r = phrase_parse(iter, end, employee, space, emp); if (r && iter == end) { std::cout << boost::fusion::tuple_open('['); std::cout << boost::fusion::tuple_close(']'); std::cout << boost::fusion::tuple_delimiter(", "); std::cout << "-------------------------\n"; std::cout << "Parsing succeeded\n"; std::cout << "got: " << emp << std::endl; std::cout << "\n-------------------------\n"; } else { std::cout << "-------------------------\n"; std::cout << "Parsing failed\n"; std::cout << "-------------------------\n"; } return 0; }