Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Brainscambler interpreter
- // http://www.esolangs.org/wiki/Brainscrambler
- // Created by nerowolfe <n3rowolfe@gmail.com> on 10-7-2008
- // Licensed as GNU GPL
- // Requires lib boost-program-options
- #include <iostream>
- #include <string>
- #include <vector>
- #include <stack>
- #include <exception>
- #include <stdio.h>
- #include <sys/times.h>
- #include <boost/program_options.hpp>
- using namespace std;
- namespace opt = boost::program_options;
- // Data types
- typedef int tDataCell;
- typedef stack<tDataCell> tData;
- typedef unsigned char tTapeCell;
- typedef vector<tTapeCell> tTape;
- // Interpreter options
- struct tParameters {
- unsigned long stacks;
- vector<string> files;
- bool debug;
- };
- // Exception class
- class bsException : public exception
- {
- public:
- inline bsException(const string &reason) : m_reason(reason) {}
- inline ~bsException() throw() {}
- inline const char* what() const throw() { return m_reason.c_str(); }
- protected:
- string m_reason;
- };
- // Procedures
- void parseOptions(const int argc, char *argv[], tParameters ¶ms);
- void loadFile(FILE* fp, tTape &tape);
- void interprete(tTape &tape, tParameters ¶ms);
- int wrap(const int value, const int max, const int min = 0);
- unsigned long findNextBracket(const tTape &tape, const unsigned long &pos);
- unsigned long findPrevBracket(const tTape &tape, const unsigned long &pos);
- //
- int main(int argc, char *argv[])
- {
- try {
- // Get options from command line
- tParameters params;
- parseOptions(argc, argv, params);
- // For each given file...
- for (int c = 0; c < params.files.size(); c++) {
- // Open it
- FILE* fp = fopen(params.files[c].c_str(), "r");
- if (!fp) throw bsException("could not open file " + params.files[c]);
- // Create the tape and load the source into it
- tTape tape;
- loadFile(fp, tape);
- // Interprete the tape
- interprete(tape, params);
- // Close the file
- fclose(fp);
- cout << endl;
- }
- }
- catch (exception &e) {
- cout << "Error: " << e.what() << endl;
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
- }
- void parseOptions(const int argc, char *argv[], tParameters ¶ms)
- {
- opt::variables_map varmap;
- opt::options_description optGeneral("General options");
- optGeneral.add_options()
- ("help,h", "Shows this help message");
- opt::options_description optInterpreter("Interpreter options");
- optInterpreter.add_options()
- ("stacks,s", opt::value<unsigned long>()->default_value(3), "Number of available stacks")
- ("debug,d", "Print some debug info");
- opt::options_description optHidden("Hidden options");
- optHidden.add_options()
- ("file,f", opt::value<vector<string> >(), "Brainscrambler source file to interprete");
- opt::options_description options("Options");
- options.add(optGeneral).add(optInterpreter).add(optHidden);
- opt::positional_options_description optPositional;
- optPositional.add("file", -1);
- opt::store(
- opt::command_line_parser(argc, argv).
- options(options).
- positional(optPositional).
- run(), varmap
- );
- opt::notify(varmap);
- // Processing parameters
- if (varmap.count("help")) {
- cout << "Usage:" << endl;
- cout << " " << argv[0] << " [options] file1.bs file2.bs ..." << endl << endl;
- cout << optGeneral << endl;
- cout << optInterpreter << endl;
- exit(EXIT_SUCCESS);
- }
- if (!varmap.count("file")) throw bsException("no input files have been specified");
- params.files = varmap["file"].as<vector<string> >();
- params.stacks = varmap["stacks"].as<unsigned long>();
- if (params.stacks == 0) throw bsException("at least 1 stack must be available");
- params.debug = varmap.count("debug");
- }
- void loadFile(FILE* fp, tTape &tape)
- {
- tTapeCell c;
- while (fread(&c, sizeof(tTapeCell), 1, fp))
- tape.push_back(c);
- }
- void interprete(tTape &tape, tParameters ¶ms)
- {
- // Stacks
- tData stacks[params.stacks];
- unsigned long current = 0;
- tDataCell tmp;
- // Debug info
- double ticksPerSecond = (double)sysconf(_SC_CLK_TCK);
- double execTime;
- tms startTime, endTime;
- if (params.debug) times(&startTime);
- // Starting interpretation
- for (int c = 0; c < tape.size(); c++) {
- // If the current stack is empty, push a zero in it
- if (stacks[current].empty())
- stacks[current].push(0);
- switch (tape[c]) {
- case '+': // Increment current number
- stacks[current].top()++;
- break;
- case '-': // Decrement current number
- stacks[current].top()--;
- break;
- case '>': // Copy current number to the next stack (wraps around)
- tmp = stacks[current].top();
- stacks[wrap(current + 1, params.stacks - 1)].push(tmp);
- break;
- case '<': // Copy current number to the previous stack (wraps around)
- tmp = stacks[current].top();
- stacks[wrap(current - 1, params.stacks - 1)].push(tmp);
- break;
- case '.': // Prints current number
- printf("%d ", stacks[current].top());
- break;
- case ':': // Prints current number as ascii char (wrapped)
- printf("%c", wrap(stacks[current].top(), 255));
- break;
- case ',': // Inputs a number and pushes it on the current stack
- scanf("%d", &tmp); stacks[current].push(tmp);
- break;
- case '*': // Pushes a 0 on the current stack
- stacks[current].push(0);
- break;
- case '^': // Pops a number from the current stack and discards it
- stacks[current].pop();
- break;
- case '#': // Rotates stacks (wraps around)
- current = wrap(current + 1, params.stacks - 1);
- break;
- case '[': // While (*ptr) { ...
- if (stacks[current].top() == 0)
- c = findNextBracket(tape, c);
- break;
- case ']': // }
- if (stacks[current].top() != 0)
- c = findPrevBracket(tape, c);
- break;
- }
- }
- // Debug info
- if (params.debug) {
- times(&endTime);
- execTime = (endTime.tms_utime / ticksPerSecond) - (startTime.tms_utime / ticksPerSecond);
- }
- if (params.debug) {
- cout << endl << endl;
- cout << "Debug info:" << endl;
- cout << " execution time: " << execTime << " s" << endl;
- }
- }
- int wrap(const int value, const int max, const int min)
- {
- int r;
- if (value > max)
- r = min + value - max - 1;
- else if (value < min)
- r = max + value - min + 1;
- else
- return value;
- return wrap(r, max, min);
- }
- unsigned long findNextBracket(const tTape &tape, const unsigned long &pos)
- {
- int open = 0;
- for (int c = pos; c < tape.size(); c++) {
- if (tape[c] == '[')
- open++;
- else if (tape[c] == ']' and --open == 0)
- return c;
- }
- throw bsException("unmatched [");
- }
- unsigned long findPrevBracket(const tTape &tape, const unsigned long &pos)
- {
- int open = 0;
- for (int c = pos; c > 0; c--) {
- if (tape[c] == ']')
- open++;
- else if (tape[c] == '[' and --open == 0)
- return c;
- }
- throw bsException("unmatched ]");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement