Advertisement
Guest User

nerowolfe

a guest
Jul 10th, 2008
206
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.90 KB | None | 0 0
  1. // Brainscambler interpreter
  2. // http://www.esolangs.org/wiki/Brainscrambler
  3. // Created by nerowolfe <n3rowolfe@gmail.com> on 10-7-2008
  4. // Licensed as GNU GPL
  5. // Requires lib boost-program-options
  6.  
  7. #include <iostream>
  8. #include <string>
  9. #include <vector>
  10. #include <stack>
  11. #include <exception>
  12.  
  13. #include <stdio.h>
  14. #include <sys/times.h>
  15.  
  16. #include <boost/program_options.hpp>
  17.  
  18. using namespace std;
  19. namespace opt = boost::program_options;
  20.  
  21. // Data types
  22.  
  23. typedef int tDataCell;
  24. typedef stack<tDataCell> tData;
  25.  
  26. typedef unsigned char tTapeCell;
  27. typedef vector<tTapeCell> tTape;
  28.  
  29. // Interpreter options
  30.  
  31. struct tParameters {
  32.     unsigned long stacks;
  33.     vector<string> files;
  34.     bool debug;
  35. };
  36.  
  37. // Exception class
  38.  
  39. class bsException : public exception
  40. {
  41.  
  42.     public:
  43.  
  44.         inline bsException(const string &reason) : m_reason(reason) {}
  45.         inline ~bsException() throw() {}
  46.  
  47.         inline const char* what() const throw() { return m_reason.c_str(); }
  48.  
  49.     protected:
  50.  
  51.         string m_reason;
  52. };
  53.  
  54. // Procedures
  55.  
  56. void parseOptions(const int argc, char *argv[], tParameters &params);
  57. void loadFile(FILE* fp, tTape &tape);
  58. void interprete(tTape &tape, tParameters &params);
  59. int wrap(const int value, const int max, const int min = 0);
  60. unsigned long findNextBracket(const tTape &tape, const unsigned long &pos);
  61. unsigned long findPrevBracket(const tTape &tape, const unsigned long &pos);
  62.  
  63.  
  64. //
  65.  
  66. int main(int argc, char *argv[])
  67. {
  68.  
  69.     try {
  70.  
  71.         // Get options from command line
  72.  
  73.         tParameters params;
  74.  
  75.         parseOptions(argc, argv, params);
  76.  
  77.         // For each given file...
  78.  
  79.         for (int c = 0; c < params.files.size(); c++) {
  80.  
  81.             // Open it
  82.  
  83.             FILE* fp = fopen(params.files[c].c_str(), "r");
  84.             if (!fp) throw bsException("could not open file " + params.files[c]);
  85.  
  86.             // Create the tape and load the source into it
  87.  
  88.             tTape tape;
  89.             loadFile(fp, tape);
  90.  
  91.             // Interprete the tape
  92.  
  93.             interprete(tape, params);
  94.  
  95.             // Close the file
  96.  
  97.             fclose(fp);
  98.  
  99.             cout << endl;
  100.  
  101.         }
  102.  
  103.     }
  104.  
  105.     catch (exception &e) {
  106.  
  107.         cout << "Error: " << e.what() << endl;
  108.         return EXIT_FAILURE;
  109.  
  110.     }
  111.  
  112.   return EXIT_SUCCESS;
  113. }
  114.  
  115. void parseOptions(const int argc, char *argv[], tParameters &params)
  116. {
  117.     opt::variables_map varmap;
  118.  
  119.     opt::options_description optGeneral("General options");
  120.     optGeneral.add_options()
  121.         ("help,h", "Shows this help message");
  122.  
  123.     opt::options_description optInterpreter("Interpreter options");
  124.     optInterpreter.add_options()
  125.         ("stacks,s", opt::value<unsigned long>()->default_value(3), "Number of available stacks")
  126.         ("debug,d", "Print some debug info");
  127.  
  128.     opt::options_description optHidden("Hidden options");
  129.     optHidden.add_options()
  130.         ("file,f", opt::value<vector<string> >(), "Brainscrambler source file to interprete");
  131.  
  132.     opt::options_description options("Options");
  133.     options.add(optGeneral).add(optInterpreter).add(optHidden);
  134.  
  135.     opt::positional_options_description optPositional;
  136.     optPositional.add("file", -1);
  137.  
  138.     opt::store(
  139.         opt::command_line_parser(argc, argv).
  140.         options(options).
  141.         positional(optPositional).
  142.         run(), varmap
  143.     );
  144.  
  145.     opt::notify(varmap);
  146.  
  147.     // Processing parameters
  148.  
  149.     if (varmap.count("help")) {
  150.         cout << "Usage:" << endl;
  151.         cout << "  " << argv[0] << " [options] file1.bs file2.bs ..." << endl << endl;
  152.         cout << optGeneral << endl;
  153.         cout << optInterpreter << endl;
  154.         exit(EXIT_SUCCESS);
  155.     }
  156.  
  157.     if (!varmap.count("file")) throw bsException("no input files have been specified");
  158.     params.files = varmap["file"].as<vector<string> >();
  159.  
  160.     params.stacks = varmap["stacks"].as<unsigned long>();
  161.     if (params.stacks == 0) throw bsException("at least 1 stack must be available");
  162.  
  163.     params.debug = varmap.count("debug");
  164.  
  165. }
  166.  
  167. void loadFile(FILE* fp, tTape &tape)
  168. {
  169.     tTapeCell c;
  170.  
  171.     while (fread(&c, sizeof(tTapeCell), 1, fp))
  172.         tape.push_back(c);
  173. }
  174.  
  175. void interprete(tTape &tape, tParameters &params)
  176. {
  177.  
  178.     // Stacks
  179.  
  180.     tData stacks[params.stacks];
  181.  
  182.     unsigned long current = 0;
  183.     tDataCell tmp;
  184.  
  185.     // Debug info
  186.  
  187.     double ticksPerSecond = (double)sysconf(_SC_CLK_TCK);
  188.     double execTime;
  189.     tms startTime, endTime;
  190.  
  191.     if (params.debug) times(&startTime);
  192.  
  193.     // Starting interpretation
  194.  
  195.     for (int c = 0; c < tape.size(); c++) {
  196.  
  197.         // If the current stack is empty, push a zero in it
  198.         if (stacks[current].empty())
  199.             stacks[current].push(0);
  200.  
  201.     switch (tape[c]) {
  202.  
  203.       case '+': // Increment current number
  204.         stacks[current].top()++;
  205.       break;
  206.  
  207.       case '-': // Decrement current number
  208.         stacks[current].top()--;
  209.       break;
  210.  
  211.       case '>': // Copy current number to the next stack (wraps around)
  212.         tmp = stacks[current].top();
  213.         stacks[wrap(current + 1, params.stacks - 1)].push(tmp);
  214.       break;
  215.  
  216.       case '<': // Copy current number to the previous stack (wraps around)
  217.         tmp = stacks[current].top();
  218.         stacks[wrap(current - 1, params.stacks - 1)].push(tmp);
  219.       break;
  220.  
  221.       case '.': // Prints current number
  222.         printf("%d ", stacks[current].top());
  223.       break;
  224.  
  225.       case ':': // Prints current number as ascii char (wrapped)
  226.         printf("%c", wrap(stacks[current].top(), 255));
  227.       break;
  228.  
  229.       case ',': // Inputs a number and pushes it on the current stack
  230.         scanf("%d", &tmp); stacks[current].push(tmp);
  231.       break;
  232.  
  233.       case '*': // Pushes a 0 on the current stack
  234.         stacks[current].push(0);
  235.             break;
  236.  
  237.             case '^': // Pops a number from the current stack and discards it
  238.                 stacks[current].pop();
  239.             break;
  240.  
  241.             case '#': // Rotates stacks (wraps around)
  242.         current = wrap(current + 1, params.stacks - 1);
  243.             break;
  244.  
  245.       case '[': // While (*ptr) { ...
  246.         if (stacks[current].top() == 0)
  247.           c = findNextBracket(tape, c);
  248.       break;
  249.  
  250.       case ']': // }
  251.         if (stacks[current].top() != 0)
  252.           c = findPrevBracket(tape, c);
  253.       break;
  254.  
  255.     }
  256.  
  257.     }
  258.  
  259.     // Debug info
  260.  
  261.     if (params.debug) {
  262.         times(&endTime);
  263.         execTime = (endTime.tms_utime / ticksPerSecond) - (startTime.tms_utime / ticksPerSecond);
  264.     }
  265.  
  266.     if (params.debug) {
  267.         cout << endl << endl;
  268.         cout << "Debug info:" << endl;
  269.         cout << "  execution time: " << execTime << " s" << endl;
  270.     }
  271.  
  272. }
  273.  
  274. int wrap(const int value, const int max, const int min)
  275. {
  276.     int r;
  277.  
  278.     if (value > max)
  279.         r = min + value - max - 1;
  280.     else if (value < min)
  281.         r = max + value - min + 1;
  282.     else
  283.         return value;
  284.  
  285.     return wrap(r, max, min);
  286. }
  287.  
  288. unsigned long findNextBracket(const tTape &tape, const unsigned long &pos)
  289. {
  290.     int open = 0;
  291.  
  292.     for (int c = pos; c < tape.size(); c++) {
  293.         if (tape[c] == '[')
  294.             open++;
  295.         else if (tape[c] == ']' and --open == 0)
  296.             return c;
  297.     }
  298.  
  299.     throw bsException("unmatched [");
  300. }
  301.  
  302. unsigned long findPrevBracket(const tTape &tape, const unsigned long &pos)
  303. {
  304.     int open = 0;
  305.  
  306.     for (int c = pos; c > 0; c--) {
  307.         if (tape[c] == ']')
  308.             open++;
  309.         else if (tape[c] == '[' and --open == 0)
  310.             return c;
  311.     }
  312.  
  313.     throw bsException("unmatched ]");
  314. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement