// -*- mode: c++ -*-

#ifndef MIX_TOKENIZER_H_
#define MIX_TOKENIZER_H_


#include "classes.h"
#include "misc.h"
#include "XMLToken.h"

#include <stack>
#include <string>

namespace MiX{

  template <class charT,class char_traits,class xml_traits>
  class Tokenizer{
  public:
    MiX_Template_Typedef(charT,char_traits,xml_traits);
    typedef Tokenizer<charT,char_traits,xml_traits> this_type;
    typedef XMLToken<charT,char_traits,xml_traits> token_type;
  private:
    const charT* data_;
    const charT* start_;
    const charT* current_;
    /**
     * Streamからの解釈の時に1行ずつ格納しておくバッファ
     * std::string::c_strで得るポインタを保存して使用するのは、
     * 不安定なので、一回ココにコピー。
     */
    charT* line_;
    long len_;
    static const charT tokens_[15];
    std::stack<token_type> stack_;
    static TokenType isToken(charT);

    std::basic_istream<charT, char_traits>* is_;

    bool injectStringFromBuffer(const charT* text)
      { current_ = start_ = data_ = text; return true; }

    bool fillUpBuffer();
  public:
    ///コンストラクタ
    Tokenizer() : is_(0),line_(0) { }
    ///デストラクタ
    ~Tokenizer(){ if(line_) delete line_; }
    ///トークナイザに文字列を入れる
    bool injectString(const charT* text)
      { current_ = start_ = data_ = text; return true; }
    ///トークナイザの先頭にあるトークンを取り出す
    bool ejectToken(token_type& dest);
    ///トークナイザの先頭に指定したトークンを押し込む
    void pushToken(const token_type& tok){
      stack_.push(tok);
    }

    bool injectStream(std::basic_istream<charT, char_traits>& is)
      { is_ = &is; fillUpBuffer(); return true; }
  
  };

}

#ifndef MIX_TOKENIZER_CPP_
#include "Tokenizer.cpp"
#endif

#endif
