| 1 |
//---------------------------------------------------------------------------- |
| 2 |
// QCompiler.cpp |
| 3 |
// Compile intermediate codes |
| 4 |
// $Date: 2003/01/17 19:37:43 $ |
| 5 |
// $Revision: 1.3 $ |
| 6 |
//---------------------------------------------------------------------------- |
| 7 |
#ifdef __BORLANDC__ |
| 8 |
#include <vcl.h> |
| 9 |
#pragma hdrstop |
| 10 |
#endif //__BORLANDC__ |
| 11 |
|
| 12 |
#include <iostream> |
| 13 |
#include <vector> |
| 14 |
#include <string> |
| 15 |
#include <cstdlib> |
| 16 |
#include "QCompiler.h" |
| 17 |
#include "QParseInfo.h" |
| 18 |
|
| 19 |
//---------------------------------------------------------------------------- |
| 20 |
#ifdef __BORLANDC__ |
| 21 |
#pragma package(smart_init) |
| 22 |
#endif //__BORLANDC__ |
| 23 |
|
| 24 |
using namespace std; |
| 25 |
|
| 26 |
//---------------------------------------------------------------------------- |
| 27 |
// Syntax of intermediate code (see also `QCompiler.h') |
| 28 |
//---------------------------------------------------------------------------- |
| 29 |
const char QCompiler::OP_BRA = '('; |
| 30 |
const char QCompiler::OP_KET = ')'; |
| 31 |
const char QCompiler::QB_BRA = '['; |
| 32 |
const char QCompiler::QB_KET = ']'; |
| 33 |
const char QCompiler::DELIM = ','; |
| 34 |
|
| 35 |
const QCompiler::QGATES QCompiler::qgates[] = { |
| 36 |
{"CNOT" ,2,{ at_qbit, at_qbit, at_null}}, |
| 37 |
{"ROT" ,2,{ at_qbit, at_real, at_null}}, |
| 38 |
{"CROT" ,3,{ at_qbit, at_qbit, at_real}}, |
| 39 |
{"H" ,1,{ at_qbit, at_null, at_null}}, |
| 40 |
{"MEASURE" ,1,{ at_qbit, at_null, at_null}}, |
| 41 |
{"SWAP" ,2,{ at_qbit, at_qbit, at_null}}, |
| 42 |
{"PAULIX" ,1,{ at_qbit, at_null, at_null}}, |
| 43 |
{"PAULIY" ,1,{ at_qbit, at_null, at_null}}, |
| 44 |
{"PAULIZ" ,1,{ at_qbit, at_null, at_null}}, |
| 45 |
{"NOT" ,1,{ at_qbit, at_null, at_null}}, |
| 46 |
{"CCNOT",3,{ at_qbit, at_qbit, at_qbit}}, |
| 47 |
{"INIT" ,1,{ at_real, at_null, at_null}} |
| 48 |
}; |
| 49 |
|
| 50 |
const int QCompiler::opn_max = sizeof(QCompiler::qgates)/sizeof(QCompiler::QGATES); |
| 51 |
|
| 52 |
//---------------------------------------------------------------------------- |
| 53 |
/** |
| 54 |
* Constructor |
| 55 |
*/ |
| 56 |
QCompiler::QCompiler(void) { |
| 57 |
mError = false; |
| 58 |
mState = false; |
| 59 |
} |
| 60 |
//---------------------------------------------------------------------------- |
| 61 |
/** |
| 62 |
* Constructor with input stream |
| 63 |
*/ |
| 64 |
QCompiler::QCompiler(std::istream &is) { |
| 65 |
mError = false; |
| 66 |
mState = false; |
| 67 |
ReadFromStream(is); |
| 68 |
} |
| 69 |
//---------------------------------------------------------------------------- |
| 70 |
/** |
| 71 |
* Destructor |
| 72 |
*/ |
| 73 |
QCompiler::~QCompiler() { |
| 74 |
} |
| 75 |
//---------------------------------------------------------------------------- |
| 76 |
/** |
| 77 |
* Read intermediate code from stream |
| 78 |
*/ |
| 79 |
void |
| 80 |
QCompiler::ReadFromStream(std::istream &is) { |
| 81 |
char c1; |
| 82 |
std::string st1 = ""; |
| 83 |
int nlcode = -1; // -1:unknown 0:CR+LF 1:LF+CR 2:CR 3:LF |
| 84 |
|
| 85 |
mLines.clear(); |
| 86 |
mError = mState = false; |
| 87 |
|
| 88 |
while (!is.eof()) { |
| 89 |
is.read(&c1, 1); |
| 90 |
if (c1 == 0x0d || c1 == 0x0a) { |
| 91 |
switch (nlcode) { |
| 92 |
case -1: // unknown |
| 93 |
if (c1 == 0x0d) { |
| 94 |
if (0x0a == is.peek()) { |
| 95 |
nlcode = 0; |
| 96 |
} else { |
| 97 |
nlcode = 2; |
| 98 |
goto push; |
| 99 |
} |
| 100 |
} else {// c1 == 0x0a |
| 101 |
if (0x0d == is.peek()) { |
| 102 |
nlcode = 1; |
| 103 |
} else { |
| 104 |
nlcode = 3; |
| 105 |
goto push; |
| 106 |
} |
| 107 |
} |
| 108 |
case 0: |
| 109 |
case 1: |
| 110 |
is.read(&c1, 1); // skip one char |
| 111 |
case 2: |
| 112 |
case 3: |
| 113 |
push: |
| 114 |
mLines.push_back(st1); |
| 115 |
st1 = ""; |
| 116 |
break; |
| 117 |
default: |
| 118 |
break; |
| 119 |
} |
| 120 |
} else { |
| 121 |
st1 += c1; |
| 122 |
} |
| 123 |
} |
| 124 |
} |
| 125 |
//---------------------------------------------------------------------------- |
| 126 |
/** |
| 127 |
* Compile |
| 128 |
*/ |
| 129 |
bool |
| 130 |
QCompiler::Compile(void) { |
| 131 |
int i, vec_size = mLines.size(); |
| 132 |
for (i = 0; i < vec_size; i++) { |
| 133 |
if (mLines[i].length() == 0 || mLines[i][0] == '#') { |
| 134 |
// skip |
| 135 |
continue; |
| 136 |
} |
| 137 |
QParseInfo pinfo = ParseOneLine(mLines[i]); |
| 138 |
try { |
| 139 |
if (!CompileOneLine(pinfo)) throw pinfo; |
| 140 |
} catch (QParseInfo einfo) { |
| 141 |
mError = true; |
| 142 |
CatchError(einfo, i); // is abstract virtual member |
| 143 |
break; |
| 144 |
} |
| 145 |
} |
| 146 |
mState = true; |
| 147 |
return !mError; |
| 148 |
} |
| 149 |
//---------------------------------------------------------------------------- |
| 150 |
/** |
| 151 |
* Parser |
| 152 |
*/ |
| 153 |
QParseInfo |
| 154 |
QCompiler::ParseOneLine(const std::string &strline) const { |
| 155 |
int i, j; // tmp |
| 156 |
std::string s1, s2; // tmp |
| 157 |
std::vector<std::string> args; |
| 158 |
int comint; |
| 159 |
std::vector<int> targets; |
| 160 |
double rotation = 0; |
| 161 |
|
| 162 |
// Com(Arg) |
| 163 |
if (!ExtractComArg(strline, OP_BRA, OP_KET, s1, s2)) { |
| 164 |
return QParseInfo(QParseInfo::er_syntax_error); |
| 165 |
} |
| 166 |
|
| 167 |
// Extract aa, bb, and cc from "aa,bb,cc" |
| 168 |
if (!ExtractField(s2, DELIM, args)) { |
| 169 |
// discard s2 |
| 170 |
return QParseInfo(QParseInfo::er_syntax_error); |
| 171 |
} |
| 172 |
|
| 173 |
// Get command number from command string |
| 174 |
if ((comint = GetComint(s1)) == -1) { |
| 175 |
// discard s1 |
| 176 |
return QParseInfo(QParseInfo::er_unknown_operation); |
| 177 |
} |
| 178 |
|
| 179 |
j = args.size(); |
| 180 |
if (j < qgates[comint].arg_num) { |
| 181 |
return QParseInfo(QParseInfo::er_lack_of_arguments); |
| 182 |
} |
| 183 |
if (j > qgates[comint].arg_num) { |
| 184 |
return QParseInfo(QParseInfo::er_too_many_arguments); |
| 185 |
} |
| 186 |
|
| 187 |
for (i = 0; i < j; i++) { |
| 188 |
switch (qgates[comint].arg_types[i]) { |
| 189 |
case at_qbit: |
| 190 |
if (ExtractComArg(args[i], QB_BRA, QB_KET, s1, s2) && s1 == "q" && s2 != "") { |
| 191 |
targets.push_back(std::atoi(s2.c_str())); |
| 192 |
} else { |
| 193 |
return QParseInfo(QParseInfo::er_invalid_arguments); |
| 194 |
} |
| 195 |
break; |
| 196 |
case at_real: |
| 197 |
rotation = std::atof(args[i].c_str()); |
| 198 |
targets.push_back(std::atof(args[i].c_str())); |
| 199 |
case at_oprt: |
| 200 |
break; |
| 201 |
default: |
| 202 |
break; |
| 203 |
} |
| 204 |
} |
| 205 |
return QParseInfo(comint, targets, rotation); |
| 206 |
} |
| 207 |
//---------------------------------------------------------------------------- |
| 208 |
/** |
| 209 |
* ex) bra = '[', ket = ']', strline = "q[20]" --> get "q" and "20" as string |
| 210 |
* bra = '(', ket = ')', strline = CNOT(q[0],q[1]) |
| 211 |
* --> get "CNOT" and "q[0],q[1]" as string |
| 212 |
*/ |
| 213 |
bool |
| 214 |
QCompiler::ExtractComArg(const std::string &strline, const char bra, const char ket, |
| 215 |
std::string &Com, |
| 216 |
std::string &Arg) const { |
| 217 |
int pos_bra = strline.find(bra); |
| 218 |
int pos_ket = strline.find(ket); |
| 219 |
int length = strline.length(); |
| 220 |
|
| 221 |
Com = Arg = ""; |
| 222 |
if (pos_bra < 1 || pos_ket - pos_bra < 1 || pos_ket != length - 1) { |
| 223 |
return false; |
| 224 |
} |
| 225 |
Com = strline.substr(0, pos_bra); |
| 226 |
if (pos_ket - pos_bra >= 2) { |
| 227 |
Arg = strline.substr(pos_bra + 1, pos_ket - pos_bra - 1); |
| 228 |
} |
| 229 |
return true; |
| 230 |
} |
| 231 |
//---------------------------------------------------------------------------- |
| 232 |
/** |
| 233 |
* Null field is not allowd, but "" (zero string) is OK. |
| 234 |
* |
| 235 |
* ex) delim = ',', strline = "q[0],q[4],10" |
| 236 |
* --> get "q[0]", "q[4]" and "10" as vector<string>, and return true |
| 237 |
* delim = ',', strline = "aa,,bb" (having null field between aa and bb) |
| 238 |
* --> return false |
| 239 |
* delim = ',', strline = "" |
| 240 |
* --> return true |
| 241 |
*/ |
| 242 |
bool |
| 243 |
QCompiler::ExtractField(const std::string &strline, const char delim, |
| 244 |
std::vector<std::string> &Args) const { |
| 245 |
int i; |
| 246 |
int fpos = 0; |
| 247 |
int length = strline.length(); |
| 248 |
std::string s1 = ""; |
| 249 |
|
| 250 |
Args.clear(); |
| 251 |
for (i = 0; i < length; i++) { |
| 252 |
if (strline.at(i) == delim) { |
| 253 |
if (i > fpos) { |
| 254 |
Args.push_back(s1); |
| 255 |
s1 = ""; |
| 256 |
fpos = i + 1; |
| 257 |
} else { |
| 258 |
return false; |
| 259 |
} |
| 260 |
} else { |
| 261 |
s1 += strline.at(i); |
| 262 |
} |
| 263 |
} |
| 264 |
if (s1.length() > 0) { |
| 265 |
Args.push_back(s1); |
| 266 |
} |
| 267 |
return true; |
| 268 |
} |
| 269 |
//---------------------------------------------------------------------------- |
| 270 |
/** |
| 271 |
* Get command number from command string |
| 272 |
*/ |
| 273 |
int |
| 274 |
QCompiler::GetComint(const std::string &_str) const { |
| 275 |
for (int i = 0; i < opn_max; i++)if (_str == qgates[i].opstr) return i; |
| 276 |
return -1; |
| 277 |
} |
| 278 |
//---------------------------------------------------------------------------- |