mirror of
https://github.com/boostorg/spirit.git
synced 2026-01-19 04:42:11 +00:00
253 lines
7.2 KiB
C++
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 << "<"; break;
|
|
case '>': out << ">"; break;
|
|
case '&': out << "&"; break;
|
|
case '"': out << """; 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;
|
|
}
|
|
|