blob: 9ffb4168dd9b1309c7ab4abbcddd72a6da632483 [file] [log] [blame]
/*=============================================================================
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;
}