/main.cpp
C++ | 215 lines | 154 code | 30 blank | 31 comment | 37 complexity | 9762aba8e9493ebe56ac6fcc0d9efdbd MD5 | raw file
Possible License(s): GPL-3.0
- /*
- * PROGRAM:
- * Brainfuck interpreter
- *
- * AUTHOR:
- * Théophile BASTIAN (a.k.a. Tobast)
- *
- * CONTACT & WEBSITE:
- * http://tobast.fr/ (contact feature included)
- * error-report@tobast.fr (error reporting only)
- *
- * SHORT DESCRIPTION:
- * See first license line.
- *
- * LICENSE:
- * This software is (another) classical brainfuck interpreter, with errors handling and support of both stdin and source-file argument.
- * Copyright (C) 2011 Théophile BASTIAN
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see http://www.gnu.org/licenses/gpl.txt.
- */
- #include <iostream>
- #include <vector>
- #include <string>
- #include <stdexcept>
- #include <cstdio>
- #include <fstream>
- #define DEFAULT_MEM_VALUE 0
- using namespace std;
- string inputCode(void)
- {
- std::string outstr;
- cin.seekg(0, ios::end);
- if(!cin.fail()) // buffer not empty
- {
- cin.seekg(0, ios::beg);
- while(!cin.eof())
- outstr+=cin.get();
- cin.clear();
- }
- else
- {
- cin.seekg(0, ios::beg);
- cin.clear();
- while(1)
- {
- std::string tmp;
- std::cin >> tmp;
- outstr+=tmp;
- if(tmp.find(-1) != std::string::npos || tmp.find('\\') != string::npos) // found a ^D or a backslash
- break;
- }
- }
- return outstr;
- }
- int main(int argc, char** argv)
- {
- string code;
- vector<unsigned char> memtab(10000, DEFAULT_MEM_VALUE);
- unsigned ptr=0, i=0;
- bool quiet=true, inputfile=false;
- if(argc>1)
- {
- ifstream file(argv[1]);
- if(file)
- {
- inputfile=true;
- while(!file.eof())
- code+=file.get();
- file.close();
- }
-
- for(int i=1;i<argc;i++)
- {
- if(string(argv[i]) == "-v")
- quiet=false;
- }
- }
-
- if(!inputfile)
- code=inputCode();
- if(!quiet)
- cout << endl << "Executing...";
- cout << endl;
- try {
- for(i=0;i<code.size();i++)
- {
- int matchcount=0, input=0; // useful only for respectively ( [ & ] ) ; ,
- switch(code[i])
- {
- case '>':
- ptr++;
- if(ptr >= memtab.size())
- {
- if(memtab.size() == memtab.max_size())
- throw out_of_range("Maximal memory array index reached.");
- else if(memtab.size()+1000 > memtab.max_size())
- memtab.resize(memtab.max_size(), DEFAULT_MEM_VALUE);
- memtab.resize(memtab.size()+1000, DEFAULT_MEM_VALUE);
- }
- break;
- case '<':
- if(ptr==0) // will go under 0 (unsigned int must be above 0, either as a vector index).
- throw out_of_range("Minimal memory array index reached.");
- ptr--;
- break;
- case '+':
- memtab[ptr]++;
- break;
- case '-':
- memtab[ptr]--;
- break;
- case '.':
- cout << memtab[ptr];
- break;
- case ',':
- input=getchar();
- if(input < 0 || input > 128)
- throw range_error("Input out of byte range.");
- memtab[ptr]=(unsigned char) input;
- break;
- case '[':
- if(!memtab[ptr]) // jump to next ]
- {
- i++;
- for(;i<code.size();i++)
- {
- if(code[i]=='[')
- matchcount++;
- else if(code[i]==']')
- matchcount--;
- if(matchcount < 0)
- break;
- }
- if(matchcount>=0)
- throw runtime_error("No matching ']' found after '[' token.");
- }
- break;
- case ']':
- if(memtab[ptr]) // jump to previous [
- {
- i--;
- for(; i!=0 ; i--)
- {
- if(code[i]=='[')
- matchcount--;
- else if(code[i]==']')
- matchcount++;
- if(matchcount < 0)
- break;
- }
- if(code[i]=='[')
- matchcount--;
- if(matchcount>=0)
- throw runtime_error("No matching '[' found before ']' token.");
- }
- break;
- default:
- break;
- }
- }
- cout << endl;
- if(!quiet)
- cout << "Done." << endl;
- return 0;
- }
- catch(const range_error &e) {
- cerr << "FATAL: " << e.what() << endl;
- }
- catch(const out_of_range &e) {
- cerr << i+1 << " = " << code[i] << " : " << e.what() << ". Memory table size: 0 -> " << memtab.max_size() << "." << endl;
- }
- catch(const exception &e) {
- cerr << i+1 << " = " << code[i] << " : " << e.what() << endl;
- }
- return 1;
- }