summaryrefslogtreecommitdiffstats
path: root/ue4/mycpu/cprogram.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ue4/mycpu/cprogram.cpp')
-rw-r--r--ue4/mycpu/cprogram.cpp161
1 files changed, 161 insertions, 0 deletions
diff --git a/ue4/mycpu/cprogram.cpp b/ue4/mycpu/cprogram.cpp
new file mode 100644
index 0000000..3fcf734
--- /dev/null
+++ b/ue4/mycpu/cprogram.cpp
@@ -0,0 +1,161 @@
1/**
2 * @module cprogram
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief CProgram extends std::vector and adds a method for parsing programfile
5 * @date 12.05.2009
6 */
7
8#include <boost/algorithm/string.hpp>
9#include <boost/algorithm/string/split.hpp>
10#ifdef DEBUG
11# include <iostream>
12# include <iomanip>
13#endif
14#include "cprogram.h"
15#include "instructions.h"
16
17using namespace std;
18
19CProgram::CProgram()
20{
21 m_instrset.insert(new CInstructionInc);
22 m_instrset.insert(new CInstructionDec);
23 m_instrset.insert(new CInstructionAdd);
24 m_instrset.insert(new CInstructionSub);
25 m_instrset.insert(new CInstructionMul);
26 m_instrset.insert(new CInstructionDiv);
27 m_instrset.insert(new CInstructionLoad);
28 m_instrset.insert(new CInstructionStore);
29 m_instrset.insert(new CInstructionTest);
30 m_instrset.insert(new CInstructionLabel);
31 m_instrset.insert(new CInstructionJumpA);
32 m_instrset.insert(new CInstructionJumpZ);
33 m_instrset.insert(new CInstructionJumpS);
34 m_instrset.insert(new CInstructionWrite);
35}
36
37/*----------------------------------------------------------------------------*/
38
39CProgram::~CProgram()
40{
41 /* free instruction set */
42 set<CInstruction *>::iterator it;
43 for (it = m_instrset.begin(); it != m_instrset.end(); ++it)
44 delete *it;
45
46 /* free instruction */
47 for (iterator it = begin(); it != end(); ++it)
48 delete *it;
49}
50
51/*----------------------------------------------------------------------------*/
52
53void CProgram::compile(std::istream& in)
54{
55 if (!in.good())
56 return;
57
58 string line;
59 unsigned i = 0;
60 while (!in.eof() && in.good())
61 {
62 ++i;
63
64 /* read stream per line */
65 getline(in, line);
66 if (line.empty())
67 continue;
68
69 boost::trim(line);
70 boost::to_lower(line);
71
72 /* ignore comments */
73 if (line.find_first_of('#') == 0)
74 continue;
75
76 /* get instruction name */
77 size_t pos = line.find_first_of(' ');
78 string instrname(line.substr(0, pos));
79
80 /* search and create instruction */
81 CInstruction *instrptr = NULL;
82 set<CInstruction *>::iterator it;
83 for (it = m_instrset.begin(); it != m_instrset.end(); ++it)
84 {
85 if (*(*it) == instrname)
86 {
87 instrptr = *it;
88 break;
89 }
90 }
91 if (instrptr == NULL)
92 {
93 stringstream sstr;
94 sstr << "Unknown instruction '" << instrname << "' on line " << i << ".";
95 throw runtime_error(sstr.str());
96 }
97
98 /* create instruction */
99 CInstruction *instr = instrptr->factory();
100
101 /* parse instruction parameters */
102 string params = (pos == string::npos) ? "" : line.substr(pos + 1);
103 boost::trim(params);
104 list<string> instrparams;
105 boost::split(instrparams, params, boost::is_any_of(", \t"), boost::token_compress_on);
106
107 /* let instruction parse the parameters. catch+throw exception */
108 try
109 {
110 /* handle label instruction ourself, but still add a dummy instruction */
111 if (instrname == "label")
112 {
113 if (instrparams.size() != 1)
114 throw runtime_error("Invalid paramater count - must be 1");
115 string label(instrparams.front());
116 if (label.length() < 2 || label[ label.length() - 1] != ':')
117 throw runtime_error("Label has invalid syntax");
118 m_labels[ label.substr(0, label.length() - 1) ] = size();
119 }
120 instr->compile(instrparams);
121 }
122 catch(runtime_error& ex)
123 {
124 stringstream sstr;
125 sstr << "Unable to compile instruction '" << instrname
126 << "' (line " << i << "): " << ex.what();
127 throw runtime_error(sstr.str());
128 }
129
130 push_back(instr);
131 }
132}
133
134/*----------------------------------------------------------------------------*/
135
136unsigned CProgram::findLabel(const std::string& label) const
137{
138 map<string, unsigned>::const_iterator it;
139 it = m_labels.find(label);
140 if (it == m_labels.end())
141 throw runtime_error("Unknown label '" + label + "'");
142 return it->second;
143}
144
145/*----------------------------------------------------------------------------*/
146
147#if DEBUG
148void CProgram::dump(std::ostream& out)
149{
150 out << "[PROGRAM DUMP]" << endl;
151 unsigned i = 0;
152 for(iterator it = begin(); it < end(); ++it)
153 {
154 out << "[" << std::setw(4) << std::setfill('0') << i << "] "
155 << *(*it) << endl;
156 ++i;
157 }
158}
159#endif
160
161/* vim: set et sw=2 ts=2: */