Author: | Valentin David |
---|---|
Contact: | valentin@lrde.epita.fr |
Date: | December 2003 |
This document describe the Vaucanson XML developement.
There are three ways to use the Vaucanson XML interface.
This mode use the standard Vaucanson I/O system. An instance of the vcsn::xml::xml_loader class has to be passed to the automaton_loader and automaton_saver functions:
#include <vaucanson/xml/static.hh> #include <vaucanson/tools/usual.hh> #include <iostream> int main() { using namespace vcsn; using namespace vcsn::tools; using namespace vcsn::xml; XML_BEGIN; AUTOMATON_TYPES_EXACT(usual_automaton_t); automaton_t a; std::cin >> automaton_loader(a, io::string_out(), xml::xml_loader()); /* work on a */ std::cout << automaton_saver(a, io::string_out(), xml::xml_loader()); XML_END; }
This mode able to choose the implementation following the type of the automaton described in the XML Document.
The automaton is first loaded in a xml_automaton_t typed variable. Then the type can be accessed.
Here is an easy to understand example:
#include <vaucanson/xml/dynamic.hh> #include <vaucanson/tools/usual.hh> #include <iostream> int main() { xml_automaton_t dynamic_automaton; std::cin >> dynamic_automaton; if (x.set().semiring_set() == XmlSet::B) { AUTOMATON_TYPES_EXACT(usual_automaton_t); XMLOF(automaton_t) xml_automaton = dynamic_automaton; automaton_t automaton = xml_automaton; /* work on automaton */ xml_automaton = automaton; std::cout << xml_automaton; } if ((x.set().semiring_type() == XmlSet::NUMERICAL) && (x.set().semiring_set() == XmlSet::Z)) { AUTOMATON_TYPES_EXACT(weighted_automaton_t); XMLOF(automaton_t) xml_automaton = dynamic_automaton; automaton_t automaton = xml_automaton; /* work on automaton */ xml_automaton = automaton; std::cout << xml_automaton; } return 0; }
But this example can be written better using generic programming:
#include <vaucanson/xml/dynamic.hh> #include <vaucanson/tools/usual.hh> #include <iostream> template <typename T> int print_out(typename XMLOF(T) x) { using namespace vcsn; using namespace vcsn::tools; using namespace vcsn::xml; AUTOMATON_TYPES_EXACT(T); automaton_t a = x; /* work on a */ x = a; std::cout << x; return 0; } int main() { using namespace vcsn; using namespace vcsn::tools; using namespace vcsn::xml; XML_BEGIN; xml_automaton_t x; std::cin >> x; if ((x.set().semiring_type() == XmlSet::NUMERICAL) && (x.set().semiring_set() == XmlSet::Z)) return print_out<numerical_automaton_t>(x); if (x.set().semiring_set() == XmlSet::B) return print_out<usual_automaton_t>(x); std::cerr << "Automaton type not dealt" << std::endl; return -1; }
The generic mode is very long to compile. So, some constants have to be set for activating some parts.
Here is an example:
#define VCSN_XML_GENERIC_WEIGHTED 1 #include <vaucanson/xml/generic.hh> #include <vaucanson/tools/usual.hh> #include <iostream> struct MyData { int argc; char **argv; MyData(int c, char** v) : argc(c), argv(v) { } }; template <typename Auto> struct MyCallBack { int operator()(Auto& a, MyData&) { using namespace vcsn; using namespace vcsn::tools; using namespace vcsn::xml; AUTOMATON_TYPES(Auto); /* work on a */ return 0; } }; int main(int argc, char *argv[]) { using namespace vcsn; using namespace vcsn::xml; XML_BEGIN; MyData data(argc, argv); return apply<MyCallBack, MyData>(std::cin, data); }
There are two possibilities, for error processing.
To switch this mode a macro has to be set.
When raising exceptions, the raised exception is mainly an instance of vcsn::xml::LoaderException. This exception type provides the method get_msg():
xml_automaton_t x; try { std::cin >> x; } catch (const xml::LoaderException& e) { std::cerr << "XML parser error: " << e.get_msg() << std::endl; return -1; }
To keep the geometry in a graph implemented automaton, the type has to be converted to accept attached data:
template <typename T> int print_out(typename XMLOF(T) x) { using namespace vcsn; using namespace vcsn::tools; using namespace vcsn::xml; typedef typename ATTACHXMLINFOS(T) my_automaton_t; AUTOMATON_TYPES(my_automaton_t); automaton_t a = x; /* then, here, a contains the geometry */ return 0; }
The data are in the Tag. This tag is XmlInfosTag typed. See Vaucanson API documentation for more information:
// This example aling states diagonnaly with a depth-first traversal. template<typename I> void align(I& a) { AUTOMATON_TYPES(I); int x = 0; std::map<hstate_t,bool> visited; std::stack<hstate_t> stack; for_each_state(i, a) { visited[*i] = false; // ensure inaccessible states will be visited stack.push(*i); } for_each_initial_state(i, a) stack.push(*i); while (!stack.empty()) { hstate_t i = stack.top(); stack.pop(); if (!visited[i]) { visited[i] = true; a.tag().states[i]().x = a.tag().states[i]().y = x++; std::list<hedge_t> aim; a.deltac(aim, i, delta_kind::edges()); for_all_const_(std::list<hedge_t>, j, aim) stack.push(a.aim_of(*j)); } } }
Sessions are handled like lifo by class xml::XmlSession. Stream output and input operators are used for popping and pushing:
#include <vaucanson/xml/session.hh> #include <vaucanson/tools/usual.hh> #include <iostream> int main() { using namespace vcsn; using namespace vcsn::tools; using namespace vcsn::xml; XML_BEGIN; typedef XMLOF(usual_automaton_t) my_xml_automaton_t; AUTOMATON_TYPES_EXACT(usual_automaton_t); automaton_t a; my_xml_automaton_t x; xml_automaton_t dyn; XmlSession session1, session2; std::cin >> session1; session1 >> dyn; a = my_xml_automaton_t(dyn); /* work on a */ session2 << my_xml_automaton_t(a); session >> dyn; a = my_xml_automaton_t(dyn); /* work on a */ session2 << my_xml_automaton_t(a); XML_END; return 0; }