📄 runnerline.cpp
字号:
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 + -