Download | Plain Text | No Line Numbers
- /**
- * @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: */
-