⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 runnerline.cpp

📁 由一个古老的BASIC解释器改进而成, 保留了ANSI C固有的艺术美感.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			out.tab (n);
                        break;
                case keySPC:
                        getparenarg (result);
                        n= result.integer ();
                        //out << std::string (n, ' ');
			out.putspaces (n);
                        break;
                case keyAT:
                	out.flush ();
                        {
				expect (result);
				//BlInteger row= result.integer () + 1;
				BlInteger row= result.integer ();
				requiretoken (',');
				expect (result);
				//BlInteger col= result.integer () + 1;
				BlInteger col= result.integer ();
				#if 0
				if (graphics::ingraphicsmode () )
					graphics::locate (row, col);
				else
					locate (row, col);
				#else
				out.gotoxy (col, row);
				#endif
                        }
                        break;
                default:
                        eval (result);
                        switch (result.type () ) {
                        case VarString:
                                out << result.str ();
                                break;
                        case VarNumber:
                                out << result.number ();
                                break;
			case VarInteger:
				out << result.integer ();
				break;
                        default:
                                throw ErrBlassicInternal;
                                ;
                        }
                }
		if (ended)
			break;
                if (endsentence () )
                {
                        out << '\n';
                        break;
                }
		if (token.code != ';' && token.code != ',')
			throw ErrSyntax;
		if (token.code == ',')
                        out << '\x09';
		gettoken ();
	} while (! endsentence () );
	out.flush ();
	return false;
}

bool RunnerLine::do_for ()
{
	//ProgramPos posfor= runner.getposactual ();
	ProgramPos posfor (getposactual () );
	//posfor.nextchunk ();
	expecttoken (keyIDENTIFIER);
	std::string varname= token.str;
	expecttoken ('=');

	//BlNumber initial= expectnum ();
	BlResult initial;
	expect (initial);

	requiretoken (keyTO);

	//BlNumber final= expectnum ();
	BlResult final;
	expect (final);

	//BlNumber step= (token.code == keySTEP) ? expectnum () : 1;
	BlResult step;
	if (token.code == keySTEP)
		expect (step);
	else
		step= 1;

	switch (token.code)
	{
	case ':':
		posfor.nextchunk ();
		break;
	case keyENDLINE:
		#if 1
		posfor.nextline ();
		#else
		{
			BlLineNumber num= program.getnextnum (line);
			if (num != 0)
				posfor= num;
		}
		#endif
		break;
	default:
		throw ErrSyntax;
	}
	switch (typeofvar (varname) )
	{
	case VarNumber:
		runner.push_for (new ForElementNumber
			(varname, posfor, initial.number (),
				final.number (), step.number () ) );
			//(varname, posfor, initial,
			//	final, step) );
		break;
	case VarInteger:
		runner.push_for (new ForElementInteger
			(varname, posfor, initial.integer (),
				final.integer (), step.integer () ) );
			//(varname, posfor, initial,
			//	final, step) );
		break;
	case VarString:
		throw ErrMismatch;
	default:
		throw ErrBlassicInternal;
	}
	return false;
}

bool RunnerLine::do_next ()
{
	gettoken ();
	//std::string varname;
	if (endsentence () )
        {
		//if (runner.for_empty () )
		//	throw ErrNextWithoutFor;
		ForElement & fe= runner.for_top ();
		if (fe.next () )
		{
			runner.jump_to (fe.getpos () );
			return true;
		}
		runner.for_pop ();
		return false;
	}

	for (;;)
	{
		requiretoken (keyIDENTIFIER);
		//varname= token.str;
		//gettoken ();
		//if (runner.for_empty () )
		//	throw ErrNextWithoutFor;
		ForElement * pfe= & runner.for_top ();
		//if (! varname.empty () && ! fe.isvar (varname) )
		if (! pfe->isvar (token.str) )
		{
			if (sysvar::get (sysvar::TypeOfNextCheck) == 0)
				throw ErrNextWithoutFor;
			else
			{
				// In ZX style NEXT can be omitted.
				do {
					runner.for_pop ();
					pfe= & runner.for_top ();
				} while (! pfe->isvar (token.str) );
			}
		}
		if (pfe->next () )
		{
			runner.jump_to (pfe->getpos () );
			return true;
		}
		runner.for_pop ();
		gettoken ();
		if (endsentence () )
			break;
		requiretoken (',');
		//expecttoken (keyIDENTIFIER);
		//varname= token.str;
		gettoken ();
	}
	return false;
}

bool RunnerLine::do_if ()
{
	BlNumber result= expectnum ();
	requiretoken (keyTHEN);
	if (result != 0) return false;
	else {
		unsigned int iflevel= 1;
		do {
			gettoken ();
			if (token.code == keyIF)
				++iflevel;
			if (token.code == keyELSE)
				--iflevel;
		} while (iflevel > 0 && token.code != keyENDLINE);
		if (token.code == keyELSE)
                {
			fInElse= true;
			return false;
		}
		return true;
	}
}

bool RunnerLine::do_tron ()
{
	gettoken ();
	bool fLine= false;
	if (token.code == keyLINE)
	{
		fLine= true;
		gettoken ();
	}
	BlChannel channel= 0;
	if (token.code == '#')
		channel= expectchannel ();
	require_endsentence ();
	runner.tron (fLine, channel);
	return false;
}

bool RunnerLine::do_troff ()
{
	errorifparam ();
	runner.troff ();
	return false;
}

void RunnerLine::letsubindex (const std::string & varname)
{
        Dimension dims= expectdims ();
	requiretoken ('=');
        BlResult result;
        expect (result);
        require_endsentence ();
	switch (typeofvar (varname) )
	{
	case VarNumber:
                assigndimnumber (varname, dims, result.number () );
		break;
        case VarInteger:
                assigndiminteger (varname, dims, result.integer () );
                break;
	case VarString:
                assigndimstring (varname, dims, result.str () );
		break;
	default:
		throw ErrBlassicInternal;
	}
}

bool RunnerLine::do_let ()
{
	if (token.code == keyLET)
		gettoken ();
	requiretoken (keyIDENTIFIER);
	std::string varname= token.str;
	gettoken ();
	if (token.code == '(')
	{
		letsubindex (varname);
		return false;
	}
	//requiretoken ('=');
	// Crash on hp-ux when failed. Compiler fault?
	// Workaround:
	if (token.code != '=')
		throw ErrSyntax;

        BlResult result;
        expect (result);
	require_endsentence ();
	switch (typeofvar (varname) )
        {
	case VarNumber:
                assignvarnumber (varname, result.number () );
		break;
	case VarInteger:
                assignvarinteger (varname, result.integer () );
		break;
	case VarString:
                assignvarstring (varname, result.str () );
		break;
	default:
		throw ErrBlassicInternal;
	}
	return false;
}

bool RunnerLine::do_goto ()
{
	gettoken ();
	BlLineNumber bln= evallinenumber ();
	require_endsentence ();
	runner.goto_line (bln);
	return true;
}

bool RunnerLine::do_stop ()
{
	errorifparam ();
	BlFile & f= getfile (0);
	f << "**Stopped**";
	//if (line.number () != 0)
	//	f << " in " << line.number ();
	if (pline->number () != 0)
		f << " in " << pline->number ();
	f << '\n';
	//ProgramPos posbreak (runner.getposactual () );
	ProgramPos posbreak (getposactual () );
	posbreak.nextchunk ();
	runner.set_break (posbreak);
	runner.setstatus (ProgramStopped);
	return true;
}

bool RunnerLine::do_cont ()
{
	runner.jump_break ();
        return true;
}

bool RunnerLine::do_clear ()
{
	errorifparam ();
	clearvars ();
	return false;
}

bool RunnerLine::do_gosub ()
{
	gettoken ();
        BlLineNumber dest= evallinenumber ();
	require_endsentence ();
        gosub_line (dest);
	return true;
}

bool RunnerLine::do_return ()
{
	errorifparam ();
	ProgramPos pos;
	runner.gosub_pop (pos);
	runner.jump_to (pos);
	return true;
}

bool RunnerLine::do_poke ()
{
	BlNumber bnAddr= expectnum ();
	requiretoken (',');
	BlChar * addr= (BlChar *) (unsigned int) bnAddr;
	BlNumber bnValue= expectnum ();
	require_endsentence ();
	BlChar value= (BlChar) (unsigned int) bnValue;
	* addr= value;
	return false;
}

bool RunnerLine::do_read ()
{
	BlLineNumber & datanumline= runner.getdatanumline ();
	BlChunk & datachunk= runner.getdatachunk ();
	unsigned short & dataelem= runner.getdataelem ();

	//CodeLine dataline= program.getline (datanumline);
	CodeLine dataline;
	program.getline (datanumline, dataline);
	CodeLine::Token datatok;
otra:
	if (dataline.number () == 0)
		throw ErrDataExhausted;
	if (dataline.number () > datanumline)
	{
		datachunk= 0;
		dataelem= 0;
	}
	//datatok= dataline.gettoken ();
	dataline.gettoken (datatok);
        if (dataline.chunk () < datachunk)
        {
        	while (dataline.chunk () < datachunk)
        	{
	        	//datatok= dataline.gettoken ();
			dataline.gettoken (datatok);
		        if (datatok.code == keyENDLINE)
			        break;
	        }
	        if (datatok.code != keyENDLINE)
			//datatok= dataline.gettoken ();
			dataline.gettoken (datatok);
        }
	if (datatok.code == keyENDLINE)
	{
		cerr << "Read searching next line" << endl;
		//dataline= program.getnextline (dataline);
		program.getnextline (dataline);
		goto otra;
	}
otra2:
	while (datatok.code != keyDATA)
	{
		dataelem= 0;
		datachunk= dataline.chunk ();
		do {
			//datatok= dataline.gettoken ();
			dataline.gettoken (datatok);
		} while (datatok.code != keyENDLINE &&
			dataline.chunk () == datachunk);
		if (datatok.code == keyENDLINE)
		{
			//cerr << "Read searching next line" << endl;
			//dataline= program.getnextline (dataline);
			program.getnextline (dataline);
			if (dataline.number () == 0)
				throw ErrDataExhausted;
			//datatok= dataline.gettoken ();
			dataline.gettoken (datatok);
		}
                else
                        //datatok= dataline.gettoken ();
			dataline.gettoken (datatok);
	}
        datatok= dataline.getdata ();
	unsigned short elem= 0;
otra3:
	while (elem < dataelem)
	{
		//datatok= dataline.gettoken ();
		dataline.gettoken (datatok);
		if (datatok.code == ':')
		{
                        //datatok= dataline.gettoken ();
			dataline.gettoken (datatok);
                        dataelem= 0;
			goto otra2;
                }
		if (datatok.code == keyENDLINE)
		{
			//cerr << "Read searching next line" << endl;
			//dataline= program.getnextline (dataline);
			program.getnextline (dataline);
			goto otra;
		}
		if (datatok.code != ',')
			throw ErrSyntax;
                datatok= dataline.getdata ();
                if (datatok.isendsentence () )
                	throw ErrSyntax;
		++elem;
	}

	//cerr << "(Data en linea " << dataline.number () <<
	//	' ' << datatok.str << ')';

	datanumline= dataline.number ();
        datachunk= dataline.chunk ();
	dataelem= (unsigned short) (elem + 1);
	gettoken ();
	if (token.code != keyIDENTIFIER)
		throw ErrSyntax;
	std::string varname (token.str);
	gettoken ();
	if (token.code == '(')
	{
		Dimension dims= expectdims ();
		switch (typeofvar (varname) )
		{
		case VarNumber:
			assigndimnumber (varname, dims, datatok.number () );
			break;
		case VarInteger:
			assigndiminteger (varname, dims,
				BlInteger (datatok.number () ) );
			break;
		case VarString:
			switch (datatok.code)
			{
			case keySTRING:
				assigndimstring (varname, dims, datatok.str);
				break;
			case keyINTEGER:
				assigndimstring (varname, dims,
					util::to_string (datatok.valueint) );
				break;
			default:
				throw ErrBlassicInternal;
			}
			break;
		default:
			cerr << "Unexpected array type in READ" << endl;
			throw ErrBlassicInternal;
		}
	}
	else
	{
		switch (typeofvar (varname) )
		{
		case VarNumber:
			assignvarnumber (varname, datatok.number () );
			break;
		case VarInteger:
			assignvarinteger (varname,
				BlInteger (datatok.number () ) );
			break;
		case VarString:
			switch (datatok.code)
			{
			case keySTRING:
				assignvarstring (varname, datatok.str);
				break;
			case keyINTEGER:
				assignvarstring (varname,
					util::to_string (datatok.valueint) );
				break;
			default:
				throw ErrBlassicInternal;
			}
			break;
		default:
			cerr << "Unexpected var type in READ" << endl;
			throw ErrBlassicInternal;
		}
	}
        if (token.code == ',')
                goto otra3;
	require_endsentence ();
	return false;
}

bool RunnerLine::do_data ()
{
	do {
		gettoken ();
	} while (! endsentence () );
	return false;
}

bool RunnerLine::do_restore ()
{
	gettoken ();
	BlLineNumber bln= 0;
	if (! endsentence () )
	{
		bln= evallinenumber ();
		require_endsentence ();
	}
	runner.setreadline (bln);
	return false;
}

namespace {

struct VarPointer {
	VarType type;
	union {
		BlNumber * pnumber;
		BlInteger * pinteger;
		std::string * pstring;
	};
	int clearvar () const
        // returns an int because Borland can't use mem_fun_ref
        // with a void function.
	{
		switch (type)
                {
		case VarNumber:
			* pnumber= 0;
			break;
		case VarInteger:
			* pinteger= 0;
			break;
		case VarString:
			pstring->erase ();
			break;
		default:
			throw ErrBlassicInternal;
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -