OSDN Git Service

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