summaryrefslogtreecommitdiffstats
path: root/ue4/mycpu/cprogram.h
diff options
context:
space:
mode:
Diffstat (limited to 'ue4/mycpu/cprogram.h')
-rw-r--r--ue4/mycpu/cprogram.h173
1 files changed, 170 insertions, 3 deletions
diff --git a/ue4/mycpu/cprogram.h b/ue4/mycpu/cprogram.h
index 27e7647..43193ac 100644
--- a/ue4/mycpu/cprogram.h
+++ b/ue4/mycpu/cprogram.h
@@ -2,7 +2,7 @@
2 * @module cprogram 2 * @module cprogram
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) 3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief CProgram extends std::vector and adds a method for parsing programfile 4 * @brief CProgram extends std::vector and adds a method for parsing programfile
5 * @date 10.05.2009 5 * @date 26.05.2009
6 */ 6 */
7 7
8#ifndef CPROGRAM_H 8#ifndef CPROGRAM_H
@@ -11,7 +11,18 @@
11#include <vector> 11#include <vector>
12#include <set> 12#include <set>
13#include <map> 13#include <map>
14#include <boost/algorithm/string.hpp>
15#include <boost/algorithm/string/split.hpp>
16#ifdef DEBUG
17# include <iostream>
18# include <iomanip>
19#endif
14#include "cinstruction.h" 20#include "cinstruction.h"
21#include "instructions.h"
22
23/* forward declare CInstruction */
24template <class T>
25class CInstruction;
15 26
16/** 27/**
17 * @class CProgram 28 * @class CProgram
@@ -19,9 +30,17 @@
19 * CProgram extends std::vector and adds a method for parsing 30 * CProgram extends std::vector and adds a method for parsing
20 * programfile. This adds instances of CInstruction to CProgram itself. 31 * programfile. This adds instances of CInstruction to CProgram itself.
21 */ 32 */
33template <class T>
22class CProgram 34class CProgram
23 : public std::vector<CInstruction *> 35 : public std::vector<CInstruction<T> *>
24{ 36{
37 typedef typename std::set<CInstruction<T> *>::iterator setiterator;
38 typedef std::vector<CInstruction<T> *> super;
39 typedef typename super::iterator iterator;
40 using super::begin;
41 using super::end;
42 using super::size;
43
25 public: 44 public:
26 /** 45 /**
27 * @method CProgram 46 * @method CProgram
@@ -97,10 +116,158 @@ class CProgram
97 private: 116 private:
98 /* members */ 117 /* members */
99 /** set of known instructions */ 118 /** set of known instructions */
100 std::set<CInstruction *> m_instrset; 119 std::set<CInstruction<T> *> m_instrset;
101 std::map<std::string, unsigned> m_labels; 120 std::map<std::string, unsigned> m_labels;
102}; 121};
103 122
123/*----------------------------------------------------------------------------*/
124
125template <class T>
126CProgram<T>::CProgram()
127{
128 m_instrset.insert(new CInstructionInc<T>);
129 m_instrset.insert(new CInstructionDec<T>);
130 m_instrset.insert(new CInstructionAdd<T>);
131 m_instrset.insert(new CInstructionSub<T>);
132 m_instrset.insert(new CInstructionMul<T>);
133 m_instrset.insert(new CInstructionDiv<T>);
134 m_instrset.insert(new CInstructionLoad<T>);
135 m_instrset.insert(new CInstructionStore<T>);
136 m_instrset.insert(new CInstructionTest<T>);
137 m_instrset.insert(new CInstructionLabel<T>);
138 m_instrset.insert(new CInstructionJumpA<T>);
139 m_instrset.insert(new CInstructionJumpZ<T>);
140 m_instrset.insert(new CInstructionJumpS<T>);
141 m_instrset.insert(new CInstructionWrite<T>);
142}
143
144/*----------------------------------------------------------------------------*/
145
146template <class T>
147CProgram<T>::~CProgram()
148{
149 /* free instruction set */
150 for (setiterator it = m_instrset.begin(); it != m_instrset.end(); ++it)
151 delete *it;
152
153 /* free instruction */
154 for (iterator it2 = begin(); it2 != end(); ++it2)
155 delete *it2;
156}
157
158/*----------------------------------------------------------------------------*/
159
160template <class T>
161void CProgram<T>::compile(std::istream& in)
162{
163 if (!in.good())
164 return;
165
166 std::string line;
167 unsigned i = 0;
168 while (!in.eof() && in.good())
169 {
170 ++i;
171
172 /* read stream per line */
173 std::getline(in, line);
174 if (line.empty())
175 continue;
176
177 boost::trim(line);
178 boost::to_lower(line);
179
180 /* ignore comments */
181 if (line.find_first_of('#') == 0)
182 continue;
183
184 /* get instruction name */
185 size_t pos = line.find_first_of(' ');
186 std::string instrname(line.substr(0, pos));
187
188 /* search and create instruction */
189 CInstruction<T> *instrptr = NULL;
190 setiterator it;
191 for (it = m_instrset.begin(); it != m_instrset.end(); ++it)
192 {
193 if (*(*it) == instrname)
194 {
195 instrptr = *it;
196 break;
197 }
198 }
199 if (instrptr == NULL)
200 {
201 std::stringstream sstr;
202 sstr << "Unknown instruction '" << instrname << "' on line " << i << ".";
203 throw std::runtime_error(sstr.str());
204 }
205
206 /* create instruction */
207 CInstruction<T> *instr = instrptr->factory();
208
209 /* parse instruction parameters */
210 std::string params = (pos == std::string::npos) ? "" : line.substr(pos + 1);
211 boost::trim(params);
212 std::list<std::string> instrparams;
213 boost::split(instrparams, params, boost::is_any_of(", \t"), boost::token_compress_on);
214
215 /* let instruction parse the parameters. catch+throw exception */
216 try
217 {
218 /* handle label instruction ourself, but still add a dummy instruction */
219 if (instrname == "label")
220 {
221 if (instrparams.size() != 1)
222 throw std::runtime_error("Invalid paramater count - must be 1");
223 std::string label(instrparams.front());
224 if (label.length() < 2 || label[ label.length() - 1] != ':')
225 throw std::runtime_error("Label has invalid syntax");
226 m_labels[ label.substr(0, label.length() - 1) ] = size();
227 }
228 instr->compile(instrparams);
229 }
230 catch(std::runtime_error& ex)
231 {
232 std::stringstream sstr;
233 sstr << "Unable to compile instruction '" << instrname
234 << "' (line " << i << "): " << ex.what();
235 throw std::runtime_error(sstr.str());
236 }
237
238 push_back(instr);
239 }
240}
241
242/*----------------------------------------------------------------------------*/
243
244template <class T>
245unsigned CProgram<T>::findLabel(const std::string& label) const
246{
247 std::map<std::string, unsigned>::const_iterator it;
248 it = m_labels.find(label);
249 if (it == m_labels.end())
250 throw std::runtime_error("Unknown label '" + label + "'");
251 return it->second;
252}
253
254/*----------------------------------------------------------------------------*/
255
256#if DEBUG
257template <class T>
258void CProgram<T>::dump(std::ostream& out)
259{
260 out << "[PROGRAM DUMP]" << std::endl;
261 unsigned i = 0;
262 for(iterator it = begin(); it != end(); ++it)
263 {
264 out << "[" << std::setw(4) << std::setfill('0') << i << "] "
265 << *(*it) << std::endl;
266 ++i;
267 }
268}
269#endif
270
104#endif 271#endif
105 272
106/* vim: set et sw=2 ts=2: */ 273/* vim: set et sw=2 ts=2: */