#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
#define foreach BOOST_FOREACH


namespace Doubleplusungood {
#define DOUBLEPLUSUNGOOD_DEBUG  false
#define DOUBLEPLUSUNGOOD_DBGPRINT(cont) if(DOUBLEPLUSUNGOOD_DEBUG){std::cout << cont << std::endl;}

    template<typename T> void dieWithError(T const cont, int const wordNum) {
		std::cout << "Error: " << cont << " at "<<  wordNum + 1 << std::endl;
		exit(1);
	}
namespace Engine {
	namespace Opera {
		enum Type {
			pop,
			dup,
			swap,
			lrot,
			rrot,
			beg,
			end,
			call,
			if_else,
			add,
			neg,
			less_than,
			print,
			input
		};
		struct stringize : std::string {
			stringize(Type e) {
				switch(e) {
#define ENUM_STRINGIZE(elem) break;case elem:assign(#elem)
					ENUM_STRINGIZE(Opera::pop);
					ENUM_STRINGIZE(Opera::dup);
					ENUM_STRINGIZE(Opera::swap);
					ENUM_STRINGIZE(Opera::lrot);
					ENUM_STRINGIZE(Opera::rrot);
					ENUM_STRINGIZE(Opera::beg);
					ENUM_STRINGIZE(Opera::end);
					ENUM_STRINGIZE(Opera::call);
					ENUM_STRINGIZE(Opera::if_else);
					ENUM_STRINGIZE(Opera::add);
					ENUM_STRINGIZE(Opera::neg);
					ENUM_STRINGIZE(Opera::less_than);
					ENUM_STRINGIZE(Opera::print);
					ENUM_STRINGIZE(Opera::input);
#undef ENUM_STRINGIZE
					break;default:assign("Undef");
				} // switch(e)
			} // ctor stringize
		}; // struct stringize
	} // namespace Oper
	namespace ErrCode {
		enum Type {
			normalExit,
			stackShortage,
			expectedInt,
			expectedBlock,
			unclosedBlock,
			outOfRange,
			unknownCommand
		};
		struct stringize : std::string {
			stringize(Type e) {
				switch(e) {
#define ENUM_STRINGIZE(elem) break;case elem:assign(#elem)
					ENUM_STRINGIZE(ErrCode::normalExit);
					ENUM_STRINGIZE(ErrCode::stackShortage);
					ENUM_STRINGIZE(ErrCode::expectedInt);
					ENUM_STRINGIZE(ErrCode::expectedBlock);
					ENUM_STRINGIZE(ErrCode::unclosedBlock);
					ENUM_STRINGIZE(ErrCode::outOfRange);
					ENUM_STRINGIZE(ErrCode::unknownCommand);
#undef ENUM_STRINGIZE
					break;default:assign("Undef");
				} // switch(e)
			} // ctor stringize
		}; // struct stringize
	} // namespace ErrCode


	struct Address{
		int datum;
		Address& operator=(int const i){datum = i;return *this;}
	};

	typedef boost::variant<int, Opera::Type> CodeWord;
	typedef std::vector<CodeWord> Source;
	typedef boost::variant<int, Address> MemDatum;

	class Interpreter {
	private:
		std::deque<Address> callStack;
		public: std::deque<MemDatum> memStack; private:
		Address crntAddress;

		ErrCode::Type applyOpera(Opera::Type op) {
			switch(op) {
			case Opera::pop: {
				if(memStack.empty()){return ErrCode::stackShortage;}
				memStack.pop_back();
				break;
			}

			case Opera::dup: {
				if(memStack.empty()){return ErrCode::stackShortage;}
				memStack.push_back(memStack.back());
				break;
			}

			case Opera::swap: {
				if(memStack.size() < 2){return ErrCode::stackShortage;}
				MemDatum const t1 = memStack.back();
				memStack.pop_back();
				MemDatum const t2 = memStack.back();
				memStack.pop_back();
				memStack.push_back(t1);
				memStack.push_back(t2);
				break;
			}

			case Opera::lrot: {
				memStack.push_back(memStack.front());
				memStack.pop_front();
				break;
			}

			case Opera::rrot: {
				memStack.push_front(memStack.back());
				memStack.pop_back();
				break;
			}

			case Opera::add: {
				if(memStack.size() < 2){return ErrCode::stackShortage;}
				if(memStack.back().which() != 0) {return ErrCode::expectedInt;}
				int const i = boost::get<int>(memStack.back());
				memStack.pop_back();

				if(memStack.back().which() != 0) {return ErrCode::expectedInt;}
				int const j = boost::get<int>(memStack.back());
				memStack.pop_back();
				DOUBLEPLUSUNGOOD_DBGPRINT(i + j);
				memStack.push_back(i + j);
				break;
			}

			case Opera::neg: {
				if(memStack.empty()){return ErrCode::stackShortage;}
				if(memStack.back().which() != 0){return ErrCode::expectedInt;}
				int const i = boost::get<int>(memStack.back());
				memStack.pop_back();
				memStack.push_back(i * -1);
				break;
			}
			case Opera::less_than: {
				if(memStack.size() < 2){return ErrCode::stackShortage;}
				if(memStack.back().which() != 0) {return ErrCode::expectedInt;}
				int const i = boost::get<int>(memStack.back());
				memStack.pop_back();

				if(memStack.back().which() != 0) {return ErrCode::expectedInt;}
				int const j = boost::get<int>(memStack.back());
				memStack.pop_back();
				memStack.push_back(((j < i)? 1: 0));
				break;
			}
			case Opera::print: {
				if(memStack.empty()){return ErrCode::stackShortage;}
				if(memStack.back().which() != 0) {return ErrCode::expectedInt;}
				int const cont = boost::get<int>(memStack.back());

				if(-128 <= cont && cont <= 127) {
					std::cout << static_cast<char>(cont) << std::flush;
				} else {
					// std::cout << cont << std::flush;
					return(ErrCode::outOfRange); // Err
				}
				memStack.pop_back();
				break;
			}
		case Opera::input: {
			char c;
			std::cin >> c;
			memStack.push_back(static_cast<int>(c));
			break;
		}
			default:
				dieWithError(ErrCode::stringize(ErrCode::unknownCommand), crntAddress.datum);// Err
				break;
			} // switch(op)
			return ErrCode::normalExit;
		} // applyOpera

	public:

		void interpret(Source const& src) {
			DOUBLEPLUSUNGOOD_DBGPRINT("src.size: " << src.size());
			for(crntAddress.datum = 0; src.size() > crntAddress.datum; crntAddress.datum++){
				DOUBLEPLUSUNGOOD_DBGPRINT("----------");
				if(DOUBLEPLUSUNGOOD_DEBUG) {
					std::cout << "[ ";
					foreach(MemDatum const& e, memStack) {
						if(e.which() == 0){
							std::cout << boost::get<int>(e) << ' ';
						} else {
							std::cout << "<Addr> ";
						}
					}
					std::cout << "]" << std::endl;
				}

				CodeWord const& word = src.at(crntAddress.datum);
				switch(word.which()) {
				case 0: {
					DOUBLEPLUSUNGOOD_DBGPRINT("<=" << boost::get<int>(word));
					memStack.push_back(boost::get<int>(word));
					break;
				}

				case 1: {
					DOUBLEPLUSUNGOOD_DBGPRINT("<=" << Opera::stringize(boost::get<Opera::Type>(word)));
					Opera::Type const opera = boost::get<Opera::Type>(src.at(crntAddress.datum));
					switch(opera) {
					case Opera::end: {
						crntAddress = callStack.back();
						callStack.pop_back();
						break;
					}

					case Opera::call: {
						if(memStack.empty()) {
						   dieWithError(ErrCode::stringize(ErrCode::stackShortage), crntAddress.datum);// Err
						}
						if(memStack.back().which() != 1){
							dieWithError(ErrCode::stringize(ErrCode::expectedBlock), crntAddress.datum);// Err
							return;
						}
						callStack.push_back(crntAddress);
						crntAddress = boost::get<Address>(memStack.back());
						memStack.pop_back();
						break;
					}
					case Opera::if_else: {
						int cond;
						Address t;
						Address f;
						if(memStack.size() < 3) {
							dieWithError(ErrCode::stringize(ErrCode::stackShortage), crntAddress.datum);// Err
							return;
						}
						if(memStack.back().which() != 0){
							dieWithError(ErrCode::stringize(ErrCode::stackShortage), crntAddress.datum);// Err
							return;
						}
						cond = boost::get<int>(memStack.back());
						memStack.pop_back();

						if(memStack.back().which() != 1){
							dieWithError(ErrCode::stringize(ErrCode::expectedBlock), crntAddress.datum); // Err
							return;
						}
						t = boost::get<Address>(memStack.back());
						memStack.pop_back();

						if(memStack.back().which() != 1){
							dieWithError(ErrCode::stringize(ErrCode::expectedBlock), crntAddress.datum); // Err
							return;
						}
						f = boost::get<Address>(memStack.back());
						memStack.pop_back();

						callStack.push_back(crntAddress);
						crntAddress = (cond)? t: f;
						break;
					}

					case Opera::beg: {
						memStack.push_back(crntAddress);

						int counter = 1;
						while(counter != 0) {
							if(crntAddress.datum >= src.size()) {
								dieWithError(ErrCode::stringize(ErrCode::unclosedBlock), crntAddress.datum);
							}
							crntAddress.datum++;
							CodeWord const& word = src.at(crntAddress.datum);
							if(word.which() == 1) {
								if(boost::get<Opera::Type>(word) == Opera::end) {
									counter--;
								}
								if(boost::get<Opera::Type>(word) == Opera::beg) {
									counter++;
								}
							}
						}
						break;
					}
					default: {
						ErrCode::Type const operaRes = applyOpera(opera);
						if(operaRes != ErrCode::normalExit) {
							dieWithError(ErrCode::stringize(operaRes), crntAddress.datum);
						}
						break;
					}
					} // switch(opera)
					break;
				}

				default:
					dieWithError(ErrCode::stringize(ErrCode::unknownCommand), crntAddress.datum); // Err
					break;
				} // switch(word)
			} // for
			std::cout << std::endl;
		} // interpret
	}; // Interpreter

	class Decoder {
	private:
		/*
		  ldp : 後置++
		  fdp : 前置++
		  fsp : 前置1項+
		  lsp : 2項+
		 */
		/* state
		   0 : 初期状態
		   1 : ldp後
		   2 : fdp、fsp後
		   3 : lsp後
		 */
		int state;
		int ldpCounter;
		int lspCounter;
		int fpCounter;
		int fpNum;
		Source & source; 

		void initState() {
			state = 0;
			ldpCounter = 0;
			lspCounter = 0;
			fpCounter = 0;
			fpNum = 0;
		}

		Opera::Type convOpera() const{
			switch(fpCounter) {
			case 0: {
				break;
			}
			case 1: { // +(0) , ++(1)
				switch(fpNum) {
				case 0: {
					return Opera::beg; // +
				}
				case 1: {
					return Opera::end; // ++
				}
				}
				break;
			}
			case 2: { // + +(0) , ++ +(1)  ,+ ++(2) , ++ ++(3)
				switch(fpNum) {
				case 0: {
					return Opera::dup; // + +
				}
				case 1: {
					return Opera::lrot; // ++ +
				}
				case 2: {
					return Opera::rrot; // + ++
				}
				case 3: {
					return Opera::swap; // ++ ++
				}
				}
			}
			case 3: { // +  + +(0) , ++ + +(1) , + ++ + (2) , ++ ++ + (3) , + + ++(4) , ++ + ++(5) , + ++ ++(6) , ++ ++ ++(7)
				switch(fpNum) {
				case 0: {
					return Opera::call; // + + +
				}
				case 1: {
					return Opera::if_else; // ++ + +
				}
				case 2: {
					return Opera::add; // + ++ +
				}
				case 3: {
					return Opera::neg; // ++ ++ +
				}
				case 4: {
					return Opera::print; // + + ++
				}
				case 5: {
					return Opera::input; // ++ + ++
				}
				case 6: {
					return Opera::less_than; // + ++ ++
				}
				case 7: {
					return Opera::pop; // ++ ++ ++
				}
				}
			}
			}
		}
		void convMidCode() {
			DOUBLEPLUSUNGOOD_DBGPRINT("fpNum: " << fpNum << "fpCtr: " << fpCounter << "ldpCtr: " << ldpCounter << "lspCtr: " << lspCounter);
			switch(lspCounter) {
			case 0: {
				source.push_back(convOpera());
				break;
			}
			case 1: {
				source.push_back(fpNum << ((ldpCounter - 1) * 4));
				break;
			}
			default: {
				// Err
				break;
			}
			}
			initState();
		}


	public:
		void putLdp() {
			if(state > 1){convMidCode();}
			ldpCounter++;
			state = 1;
		}
		void putLsp() {
			if(state > 3){convMidCode();}
			lspCounter++;
			state = 3;
		}
		void putFdp() {
			if(state > 2){convMidCode();}
			fpNum <<= 1;
			fpNum += 1;
			fpCounter++;
			state = 2;
		}
		void putFsp() {
			if(state > 2){convMidCode();}
			fpNum <<= 1;
			fpCounter++;
			state = 2;
		}
		void finishDecode(){convMidCode();}
		Decoder(Source& src): source(src){initState();}
	}; // class Decoder

}


class C_ {
private:
	Engine::Decoder decoder;
	Engine::Source source;
public:
	C_& operator++(int) {
		decoder.putLdp();
		return *this;
	}
	C_& operator++() {
		decoder.putFdp();
		return *this;
	}
	C_& operator+(C_&) {
		decoder.putLsp();
		return *this;
	}
	C_& operator+() {
		decoder.putFsp();
		return *this;
	}
	C_(): decoder(source){}
	~C_(){
		decoder.finishDecode();
		Engine::Interpreter interpreter;
		interpreter.interpret(source);
	}
};
#undef DOUBLEPLUSUNGOOD_DEBUG
#undef DOUBLEPLUSUNGOOD_DBGPRINT
}


int main() {
	Doubleplusungood::C_ C;
    
	+C++; + + ++C++++ + C; + ++C++++ + C; + ++ + C++; + ++ + C++; + + ++ C++;
    ++C++; + ++C++; + + + ++ C++ + C; + + ++C++++ + C; + ++ + C++; + + ++ C++;
    ++ + ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; + + ++ ++C++ + C; ++ +C
    ++; + +C++; + ++C++; + + +C++; + + ++ ++C++ + C; ++ +C++; + +C++; + ++C++;
    + + +C++; ++ ++ ++ ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; + + ++ ++
    C++ + C; + ++ C++++ + C; + ++ + C++; + + ++ C++; + ++ C++++ + C; + + ++ C++;
    ++ ++ ++ C++ + C; ++ + ++ C++++ + C; + ++ + C++; + + ++ C++; ++ ++ ++ ++C++
    + C; ++ +C++; + +C++; + ++C++; + + +C++; ++C++++ + C; + ++C++ + C;+ ++ +C++;
    ++ +C++; + +C++; + ++C++; + + +C++; + + ++ ++C++ + C; ++ +C++; + +C++; + ++C
    ++; + + +C++; + + ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; ++ C++ + C;
    + ++ C++++ + C; + ++ + C++; + + ++ C++;

	return 0;
}
