diff options
Diffstat (limited to 'ue4/mycpu/cprogram.h')
| -rw-r--r-- | ue4/mycpu/cprogram.h | 173 |
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 */ | ||
| 24 | template <class T> | ||
| 25 | class 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 | */ |
| 33 | template <class T> | ||
| 22 | class CProgram | 34 | class 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 | |||
| 125 | template <class T> | ||
| 126 | CProgram<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 | |||
| 146 | template <class T> | ||
| 147 | CProgram<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 | |||
| 160 | template <class T> | ||
| 161 | void 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 | |||
| 244 | template <class T> | ||
| 245 | unsigned 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 | ||
| 257 | template <class T> | ||
| 258 | void 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: */ |
