Index: src/work/deba/graph_io_test.cc
===================================================================
--- src/work/deba/graph_io_test.cc	(revision 1032)
+++ src/work/deba/graph_io_test.cc	(revision 1036)
@@ -1,4 +1,4 @@
 #include <lemon/smart_graph.h>
-#include <lemon/graph_reader.h>
+#include "graph_reader.h"
 
 #include <iostream>
@@ -12,11 +12,28 @@
   SmartGraph graph;
   GraphReader<SmartGraph> reader(input, graph);
+  SmartGraph::NodeMap<int> id(graph);
+  reader.readNodeMap("id", id);
   SmartGraph::NodeMap<int> cost(graph);
   reader.readNodeMap("cost", cost);
   SmartGraph::NodeMap<string> color(graph);
   reader.readNodeMap("color", color);
-  reader.read();
+  SmartGraph::NodeMap<string> description(graph);
+  reader.readNodeMap<QuotedStringReader>("description", description);
+  SmartGraph::EdgeMap<char> mmap(graph);
+  reader.readEdgeMap("mmap", mmap);
+  reader.skipEdgeMap<QuotedStringReader>("description");
+  try {
+    reader.read();
+  } catch (IOException& e) {
+    cerr << e.what() << endl;
+  } catch (Exception e) {
+    cerr << e.what() << endl;
+  }
   for (SmartGraph::NodeIt it(graph); it != INVALID; ++it) {
-    cout << cost[it] << color[it] << endl;
+    cout << cost[it] << ' ' << color[it] << ' ' << description[it] << endl;
+  }
+
+  for (SmartGraph::EdgeIt it(graph); it != INVALID; ++it) {
+    cout << mmap[it] << ' ' << id[graph.source(it)] << ' ' << id[graph.target(it)]  << endl;
   }
   return 0;
Index: src/work/deba/graph_reader.h
===================================================================
--- src/work/deba/graph_reader.h	(revision 1032)
+++ src/work/deba/graph_reader.h	(revision 1036)
@@ -17,5 +17,5 @@
 ///\ingroup gio
 ///\file
-///\brief Map utilities.
+///\brief Graph reader.
 
 #include <iostream>
@@ -31,4 +31,32 @@
 
 namespace lemon {
+
+  // Exceptions
+
+  class IOException {
+  public:
+    virtual string what() const = 0;
+  };
+
+  class DataFormatException : public IOException {
+    std::string message;
+  public:
+    DataFormatException(const std::string& _message) 
+      : message(_message) {}
+    std::string what() const {
+      return "DataFormatException: " + message; 
+    }
+  };
+
+  class StreamException : public IOException {
+  public:
+    virtual int line() = 0;
+  private:
+    IOException* exception;
+    int line_num;
+  };  
+
+
+  // Readers and ReaderTraits
   
   struct DefaultReaderTraits {
@@ -38,34 +66,107 @@
       typedef _Value Value;
       void read(std::istream& is, Value& value) {
-	is >> value;
-      }
-    };
-
-    template <typename _Value>
-    struct Skipper {
-      typedef _Value Value;
-      void read(std::istream& is) {
-	Value tmp;
-	is >> tmp;
-      }      
-    };
-
-    struct DefaultSkipper {
-      void read(std::istream& is) {
-	std::string tmp;
-	is >> tmp;
-      }
-    };
+	if (!(is >> value)) 
+	  throw DataFormatException("Default Reader format exception");
+      }
+    };
+
+    typedef Reader<std::string> DefaultReader;
+
   };
 
-  class IOException {
-    virtual string message() = 0;
+  class QuotedStringReader {
+  public:
+    typedef std::string Value;
+
+    QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
+
+    void read(std::istream& is, std::string& value) {
+      char c;
+      value.clear();
+      is >> ws;
+      if (!is.get(c) || c != '\"') throw DataFormatException("Quoted string format exception");
+      while (is.get(c) && c != '\"') {
+	if (escaped && c == '\\') {
+	  value += readEscape(is);
+	} else {
+	  value += c;
+	}
+      }
+      if (!is) throw DataFormatException("Quoted string format exception");
+    }
+
+  private:
+    
+    static char readEscape(std::istream& is) {
+      char c;
+      switch (is.get(c), c) {
+      case '\\':
+	return '\\';
+      case '\"':
+	return '\"';
+      case '\'':
+	return '\'';
+      case '\?':
+	return '\?';
+      case 'a':
+	return '\a';
+      case 'b':
+	return '\b';
+      case 'f':
+	return '\f';
+      case 'n':
+	return '\n';
+      case 'r':
+	return '\r';
+      case 't':
+	return '\t';
+      case 'v':
+	return '\v';
+      case 'x':
+	{
+	  int code;
+	  if (!is.get(c) || !isHex(c)) throw DataFormatException("Escape format exception");
+	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
+	  else code = code * 16 + valueHex(c);
+	  return code;
+	}
+      default:
+	{
+	  int code;
+	  if (!isOct(c)) throw DataFormatException("Escape format exception");
+	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) is.putback(c);
+	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) is.putback(c);
+	  else code = code * 8 + valueOct(c);
+	  return code;
+	}	      
+      } 
+    }
+
+    static bool isOct(char c) {
+      return '0' <= c && c <='7'; 
+    }
+    
+    static int valueOct(char c) {
+      return c - '0';
+    }
+
+   static bool isHex(char c) {
+      return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); 
+    }
+    
+    static int valueHex(char c) {
+      if ('0' <= c && c <= '9') return c - '0';
+      if ('a' <= c && c <= 'z') return c - 'a' + 10;
+      return c - 'A' + 10;
+    }
+
+    bool escaped;
   };
 
-  class FileReaderException {
-    virtual int getLine() = 0;    
-  };
-
-  
+
+
+
+
+  // Graph reader
   
   template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits> 
@@ -79,51 +180,102 @@
 
     typedef _ReaderTraits ReaderTraits;
-    
-
-    GraphReader(std::istream& _is, Graph& _graph) : is(_is), graph(_graph) {}
+    typedef typename ReaderTraits::DefaultReader DefaultReader;
+
+    GraphReader(istream& _is, Graph& _graph, const DefaultReader& _reader = DefaultReader()) 
+      : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {}
+
+
+    ~GraphReader() {
+
+      for (typename NodeReaders::iterator it = node_readers.begin(); it != node_readers.end(); ++it) {
+	delete it->second;
+      }
+
+      for (typename EdgeReaders::iterator it = edge_readers.begin(); it != edge_readers.end(); ++it) {
+	delete it->second;
+      }
+
+    }
 
     template <typename Map>
-    GraphReader& readNodeMap(std::string name, Map& map, 
-			     const typename ReaderTraits::template Reader<typename Map::Value>& reader =
-			     typename ReaderTraits::template Reader<typename Map::Value>()) {
-      return readNodeMap<Map, typename ReaderTraits::template Reader<typename Map::Value> >(name, map, reader);
-    }
-
-    template <typename Map, typename Reader>
+    GraphReader& readNodeMap(std::string name, Map& map) {
+      return readNodeMap<typename ReaderTraits::template Reader<typename Map::Value>, Map>(name, map);
+    }
+
+    template <typename Reader, typename Map>
     GraphReader& readNodeMap(std::string name, Map& map, const Reader& reader = Reader()) {
+      if (node_readers.find(name) != node_readers.end()) {
+	Exception e;
+	e << "Multiple read rule for node map: " << name;
+	throw e;
+      }
       node_readers.insert(make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
       return *this;
     }
 
+    template <typename Reader>
+    GraphReader& skipNodeMap(std::string name, const Reader& reader = Reader()) {
+      if (node_readers.find(name) != node_readers.end()) {
+	Exception e;
+	e << "Multiple read rule for node map: " << name;
+	throw e;
+      }
+      node_readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
+      return *this;
+    }
+
     template <typename Map>
-    GraphReader& readEdgeMap(std::string name, Map& map, 
-			     const typename ReaderTraits::template Reader<typename Map::Value>& reader =
-			     typename ReaderTraits::template Reader<typename Map::Value>()) {
-      return readEdgeMap<Map, typename ReaderTraits::template Reader<typename Map::Value> >(name, map, reader);
-    }
-
-    template <typename Map, typename Reader>
+    GraphReader& readEdgeMap(std::string name, Map& map) { 
+      return readEdgeMap<typename ReaderTraits::template Reader<typename Map::Value>, Map>(name, map);
+    }
+
+
+    template <typename Reader, typename Map>
     GraphReader& readEdgeMap(std::string name, Map& map, const Reader& reader = Reader()) {
+      if (edge_readers.find(name) != edge_readers.end()) {
+	Exception e;
+	e << "Multiple read rule for edge map: " << name;
+	throw e;
+      }
       edge_readers.insert(make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
       return *this;
     }
 
+    template <typename Reader>
+    GraphReader& skipEdgeMap(std::string name, const Reader& reader = Reader()) {
+      if (edge_readers.find(name) != edge_readers.end()) {
+	Exception e;
+	e << "Multiple read rule for edge map: " << name;
+	throw e;
+      }
+      edge_readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
+      return *this;
+    }
+
     void read() {
       int line_num = 0;
-      readNodeSet(line_num);
-      readEdgeSet(line_num);
-      {
-	std::string line = readNotEmptyLine(is, line_num);
-      }
+      InverterBase<Node>* nodeInverter = 0;
+      InverterBase<Edge>* edgeInverter = 0;
+      // \todo delete the inverters
+      //      try {
+	{
+	  std::string line = readNotEmptyLine(is, line_num);
+	}
+	readNodeSet(line_num, nodeInverter);
+	readEdgeSet(line_num, edgeInverter, nodeInverter);
+	//      } catch (...){
+	if (nodeInverter != 0) delete nodeInverter;
+	if (edgeInverter != 0) delete edgeInverter;
+	//      }
     }
 
   private:
 
-    void readNodeSet(int& line_num) {
+    template <typename Item> class InverterBase;
+    //    template <typename Item> class InverterBase;
+
+    void readNodeSet(int& line_num, InverterBase<Node>* & nodeInverter) {
       int n = 0;
-      {
-	std::string line = readNotEmptyLine(is, line_num);	
-      }
-      std::vector<MapReaderBase<Node>*> index;
+      std::vector<ReaderBase<Node>*> index;
       {
 	std::string line = readNotEmptyLine(is, line_num);    
@@ -131,29 +283,57 @@
 	std::istringstream ls(line);	
 	while (ls >> id) {
-	  typename map<std::string, MapReaderBase<Node>* >::iterator it = node_readers.find(id);
+	  if (id[0] == '#') break;
+	  typename NodeReaders::iterator it = node_readers.find(id);
 	  if (it != node_readers.end()) {
 	    index.push_back(it->second);
 	  } else {
-	    index.push_back(0);
+	    index.push_back(&nodeSkipper);
 	  }
 	  ++n;
 	}
       }
+
+      nodeInverter = index[0]->getInverter();
       std::string line;
       while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
 	Node node = graph.addNode();
 	std::istringstream ls(line);
-	for (int i = 0; i < n; ++i) {
-	  if (index[i] != 0) {	    
-	    index[i]->read(ls, node);
+	nodeInverter->read(ls, node);
+	for (int i = 1; i < n; ++i) {
+	  index[i]->read(ls, node);
+	}
+      }
+    }
+
+    void readEdgeSet(int& line_num, InverterBase<Edge>* & edgeInverter, InverterBase<Node>* & nodeInverter) {
+      int n = 0;
+      std::vector<ReaderBase<Edge>*> index;
+      {
+	std::string line = readNotEmptyLine(is, line_num);    
+	std::string id;
+	std::istringstream ls(line);	
+	while (ls >> id) {
+	  if (id[0] == '#') break;
+	  typename EdgeReaders::iterator it = edge_readers.find(id);
+	  if (it != edge_readers.end()) {
+	    index.push_back(it->second);
 	  } else {
-	    default_skipper.read(ls);
+	    index.push_back(&edgeSkipper);
 	  }
-	}
-      }
-    }
-
-    void readEdgeSet(int& line_num) {
-      
+	  ++n;
+	}
+      }
+      edgeInverter = index[0]->getInverter();
+      std::string line;
+      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {	
+	std::istringstream ls(line);
+	Node source = nodeInverter->read(ls);
+	Node target = nodeInverter->read(ls);
+	Edge edge = graph.addEdge(source, target);
+	edgeInverter->read(ls, edge);
+	for (int i = 1; i < n; ++i) {
+	  index[i]->read(ls, edge);
+	}
+      }      
     }
 
@@ -169,21 +349,105 @@
     }
     
-    istream& is;
-    Graph& graph;
-
-    typename ReaderTraits::DefaultSkipper default_skipper;
+    template <typename _Item>
+    class InverterBase {
+    public:
+      typedef _Item Item;
+      virtual void read(istream&, const Item&) = 0;
+      virtual Item read(istream&) = 0;
+    };
+
+    template <typename _Item, typename _Map, typename _Reader>
+    class MapReaderInverter : public InverterBase<_Item> {
+    public:
+      typedef _Item Item;
+      typedef _Reader Reader;
+      typedef typename Reader::Value Value;
+      typedef _Map Map;
+      typedef std::map<Value, Item> Inverse;
+
+      Map& map;
+      Reader reader;
+      Inverse inverse;
+
+      MapReaderInverter(Map& _map, const Reader& _reader) 
+	: map(_map), reader(_reader) {}
+
+      virtual void read(istream& is, const Item& item) {
+	Value value;
+	reader.read(is, value);
+	map.set(item, value);
+	typename Inverse::iterator it = inverse.find(value);
+	if (it == inverse.end()) {
+	  inverse.insert(make_pair(value, item));
+	} else {
+	  throw DataFormatException("Multiple ID occurence");
+	}
+      }
+
+      virtual Item read(istream& is) {
+	Value value;
+	reader.read(is, value);	
+	typename Inverse::const_iterator it = inverse.find(value);
+	if (it != inverse.end()) {
+	  return it->second;
+	} else {
+	  throw DataFormatException("Invalid ID");
+	}
+      }      
+    };
+
+    template <typename _Item, typename _Reader>
+    class SkipReaderInverter : public InverterBase<_Item> {
+    public:
+      typedef _Item Item;
+      typedef _Reader Reader;
+      typedef typename Reader::Value Value;
+      typedef std::map<Value, Item> Inverse;
+
+      Reader reader;
+
+      SkipReaderInverter(const Reader& _reader) 
+	: reader(_reader) {}
+
+      virtual void read(istream& is, const Item& item) {
+	Value value;
+	reader.read(is, value);
+	typename Inverse::iterator it = inverse.find(value);
+	if (it == inverse.end()) {
+	  inverse.insert(make_pair(value, item));
+	} else {
+	  throw DataFormatException("Multiple ID occurence");
+	}
+      }
+
+      virtual Item read(istream& is) {
+	Value value;
+	reader.read(is, value);	
+	typename Inverse::const_iterator it = inverse.find(value);
+	if (it != inverse.end()) {
+	  return it->second;
+	} else {
+	  throw DataFormatException("Invalid ID");
+	}
+      }      
+    private:
+      Inverse inverse;
+    };
+
 
     template <typename _Item>    
-    class MapReaderBase {
+    class ReaderBase {
     public:
       typedef _Item Item;
       virtual void read(istream& is, const Item& item) = 0;
-    };
-    
+      virtual InverterBase<_Item>* getInverter() = 0;
+    };
+
     template <typename _Item, typename _Map, typename _Reader>
-    class MapReader : public MapReaderBase<_Item> {
+    class MapReader : public ReaderBase<_Item> {
     public:
       typedef _Map Map;
       typedef _Reader Reader;
+      typedef typename Reader::Value Value;
       typedef _Item Item;
       
@@ -196,16 +460,48 @@
 
       virtual void read(istream& is, const Item& item) {
-	typename Reader::Value value;
+	Value value;
 	reader.read(is, value);
 	map.set(item, value);
       }
-    };
-
-    typedef std::map<std::string, MapReaderBase<Node>* > NodeReaders;
+
+      virtual InverterBase<_Item>* getInverter() {
+	return new MapReaderInverter<Item, Map, Reader>(map, reader);
+      }
+    };
+
+
+    template <typename _Item, typename _Reader>
+    class SkipReader : public ReaderBase<_Item> {
+    public:
+      typedef _Reader Reader;
+      typedef typename Reader::Value Value;
+      typedef _Item Item;
+
+      Reader reader;
+      SkipReader(const Reader& _reader) : reader(_reader) {}
+
+      virtual void read(istream& is, const Item& item) {
+	Value value;
+	reader.read(is, value);
+      }      
+
+      virtual InverterBase<Item>* getInverter() {
+	return new SkipReaderInverter<Item, Reader>(reader);
+      }
+    };
+
+
+    typedef std::map<std::string, ReaderBase<Node>* > NodeReaders;
     NodeReaders node_readers;
 
-    typedef std::map<std::string, MapReaderBase<Edge>* > EdgeReaders;
+    typedef std::map<std::string, ReaderBase<Edge>* > EdgeReaders;
     EdgeReaders edge_readers;
 
+    std::istream& is;
+    Graph& graph;
+
+    SkipReader<Node, DefaultReader> nodeSkipper;
+    SkipReader<Edge, DefaultReader> edgeSkipper;
+
   };
 
Index: src/work/deba/test.cpp
===================================================================
--- src/work/deba/test.cpp	(revision 1036)
+++ src/work/deba/test.cpp	(revision 1036)
@@ -0,0 +1,51 @@
+#include <iostream>
+
+using namespace std;
+
+
+struct _EmptyList {
+  void write() const {}
+};
+
+template <typename _Item, typename _Next>
+struct _AddNode {
+  typedef _Next Next;
+  typedef _Item Item;
+  
+  const Item item;
+  const Next& next;
+  
+  _AddNode(const Item& _item, const Next& _next) 
+    : item(_item), next(_next) {}
+
+  void write() const {
+    next.write();
+    cout << item << ' ';
+  }
+};
+
+template <typename _List = _EmptyList>
+struct _Writer {
+  typedef _List List;
+
+  const List list;
+
+  _Writer(const List& _list = List()) : list(_list) {}
+
+  
+  template <typename Item> _Writer<_AddNode<Item, List> > add(Item item) const {
+    return _Writer<_AddNode<Item, List> >(_AddNode<Item, List>(item, list));
+  }
+
+  void write() const {
+    list.write();
+    cout << endl;
+  }
+};
+
+
+typedef _Writer<> Writer;
+
+int main() {
+  Writer().add(3).add("alpha").add(4.53).write();
+}
Index: src/work/deba/test.lgf
===================================================================
--- src/work/deba/test.lgf	(revision 1032)
+++ src/work/deba/test.lgf	(revision 1036)
@@ -1,30 +1,36 @@
+@nodeset
+id cost color description mmap
+1 1 green "A -> B \t: 10" a
+2 2 blue "A -> B \t: 10" b
+# hatalom dicsoseg "A -> B \t: 10" c
+3 1 red "A -> B \t: 10" d #adjkhj
+4 2 red "A -> B \t: 10" e
+5 1 green "A -> B \t: 10" f
+10 1 green "A -> B \t: 10" g
+    # hello - bello csucsok "A -> B \t: 10"
+6 2 blue "A -> B \t: 10" h
+7 1 blue "A -> B \t: 10" i
+8 2 red "A -> B \t: 10" j
+9 1 green "A -> B \t: 10" k
+
+@edgeset 
+		id	weight 	description		mmap
+1	4	1	10 	"A -> B \t: 101"	a
+3 	5	5	29 	"A -> B \t: 10q"	b
+3	4	2	92 	"A -> B \t: 10a"	c
+2	3	6	92	"A -> B \t: 10d"	d
+9	5	9 	49	"A -> B \t: 10c"	e
+10	4	3	40	"A -> B \t: 10v"	f
+1	3	8	84	"A -> B \t: 10g"	g
+6	7	4	83 	"A -> B \t: 10h"	h
+8	9	7	37 	"A -> B \t: 10j"	i
+7	8	10	12 	"A -> B \t: 10g"	j
 
 @nodes
+source 1
+target 7
 
-id cost color
+@edges
+newedge 7
 
-1 1 green
-2 2 blue
-# hatalom dicsoseg
-3 1 red
-4 2 red
-5 1 green
-10 1 green # ez nem egy igazan jo sor
-    # hello - bello csucsok
-6 2 blue
-7 1 blue
-8 2 red
-9 1 green
-@edges
-source target weight
-1 4 10
-3 5 29
-3 4 92
-2 3 92
-9 5 49
-10 4 40
-1 3 84
-6 7 83
-8 9 37
-7 8 89
 @end
