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 26.05.2009
- */
-
- #ifndef CPROGRAM_H
- #define CPROGRAM_H 1
-
- #include <vector>
- #include <set>
- #include <map>
- #include <stdexcept>
- #include <boost/algorithm/string.hpp>
- #include <boost/algorithm/string/split.hpp>
- #ifdef DEBUG
- # include <iostream>
- # include <iomanip>
- #endif
-
- /**
- * @class CProgramError
- *
- * Exception thrown by implemententations of CProgram
- */
- class CProgramError
- : public std::invalid_argument
- {
- public:
- /**
- * @method CProgramError
- * @brief Default exception ctor
- * @param what message to pass along
- * @return -
- * @globalvars none
- * @exception none
- * @pre none
- * @post none
- */
- CProgramError(const std::string& what)
- : std::invalid_argument(what)
- {}
- };
-
- #include "cinstruction.h"
- #include "instructions.h"
-
- /* forward declare CInstruction */
- template <class T>
- class CInstruction;
-
- /**
- * @class CProgram
- *
- * CProgram extends std::vector and adds a method for parsing
- * programfile. This adds instances of CInstruction to CProgram itself.
- */
- template <class T>
- class CProgram
- : public std::vector<CInstruction<T> *>
- {
- typedef typename std::set<CInstruction<T> *>::iterator setiterator;
- typedef std::vector<CInstruction<T> *> super;
- typedef typename super::iterator iterator;
- using super::begin;
- using super::end;
- using super::size;
-
- public:
- /**
- * @method CProgram
- * @brief Default ctor
- * @param -
- * @return -
- * @globalvars none
- * @exception none
- * @pre none
- * @post none
- */
- CProgram();
-
- /**
- * @method ~CProgram
- * @brief Default dtor
- * @param -
- * @return -
- * @globalvars none
- * @exception none
- * @pre none
- * @post none
- */
- ~CProgram();
-
- /**
- * @method getLabels
- * @brief get reference to labels map
- * @param -
- * @return reference to labels map
- * @globalvars none
- * @exception none
- * @pre none
- * @post none
- */
- const std::map<std::string, unsigned>& getLabels() const
- {
- return m_labels;
- }
-
- /**
- * @method findLabel
- * @brief search for label
- * @param label name of label to search for
- * @return index of found label in program
- * @globalvars none
- * @exception CProgramError
- * @pre none
- * @post none
- */
- unsigned findLabel(const std::string& label) const;
-
- /**
- * @method compile
- * @brief create instructions from parsing stream
- * @param in inputstream to read from
- * @return void
- * @globalvars none
- * @exception CProgramError
- * @pre none
- * @post none
- */
- void compile(std::istream& in);
-
- #if DEBUG
- /**
- * @method dump
- * @brief dumps contents to outputstream
- * @param out outputstream to write to
- * @return void
- * @globalvars none
- * @exception none
- * @pre none
- * @post none
- */
- void dump(std::ostream& out);
- #endif
-
- private:
- /* members */
- /** set of known instructions */
- std::set<CInstruction<T> *> m_instrset;
- std::map<std::string, unsigned> m_labels;
- };
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- CProgram<T>::CProgram()
- {
- m_instrset.insert(new CInstructionInc<T>);
- m_instrset.insert(new CInstructionDec<T>);
- m_instrset.insert(new CInstructionAdd<T>);
- m_instrset.insert(new CInstructionSub<T>);
- m_instrset.insert(new CInstructionMul<T>);
- m_instrset.insert(new CInstructionDiv<T>);
- m_instrset.insert(new CInstructionLoad<T>);
- m_instrset.insert(new CInstructionStore<T>);
- m_instrset.insert(new CInstructionTest<T>);
- m_instrset.insert(new CInstructionLabel<T>);
- m_instrset.insert(new CInstructionJumpA<T>);
- m_instrset.insert(new CInstructionJumpZ<T>);
- m_instrset.insert(new CInstructionJumpS<T>);
- m_instrset.insert(new CInstructionWrite<T>);
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- CProgram<T>::~CProgram()
- {
- /* free instruction set */
- for (setiterator it = m_instrset.begin(); it != m_instrset.end(); ++it)
- delete *it;
-
- /* free instruction */
- for (iterator it2 = begin(); it2 != end(); ++it2)
- delete *it2;
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- void CProgram<T>::compile(std::istream& in)
- {
- if (!in.good())
- return;
-
- std::string line;
- unsigned i = 0;
- while (!in.eof() && in.good())
- {
- ++i;
-
- /* read stream per line */
- std::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(' ');
- std::string instrname(line.substr(0, pos));
-
- /* search and create instruction */
- CInstruction<T> *instrptr = NULL;
- setiterator it;
- for (it = m_instrset.begin(); it != m_instrset.end(); ++it)
- {
- if (*(*it) == instrname)
- {
- instrptr = *it;
- break;
- }
- }
- if (instrptr == NULL)
- {
- std::stringstream sstr;
- sstr << "Unknown instruction '" << instrname << "' on line " << i << ".";
- throw CProgramError(sstr.str());
- }
-
- /* create instruction */
- CInstruction<T> *instr = instrptr->factory();
-
- /* parse instruction parameters */
- std::string params = (pos == std::string::npos) ? "" : line.substr(pos + 1);
- boost::trim(params);
- std::list<std::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 CInstructionError("Invalid paramater count - must be 1");
- std::string label(instrparams.front());
- if (label.length() < 2 || label[ label.length() - 1] != ':')
- throw CInstructionError("Label has invalid syntax");
- m_labels[ label.substr(0, label.length() - 1) ] = size();
- }
- instr->compile(instrparams);
- }
- catch(CInstructionError& ex)
- {
- std::stringstream sstr;
- sstr << "Unable to compile instruction '" << instrname
- << "' (line " << i << "): " << ex.what();
- throw CProgramError(sstr.str());
- }
-
- push_back(instr);
- }
- }
-
- /*----------------------------------------------------------------------------*/
-
- template <class T>
- unsigned CProgram<T>::findLabel(const std::string& label) const
- {
- std::map<std::string, unsigned>::const_iterator it;
- it = m_labels.find(label);
- if (it == m_labels.end())
- throw CProgramError("Unknown label '" + label + "'");
- return it->second;
- }
-
- /*----------------------------------------------------------------------------*/
-
- #if DEBUG
- template <class T>
- void CProgram<T>::dump(std::ostream& out)
- {
- out << "[PROGRAM DUMP]" << std::endl;
- unsigned i = 0;
- for(iterator it = begin(); it != end(); ++it)
- {
- out << "[" << std::setw(4) << std::setfill('0') << i << "] "
- << *(*it) << std::endl;
- ++i;
- }
- }
- #endif
-
- #endif
-
- /* vim: set et sw=2 ts=2: */
-