BrainF**k的解释器

Windows Only!

按照语法编写了这个“解释器”。

功能:

1.解释并运行一个后缀为 '.bf' 的文件;

2.提供错误指示,目前包括 RE 和 CE ;

3.提供 'help' 的指令帮助;

4.提供文件打开的功能;

源码:

#include <conio.h>
#include <windows.h>
#include <bits/stdc++.h>
using namespace std;

typedef bool ( * Functions )();
typedef pair<int, int> pii;

const char *LoadingBar[11] = 
{ 
  "          ",
  "-         ", 
  "--        ", 
  "---       ", 
  "----      ", 
  "-----     ", 
  "------    ", 
  "-------   ", 
  "--------  ", 
  "--------- ",
  "----------" };
const int MAXN = 1e6 + 5;

pii pos[MAXN];
int stk[MAXN], cp[MAXN], top;
int val[MAXN] = {}, ed[MAXN];
char code[MAXN], buf[MAXN];
int len, cnt;

namespace Error
{
	void PrintPosition( const int cur, char ptr )
	{
		int r = pos[cur].first;
		int beg = ed[r - 1] + 1, eed = ed[r];
		for( int i = max( beg, cur - 3 ) ; i <= min( eed, cur + 3 ) ; i ++ ) putchar( code[i] );
		putchar( '\n' ); for( int i = max( beg, cur - 3 ) ; i < cur ; i ++ ) putchar( ' ' );
		putchar( ptr ), putchar( '\n' );
	}
	
	void RE( const int cur )
	{
		printf( "Runtime error on: Line %d, Character %d.\n", pos[cur].first, pos[cur].second );
		printf( "Error: out of memory.\n" );	
		PrintPosition( cur, 'x' ), putchar( '\n' );
	}
	
	void CE( const int cur, bool type )
	{
		printf( "Compilation error on: Line %d, Character %d.\n", pos[cur].first, pos[cur].second );
		printf( "Mismatched %s bracket.\n", type ? "right" : "left" );
		PrintPosition( cur, '?' ), putchar( '\n' );
	}
	
	void UF()
	{
		puts( "Unknown file name." );
	}
	
	void UC()
	{
		puts( "Unknown command. Please put in \'help\' for help." );
	}

	void UnknownFormat()
	{
		puts( "Unknown format, please input \'help\' for help." );
	}
};

using namespace Error;

namespace Function
{
	bool Compile()
	{
		bool flag; int lst = 0;
		printf( "Processing: [%s]: 0%%\n", LoadingBar[0] );
		for( int i = 1 ; i <= len ; i ++ )
		{
			if( code[i] == '[' ) stk[++ top] = i;
			if( code[i] == ']' ) 
			{
				cp[i] = stk[top], cp[stk[top --]] = i;
				if( top < 0 ) { CE( i, 1 ); return false; }
			}
			
			flag = false;
			while( lst < 10 && lst + 1 < 10.0 * i / len ) flag = true, lst ++;
			if( flag ) printf( "Processing: [%s]: %.1lf%%\n", LoadingBar[lst], 100.0 * i / len );
		}
		
		if( top ) { CE( stk[1], 0 ); return false; }
		puts( "Done!\n" );
		return true;
	}
	
	FILE* GetFile( string Name )
	{
		int L = Name.size(); len = cnt = 0;
		for( int i = 0 ; i < L ; i ++ ) buf[i] = Name[i];
		buf[L] = '.', buf[L + 1] = 'b', buf[L + 2] = 'f';
		FILE *source = fopen( buf, "r" );
		for( int i = 0 ; i < L + 5 ; i ++ ) buf[i] = '\0';
		return source;
	}
	
	int GetCode( string Name )
	{
		FILE *source = GetFile( Name );
		if( source == NULL ) { UF(); return 0; }
		
		while( ~ fscanf( source, "%s", buf + 1 ) )
		{
			cnt ++;
			for( int i = 1 ; buf[i] && buf[i] != '\r' && buf[i] != '\n' ; i ++ )
				code[++ len] = buf[i], pos[len] = pii( cnt, i );
			for( int i = 1 ; buf[i] ; i ++ ) buf[i] = '\0';
			ed[cnt] = len;
		}
		
		fclose( source );
		return 1;
	}	

	bool CheckOrder( string A, string B )
	{
		if( A.length() < B.length() ) return false;
		for( int i = 0 ; i < B.length() ; i ++ )
			if( A[i] != B[i] ) return false;
		return true;
	}
};

using namespace Function;

struct Interface
{
	public : 
	int act();
};

struct Basic : public Interface
{
	private :
	bool Help()
	{
		puts( 
"Command - Use\n\
help      Show the usable commands.\n\
quit      Quit the program.\n\
exit      Exactly the same as command \"quit\".\n\
run       Compile and run a file with suffix \".bf\".\n\
          Format:\n\
              run [File Name]\n\
open      Open a file with suffix \".bf\".\n\
          Format:\n\
              open [File Name]\n\
clean     Clean the screen.\n" );
		return false;
	}

	bool Run()
	{
		puts( "Running..." );
		Sleep( 300 );
		
		int ptr = 0;
		memset( val, 0, sizeof val );
		
		clock_t start = clock();
		for( int i = 1 ; i <= len ; i ++ )
		{
			if( code[i] == '>' ) { ptr ++; if( ptr == MAXN ) { RE( i ); return false; } }
			else if( code[i] == '<' ) { ptr --; if( ptr < 0 ) { RE( i ); return false; } }
			else if( code[i] == '+' ) val[ptr] ++;
			else if( code[i] == '-' ) val[ptr] --;
			else if( code[i] == '.' ) putchar( val[ptr] );
			else if( code[i] == ',' ) val[ptr] = getchar();
			else if( code[i] == '[' ) { if( val[ptr] == 0 ) i = cp[i]; }
			else if( code[i] == ']' ) { if( val[ptr] ) i = cp[i]; }
		}
		
		clock_t ed = clock();
		puts( "\n--------------------------------------------------" );
		printf( "Run Time: %lfs\n\n", ( double ) ( ed - start ) / CLOCKS_PER_SEC );
		
		return true;
	}

	void CompileAndRun( const string order )
	{
		string name;
		stringstream ss( order );
		ss >> name; 
		if( ! ( ss >> name ) ) { UnknownFormat(); return ; }
		if( ss >> name ) { UnknownFormat(); return ; }
		
		if( ! GetCode( name ) ) return ;
		if( Compile() ) Run();
	}

	void OpenFile( const string order )
	{
		string name;
		stringstream ss( order );
		ss >> name;
		if( ! ( ss >> name ) ) { UnknownFormat(); return ; }
		if( ss >> name ) { UnknownFormat(); return ; }
		
		FILE *source = GetFile( name );
		if( source == NULL ) { UF(); return ; }
		fclose( source );
		system( ( "notepad " + name + ".bf" ).c_str() );
	}

	public :
	int act()
	{
		string comm;
		while( true )
		{
			system( "cls" );
			cout << "BrainFuck Environment : Version : 1.1.0" << endl;
			while( true )
			{
				cout << "BFE > ";
				getline( cin, comm, '\n' );
				if( comm == "debug" ) return 2;
				else if( comm == "quit" || comm == "exit" ) goto quit;
				else if( CheckOrder( comm, "run" ) ) CompileAndRun( comm );
				else if( CheckOrder( comm, "open" ) ) OpenFile( comm );
				else if( comm == "clean" ) break;
				else if( comm == "help" ) Help();
				else UC();
			}
		}
		quit :
		return 0;
	}
}base;

struct Debuger : public Interface
{
	private : 
	void Help()
	{
		puts( 
"Command - Use\n\
help      Show the usable Commands.\n\
quit      Quit the debuger.\n\
exit      Exactly the same as command \"quit\".\n\
load      Load a file with suffix \".bf\" into buffer.\n\
          Format:\n\
              load [File Name]" );
	}

	void Load( const string order )
	{
		string name;
		stringstream ss( order );
		ss >> name;
		if( ! ( ss >> name ) ) { UnknownFormat(); return ; }
		if( ss >> name ) { UnknownFormat(); return ; }
		
		FILE *source = GetFile( name );
		if( source == NULL ) { UF(); return ; }
		GetCode( name );
	}
	public :
	int act()
	{
		string comm;
		while( true )
		{
			system( "cls" );
			cout << "Brain Fuck Environment :: Debuger : Version : 0.0.0" << endl;
			while( true )
			{
				cout << "Debuger > ";
				getline( cin, comm, '\n' );
				if( CheckOrder( comm, "help" ) ) Help();
				else if( CheckOrder( comm, "quit" ) ) goto quit;
				else if( CheckOrder( comm, "exit" ) ) goto quit;
				else if( CheckOrder( comm, "load" ) ) Load( comm );
			}
		}
		quit :
		return 1;
	}
}debug;

struct End : public Interface
{
	public :
	int act() { exit( 0 ); return 0; }
}finish;

int main()
{
	system( "@echo off" );
	int cur = 1;
	while( true )
	{
		if( cur == 0 ) cur = finish.act();
		if( cur == 1 ) cur = base.act();
		if( cur == 2 ) cur = debug.act();
	}
	return 0;
}
posted @ 2020-06-03 19:12  crashed  阅读(294)  评论(0编辑  收藏  举报