pretty_print.cpp

A pretty-printer using openvrml::vrml97_grammar.

// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 78 -*-
//
// pretty-print
//
// Copyright 2007 Braden McDaniel
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; if not, see <http://www.gnu.org/licenses/>.
//
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
# include <openvrml/browser.h>
# include <fstream>
using namespace std;
using namespace boost::spirit::classic;
using namespace openvrml;
class indent;
std::ostream & operator<<(std::ostream & out, const indent & indent_);
class indent {
friend std::ostream & operator<<(std::ostream & out, const indent & indent_);
const std::string increment_;
std::vector<std::string> indent_;
public:
explicit indent(const std::string & increment):
increment_(increment)
{}
indent & operator++()
{
this->indent_.push_back(this->increment_);
return *this;
}
indent & operator--()
{
this->indent_.pop_back();
return *this;
}
};
std::ostream & operator<<(std::ostream & out, const indent & indent_)
{
std::copy(indent_.indent_.begin(),
indent_.indent_.end(),
std::ostream_iterator<std::string>(out));
return out;
}
struct actions;
template <typename MFValueType>
struct on_mfvalue {
explicit on_mfvalue(actions & a):
a(a)
{}
void operator()(const std::vector<MFValueType> & val) const;
private:
actions & a;
};
template <>
struct on_mfvalue<std::string> {
explicit on_mfvalue(actions & a):
a(a)
{}
void operator()(const std::vector<std::string> & val) const;
private:
actions & a;
};
template <typename SFValueType>
struct on_sfvalue {
explicit on_sfvalue(actions & a):
a(a)
{}
void operator()(const SFValueType & val) const
{
a.out << ' ' << val << '\n';
}
private:
actions & a;
};
std::ostream & out;
indent indent_;
explicit actions(std::ostream & out):
out(out),
indent_(" "),
on_externproto(*this),
on_proto_start(*this),
on_proto_interface(*this),
on_proto_body_start(*this),
on_proto_finish(*this),
on_node_start(*this),
on_node_finish(*this),
on_script_interface_decl(*this),
on_route(*this),
on_use(*this),
on_is_mapping(*this),
on_field_start(*this),
on_sfnode(*this),
on_sfbool(*this),
on_sfcolor(*this),
on_sffloat(*this),
on_sfimage(*this),
on_sfint32(*this),
on_sfrotation(*this),
on_sfstring(*this),
on_sftime(*this),
on_sfvec2f(*this),
on_sfvec3f(*this),
on_mfcolor(*this),
on_mffloat(*this),
on_mfint32(*this),
on_mfrotation(*this),
on_mfstring(*this),
on_mftime(*this),
on_mfvec2f(*this),
on_mfvec3f(*this)
{}
struct on_externproto_t {
explicit on_externproto_t(actions & a):
a(a)
{}
void operator()(const std::string & node_type_id,
const node_interface_set & interfaces,
const std::vector<std::string> & uri_list) const
{
using std::string;
using std::vector;
a.out << a.indent_ << "EXTERNPROTO " << node_type_id << " [\n";
++a.indent_;
for (node_interface_set::const_iterator interface_ =
interfaces.begin();
interface_ != interfaces.end();
++interface_) {
a.out << a.indent_ << *interface_ << '\n';
}
--a.indent_;
a.out << a.indent_ << "] [\n";
++a.indent_;
for (vector<string>::const_iterator uri = uri_list.begin();
uri != uri_list.end();
++uri) {
a.out << a.indent_ << '"' << *uri << '"';
if (uri + 1 != uri_list.end()) {
a.out << ',';
}
a.out << '\n';
}
--a.indent_;
a.out << a.indent_ << "]\n";
}
actions & a;
} on_externproto;
struct on_proto_start_t {
explicit on_proto_start_t(actions & a):
a(a)
{}
void operator()(const std::string & node_type_id) const
{
a.out << "PROTO " << node_type_id << " [\n";
++a.indent_;
}
actions & a;
} on_proto_start;
struct on_proto_interface_t {
explicit on_proto_interface_t(actions & a):
a(a)
{}
void operator()(const node_interface & interface_) const
{
a.out << a.indent_ << interface_;
if (interface_.type == node_interface::eventin_id
|| interface_.type == node_interface::eventout_id) {
a.out << '\n';
}
}
actions & a;
} on_proto_interface;
struct on_proto_body_start_t {
explicit on_proto_body_start_t(actions & a):
a(a)
{}
void operator()() const
{
--a.indent_;
a.out << a.indent_ << "] {\n";
++a.indent_;
}
actions & a;
} on_proto_body_start;
struct on_proto_finish_t {
explicit on_proto_finish_t(actions & a):
a(a)
{}
void operator()() const
{
--a.indent_;
a.out << a.indent_ << "}\n";
}
actions & a;
} on_proto_finish;
struct on_node_start_t {
explicit on_node_start_t(actions & a):
a(a)
{}
void operator()(const std::string & node_name_id,
const std::string & node_type_id) const
{
a.out << '\n' << a.indent_;
if (!node_name_id.empty()) {
a.out << "DEF " << node_name_id << ' ';
}
a.out << node_type_id << " {\n";
++a.indent_;
}
actions & a;
} on_node_start;
struct on_node_finish_t {
explicit on_node_finish_t(actions & a):
a(a)
{}
void operator()() const
{
--a.indent_;
a.out << a.indent_ << "}\n";
}
actions & a;
} on_node_finish;
struct on_script_interface_decl_t {
explicit on_script_interface_decl_t(actions & a):
a(a)
{}
void operator()(const node_interface & interface_) const
{
a.out << a.indent_ << interface_;
}
actions & a;
} on_script_interface_decl;
struct on_route_t {
explicit on_route_t(actions & a):
a(a)
{}
void operator()(const std::string & from_node_name_id,
const node_interface & from_node_interface,
const std::string & to_node_name_id,
const node_interface & to_node_interface) const
{
a.out << a.indent_ << "ROUTE "
<< from_node_name_id << '.' << from_node_interface.id
<< " TO "
<< to_node_name_id << '.' << to_node_interface.id << '\n';
}
actions & a;
} on_route;
struct on_use_t {
explicit on_use_t(actions & a):
a(a)
{}
void operator()(const std::string & node_name_id) const
{
a.out << '\n' << a.indent_ << "USE" << node_name_id << '\n';
}
actions & a;
} on_use;
struct on_is_mapping_t {
explicit on_is_mapping_t(actions & a):
a(a)
{}
void operator()(const std::string & proto_interface_id) const
{
a.out << " IS " << proto_interface_id << '\n';
}
actions & a;
} on_is_mapping;
struct on_field_start_t {
explicit on_field_start_t(actions & a):
a(a)
{}
void operator()(const std::string & field_name_id,
field_value::type_id /* field_type */) const
{
a.out << a.indent_ << field_name_id;
}
actions & a;
} on_field_start;
struct on_sfnode_t {
explicit on_sfnode_t(actions & a):
a(a)
{}
void operator()(const bool null) const
{
if (null) { a.out << " NULL\n"; }
}
actions & a;
} on_sfnode;
struct on_sfbool_t {
explicit on_sfbool_t(actions & a):
a(a)
{}
void operator()(const bool val) const
{
a.out << ' ' << (val ? "TRUE" : "FALSE") << '\n';
}
actions & a;
} on_sfbool;
on_sfvalue<color> on_sfcolor;
on_sfvalue<float> on_sffloat;
on_sfvalue<image> on_sfimage;
on_sfvalue<int32> on_sfint32;
on_sfvalue<rotation> on_sfrotation;
on_sfvalue<string> on_sfstring;
on_sfvalue<double> on_sftime;
on_sfvalue<vec2f> on_sfvec2f;
on_sfvalue<vec3f> on_sfvec3f;
on_mfvalue<color> on_mfcolor;
on_mfvalue<float> on_mffloat;
on_mfvalue<int32> on_mfint32;
on_mfvalue<rotation> on_mfrotation;
on_mfvalue<string> on_mfstring;
on_mfvalue<double> on_mftime;
on_mfvalue<vec2f> on_mfvec2f;
on_mfvalue<vec3f> on_mfvec3f;
};
int main(int argc, char * argv[])
{
ifstream infile;
if (argc > 1) {
infile.open(argv[1]);
if (!infile.is_open()) {
cerr << argv[0] << ": could not open file \"" << argv[1] << endl;
return EXIT_FAILURE;
}
}
istream & in(infile.is_open() ? infile : cin);
const string filename(infile.is_open() ? argv[1] : "<stdin>");
typedef multi_pass<istreambuf_iterator<char> > multi_pass_iterator_t;
typedef istream::char_type char_t;
multi_pass_iterator_t
in_begin(make_multi_pass(istreambuf_iterator<char_t>(in))),
in_end(make_multi_pass(istreambuf_iterator<char_t>()));
typedef position_iterator<multi_pass_iterator_t> iterator_t;
iterator_t first(in_begin, in_end, filename), last;
actions act(std::cout);
BOOST_SPIRIT_DEBUG_NODE(skip_g);
BOOST_SPIRIT_DEBUG_NODE(g);
if (!parse(first, last, g, skip_g).full) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
template <typename MFValueType>
void
on_mfvalue<MFValueType>::operator()(const std::vector<MFValueType> & val) const
{
a.out << " [\n";
++a.indent_;
for (typename std::vector<MFValueType>::const_iterator element =
val.begin();
element != val.end();
++element) {
a.out << a.indent_ << *element << ",\n";
}
--a.indent_;
a.out << a.indent_ << "]\n";
}
void
on_mfvalue<std::string>::operator()(const std::vector<std::string> & val) const
{
a.out << " [\n";
++a.indent_;
for (std::vector<std::string>::const_iterator element =
val.begin();
element != val.end();
++element) {
a.out << a.indent_ << '"' << *element << "\",\n";
}
--a.indent_;
a.out << a.indent_ << "]\n";
}