fork download
  1. #include <cassert>
  2. #include <iostream>
  3. #include <stack>
  4. #include <sstream>
  5. #include <string>
  6. #include <vector>
  7.  
  8. using namespace std;
  9.  
  10. // super class of all operations
  11. class Op {
  12. protected:
  13. Op() = default;
  14. public:
  15. virtual ~Op() = default;
  16. virtual void exec() const = 0;
  17. // disabled: (to prevent accidental usage)
  18. Op(const Op&) = delete;
  19. Op& operator=(const Op&) = delete;
  20. };
  21.  
  22. // super class of grouping operations
  23. class Grp: public Op {
  24. protected:
  25. vector<Op*> _pOps; // nested operations
  26.  
  27. protected:
  28. Grp() = default;
  29. virtual ~Grp()
  30. {
  31. for (Op *pOp : _pOps) delete pOp;
  32. }
  33. public:
  34. void add(Op *pOp) { _pOps.push_back(pOp); }
  35. // disabled: (to prevent accidental usage)
  36. Grp(const Grp&) = delete;
  37. Grp& operator=(const Grp&) = delete;
  38. };
  39.  
  40. // class for repeat op.
  41. class RP: public Grp {
  42. private:
  43. unsigned _n; // repeat count
  44. public:
  45. RP(unsigned n): Grp(), _n(n) { }
  46. virtual ~RP() = default;
  47. virtual void exec() const
  48. {
  49. cout << "Exec. RP" << _n << endl;
  50. for (unsigned i = 0; i < _n; ++i) {
  51. for (const Op *pOp : _pOps) pOp->exec();
  52. }
  53. }
  54. // disabled: (to prevent accidental usage)
  55. RP(const RP&) = delete;
  56. RP& operator=(const RP&) = delete;
  57. };
  58.  
  59. // class for TP op.
  60. class TP: public Op {
  61. public:
  62. TP() = default;
  63. virtual ~TP() = default;
  64. virtual void exec() const
  65. {
  66. cout << "Exec. TP" << endl;
  67. }
  68. };
  69.  
  70. // class for TT op.
  71. class TT: public Op {
  72. public:
  73. TT() = default;
  74. virtual ~TT() = default;
  75. virtual void exec() const
  76. {
  77. cout << "Exec. TT" << endl;
  78. }
  79. };
  80.  
  81. // class for MD sequence
  82. class MD: public Grp {
  83. private:
  84. unsigned _axis;
  85. public:
  86. MD(unsigned axis): Grp(), _axis(axis) { }
  87. virtual ~MD() = default;
  88. virtual void exec() const
  89. {
  90. cout << "Exec. MD" << _axis << endl;
  91. for (const Op *pOp : _pOps) pOp->exec();
  92. }
  93. };
  94.  
  95. typedef unsigned char uchar;
  96.  
  97. enum Token {
  98. TkMD = 'M' | 'D' << 8,
  99. TkRP = 'R' | 'P' << 8,
  100. TkTP = 'T' | 'P' << 8,
  101. TkTT = 'T' | 'T' << 8
  102. };
  103.  
  104. inline Token tokenize(uchar c0, uchar c1) { return (Token)(c0 | c1 << 8); }
  105.  
  106. MD* compile(istream &in)
  107. {
  108. MD *pMD = nullptr;
  109. stack<Op*> pOpsNested;
  110. #define ERROR \
  111.   delete pMD; \
  112.   while (pOpsNested.size()) { delete pOpsNested.top(); pOpsNested.pop(); } \
  113.   return nullptr
  114. for (;;) {
  115. // read command (2 chars)
  116. char cmd[2];
  117. if (in >> cmd[0] >> cmd[1]) {
  118. //cout << "DEBUG: token: " << hex << tokenize(cmd[0], cmd[1]) << dec << endl;
  119. switch (tokenize(cmd[0], cmd[1])) {
  120. case TkMD: { // MD<num>
  121. int num;
  122. if (in >> num) {
  123. if (pMD) {
  124. cerr << "ERROR: Unexpected command 'MD" << num << "'!" << endl;
  125. ERROR;
  126. }
  127. pMD = new MD(num);
  128. } else {
  129. cerr << "ERROR: Number expected after 'MD'!" << endl;
  130. ERROR;
  131. }
  132. } break;
  133. case TkRP: { // RP<num>
  134. int num;
  135. if (in >> num) {
  136. if (!pMD) {
  137. cerr << "ERROR: Unexpected command 'RP" << num << "'!" << endl;
  138. ERROR;
  139. }
  140. RP *pRP = new RP(num);
  141. while (pOpsNested.size()) {
  142. pRP->add(pOpsNested.top());
  143. pOpsNested.pop();
  144. }
  145. pOpsNested.push(pRP);
  146. } else {
  147. cerr << "ERROR: Number expected after 'MD'!" << endl;
  148. ERROR;
  149. }
  150. } break;
  151. case TkTP: { // TP
  152. if (!pMD) {
  153. cerr << "ERROR: Unexpected command 'TP'!" << endl;
  154. ERROR;
  155. }
  156. pOpsNested.push(new TP());
  157. } break;
  158. case TkTT: { // TT
  159. if (pOpsNested.empty()) {
  160. cerr << "ERROR: Unexpected command 'TT'!" << endl;
  161. ERROR;
  162. }
  163. pOpsNested.push(new TT());
  164. } break;
  165. default:
  166. cerr << "ERROR: Wrong command '" << cmd[0] << cmd[1] << "'!" << endl;
  167. ERROR;
  168. }
  169. } else {
  170. cerr << "ERROR: Command expected!" << endl;
  171. ERROR;
  172. }
  173. // try to read separator
  174. char sep;
  175. if (!(in >> sep)) break; // probably EOF (further checks possible)
  176. if (sep != ',') {
  177. cerr << "ERROR: ',' expected!" << endl;
  178. ERROR;
  179. }
  180. }
  181. #undef ERROR
  182. assert(pMD != nullptr);
  183. while (pOpsNested.size()) {
  184. pMD->add(pOpsNested.top());
  185. pOpsNested.pop();
  186. }
  187. return pMD;
  188. }
  189.  
  190. int main()
  191. {
  192. // test string
  193. string sample("MD1,TP,RP3,TT,RP2");
  194. // read test string
  195. istringstream in(sample);
  196. MD *pMD = compile(in);
  197. if (!pMD) {
  198. cerr << "Interpreting aborted!" << endl;
  199. return 1;
  200. }
  201. // execute sequence
  202. pMD->exec();
  203. delete pMD;
  204. // done
  205. return 0;
  206. }
Success #stdin #stdout 0s 4396KB
stdin
Standard input is empty
stdout
Exec. MD1
Exec. RP2
Exec. TT
Exec. RP3
Exec. TP
Exec. TP
Exec. TP
Exec. TT
Exec. RP3
Exec. TP
Exec. TP
Exec. TP