Home | Download | Screen shots | Discussion | Documentation
--- | --- | --- | --- | ---

# 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/vrml97_grammar.h>
    # 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;
    };

    struct actions : openvrml::null_vrml97_parse_actions {

        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;

        vrml97_skip_grammar skip_g;
        actions act(std::cout);
        vrml97_grammar<actions> g(act);

        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";
    }