//----------------------------------------------------------------------------
//  QCompiler.h
//  Compile intermediate codes
//  $Date: 2003/01/17 19:37:43 $
//  $Revision: 1.3 $
//----------------------------------------------------------------------------
#ifndef QCOMPILER_H
#define QCOMPILER_H

#include <iostream>
#include <string>
#include <vector>
#include "QParseInfo.h"

class QCompiler {

public:
  QCompiler(void);
  QCompiler(std::istream &is);
  virtual ~QCompiler();
  bool Compile(void);
  void ReadFromStream(std::istream &is);
  bool HasError(void) {
    return mError;
  }
  bool GetState(void) {
    return mState;
  }

  typedef enum _opnumber {
    opn_arg_max = 3,
    opn_length  = 10
  } OpNumber;

  static const int opn_max;

protected:
  virtual bool CompileOneLine(const QParseInfo &pinfo) = 0;
  virtual void CatchError(const QParseInfo &pinfo, const int at) = 0;

  QParseInfo  ParseOneLine(const std::string &strline) const;
  bool        ExtractComArg(const std::string &strline, const char bra, const char ket,
                            std::string &Com, std::string &Arg) const;
  bool        ExtractField(const std::string &strline, const char delim,
                           std::vector<std::string> &Args) const ;
  int         GetComint(const std::string &_str) const;

  // Member valuables
  std::vector<std::string>    mLines;
  bool                        mError;
  bool                        mState; // true == finished

  //------------------------------------------------------------------------
  //  Syntax of intermediate code  (see also `QCompiler.cpp')
  //------------------------------------------------------------------------
  // Argument types
  typedef enum _argtype {
    at_null = 0,
    at_qbit = 1,
    at_real = 2,
    at_oprt = 3
  } ArgType;

  // Command numbers, each of which corresponds to the index num of OPSTR

  typedef enum _commandnumber {
    cn_cnot     = 0,
    cn_rot ,
    cn_crot ,
    cn_h    ,
    cn_m    ,
    cn_swap ,
    cn_x    ,
    cn_y    ,
    cn_z    ,
    cn_not  ,
    cn_ccnot,
    cn_init
  } CommandNumber;

  // Size of array



  struct QGATES {
    char opstr[opn_length];
    int arg_num;
    int arg_types[opn_arg_max];
  };

  static const QGATES qgates[];

  static const char   OP_BRA;
  static const char   OP_KET;
  static const char   QB_BRA;
  static const char   QB_KET;
  static const char   DELIM;
};

#endif //QCOMPILER_H
