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