diff --git a/swig/Makefile b/swig/Makefile
index 411277733c48c58dc039ff54d33f3bdf0e7a04dd..8b8bbfe45b50def4ce1ea604b8460bced6d6c362 100644
--- a/swig/Makefile
+++ b/swig/Makefile
@@ -19,7 +19,8 @@ CBIN=libcorpustag.o \
 		 libcorpuslexeme.o \
 		 libcorpussentence.o \
 		 libcorpuschunk.o \
-		 libcorpustokenwriter.o
+		 libcorpustokenwriter.o \
+		 libcorpustokenreader.o
 
 CBINOUT=_boost_shared_ptr.so \
 				_libcorpustag.so \
@@ -29,7 +30,8 @@ CBINOUT=_boost_shared_ptr.so \
 				_libcorpustoken.so \
 				_libcorpussentence.so \
 				_libcorpuschunk.so \
-				_libcorpustokenwriter.so
+				_libcorpustokenwriter.so \
+				_libcorpustokenreader.so
 
 CWRAP=boost_shared_ptr_wrap.cxx \
 			libcorpustag_wrap.cxx \
@@ -39,7 +41,8 @@ CWRAP=boost_shared_ptr_wrap.cxx \
 			libcorpustoken_wrap.cxx \
 			libcorpussentence_wrap.cxx \
 			libcorpuschunk_wrap.cxx \
-			libcorpustokenwriter_wrap.cxx
+			libcorpustokenwriter_wrap.cxx \
+			libcorpustokenreader_wrap.cxx
 
 CWRAPBIN=boost_shared_ptr_wrap.o \
 				 libcorpustag_wrap.o \
@@ -49,7 +52,8 @@ CWRAPBIN=boost_shared_ptr_wrap.o \
 				 libcorpustoken_wrap.o \
 				 libcorpussentence_wrap.o \
 				 libcorpuschunk_wrap.o \
-				 libcorpustokenwriter_wrap.o
+				 libcorpustokenwriter_wrap.o \
+				 libcorpustokenreader_wrap.o
 
 PYMODULES=boost_shared_ptr.py \
 					libcorpustag.py \
@@ -59,7 +63,8 @@ PYMODULES=boost_shared_ptr.py \
 					libcorpustoken.py \
 					libcorpussentence.py \
 					libcorpuschunk.py \
-					libcorpustokenwriter.py
+					libcorpustokenwriter.py \
+					libcorpustokenreader.py
 
 PYCBIN=boost_shared_ptr.pyc \
 			 libcorpustag.pyc \
@@ -69,7 +74,8 @@ PYCBIN=boost_shared_ptr.pyc \
 			 libcorpustoken.pyc \
 			 libcorpussentence.pyc \
 			 libcorpuschunk.pyc \
-			 libcorpustokenwriter.pyc
+			 libcorpustokenwriter.pyc \
+			 libcorpustokenreader.pyc
 
 # -----------------------------------------------------------------------------
 all:boost_shared_ptr.o $(CBIN)
@@ -138,6 +144,13 @@ libcorpustokenwriter.o:
 	$(CPP) -shared libcorpustokenwriter_wrap.o \
 		$(PWRUTILBIN) $(CORPUS2BIN) -o _libcorpustokenwriter.so
 
+# TokenReader
+libcorpustokenreader.o:
+	$(SWIG) $(SWIGOPTS_LANG) libcorpustokenreader.i
+	$(CPP) -c libcorpustokenreader_wrap.cxx -I$(PYTHONDIR) $(CPPFLAGS)
+	$(CPP) -shared libcorpustokenreader_wrap.o \
+		$(PWRUTILBIN) $(CORPUS2BIN) -o _libcorpustokenreader.so
+
 # -----------------------------------------------------------------------------
 clean:
 	rm -f $(CBIN) $(CBINOUT) $(CWRAP) $(CWRAPBIN) $(PYMODULES) $(PYCBIN)
diff --git a/swig/libcorpustokenreader.i b/swig/libcorpustokenreader.i
new file mode 100644
index 0000000000000000000000000000000000000000..1a6803611491f9303f9ce878fcb090b4283892a9
--- /dev/null
+++ b/swig/libcorpustokenreader.i
@@ -0,0 +1,63 @@
+#ifndef SWIG_LIBCORPUS2_TOKENREADER_I
+#define SWIG_LIBCORPUS2_TOKENREADER_I
+
+%module libcorpustokenreader
+%{
+  #include <libcorpus2/io/reader.h>
+%}
+
+%include "libcorpustag.i"
+%include "libcorpustoken.i"
+%include "libcorpuschunk.i"
+%include "libcorpustagset.i"
+%include "libcorpussentence.i"
+%include "std_string.i"
+%include "std_vector.i"
+%include "boost_shared_ptr.i"
+
+%nodefaultctor Corpus2::TokenReader;
+%template(TokenReaderPtr) boost::shared_ptr<Corpus2::TokenReader>;
+
+namespace Corpus2 {
+  class TokenReader {
+  public:
+    typedef boost::shared_ptr<TokenReader> TokenReaderPtr;
+
+    /* --------------------------------------------------------------------- */
+    explicit TokenReader(const Tagset& tagset);
+    virtual ~TokenReader();
+    
+    /* --------------------------------------------------------------------- */
+    static TokenReaderPtr create_path_reader(
+      const std::string& class_id,
+      const Tagset& tagset,
+      const std::string& path);
+
+    static TokenReaderPtr create_stream_reader(
+      const std::string& class_id,
+      const Tagset& tagset,
+      std::istream& stream);
+
+    /* --------------------------------------------------------------------- */
+    virtual Token* get_next_token() = 0;
+    virtual Sentence::Ptr get_next_sentence() = 0;
+    virtual boost::shared_ptr<Chunk> get_next_chunk() = 0;
+
+    /* --------------------------------------------------------------------- */
+    virtual void set_option(const std::string& option);
+    virtual std::string get_option(const std::string& option) const;
+
+    /* --------------------------------------------------------------------- */
+    const Tagset& tagset() const;
+    static std::vector<std::string> available_reader_types();
+
+    /* --------------------------------------------------------------------- */
+    static std::string reader_help(const std::string& class_id);
+    static std::vector<std::string> available_reader_types_help();
+  };
+}
+
+using namespace std;
+using namespace Corpus2;
+
+#endif /* SWIG_LIBCORPUS2_TOKENREADER_I */