|
Boost Users : |
Subject: [Boost-users] [Spirit] question about alternative list expressions
From: philip tucker (phhht_at_[hidden])
Date: 2010-05-13 17:32:48
/*
Hello,
This code (second copy attached) compiles to recognize dotlists, ie
"a", "a.b", etc.
I want to report on incomplete list errors of the following kind
a.
a.#
The parser now detects such errors by failing to parse them completely.
Instead I want to expect an id after a '.'.
In dotlist_grammar() I wanted to replace this expression
start %= (id % '.') ;
with this one
start %= (id >> (*('.' > id))) ; // XXX
but it won't compile. Neither will this
start %= (id >> (*('.' >> id))) ; // XXX
What's wrong? Is there a difference between the synthesized
attributes of
the two alternative list expressions? Or is it a different bug?
P.S. Both expressions seem to work for int_ instead of id.
Thanks.
*/
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/sequence.hpp>
#include <boost/fusion/include/sequence.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <iostream>
namespace ecgp
{
using namespace std;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;
typedef ascii::space_type space;
// structures, etc.
struct structure
{
vector<string> dotlist;
int filler; // fusion requires >1 members?!
void print(ostream& o) const
{
int i=0;
BOOST_FOREACH(string s, dotlist)
{
if(++i > 1) o << '.';
o << s;
}
}
};
ostream& operator<<(ostream& o, structure const & c)
{
c.print(o);
return o;
};
}
BOOST_FUSION_ADAPT_STRUCT(
ecgp::structure,
(std::vector<std::string>, dotlist)
(int, filler) // fusion requires >1 members?!
)
namespace ecgp
{
// actions
void print_str(string const & v)
{
cout << "str: ";
cout << v << endl;
}
void print_dotlist(vector<string> const & v)
{
cout << "dotlist: ";
int i=0;
BOOST_FOREACH(string s, v)
{
if(++i > 1) cout << '.';
cout << s;
}
cout << endl;
}
void print_structure(structure const & v)
{
cout << "structure: ";
print_dotlist(v.dotlist);
cout << endl;
}
// grammars
template <typename Iterator> // recognize an identifier
struct id_grammar : qi::grammar<Iterator, string(), space>
{
id_grammar() : id_grammar::base_type(start)
{
using ascii::alpha;
using qi::lexeme;
start
%=
lexeme[ +alpha ]
[ &print_str ]
;
}
qi::rule<Iterator, string(), space> start;
};
template <typename Iterator> // recognize a dotlist, ie (string %
'.')
struct dotlist_grammar : qi::grammar<Iterator, vector<string>(),
space>
{
dotlist_grammar() : dotlist_grammar::base_type(start)
{
using qi::int_;
using qi::lexeme;
start %=
// (id >> (*('.' > id))) // XXX
(id % '.')
[ &print_dotlist ]
;
}
id_grammar<Iterator> id;
qi::rule<Iterator, vector<string>(), space> start;
};
template <typename Iterator>
struct structure_grammar : qi::grammar<Iterator,structure(),space>
{
structure_grammar() : structure_grammar::base_type(start)
{
using qi::eps;
using qi::int_;
start
%=
( dotlist
>>
(int_ | eps) // filler
)
[ &print_structure ]
;
}
dotlist_grammar<Iterator> dotlist;
qi::rule<Iterator, structure(), space> start;
};
}
int
main()
{
using namespace std;
using namespace ecgp;
using namespace boost;
typedef string::const_iterator string_iterator;
string s;
cout << "enter a dotlist:\n";
while (getline(cin, s))
{
trim(s);
string_iterator iter = s.begin();
string_iterator end = s.end();
string target(iter, end);
structure list_container;
structure_grammar<string_iterator> g;
bool r = phrase_parse(iter, end, g, boost::spirit::ascii::space,
list_container);
if (r && iter == end) {
cout << "OK: " << target;
cout << endl << endl;
}
else {
cout << "FAIL";
if(! r) cout << "(p)";
if(iter != end) cout << "(e)";
cout << ": " << target;
cout << endl << endl;
}
cout << "enter a dotlist:\n";
}
return 0;
}
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net