summaryrefslogtreecommitdiffstats
path: root/ue3/mycpu/cprogram.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ue3/mycpu/cprogram.cpp')
-rw-r--r--ue3/mycpu/cprogram.cpp186
1 files changed, 119 insertions, 67 deletions
diff --git a/ue3/mycpu/cprogram.cpp b/ue3/mycpu/cprogram.cpp
index 9297b6e..3fcf734 100644
--- a/ue3/mycpu/cprogram.cpp
+++ b/ue3/mycpu/cprogram.cpp
@@ -1,109 +1,161 @@
1/** 1/**
2 * @module cprogram 2 * @module cprogram
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) 3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief class for parsing and saving a program 4 * @brief CProgram extends std::vector and adds a method for parsing programfile
5 * @date 11.05.2009 5 * @date 12.05.2009
6 */ 6 */
7 7
8#include <fstream>
9#include <vector>
10#include <string>
11#include <boost/tokenizer.hpp>
12#include <boost/algorithm/string.hpp> 8#include <boost/algorithm/string.hpp>
13#include <boost/algorithm/string/split.hpp> 9#include <boost/algorithm/string/split.hpp>
10#ifdef DEBUG
11# include <iostream>
12# include <iomanip>
13#endif
14#include "cprogram.h" 14#include "cprogram.h"
15 15#include "instructions.h"
16
17 16
18using namespace std; 17using namespace std;
19using namespace boost;
20 18
21CProgram::CProgram(const std::string& progfile) : 19CProgram::CProgram()
22 m_programfile(progfile)
23{ 20{
24 parse(); 21 m_instrset.insert(new CInstructionInc);
25 dump(std::cout); 22 m_instrset.insert(new CInstructionDec);
26 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);
27} 35}
28 36
29/*----------------------------------------------------------------------------*/ 37/*----------------------------------------------------------------------------*/
30 38
31CProgram::~CProgram() 39CProgram::~CProgram()
32{ 40{
33 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;
34} 49}
35 50
36
37
38/*----------------------------------------------------------------------------*/ 51/*----------------------------------------------------------------------------*/
39 52
40void CProgram::parse() 53void CProgram::compile(std::istream& in)
41{ 54{
42 /* open and read file */ 55 if (!in.good())
43 ifstream file(m_programfile.c_str(), ios::in); 56 return;
44 // if (!file) 57
45 // throw ParserError("Unable to open scriptfile '" + m_scriptfile + "'."); 58 string line;
46 59 unsigned i = 0;
47 int cur_line_nr = 0; 60 while (!in.eof() && in.good())
48
49 while (!file.eof() && file.good())
50 { 61 {
51 string cur_line; 62 ++i;
52 63
53 /* read file per line */ 64 /* read stream per line */
54 getline(file, cur_line); 65 getline(in, line);
55 if (cur_line.empty()) 66 if (line.empty())
56 continue; 67 continue;
57 68
58 trim(cur_line); 69 boost::trim(line);
70 boost::to_lower(line);
59 71
60 /* ignore comments */ 72 /* ignore comments */
61 if (cur_line.find_first_of('#') == 0) 73 if (line.find_first_of('#') == 0)
62 continue; 74 continue;
63 75
64 /*remove commas from current line */ 76 /* get instruction name */
65 unsigned int pos; 77 size_t pos = line.find_first_of(' ');
66 while (( pos = cur_line.find_first_of(",") ) != string::npos) 78 string instrname(line.substr(0, pos));
67 cur_line.erase(pos, 1); 79
68 80 /* search and create instruction */
69 /* add source line*/ 81 CInstruction *instrptr = NULL;
70 m_progsource.push_back(vector<string>()); 82 set<CInstruction *>::iterator it;
71 algorithm::split( m_progsource.back(), cur_line, is_any_of(" \t")); 83 for (it = m_instrset.begin(); it != m_instrset.end(); ++it)
72 84 {
73 /* jump addr as line number */ 85 if (*(*it) == instrname)
74 if(m_progsource[cur_line_nr][0] == "label") 86 {
75 { 87 instrptr = *it;
76 int size = m_progsource[cur_line_nr][01].size() - 1; 88 break;
77 string label(m_progsource[cur_line_nr][01].substr(0, size)); 89 }
78 m_jumpaddr[label] = cur_line_nr; 90 }
79 } 91 if (instrptr == NULL)
80 92 {
81 cur_line_nr++; 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);
82 } 131 }
83 file.close(); 132}
133
134/*----------------------------------------------------------------------------*/
84 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;
85} 143}
86 144
87/*----------------------------------------------------------------------------*/ 145/*----------------------------------------------------------------------------*/
88 146
89#ifdef DEBUG 147#if DEBUG
90void CProgram::dump(std::ostream& out) 148void CProgram::dump(std::ostream& out)
91{ 149{
92 150 out << "[PROGRAM DUMP]" << endl;
93 out << endl << "Program file:" << endl << m_programfile << endl; 151 unsigned i = 0;
94 152 for(iterator it = begin(); it < end(); ++it)
95 out << endl << "Program source:" << endl;
96 for (int i = 0; i < (int) m_progsource.size();i++)
97 { 153 {
98 for(int x = 0; x < (int) m_progsource[i].size();x++) 154 out << "[" << std::setw(4) << std::setfill('0') << i << "] "
99 out << m_progsource[i][x] << " "; 155 << *(*it) << endl;
100 out << std::endl; 156 ++i;
101 } 157 }
102
103 out << endl << "Jump addresses:" << endl;
104 map<string, unsigned int>::iterator it;
105 for (it = m_jumpaddr.begin(); it != m_jumpaddr.end(); it++)
106 out << (*it).first << " " << (*it).second << endl;
107
108} 158}
109#endif 159#endif
160
161/* vim: set et sw=2 ts=2: */