Re: X3 employee example with semantic actions
Maarten Verhage <[email protected]> Fri, 1 Jun 2018 16:21:27 +0000
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <AM5P192MB0131C2581427AF09905BE421BA620@AM5P192MB0131.EURP192.PROD.OUTLOOK.COM> |
> > IIUC, you'd do that like the example employee.cpp does here: > > https://github.com/boostorg/spirit/blob/develop/example/x3/employee.cpp#L108 > > Or am I missing what you mean by "properly instantiate"? > >> And in the semantec actions how >> I can gain access to that object. Maybe it turns out to be very simple. >> But >> as Spirit shows so many advanced C++ stuff I'm questioning many things to >> check whether that is a recommended way to build upon the examples. >> >> My intention is to first store the file contents into a data structure >> (for >> this example the employee object), > > But this is exactly what parsers do with the attribute argument; hence, > I'm a bit puzzled by your question. > >> and then dealing with some ostream. But >> the ostream part I can figure out myself. > > IOW, once the attribute is created by the parser, you then can "figure > out" how to output it to an ostream after the parser is done? > >> >> Apart for the documentation examples Are there more good Spirit x3 >> application examples. Preferably with semantic actions to teach me to >> utilize most of this API facilities. For my understanding **I have** to >> see >> real examples in which something is used to understand it's intent. > > Are the examples here: > > https://github.com/boostorg/spirit/blob/develop/example/x3/actions.cpp > > lacking in some way? > >> >> Regards, Maarten >> >> ------------------------------------------------------------------------------ >> 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 >> > > > > ------------------------------------------------------------------------------ > 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 > Hi Larry and the other list members, The actions example does not have a separate grammer section like employee does. So that was the reason that I asked for a proper suggestion to gain access to the employee object in the grammer section in order to store it properly. I appreciate your willingness to help me out on this one. However what annoys me is the amount of questioning my objectives. What I would like to see is that you just accept my objectives to exercise around this employee example and address the issue as I describe them. It's hard for me to politely asking you to not bother on this ostream stuff for example and focus on the real issue I'm facing. You know the main question has been in the title all the time: Can you show me a semantic action version of the Spirit X3 employee example? Ok, meanwhile I tried this myself. Right now I've instantiated emp in the client namespace like this. And called the 4 argument version of phrase_parse. See attachment. namespace client { ////////////////////////// // Our employee parser ////////////////////////// client::ast::employee emp; And in the semantic actions I now have access to emp. Is this a proper way to do so? I'm also experimenting with the _where iterator range attribute of Context. But I've a problem with this. Maybe I did something wrong but what I get is an iterator range from the end of the match to the end of input stream (std::string storage). The program output is my attachment result.txt. Is this intended behavior, a bug or did I something wrong? Best regards, Maarten Verhage ------------------------------------------------------------------------------ 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/plain, 5.3 KB)
/*=============================================================================
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
//
///////////////////////////////////////////////////////////////////////////////
#define STRICT 1
#include <windows.h>
#include <cstddef>
#include <cstdio>
#include <cstdint>
#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>
#include <complex>
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
///////////////////////////////////////////////////////////////////////////////
client::ast::employee emp;
namespace x3 = boost::spirit::x3;
struct print_string
{
template <typename Context>
void operator()(Context const& ctx) const
{
static int calls = 1;
printf( "call %d\n", calls );
++calls;
std::string::const_iterator iter = x3::_where( ctx ).begin();
std::string::const_iterator end = x3::_where( ctx ).end();
printf( "begin offset %d\n", iter );
printf( "end offset %d\n", end );
for ( ; iter != end; ++iter )
{
std::cout << *iter;
}
putchar( '\n' );
}
};
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> const employee = "employee";
auto const quoted_string = lexeme['"' >> +(char_ - '"') >> '"']
[client::print_string()];
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.
in.unsetf( std::ios::skipws ); // No white space skipping!
std::copy(
std::istream_iterator<char>(in),
std::istream_iterator<char>(),
std::back_inserter(storage) );
using boost::spirit::x3::ascii::space;
typedef std::string::const_iterator iterator_type;
using client::parser::employee;
iterator_type iter = storage.begin();
iterator_type const end = storage.end();
bool r = phrase_parse( iter, end, employee, space );
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: " << client::emp << std::endl;
std::cout << "\n-------------------------\n";
}
else
{
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
}
return 0;
}
1.txt
(text/plain, 49 B)
employee {
66,
"Putin",
"Vladimir",
306000
}
result.txt
(text/plain, 393 B)
///////////////////////////////////////////////////////// An employee parser for Spirit... ///////////////////////////////////////////////////////// call 1 begin offset 6453526 end offset 6453548 , "Vladimir", 306000 } call 2 begin offset 6453538 end offset 6453548 , 306000 } ------------------------- Parsing succeeded got: [0, , , 0] -------------------------