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 12.05.2009
  6.  */
  7.  
  8. #include <boost/algorithm/string.hpp>
  9. #include <boost/algorithm/string/split.hpp>
  10. #ifdef DEBUG
  11. # include <iostream>
  12. # include <iomanip>
  13. #endif
  14. #include "cprogram.h"
  15. #include "instructions.h"
  16.  
  17. using namespace std;
  18.  
  19. CProgram::CProgram()
  20. {
  21. m_instrset.insert(new CInstructionInc);
  22. m_instrset.insert(new CInstructionDec);
  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);
  35. }
  36.  
  37. /*----------------------------------------------------------------------------*/
  38.  
  39. CProgram::~CProgram()
  40. {
  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;
  49. }
  50.  
  51. /*----------------------------------------------------------------------------*/
  52.  
  53. void CProgram::compile(std::istream& in)
  54. {
  55. if (!in.good())
  56. return;
  57.  
  58. string line;
  59. unsigned i = 0;
  60. while (!in.eof() && in.good())
  61. {
  62. ++i;
  63.  
  64. /* read stream per line */
  65. getline(in, line);
  66. if (line.empty())
  67. continue;
  68.  
  69. boost::trim(line);
  70. boost::to_lower(line);
  71.  
  72. /* ignore comments */
  73. if (line.find_first_of('#') == 0)
  74. continue;
  75.  
  76. /* get instruction name */
  77. size_t pos = line.find_first_of(' ');
  78. string instrname(line.substr(0, pos));
  79.  
  80. /* search and create instruction */
  81. CInstruction *instrptr = NULL;
  82. set<CInstruction *>::iterator it;
  83. for (it = m_instrset.begin(); it != m_instrset.end(); ++it)
  84. {
  85. if (*(*it) == instrname)
  86. {
  87. instrptr = *it;
  88. break;
  89. }
  90. }
  91. if (instrptr == NULL)
  92. {
  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);
  131. }
  132. }
  133.  
  134. /*----------------------------------------------------------------------------*/
  135.  
  136. unsigned 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;
  143. }
  144.  
  145. /*----------------------------------------------------------------------------*/
  146.  
  147. #if DEBUG
  148. void CProgram::dump(std::ostream& out)
  149. {
  150. out << "[PROGRAM DUMP]" << endl;
  151. unsigned i = 0;
  152. for(iterator it = begin(); it < end(); ++it)
  153. {
  154. out << "[" << std::setw(4) << std::setfill('0') << i << "] "
  155. << *(*it) << endl;
  156. ++i;
  157. }
  158. }
  159. #endif
  160.  
  161. /* vim: set et sw=2 ts=2: */
  162.