123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- /*=============================================================================
- Copyright (c) 2001-2003 Hartmut Kaiser
- http://spirit.sourceforge.net/
- Use, modification and distribution is subject to 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)
- =============================================================================*/
- ///////////////////////////////////////////////////////////////////////////////
- //
- // This example shows:
- // 1. Parsing of different comment styles
- // parsing C/C++-style comment
- // parsing C++-style comment
- // parsing PASCAL-style comment
- // 2. Parsing tagged data with the help of the confix_parser
- // 3. Parsing tagged data with the help of the confix_parser but the semantic
- // action is directly attached to the body sequence parser
- //
- ///////////////////////////////////////////////////////////////////////////////
- #include <string>
- #include <iostream>
- #include <cassert>
- #include <boost/spirit/include/classic_core.hpp>
- #include <boost/spirit/include/classic_confix.hpp>
- #include <boost/spirit/include/classic_chset.hpp>
- ///////////////////////////////////////////////////////////////////////////////
- // used namespaces
- using namespace std;
- using namespace BOOST_SPIRIT_CLASSIC_NS;
- ///////////////////////////////////////////////////////////////////////////////
- // actor called after successfully matching a single character
- class actor_string
- {
- public:
- actor_string(std::string &rstr) :
- matched(rstr)
- {
- }
- void operator() (const char *pbegin, const char *pend) const
- {
- matched += std::string(pbegin, pend-pbegin);
- }
- private:
- std::string &matched;
- };
- ///////////////////////////////////////////////////////////////////////////////
- // actor called after successfully matching a C++-comment
- void actor_cpp (const char *pfirst, const char *plast)
- {
- cout << "Parsing C++-comment" <<endl;
- cout << "Matched (" << plast-pfirst << ") characters: ";
- cout << "\"" << std::string(pfirst, plast) << "\"" << endl;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // main entry point
- int main ()
- {
- ///////////////////////////////////////////////////////////////////////////////
- //
- // 1. Parsing different comment styles
- // parsing C/C++-style comments (non-nested!)
- //
- ///////////////////////////////////////////////////////////////////////////////
- char const* pCComment = "/* This is a /* nested */ C-comment */";
- rule<> cpp_comment;
- cpp_comment =
- comment_p("/*", "*/") // rule for C-comments
- | comment_p("//") // rule for C++ comments
- ;
- std::string comment_c;
- parse_info<> result;
- result = parse (pCComment, cpp_comment[actor_string(comment_c)]);
- if (result.hit)
- {
- cout << "Parsed C-comment successfully!" << endl;
- cout << "Matched (" << (int)comment_c.size() << ") characters: ";
- cout << "\"" << comment_c << "\"" << endl;
- }
- else
- {
- cout << "Failed to parse C/C++-comment!" << endl;
- }
- cout << endl;
- // parsing C++-style comment
- char const* pCPPComment = "// This is a C++-comment\n";
- std::string comment_cpp;
- result = parse (pCPPComment, cpp_comment[&actor_cpp]);
- if (result.hit)
- cout << "Parsed C++-comment successfully!" << endl;
- else
- cout << "Failed to parse C++-comment!" << endl;
- cout << endl;
- // parsing PASCAL-style comment (nested!)
- char const* pPComment = "{ This is a (* nested *) PASCAL-comment }";
- rule<> pascal_comment;
- pascal_comment = // in PASCAL we have two comment styles
- comment_nest_p('{', '}') // both may be nested
- | comment_nest_p("(*", "*)")
- ;
- std::string comment_pascal;
- result = parse (pPComment, pascal_comment[actor_string(comment_pascal)]);
- if (result.hit)
- {
- cout << "Parsed PASCAL-comment successfully!" << endl;
- cout << "Matched (" << (int)comment_pascal.size() << ") characters: ";
- cout << "\"" << comment_pascal << "\"" << endl;
- }
- else
- {
- cout << "Failed to parse PASCAL-comment!" << endl;
- }
- cout << endl;
- ///////////////////////////////////////////////////////////////////////////////
- //
- // 2. Parsing tagged data with the help of the confix parser
- //
- ///////////////////////////////////////////////////////////////////////////////
- std::string body;
- rule<> open_tag, html_tag, close_tag, body_text;
- open_tag =
- str_p("<b>")
- ;
- body_text =
- anychar_p
- ;
- close_tag =
- str_p("</b>")
- ;
- html_tag =
- confix_p (open_tag, (*body_text)[actor_string(body)], close_tag)
- ;
- char const* pTag = "<b>Body text</b>";
- result = parse (pTag, html_tag);
- if (result.hit)
- {
- cout << "Parsed HTML snippet \"<b>Body text</b>\" successfully "
- "(with re-attached actor)!" << endl;
- cout << "Found body (" << (int)body.size() << " characters): ";
- cout << "\"" << body << "\"" << endl;
- }
- else
- {
- cout << "Failed to parse HTML snippet (with re-attached actor)!"
- << endl;
- }
- cout << endl;
- ///////////////////////////////////////////////////////////////////////////////
- //
- // 3. Parsing tagged data with the help of the confix_parser but the
- // semantic action is directly attached to the body sequence parser
- // (see comment in confix.hpp) and out of the usage of the 'direct()'
- // construction function no automatic refactoring takes place.
- //
- // As you can see, for successful parsing it is required to refactor the
- // confix parser by hand. To see, how it fails, you can try the following:
- //
- // html_tag_direct =
- // confix_p.direct(
- // str_p("<b>"),
- // (*body_text)[actor_string(bodydirect)],
- // str_p("</b>")
- // )
- // ;
- //
- // Here the *body_text parser eats up all the input up to the end of the
- // input sequence.
- //
- ///////////////////////////////////////////////////////////////////////////////
- rule<> html_tag_direct;
- std::string bodydirect;
- html_tag_direct =
- confix_p.direct(
- str_p("<b>"),
- (*(body_text - str_p("</b>")))[actor_string(bodydirect)],
- str_p("</b>")
- )
- ;
- char const* pTagDirect = "<b>Body text</b>";
- result = parse (pTagDirect, html_tag_direct);
- if (result.hit)
- {
- cout << "Parsed HTML snippet \"<b>Body text</b>\" successfully "
- "(with direct actor)!" << endl;
- cout << "Found body (" << (int)bodydirect.size() << " characters): ";
- cout << "\"" << bodydirect << "\"" << endl;
- }
- else
- {
- cout << "Failed to parse HTML snippet (with direct actor)!" << endl;
- }
- cout << endl;
- return 0;
- }
|