blob: 79fa2e57176384bff64e0e12c6d709992946146d [file] [log] [blame]
// Copyright (c) 2001-2010 Hartmut Kaiser
//
// 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)
// The purpose of this example is to demonstrate a simple use case for the
// flush_multi_pass parser.
#include <iostream>
#include <fstream>
#include <string>
//[qi_flush_multi_pass_includes
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/repository/include/qi_flush_multi_pass.hpp>
//]
//[qi_flush_multi_pass_namespace
namespace spirit = boost::spirit;
using boost::spirit::repository::flush_multi_pass;
//]
namespace client
{
//[qi_flush_multi_pass_clear_buffer
template <typename Iterator, typename Skipper>
struct preprocessor : spirit::qi::grammar<Iterator, Skipper>
{
// This is a simplified preprocessor grammar recognizing
//
// #define MACRONAME something
// #undef MACRONAME
//
// Its sole purpose is to show an example how to use the
// flush_multi_pass parser. At the end of each line no backtracking can
// occur anymore so that it's safe to clear all internal buffers in the
// multi_pass.
preprocessor() : preprocessor::base_type(file)
{
using spirit::ascii::char_;
using spirit::qi::eol;
using spirit::qi::lit;
file =
*line
;
line = ( command | *(char_ - eol) )
>> eol
>> flush_multi_pass
;
command =
"#define" >> *lit(' ') >> *(char_ - ' ') >> *lit(' ') >> *(char_ - eol)
| "#undef" >> *lit(' ') >> *(char_ - eol)
;
}
spirit::qi::rule<Iterator, Skipper> file, line, command;
};
//]
}
template <typename Iterator, typename Skipper>
bool parse(Iterator& first, Iterator end, Skipper const& skipper)
{
client::preprocessor<Iterator, Skipper> g;
return boost::spirit::qi::phrase_parse(first, end, g, skipper);
}
int main()
{
namespace spirit = boost::spirit;
using spirit::ascii::char_;
using spirit::qi::eol;
std::ifstream in("flush_multi_pass.txt"); // we get our input from this file
if (!in.is_open()) {
std::cout << "Could not open input file: 'flush_multi_pass.txt'" << std::endl;
return -1;
}
typedef std::istreambuf_iterator<char> base_iterator_type;
spirit::multi_pass<base_iterator_type> first =
spirit::make_default_multi_pass(base_iterator_type(in));
spirit::multi_pass<base_iterator_type> end =
spirit::make_default_multi_pass(base_iterator_type());
bool result = parse(first, end, '#' >> *(char_ - eol) >> eol);
if (!result) {
std::cout << "Failed parsing input file!" << std::endl;
return -2;
}
std::cout << "Successfully parsed input file!" << std::endl;
return 0;
}