pretty_print.cpp

A pretty-printer using openvrml::vrml97_grammar.

00001 // -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 78 -*-
00002 //
00003 // pretty-print
00004 //
00005 // Copyright 2007  Braden McDaniel
00006 //
00007 // This program is free software; you can redistribute it and/or modify it
00008 // under the terms of the GNU General Public License as published by the Free
00009 // Software Foundation; either version 3 of the License, or (at your option)
00010 // any later version.
00011 //
00012 // This program is distributed in the hope that it will be useful, but WITHOUT
00013 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00015 // more details.
00016 //
00017 // You should have received a copy of the GNU General Public License along
00018 // with this library; if not, see <http://www.gnu.org/licenses/>.
00019 //
00020 
00021 # ifdef HAVE_CONFIG_H
00022 #   include <config.h>
00023 # endif
00024 
00025 # include <openvrml/vrml97_grammar.h>
00026 # include <openvrml/browser.h>
00027 # include <fstream>
00028 
00029 using namespace std;
00030 using namespace boost::spirit;
00031 using namespace openvrml;
00032 
00033 class indent;
00034 
00035 std::ostream & operator<<(std::ostream & out, const indent & indent_);
00036 
00037 class indent {
00038     friend std::ostream & operator<<(std::ostream & out, const indent & indent_);
00039 
00040     const std::string increment_;
00041     std::vector<std::string> indent_;
00042 
00043 public:
00044     explicit indent(const std::string & increment):
00045         increment_(increment)
00046     {}
00047 
00048     indent & operator++()
00049     {
00050         this->indent_.push_back(this->increment_);
00051         return *this;
00052     }
00053 
00054     indent & operator--()
00055     {
00056         this->indent_.pop_back();
00057         return *this;
00058     }
00059 };
00060 
00061 std::ostream & operator<<(std::ostream & out, const indent & indent_)
00062 {
00063     std::copy(indent_.indent_.begin(),
00064               indent_.indent_.end(),
00065               std::ostream_iterator<std::string>(out));
00066     return out;
00067 }
00068 
00069 struct actions;
00070 
00071 template <typename MFValueType>
00072 struct on_mfvalue {
00073     explicit on_mfvalue(actions & a):
00074         a(a)
00075     {}
00076 
00077     void operator()(const std::vector<MFValueType> & val) const;
00078 
00079 private:
00080     actions & a;
00081 };
00082 
00083 template <>
00084 struct on_mfvalue<std::string> {
00085     explicit on_mfvalue(actions & a):
00086         a(a)
00087     {}
00088 
00089     void operator()(const std::vector<std::string> & val) const;
00090 
00091 private:
00092     actions & a;
00093 };
00094 
00095 struct actions : openvrml::null_vrml97_parse_actions {
00096 
00097     template <typename SFValueType>
00098     struct on_sfvalue {
00099         explicit on_sfvalue(actions & a):
00100             a(a)
00101         {}
00102 
00103         void operator()(const SFValueType & val) const
00104         {
00105             a.out << ' ' << val << '\n';
00106         }
00107 
00108     private:
00109         actions & a;
00110     };
00111 
00112     std::ostream & out;
00113     indent indent_;
00114 
00115     explicit actions(std::ostream & out):
00116         out(out),
00117         indent_("  "),
00118         on_externproto(*this),
00119         on_proto_start(*this),
00120         on_proto_interface(*this),
00121         on_proto_body_start(*this),
00122         on_proto_finish(*this),
00123         on_node_start(*this),
00124         on_node_finish(*this),
00125         on_script_interface_decl(*this),
00126         on_route(*this),
00127         on_use(*this),
00128         on_is_mapping(*this),
00129         on_field_start(*this),
00130         on_sfnode(*this),
00131         on_sfbool(*this),
00132         on_sfcolor(*this),
00133         on_sffloat(*this),
00134         on_sfimage(*this),
00135         on_sfint32(*this),
00136         on_sfrotation(*this),
00137         on_sfstring(*this),
00138         on_sftime(*this),
00139         on_sfvec2f(*this),
00140         on_sfvec3f(*this),
00141         on_mfcolor(*this),
00142         on_mffloat(*this),
00143         on_mfint32(*this),
00144         on_mfrotation(*this),
00145         on_mfstring(*this),
00146         on_mftime(*this),
00147         on_mfvec2f(*this),
00148         on_mfvec3f(*this)
00149     {}
00150 
00151     struct on_externproto_t {
00152         explicit on_externproto_t(actions & a):
00153             a(a)
00154         {}
00155 
00156         void operator()(const std::string & node_type_id,
00157                         const node_interface_set & interfaces,
00158                         const std::vector<std::string> & uri_list) const
00159         {
00160             using std::string;
00161             using std::vector;
00162             a.out << a.indent_ << "EXTERNPROTO " << node_type_id << " [\n";
00163             ++a.indent_;
00164             for (node_interface_set::const_iterator interface =
00165                      interfaces.begin();
00166                  interface != interfaces.end();
00167                  ++interface) {
00168                 a.out << a.indent_ << *interface << '\n';
00169             }
00170             --a.indent_;
00171             a.out << a.indent_ << "] [\n";
00172             ++a.indent_;
00173             for (vector<string>::const_iterator uri = uri_list.begin();
00174                  uri != uri_list.end();
00175                  ++uri) {
00176                 a.out << a.indent_ << '"' << *uri << '"';
00177                 if (uri + 1 != uri_list.end()) {
00178                     a.out << ',';
00179                 }
00180                 a.out << '\n';
00181             }
00182             --a.indent_;
00183             a.out << a.indent_ << "]\n";
00184         }
00185 
00186         actions & a;
00187     } on_externproto;
00188 
00189     struct on_proto_start_t {
00190         explicit on_proto_start_t(actions & a):
00191             a(a)
00192         {}
00193 
00194         void operator()(const std::string & node_type_id) const
00195         {
00196             a.out << "PROTO " << node_type_id << " [\n";
00197             ++a.indent_;
00198         }
00199 
00200         actions & a;
00201     } on_proto_start;
00202 
00203     struct on_proto_interface_t {
00204         explicit on_proto_interface_t(actions & a):
00205             a(a)
00206         {}
00207 
00208         void operator()(const node_interface & interface) const
00209         {
00210             a.out << a.indent_ << interface;
00211             if (interface.type == node_interface::eventin_id
00212                 || interface.type == node_interface::eventout_id) {
00213                 a.out << '\n';
00214             }
00215         }
00216 
00217         actions & a;
00218     } on_proto_interface;
00219 
00220     struct on_proto_body_start_t {
00221         explicit on_proto_body_start_t(actions & a):
00222             a(a)
00223         {}
00224 
00225         void operator()() const
00226         {
00227             --a.indent_;
00228             a.out << a.indent_ << "] {\n";
00229             ++a.indent_;
00230         }
00231 
00232         actions & a;
00233     } on_proto_body_start;
00234 
00235     struct on_proto_finish_t {
00236         explicit on_proto_finish_t(actions & a):
00237             a(a)
00238         {}
00239 
00240         void operator()() const
00241         {
00242             --a.indent_;
00243             a.out << a.indent_ << "}\n";
00244         }
00245 
00246         actions & a;
00247     } on_proto_finish;
00248 
00249     struct on_node_start_t {
00250         explicit on_node_start_t(actions & a):
00251             a(a)
00252         {}
00253 
00254         void operator()(const std::string & node_name_id,
00255                         const std::string & node_type_id) const
00256         {
00257             a.out << '\n' << a.indent_;
00258             if (!node_name_id.empty()) {
00259                 a.out << "DEF " << node_name_id << ' ';
00260             }
00261             a.out << node_type_id << " {\n";
00262             ++a.indent_;
00263         }
00264 
00265         actions & a;
00266     } on_node_start;
00267 
00268     struct on_node_finish_t {
00269         explicit on_node_finish_t(actions & a):
00270             a(a)
00271         {}
00272 
00273         void operator()() const
00274         {
00275             --a.indent_;
00276             a.out << a.indent_ << "}\n";
00277         }
00278 
00279         actions & a;
00280     } on_node_finish;
00281 
00282     struct on_script_interface_decl_t {
00283         explicit on_script_interface_decl_t(actions & a):
00284             a(a)
00285         {}
00286 
00287         void operator()(const node_interface & interface) const
00288         {
00289             a.out << a.indent_ << interface;
00290         }
00291 
00292         actions & a;
00293     } on_script_interface_decl;
00294 
00295     struct on_route_t {
00296         explicit on_route_t(actions & a):
00297             a(a)
00298         {}
00299 
00300         void operator()(const std::string & from_node_name_id,
00301                         const node_interface & from_node_interface,
00302                         const std::string & to_node_name_id,
00303                         const node_interface & to_node_interface) const
00304         {
00305             a.out << a.indent_ << "ROUTE "
00306                   << from_node_name_id << '.' << from_node_interface.id
00307                   << " TO "
00308                   << to_node_name_id << '.' << to_node_interface.id << '\n';
00309         }
00310 
00311         actions & a;
00312     } on_route;
00313 
00314     struct on_use_t {
00315         explicit on_use_t(actions & a):
00316             a(a)
00317         {}
00318 
00319         void operator()(const std::string & node_name_id) const
00320         {
00321             a.out << '\n' << a.indent_ << "USE" << node_name_id << '\n';
00322         }
00323 
00324         actions & a;
00325     } on_use;
00326 
00327     struct on_is_mapping_t {
00328         explicit on_is_mapping_t(actions & a):
00329             a(a)
00330         {}
00331 
00332         void operator()(const std::string & proto_interface_id) const
00333         {
00334             a.out << " IS " << proto_interface_id << '\n';
00335         }
00336 
00337         actions & a;
00338     } on_is_mapping;
00339 
00340     struct on_field_start_t {
00341         explicit on_field_start_t(actions & a):
00342             a(a)
00343         {}
00344 
00345         void operator()(const std::string & field_name_id,
00346                         field_value::type_id /* field_type */) const
00347         {
00348             a.out << a.indent_ << field_name_id;
00349         }
00350 
00351         actions & a;
00352     } on_field_start;
00353 
00354     struct on_sfnode_t {
00355         explicit on_sfnode_t(actions & a):
00356             a(a)
00357         {}
00358 
00359         void operator()(const bool null) const
00360         {
00361             if (null) { a.out << " NULL\n"; }
00362         }
00363 
00364         actions & a;
00365     } on_sfnode;
00366 
00367     struct on_sfbool_t {
00368         explicit on_sfbool_t(actions & a):
00369             a(a)
00370         {}
00371 
00372         void operator()(const bool val) const
00373         {
00374             a.out << ' ' << (val ? "TRUE" : "FALSE") << '\n';
00375         }
00376 
00377         actions & a;
00378     } on_sfbool;
00379 
00380     on_sfvalue<color> on_sfcolor;
00381     on_sfvalue<float> on_sffloat;
00382     on_sfvalue<image> on_sfimage;
00383     on_sfvalue<int32> on_sfint32;
00384     on_sfvalue<rotation> on_sfrotation;
00385     on_sfvalue<string> on_sfstring;
00386     on_sfvalue<double> on_sftime;
00387     on_sfvalue<vec2f> on_sfvec2f;
00388     on_sfvalue<vec3f> on_sfvec3f;
00389     on_mfvalue<color> on_mfcolor;
00390     on_mfvalue<float> on_mffloat;
00391     on_mfvalue<int32> on_mfint32;
00392     on_mfvalue<rotation> on_mfrotation;
00393     on_mfvalue<string> on_mfstring;
00394     on_mfvalue<double> on_mftime;
00395     on_mfvalue<vec2f> on_mfvec2f;
00396     on_mfvalue<vec3f> on_mfvec3f;
00397 };
00398 
00399 
00400 int main(int argc, char * argv[])
00401 {
00402     ifstream infile;
00403     if (argc > 1) {
00404         infile.open(argv[1]);
00405         if (!infile.is_open()) {
00406             cerr << argv[0] << ": could not open file \"" << argv[1] << endl;
00407             return EXIT_FAILURE;
00408         }
00409     }
00410 
00411     istream & in(infile.is_open() ? infile : cin);
00412     const string filename(infile.is_open() ? argv[1] : "<stdin>");
00413 
00414     typedef multi_pass<istreambuf_iterator<char> > multi_pass_iterator_t;
00415     typedef istream::char_type char_t;
00416 
00417     multi_pass_iterator_t
00418         in_begin(make_multi_pass(istreambuf_iterator<char_t>(in))),
00419         in_end(make_multi_pass(istreambuf_iterator<char_t>()));
00420 
00421     typedef position_iterator<multi_pass_iterator_t> iterator_t;
00422 
00423     iterator_t first(in_begin, in_end, filename), last;
00424 
00425     vrml97_skip_grammar skip_g;
00426     actions act(std::cout);
00427     vrml97_grammar<actions> g(act);
00428 
00429     BOOST_SPIRIT_DEBUG_NODE(skip_g);
00430     BOOST_SPIRIT_DEBUG_NODE(g);
00431 
00432     if (!parse(first, last, g, skip_g).full) {
00433         return EXIT_FAILURE;
00434     }
00435 
00436     return EXIT_SUCCESS;
00437 }
00438 
00439 template <typename MFValueType>
00440 void
00441 on_mfvalue<MFValueType>::operator()(const std::vector<MFValueType> & val) const
00442 {
00443     a.out << " [\n";
00444     ++a.indent_;
00445     for (typename std::vector<MFValueType>::const_iterator element =
00446              val.begin();
00447          element != val.end();
00448          ++element) {
00449         a.out << a.indent_ << *element << ",\n";
00450     }
00451     --a.indent_;
00452     a.out << a.indent_ << "]\n";
00453 }
00454 
00455 void
00456 on_mfvalue<std::string>::operator()(const std::vector<std::string> & val) const
00457 {
00458     a.out << " [\n";
00459     ++a.indent_;
00460     for (std::vector<std::string>::const_iterator element =
00461              val.begin();
00462          element != val.end();
00463          ++element) {
00464         a.out << a.indent_ << '"' << *element << "\",\n";
00465     }
00466     --a.indent_;
00467     a.out << a.indent_ << "]\n";
00468 }