| // 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; |
| } |
| |