Download | Plain Text | No Line Numbers


  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 26.05.2009
  6.  */
  7.  
  8. #ifndef CPROGRAM_H
  9. #define CPROGRAM_H 1
  10.  
  11. #include <vector>
  12. #include <set>
  13. #include <map>
  14. #include <stdexcept>
  15. #include <boost/algorithm/string.hpp>
  16. #include <boost/algorithm/string/split.hpp>
  17. #ifdef DEBUG
  18. # include <iostream>
  19. # include <iomanip>
  20. #endif
  21.  
  22. /**
  23.  * @class CProgramError
  24.  *
  25.  * Exception thrown by implemententations of CProgram
  26.  */
  27. class CProgramError
  28. : public std::invalid_argument
  29. {
  30. public:
  31. /**
  32.   * @method CProgramError
  33.   * @brief Default exception ctor
  34.   * @param what message to pass along
  35.   * @return -
  36.   * @globalvars none
  37.   * @exception none
  38.   * @pre none
  39.   * @post none
  40.   */
  41. CProgramError(const std::string& what)
  42. : std::invalid_argument(what)
  43. {}
  44. };
  45.  
  46. #include "cinstruction.h"
  47. #include "instructions.h"
  48.  
  49. /* forward declare CInstruction */
  50. template <class T>
  51. class CInstruction;
  52.  
  53. /**
  54.  * @class CProgram
  55.  *
  56.  * CProgram extends std::vector and adds a method for parsing
  57.  * programfile. This adds instances of CInstruction to CProgram itself.
  58.  */
  59. template <class T>
  60. class CProgram
  61. : public std::vector<CInstruction<T> *>
  62. {
  63. typedef typename std::set<CInstruction<T> *>::iterator setiterator;
  64. typedef std::vector<CInstruction<T> *> super;
  65. typedef typename super::iterator iterator;
  66. using super::begin;
  67. using super::end;
  68. using super::size;
  69.  
  70. public:
  71. /**
  72.   * @method CProgram
  73.   * @brief Default ctor
  74.   * @param -
  75.   * @return -
  76.   * @globalvars none
  77.   * @exception none
  78.   * @pre none
  79.   * @post none
  80.   */
  81. CProgram();
  82.  
  83. /**
  84.   * @method ~CProgram
  85.   * @brief Default dtor
  86.   * @param -
  87.   * @return -
  88.   * @globalvars none
  89.   * @exception none
  90.   * @pre none
  91.   * @post none
  92.   */
  93. ~CProgram();
  94.  
  95. /**
  96.   * @method getLabels
  97.   * @brief get reference to labels map
  98.   * @param -
  99.   * @return reference to labels map
  100.   * @globalvars none
  101.   * @exception none
  102.   * @pre none
  103.   * @post none
  104.   */
  105. const std::map<std::string, unsigned>& getLabels() const
  106. {
  107. return m_labels;
  108. }
  109.  
  110. /**
  111.   * @method findLabel
  112.   * @brief search for label
  113.   * @param label name of label to search for
  114.   * @return index of found label in program
  115.   * @globalvars none
  116.   * @exception CProgramError
  117.   * @pre none
  118.   * @post none
  119.   */
  120. unsigned findLabel(const std::string& label) const;
  121.  
  122. /**
  123.   * @method compile
  124.   * @brief create instructions from parsing stream
  125.   * @param in inputstream to read from
  126.   * @return void
  127.   * @globalvars none
  128.   * @exception CProgramError
  129.   * @pre none
  130.   * @post none
  131.   */
  132. void compile(std::istream& in);
  133.  
  134. #if DEBUG
  135. /**
  136.   * @method dump
  137.   * @brief dumps contents to outputstream
  138.   * @param out outputstream to write to
  139.   * @return void
  140.   * @globalvars none
  141.   * @exception none
  142.   * @pre none
  143.   * @post none
  144.   */
  145. void dump(std::ostream& out);
  146. #endif
  147.  
  148. private:
  149. /* members */
  150. /** set of known instructions */
  151. std::set<CInstruction<T> *> m_instrset;
  152. std::map<std::string, unsigned> m_labels;
  153. };
  154.  
  155. /*----------------------------------------------------------------------------*/
  156.  
  157. template <class T>
  158. CProgram<T>::CProgram()
  159. {
  160. m_instrset.insert(new CInstructionInc<T>);
  161. m_instrset.insert(new CInstructionDec<T>);
  162. m_instrset.insert(new CInstructionAdd<T>);
  163. m_instrset.insert(new CInstructionSub<T>);
  164. m_instrset.insert(new CInstructionMul<T>);
  165. m_instrset.insert(new CInstructionDiv<T>);
  166. m_instrset.insert(new CInstructionLoad<T>);
  167. m_instrset.insert(new CInstructionStore<T>);
  168. m_instrset.insert(new CInstructionTest<T>);
  169. m_instrset.insert(new CInstructionLabel<T>);
  170. m_instrset.insert(new CInstructionJumpA<T>);
  171. m_instrset.insert(new CInstructionJumpZ<T>);
  172. m_instrset.insert(new CInstructionJumpS<T>);
  173. m_instrset.insert(new CInstructionWrite<T>);
  174. }
  175.  
  176. /*----------------------------------------------------------------------------*/
  177.  
  178. template <class T>
  179. CProgram<T>::~CProgram()
  180. {
  181. /* free instruction set */
  182. for (setiterator it = m_instrset.begin(); it != m_instrset.end(); ++it)
  183. delete *it;
  184.  
  185. /* free instruction */
  186. for (iterator it2 = begin(); it2 != end(); ++it2)
  187. delete *it2;
  188. }
  189.  
  190. /*----------------------------------------------------------------------------*/
  191.  
  192. template <class T>
  193. void CProgram<T>::compile(std::istream& in)
  194. {
  195. if (!in.good())
  196. return;
  197.  
  198. std::string line;
  199. unsigned i = 0;
  200. while (!in.eof() && in.good())
  201. {
  202. ++i;
  203.  
  204. /* read stream per line */
  205. std::getline(in, line);
  206. if (line.empty())
  207. continue;
  208.  
  209. boost::trim(line);
  210. boost::to_lower(line);
  211.  
  212. /* ignore comments */
  213. if (line.find_first_of('#') == 0)
  214. continue;
  215.  
  216. /* get instruction name */
  217. size_t pos = line.find_first_of(' ');
  218. std::string instrname(line.substr(0, pos));
  219.  
  220. /* search and create instruction */
  221. CInstruction<T> *instrptr = NULL;
  222. setiterator it;
  223. for (it = m_instrset.begin(); it != m_instrset.end(); ++it)
  224. {
  225. if (*(*it) == instrname)
  226. {
  227. instrptr = *it;
  228. break;
  229. }
  230. }
  231. if (instrptr == NULL)
  232. {
  233. std::stringstream sstr;
  234. sstr << "Unknown instruction '" << instrname << "' on line " << i << ".";
  235. throw CProgramError(sstr.str());
  236. }
  237.  
  238. /* create instruction */
  239. CInstruction<T> *instr = instrptr->factory();
  240.  
  241. /* parse instruction parameters */
  242. std::string params = (pos == std::string::npos) ? "" : line.substr(pos + 1);
  243. boost::trim(params);
  244. std::list<std::string> instrparams;
  245. boost::split(instrparams, params, boost::is_any_of(", \t"), boost::token_compress_on);
  246.  
  247. /* let instruction parse the parameters. catch+throw exception */
  248. try
  249. {
  250. /* handle label instruction ourself, but still add a dummy instruction */
  251. if (instrname == "label")
  252. {
  253. if (instrparams.size() != 1)
  254. throw CInstructionError("Invalid paramater count - must be 1");
  255. std::string label(instrparams.front());
  256. if (label.length() < 2 || label[ label.length() - 1] != ':')
  257. throw CInstructionError("Label has invalid syntax");
  258. m_labels[ label.substr(0, label.length() - 1) ] = size();
  259. }
  260. instr->compile(instrparams);
  261. }
  262. catch(CInstructionError& ex)
  263. {
  264. std::stringstream sstr;
  265. sstr << "Unable to compile instruction '" << instrname
  266. << "' (line " << i << "): " << ex.what();
  267. throw CProgramError(sstr.str());
  268. }
  269.  
  270. push_back(instr);
  271. }
  272. }
  273.  
  274. /*----------------------------------------------------------------------------*/
  275.  
  276. template <class T>
  277. unsigned CProgram<T>::findLabel(const std::string& label) const
  278. {
  279. std::map<std::string, unsigned>::const_iterator it;
  280. it = m_labels.find(label);
  281. if (it == m_labels.end())
  282. throw CProgramError("Unknown label '" + label + "'");
  283. return it->second;
  284. }
  285.  
  286. /*----------------------------------------------------------------------------*/
  287.  
  288. #if DEBUG
  289. template <class T>
  290. void CProgram<T>::dump(std::ostream& out)
  291. {
  292. out << "[PROGRAM DUMP]" << std::endl;
  293. unsigned i = 0;
  294. for(iterator it = begin(); it != end(); ++it)
  295. {
  296. out << "[" << std::setw(4) << std::setfill('0') << i << "] "
  297. << *(*it) << std::endl;
  298. ++i;
  299. }
  300. }
  301. #endif
  302.  
  303. #endif
  304.  
  305. /* vim: set et sw=2 ts=2: */
  306.