113 lines
3.2 KiB
C++
113 lines
3.2 KiB
C++
/*=============================================================================
|
|
Copyright (c) 2016 Frank Hein, maxence business consulting gmbh
|
|
|
|
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)
|
|
==============================================================================*/
|
|
|
|
#include <iostream>
|
|
#include <map>
|
|
|
|
#include <boost/spirit/home/qi.hpp>
|
|
#include <boost/spirit/home/qi/nonterminal/grammar.hpp>
|
|
#include <boost/spirit/include/phoenix.hpp>
|
|
#include <boost/foreach.hpp>
|
|
|
|
namespace qi = boost::spirit::qi;
|
|
|
|
typedef std::string::const_iterator iterator_type;
|
|
typedef std::string result_type;
|
|
|
|
template<typename Parser>
|
|
void parse(const std::string message, const std::string& input, const std::string& rule, const Parser& parser) {
|
|
iterator_type iter = input.begin(), end = input.end();
|
|
|
|
std::vector<result_type> parsed_result;
|
|
|
|
std::cout << "-------------------------\n";
|
|
std::cout << message << "\n";
|
|
std::cout << "Rule: " << rule << std::endl;
|
|
std::cout << "Parsing: \"" << input << "\"\n";
|
|
|
|
bool result = qi::phrase_parse(iter, end, parser, qi::space, parsed_result);
|
|
if (result)
|
|
{
|
|
std::cout << "Parser succeeded.\n";
|
|
std::cout << "Parsed " << parsed_result.size() << " elements:";
|
|
BOOST_FOREACH(result_type const& str, parsed_result)
|
|
{
|
|
std::cout << "[" << str << "]";
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Parser failed" << std::endl;
|
|
}
|
|
if (iter == end) {
|
|
std::cout << "EOI reached." << std::endl;
|
|
}
|
|
else {
|
|
std::cout << "EOI not reached. Unparsed: \"" << std::string(iter, end) << "\"" << std::endl;
|
|
}
|
|
std::cout << "-------------------------\n";
|
|
|
|
}
|
|
|
|
namespace grammars {
|
|
namespace phx = boost::phoenix;
|
|
|
|
template <typename Iterator>
|
|
struct ident : qi::grammar < Iterator, std::string(), qi::space_type>
|
|
{
|
|
ident();
|
|
|
|
qi::rule <iterator_type, std::string(), qi::space_type>
|
|
id, id_list, qualified_id;
|
|
};
|
|
|
|
template <typename Iterator>
|
|
ident<Iterator>::ident() : ident::base_type(id_list) {
|
|
|
|
using qi::on_error;
|
|
using qi::fail;
|
|
using qi::expect;
|
|
|
|
id = (qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_'));
|
|
|
|
id_list = expect[id >> qi::lit(';')];
|
|
|
|
on_error<fail>(id_list,
|
|
phx::ref(std::cout)
|
|
<< "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl
|
|
<< "Error! Expecting "
|
|
<< qi::_4
|
|
<< " here: "
|
|
<< phx::construct<std::string>(qi::_3, qi::_2) << std::endl
|
|
<< "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl
|
|
);
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
|
|
grammars::ident<iterator_type> id;
|
|
|
|
parse("expect directive, fail on first"
|
|
, "1234; id2;"
|
|
, "qi::expect[ id >> qi::lit(';') ]"
|
|
, id);
|
|
|
|
parse("expect directive, fail on second"
|
|
, "id1, id2"
|
|
, "qi::expect[ id >> qi::lit(';') ]"
|
|
, id);
|
|
|
|
parse("expect directive, success"
|
|
, "id1;"
|
|
, "qi::expect[ id >> qi::lit(';') ]"
|
|
, id);
|
|
|
|
return 0;
|
|
}
|