2
0
mirror of https://github.com/boostorg/spirit.git synced 2026-01-19 04:42:11 +00:00
Files
spirit/example/application/cpp_to_html/cpp_to_html.cpp
2003-01-31 11:11:39 +00:00

253 lines
7.2 KiB
C++

///////////////////////////////////////////////////////////////////////////////
//
// C++ Source to HTML converter
//
// [ JDG 9/01/2002 ]
//
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/core.hpp>
#include <boost/spirit/symbols/symbols.hpp>
#include <boost/spirit/utility/chset.hpp>
#include <boost/spirit/utility/escape_char.hpp>
#include <boost/spirit/utility/confix.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
///////////////////////////////////////////////////////////////////////////////
using namespace std;
using namespace boost::spirit;
///////////////////////////////////////////////////////////////////////////////
//
// Semantic actions
//
///////////////////////////////////////////////////////////////////////////////
template <typename CharT>
void print_char(CharT ch, ostream& out)
{
switch (ch)
{
case '<': out << "&lt;"; break;
case '>': out << "&gt;"; break;
case '&': out << "&amp;"; break;
case '"': out << "&quot;"; break;
default: out << ch; break;
}
}
///////////////////////////////////////
struct process
{
process(char const* name_, ostream& out_)
: name(name_), out(out_) {}
template <typename IteratorT>
void operator()(IteratorT first, IteratorT last) const
{
out << "<span class=" << name << ">";
while (first != last)
print_char(*first++, out);
out << "</span>";
}
char const* name;
ostream& out;
};
///////////////////////////////////////
struct unexpected_char
{
unexpected_char(ostream& out_)
: out(out_) {}
template <typename CharT>
void operator()(CharT) const
{
out << '#'; // print out an unexpected character
}
ostream& out;
};
///////////////////////////////////////////////////////////////////////////////
//
// Our C++ to HTML grammar
//
///////////////////////////////////////////////////////////////////////////////
struct cpp_to_html : public grammar<cpp_to_html>
{
cpp_to_html(ostream& out_)
: out(out_) {}
template <typename ScannerT>
struct definition
{
definition(cpp_to_html const& self)
{
program
=
*( preprocessor [process("preprocessor", self.out)]
| comment [process("comment", self.out)]
| keyword [process("keyword", self.out)]
| identifier [process("identifier", self.out)]
| special [process("special", self.out)]
| string_ [process("string", self.out)]
| literal [process("literal", self.out)]
| number [process("number", self.out)]
| anychar_p [unexpected_char(self.out)]
)
;
preprocessor
= lexeme_d['#' >> ((alpha_p | '_') >> *(alnum_p | '_'))]
;
comment
= +lexeme_d[comment_p("//") | comment_p("/*", "*/")]
;
keyword
= lexeme_d[keyword_ >> (eps_p - (alnum_p | '_'))];
; // make sure we recognize whole words only
keyword_
= "and_eq", "and", "asm", "auto", "bitand", "bitor",
"bool", "break", "case", "catch", "char", "class",
"compl", "const_cast", "const", "continue", "default",
"delete", "do", "double", "dynamic_cast", "else",
"enum", "explicit", "export", "extern", "false",
"float", "for", "friend", "goto", "if", "inline",
"int", "long", "mutable", "namespace", "new", "not_eq",
"not", "operator", "or_eq", "or", "private",
"protected", "public", "register", "reinterpret_cast",
"return", "short", "signed", "sizeof", "static",
"static_cast", "struct", "switch", "template", "this",
"throw", "true", "try", "typedef", "typeid",
"typename", "union", "unsigned", "using", "virtual",
"void", "volatile", "wchar_t", "while", "xor_eq", "xor"
;
special
= lexeme_d[(+chset_p("~!%^&*()+={[}]:;,<.>?/|\\-"))]
;
string_
= !nocase_d['l'] >> confix_p('"', *c_escape_ch_p, '"')
;
literal
= !nocase_d['l'] >> confix_p('\'', *c_escape_ch_p, '\'')
;
number
= ( real_p
| nocase_d["0x"] >> hex_p
| '0' >> oct_p
)
>> *nocase_d[chset_p("ldfu")]
;
identifier
= lexeme_d[((alpha_p | '_') >> *(alnum_p | '_'))]
;
}
rule<ScannerT> program, preprocessor, comment, special,
string_, literal, number, identifier, keyword;
symbols<> keyword_;
rule<ScannerT> const&
start() const { return program; }
};
ostream& out;
};
///////////////////////////////////////////////////////////////////////////////
//
// Parse a file
//
///////////////////////////////////////////////////////////////////////////////
static void
parse(char const* filename)
{
ifstream in(filename);
if (!in)
{
cerr << "Could not open input file: " << filename << endl;
return;
}
string out_name(filename);
out_name += ".html";
ofstream out(out_name.c_str());
if (!out)
{
cerr << "Could not open output file: " << out_name << endl;
return;
}
in.unsetf(ios::skipws); // Turn of white space skipping on the stream
vector<char> vec;
std::copy(
istream_iterator<char>(in),
istream_iterator<char>(),
std::back_inserter(vec));
out << "<html>\n" << "<head>\n";
out << "<!-- Generated by the Spirit (http://spirit.sf.net) ";
out << "C++ to HTML Converter -->\n";
out << "<title>\n";
out << out_name << "</title>\n";
out << "<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">";
out << "</head>\n";
out << "<body>\n" << "<pre>\n";
vector<char>::const_iterator first = vec.begin();
vector<char>::const_iterator last = vec.end();
cpp_to_html p(out);
parse_info<vector<char>::const_iterator> info =
parse(first, last, p, space_p);
if (!info.full)
{
cerr << "---PARSING FAILURE---\n";
cerr << string(info.stop, last);
}
out << "</pre>\n" << "</body>\n" << "</html>\n";
}
///////////////////////////////////////////////////////////////////////////////
//
// Main program
//
///////////////////////////////////////////////////////////////////////////////
int
main(int argc, char* argv[])
{
if (argc > 1)
{
for (int i = 1; i < argc; ++i)
{
cout << argv[i] << endl;
parse(argv[i]);
}
}
else
{
cerr << "---NO FILENAME GIVEN---" << endl;
}
return 0;
}