Jump to content
  • Advertisement
Sign in to follow this  
  • entries
    292
  • comments
    557
  • views
    154547

Another Complete Waste of Time...

Sign in to follow this  
TANSTAAFL

173 views

I did an update to my BFI program. It is not currently uploaded, but I expect it will be before long, once I finish cleaning it up.

What has changed? Well, it's still a Brainf*** Interpreter. No, I didn't add any new tokens to the language in any sort of attempt to "improve it", although if I get a chance one day, I will add an interpreter directive that allows breakpoints(probably '!'), but that's an interpreter command, not a part of the language.

What I *DID* do is strip out the comments, do run-length encoding on the source of the BF program, and store the corresponding other end of the loop for all of the loop locations.

If you'd like to look at the source, here you go:


/*
* BFI.cpp
* An almost total rewrite of BFI.c Copyright (C) 2003 Thomas Cort
* Changes Copyright (C) 2004, 2005 Ernest S. Pazera
*
* This source 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 2 of the License, or
* (at your option) any later version.
*
* This source 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 source; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include
#include
#include
#include
#include
using namespace std;

//data size
const size_t DATA_SIZE=32768;

//shorthand command structure
struct command_t
{
char token;//the token
union
{
size_t count;//repeat count for the token(all but [ and ])
size_t position;//position after opposing token ([ and ] only)
};
size_t byte_position;//byte position within the file
};

//check for a valid source
size_t source_is_valid(const string& source_string)
{
size_t error_position=(size_t)-1;

//keep track of the nested level of [ and ]
size_t nested_level=0;

//loop through the source
for(std::string::const_iterator source_iterator=source_string.begin();source_iterator!=source_string.end();source_iterator++)
{
//look for [ or ]
switch(*source_iterator)
{
case '['://found start of loop
{
//increase nested level
nested_level++;
}break;
case ']'://found end of loop
{
//check for zero nested level
if(nested_level==0)
{
//zero nested level, ERROR!
//source is not valid
error_position=source_iterator-source_string.begin();

return(error_position);
}
else
{
//subtract one from the nested level
nested_level--;
}
}break;
}
}
//return validity
return(error_position);
}

int main(int argument_count, char **argument_list)
{
//don't skip the whitespace
cin.unsetf(ios_base::skipws);

//check argument count
if(argument_count<2)
{
//show syntax
cout<<"Usage:\n\tbfi.exe Source1 [Source2]*\n"< }
else
{
//at least one argument
//loop through arguments
for(int argument=1;argument {
//message that source is loading
cout << "Now loading: \t\n" << argument_list[argument] << "...\n" << endl;

//open the file
fstream input_file(argument_list[argument]);

//read the file into a string
string source=string((istreambuf_iterator<char>(input_file)),(istreambuf_iterator<char>()));

//close the input file
input_file.close();

//validate source
size_t error_position=source_is_valid(source);

//if an error is detected, report it and skip to next file
if(error_position!=((size_t)-1))
{
//source is invalid
cout << "Mismatched ] at byte " << (unsigned int)error_position << "." << endl;
continue;
}

//the program
vector program;

//clear the program
program.clear();

//initialize command
command_t command;
command.token=0;
command.count=0;

//loop through the source
for(string::iterator source_iterator=source.begin();source_iterator!=source.end();source_iterator++)
{
//which token are we on?
switch(*source_iterator)
{
case '['://begin loop
case ']'://end loop
{
//do not run-length encode loops
command.token=(*source_iterator);
command.count=0;
command.byte_position=(size_t)(source_iterator-source.begin());
//add to program
program.push_back(command);
}break;
case '.'://output
case ','://input
case '>'://increment pointer
case '<'://decrement pointer
case '+'://increment byte
case '-'://decrement byte
{
//if the program is not empty and the token is the same as the last token...
if(!program.empty()&&program[program.size()-1].token==(*source_iterator))
{
//add to the count of the token
program[program.size()-1].count++;
}
else
{
//new token
command.token=(*source_iterator);
command.count=1;
command.byte_position=(size_t)(source_iterator-source.begin());
//add to program
program.push_back(command);
}
}break;
}
}

//program iterator
vector::iterator program_iterator;

//loop through program
for(program_iterator=program.begin();program_iterator!=program.end();program_iterator++)
{
//check for a start of loop
if((*program_iterator).token=='[')
{
//make a note of the position
size_t start_position=program_iterator-program.begin();

//start keeping track of the nested level
size_t nested_level=0;

//use a temporary iterator
vector::iterator temp=program_iterator;

//find the end of the loop
do
{
//adjust the nested level
nested_level+=(((*temp).token=='[')-((*temp).token==']'));

//if nested level, move to next token
if(nested_level)
temp++;
}while(nested_level);

//make note of the end position
size_t end_position=temp-program.begin();

//tell start position about the end position
(*program_iterator).position=end_position;

//tell end position about the start position
(*temp).position=start_position;
}

//check for increment or decrement byte
else if((*program_iterator).token=='+' && (*program_iterator).token=='-')
{
//it's a byte, so modulo 256
(*program_iterator).count%=256;
}
}

//go to start of program
program_iterator=program.begin();

//create a string to represent the data
string data(DATA_SIZE,0);

//point to the front of the data
string::iterator data_iterator=data.begin();

//reset error position
error_position=(size_t)(-1);

string error_message="";

//interpret until the source iterator reaches the end or there is an error
while(program_iterator!=program.end() && error_message.empty())
{
//what is the current instruction?
switch((*program_iterator).token)
{
case '+'://increase byte at data pointer
{
(*data_iterator)+=(*program_iterator).count;
}break;
case '-'://decrease byte at data pointer
{
(*data_iterator)-=(*program_iterator).count;
}break;
case '>'://increase data pointer
{
//check for overflow
if((data.end()-data_iterator)>(*program_iterator).count)
{
//no overflow
data_iterator+=(*program_iterator).count;
}
else
{
//overflow
error_message="Data iterator overflow!";
error_position=(*program_iterator).byte_position;
}
}break;
case '<'://decrease data pointer
{
//check for underflow
if((data_iterator-data.begin())>=(*program_iterator).count)
{
//no underflow
data_iterator-=(*program_iterator).count;
}
else
{
//underflow
error_message="Data iterator underflow!";
error_position=(*program_iterator).byte_position;
}
}break;
case ','://read character from console
{
for(size_t i=0;i<(*program_iterator).count;i++)
cin>>(*data_iterator);
}break;
case '.'://write character to console
{
for(size_t i=0;i<(*program_iterator).count;i++)
cout<<(*data_iterator);
}break;
case '['://begin loop
{
//if byte is zero...
if(!(*data_iterator))
{
//move to stored position of the end of the loop
program_iterator=program.begin()+(*program_iterator).position;
}
}break;
case ']'://end loop
{
//if byte is non-zero
if(*data_iterator)
{
//move to stored position of the beginning of the loop
program_iterator=program.begin()+(*program_iterator).position;
}
}break;
}
//move to next instruction
program_iterator++;
}

//check for successful run
if(error_message.empty())
{
//success
cout << "\nSuccess!" << endl;
}
else
{
//error
cout << "\nRun-time error:" << endl;
cout << "\tError Message: " << error_message << endl;
cout << "\tLocation(Approximate): " << (unsigned int)error_position << endl;
}
}
}
//this is the one line I didn't change
return 0;
}




Sign in to follow this  


3 Comments


Recommended Comments

I still haven't figured out if you're the busiest lazy person I know or the laziest busy person I know.

Of course, I also know a guy who's 36 years old and can identify all of the Pokemon, so I guess we all must have some kind of useless avocation.

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!