// Basic.cpp: implementation of the CBasic class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MyBasic.h"
#include "Basic.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Please do not remove the folowing comment !!!
// This code is writen by LiuXueSong����ѩ�ɣ�aladeing@163.com
// Thanks for Zoly Farkas I used the code of tokenizer from him
// You may use this code free
// Please if any bug found send a mail to me
// Thankx
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBasic::CBasic()
{
m_VariableTable.InitHashTable(MAX_VAR);
m_LabelTable.InitHashTable(MAX_LABEL);
}
CBasic::~CBasic()
{
}
void CBasic::Init()
{
help_init_stack();
help_init_gstack();
m_VariableTable.RemoveAll( );
m_LabelTable.RemoveAll( );
}
/////////////////////////////////////////////////////////////////
//���ڼ���+,-��
void CBasic::help_level2(_Variable*result)
{
_Variable hold;
help_level3(result);
int nToken = m_BasicLex.NextToken();
while(nToken == '+' || nToken == '-')
{
help_level3(&hold);
help_arith(nToken,result,&hold);
nToken =m_BasicLex.NextToken();
}
m_BasicLex.PushBack();
}
//���ڼ���*,/,%��
void CBasic::help_level3(_Variable*result)
{
_Variable hold;
help_level4(result);
int nToken = m_BasicLex.NextToken();
while(nToken == '*' || nToken == '/' || nToken == '%')
{
help_level4(&hold);
help_arith(nToken,result,&hold);
nToken =m_BasicLex.NextToken();
}
m_BasicLex.PushBack();
}
//���ڼ���^��
void CBasic::help_level4(_Variable*result)
{
_Variable hold;
help_level6(result);
int nToken = m_BasicLex.NextToken();
while(nToken == '^')
{
help_level6(&hold);
help_arith(nToken,result,&hold);
nToken =m_BasicLex.NextToken();
}
m_BasicLex.PushBack();
}
//���ڼ��㵥Ŀ����+,-
void CBasic::help_level5(_Variable*result)
{
}
//���ڼ���( )��
void CBasic::help_level6(_Variable*result)
{
int nToken = m_BasicLex.NextToken();
if(nToken == '(')
{
help_level2(result);
nToken =m_BasicLex.NextToken();
if(nToken != ')')
{
Error(1,"û���ҵ�ƥ��� ')' !");
}
}
else
{
m_BasicLex.PushBack();
help_primitive(result);
}
}
//���ڷ������֡�����
void CBasic::help_primitive(_Variable*result)
{
int nToken = m_BasicLex.NextToken();
if(nToken ==TT_INTEGER)
{
result->m_nVariableType = typeVariableInt;
result->m_nValue = (int) m_BasicLex.GetNumValue();
return;
}else if(nToken ==TT_REAL)
{
result->m_nVariableType = typeVariableFloat;
result->m_fValue = (float) m_BasicLex.GetNumValue();
return;
}else if(nToken ==TT_WORD)
{
_Variable value;
CString strLalueName=m_BasicLex.GetStrValue();
if(!m_VariableTable.Lookup(strLalueName,value))
{
//�����δ�����,���ó�ʼֵ��ʼ�������������������
m_VariableTable[strLalueName]=value;//Ӧ���ڴ˲��Ա��Ƿ��Ѿ�������DZ����
}
*result = value;
return;
}
Error(1,"��Ԥ�ڵ��������������������");
}
//���ڼ���result = result o hold
void CBasic::help_arith(char o,_Variable*result , _Variable*hold)
{
int t,ex;
float fex;
//�������͵�ת��
switch(o)
{
case '-':
if(result->m_nVariableType == typeVariableInt && hold->m_nVariableType == typeVariableInt)
{
result->m_nValue -= hold->m_nValue;
result->m_nVariableType = typeVariableInt;
}
else if(result->m_nVariableType == typeVariableInt && hold->m_nVariableType == typeVariableFloat)
{
result->m_fValue = result->m_nValue - hold->m_fValue;
result->m_nVariableType = typeVariableFloat;
}
else if(result->m_nVariableType == typeVariableFloat && hold->m_nVariableType == typeVariableInt)
{
result->m_fValue = result->m_fValue - hold->m_nValue;
result->m_nVariableType = typeVariableFloat;
}
else if(result->m_nVariableType == typeVariableFloat && hold->m_nVariableType == typeVariableFloat)
{
result->m_fValue = result->m_fValue - hold->m_fValue;
result->m_nVariableType = typeVariableFloat;
}
break;
case '+':
if(result->m_nVariableType == typeVariableInt && hold->m_nVariableType == typeVariableInt)
{
result->m_nValue += hold->m_nValue;
result->m_nVariableType = typeVariableInt;
}
else if(result->m_nVariableType == typeVariableInt && hold->m_nVariableType == typeVariableFloat)
{
result->m_fValue = result->m_nValue + hold->m_fValue;
result->m_nVariableType = typeVariableFloat;
}
else if(result->m_nVariableType == typeVariableFloat && hold->m_nVariableType == typeVariableInt)
{
result->m_fValue = result->m_fValue + hold->m_nValue;
result->m_nVariableType = typeVariableFloat;
}
else if(result->m_nVariableType == typeVariableFloat && hold->m_nVariableType == typeVariableFloat)
{
result->m_fValue = result->m_fValue + hold->m_fValue;
result->m_nVariableType = typeVariableFloat;
}
break;
case '*':
if(result->m_nVariableType == typeVariableInt && hold->m_nVariableType == typeVariableInt)
{
result->m_nValue *= hold->m_nValue;
result->m_nVariableType = typeVariableInt;
}
else if(result->m_nVariableType == typeVariableInt && hold->m_nVariableType == typeVariableFloat)
{
result->m_fValue = result->m_nValue * hold->m_fValue;
result->m_nVariableType = typeVariableFloat;
}
else if(result->m_nVariableType == typeVariableFloat && hold->m_nVariableType == typeVariableInt)
{
result->m_fValue = result->m_fValue * hold->m_nValue;
result->m_nVariableType = typeVariableFloat;
}
else if(result->m_nVariableType == typeVariableFloat && hold->m_nVariableType == typeVariableFloat)
{
result->m_fValue = result->m_fValue * hold->m_fValue;
result->m_nVariableType = typeVariableFloat;
}
break;
case '/':
if(result->m_nVariableType == typeVariableInt && hold->m_nVariableType == typeVariableInt)
{
if(hold->m_nValue==0)
{
Error(1,"������������");
break;
}
result->m_nValue /= hold->m_nValue;
result->m_nVariableType = typeVariableInt;
}
else if(result->m_nVariableType == typeVariableInt && hold->m_nVariableType == typeVariableFloat)
{
if(hold->m_fValue==0)
{
Error(1,"������������");
break;
}
result->m_fValue = result->m_nValue / hold->m_fValue;
result->m_nVariableType = typeVariableFloat;
}
else if(result->m_nVariableType == typeVariableFloat && hold->m_nVariableType == typeVariableInt)
{
if(hold->m_nValue==0)
{
Error(1,"������������");
break;
}
result->m_fValue = result->m_fValue / hold->m_nValue;
result->m_nVariableType = typeVariableFloat;
}
else if(result->m_nVariableType == typeVariableFloat && hold->m_nVariableType == typeVariableFloat)
{
if(hold->m_fValue==0)
{
Error(1,"������������");
break;
}
result->m_fValue = result->m_fValue / hold->m_fValue;
result->m_nVariableType = typeVariableFloat;
}
break;
case '%':
if(result->m_nVariableType != typeVariableFloat || hold->m_nVariableType != typeVariableFloat)
{
Error(1,"%������������������");
break;
}
if(hold->m_nValue==0)
{
Error(1,"������������");
break;
}
result->m_nValue %= hold->m_nValue;
result->m_nVariableType = typeVariableInt;
break;
case '^':
if(hold->m_nVariableType!=typeVariableInt)
{
Error(1,"ָ������Ϊ����");
break;
}
if(result->m_nVariableType == typeVariableFloat)
{
fex = result->m_fValue;
if(hold->m_nValue==0)
{
hold->m_nValue=1;
break;
}
for(t=hold->m_nValue-1;t>0;--t)
result->m_fValue=result->m_fValue*fex;
result->m_nVariableType = typeVariableFloat;
}
if(result->m_nVariableType == typeVariableInt)
{
ex = result->m_nValue;
if(hold->m_nValue==0)
{
hold->m_nValue=1;
break;
}
for(t=hold->m_nValue-1;t>0;--t)
result->m_nValue=result->m_nValue*ex;
result->m_nVariableType = typeVariableInt;
}
break;
};
}
//�ɴ���IJ�������+,-,*,/,%,^,��Ŀ+,-,����
void CBasic::help_exp(_Variable*result)
{
help_level2(result);
}
/////////////////////////////////////////////////////////////////
void CBasic::help_scan_labels()
{
_Label value;
CString strLable;
m_BasicLex.Locate(0);
m_BasicLex.EolIsSignificant(TRUE);
int nToken= m_BasicLex.NextToken();
if(nToken == TT_INTEGER)
{
strLable = m_BasicLex.GetStrValue();
value.m_nAddress = m_BasicLex.GetLocation();
value.m_strName = strLable;
m_LabelTable[strLable]=value;//Ӧ���ڴ˲��Ա��Ƿ��Ѿ�������DZ����
//lxs AfxMessageBox("Scanlabels "+strLable);
}
if(nToken==TT_EOF)
goto ex;
else if(nToken!=TT_EOL)
while((nToken = m_BasicLex.NextToken())!=TT_EOF && nToken!=TT_EOL);
do{
nToken = m_BasicLex.NextToken();
if(nToken == TT_INTEGER)
{
strLable = m_BasicLex.GetStrValue();
if(m_LabelTable.Lookup(strLable,value))
{
Error(1,"��ű��ظ����壡");
}
else
{
value.m_nAddress = m_BasicLex.GetLocation();
value.m_strName = strLable;
m_LabelTable[strLable]=value;//Ӧ���ڴ˲��Ա��Ƿ��Ѿ�������DZ����
//lxs AfxMessageBox("Scanlabels "+strLable);
}
}
if(nToken==TT_EOF)
goto ex;
else if(nToken!=TT_EOL)
while((nToken = m_BasicLex.NextToken())!=TT_EOF && nToken!=TT_EOL);
}while(nToken!=TT_EOF);
ex:;
m_BasicLex.EolIsSignificant(FALSE);
}
/////////////////////////////////////////////////////////////////
void CBasic::exec_default()
{
m_BasicLex.EolIsSignificant(TRUE);
int nToken= m_BasicLex.NextToken();
do{
nToken = m_BasicLex.NextToken();
}while(nToken!=TT_EOL&&nToken!=TT_EOF);
m_BasicLex.EolIsSignificant(FALSE);
}
void CBasic::exec_lable()
{
// int nToken= m_BasicLex.NextToken();
// AfxMessageBox("���"+m_BasicLex.GetStrValue());
}
void CBasic::exec_goto()
{
_Label value;
CString strLable;
int nToken= m_BasicLex.NextToken();
if(nToken!=TT_INTEGER)
Error(1,"goto ��Ҫ�����ֱ��");
strLable = m_BasicLex.GetStrValue();
if(!m_LabelTable.Lookup(strLable,value))
Error(1,"goto �������");
m_BasicLex.Locate(value.m_nAddress);
// AfxMessageBox("���"+m_BasicLex.GetStrValue());
}
void CBasic::exec_print()
{
_Variable result;
int nToken;
CString strOut;
m_BasicLex.EolIsSignificant(TRUE);
do
{
nToken= m_BasicLex.NextToken();
if(nToken==TT_STRING)
{
strOut+=m_BasicLex.GetStrValue();
}
else
{
CString strTrik;
m_BasicLex.PushBack();
help_exp(&result);
if(result.m_nVariableType == typeVariableInt)
{
strTrik.Format("%d",result.m_nValue);
}
else if(result.m_nVariableType == typeVariableFloat)
{
strTrik.Format("%f",result.m_fValue);
}
strOut+=strTrik;
}
nToken= m_BasicLex.NextToken();
}while(nToken!=TT_EOF&&nToken!=TT_EOL&&(nToken==';'||nToken==','));
if(nToken!=TT_EOF&&nToken!=TT_EOL)
Error(1,"PRINT�����������");
AfxMessageBox(strOut);
m_BasicLex.EolIsSignificant(FALSE);
}
void CBasic::exec_end()
{
int nToken= m_BasicLex.NextToken();
//�����Լ����END�Ժ��н�����ǰ�Ƿ��б���ַ�����б������
}
void CBasic::exec_assignment()
{
_Variable value;
CString strLalueName;
m_BasicLex.EolIsSignificant(TRUE);
//���������
int nToken= m_BasicLex.NextToken();
strLalueName = m_BasicLex.GetStrValue();
//�����δ�����,���ó�ʼֵ��ʼ�������������������
m_VariableTable[strLalueName]=value;//Ӧ���ڴ˲��Ա��Ƿ��Ѿ�������DZ����
//����=��
nToken= m_BasicLex.NextToken();
if(nToken!='=')
{
Error(1,"��ֵ���δ����'='");
}
//���ʽ����
_Variable result;
help_exp(&result);
//�����δ������ı����ͼ������������������ı����ֵ
m_VariableTable[strLalueName]= result;
nToken= m_BasicLex.NextToken();
if(nToken!=TT_EOF&&nToken!=TT_EOL)
Error(1,"��ֵ��������������");
m_BasicLex.EolIsSignificant(FALSE);
}
void CBasic::exec_for()
{
_Variable value;
struct _StackCell i;
//���������
int nToken= m_BasicLex.NextToken();
if(nToken!=TT_WORD)
Error(1,"����ȷ�ı�����");
i.m_strValueName = m_BasicLex.GetStrValue();
//����=��
nToken= m_BasicLex.NextToken();
if(nToken!='=')
{
Error(1,"FOR��������'='");
}
//���ʽ����
help_exp(&value);
if(value.m_nVariableType!=typeVariableInt)
Error(1,"FOR �����Ӧ�÷������� ");
m_VariableTable[i.m_strValueName]= value;
//����TO
nToken= m_BasicLex.NextToken();
if(nToken!=TT_KW_TO)
{
Error(1,"FOR��������'TO'");
}
//���ʽ����
help_exp(&value);
if(value.m_nVariableType!=typeVariableInt)
Error(1,"TO ��Ӧ�÷������� ");
i.m_nTarget = value.m_nValue;
//����ִ��
if(value.m_nValue>=m_VariableTable[i.m_strValueName].m_nValue)
{
i.m_nLoc = m_BasicLex.GetLocation();
help_fPush(i);
}
else//����NEXT��
{
int iFor = 0;
do
{
nToken = m_BasicLex.NextToken();
if(nToken ==TT_EOF)
break;
else if(nToken ==TT_KW_FOR)
iFor++;
else if(nToken ==TT_KW_NEXT)
{
if(iFor==0)
return;
else
iFor--;
}
}while(TRUE);
if(iFor!=0||nToken==TT_EOF)
Error(1,"FOR ... NEXT ����ԣ�");
}
}
void CBasic::exec_next()
{
_Variable value;
struct _StackCell i;
BOOL re = help_fPop(i);
if(!re)
Error(1,"û�����NEXT��ƥ���FOR");
m_VariableTable[i.m_strValueName].m_nValue++;
if(m_VariableTable[i.m_strValueName].m_nValue>i.m_nTarget)
return;
help_fPush(i);
m_BasicLex.Locate(i.m_nLoc);
}
void CBasic::exec_if()
{
float a,b;
int nToken,op,cond=0;
_Variable x,y;
//x���ʽ����
help_exp(&x);
if(x.m_nVariableType==typeVariableInt)
a = (float)x.m_nValue;
else
a = (float)x.m_fValue;
//���벼�������
op= m_BasicLex.NextToken();
if((op!=TT_GTE)&&(op!=TT_LWE)&&(op!=TT_IS)&&(op!=TT_NE)&&(op!='>')&&(op!='<'))
Error(1,"FOR��������'TO'");
//y���ʽ����
help_exp(&y);
if(y.m_nVariableType==typeVariableInt)
b = (float)y.m_nValue;
else
b = (float)y.m_fValue;
switch(op)
{
case TT_GTE://>=
if(a>=b)
cond=1;
break;
case TT_LWE://<=
if(a<=b)
cond=1;
break;
case TT_IS://==
if(a==b)
cond=1;
break;
case TT_NE://<>
if(a!=b)
cond=1;
break;
case '>': //>
if(a>b)
cond=1;
break;
case '<': //<
if(a<b)
cond=1;
break;
};
nToken = m_BasicLex.NextToken();
if(nToken!=TT_KW_THEN)
Error(1,"IF�����THEN��");
if(cond==1)
return;
else//����ENDIF��
{
int iIf = 0;
do
{
nToken = m_BasicLex.NextToken();
if(nToken ==TT_EOF)
break;
else if(nToken ==TT_KW_IF)
iIf++;
else if(nToken ==TT_KW_ENDIF)
{
if(iIf==0)
return;
else
iIf--;
}
}while(TRUE);
if(iIf!=0||nToken==TT_EOF)
Error(1,"IF ... ENDIF ����ԣ�");
}
}
void CBasic::exec_endif()
{
}
void CBasic::exec_gosub()
{
_Label value;
CString strLable;
int nToken= m_BasicLex.NextToken();
if(nToken!=TT_INTEGER)
Error(1,"GOSUB ��Ҫ�����ֱ��");
strLable = m_BasicLex.GetStrValue();
if(!m_LabelTable.Lookup(strLable,value))
Error(1,"GOSUB �������");
help_gPush(m_BasicLex.GetLocation());
m_BasicLex.Locate(value.m_nAddress);
}
void CBasic::exec_return()
{
int address;
help_gPop(address);
m_BasicLex.Locate(address);
}
/////////////////////////////////////////////////////////////////
void CBasic::Error(int nError,CString strError)
{
_Error*pError = new _Error;
pError->m_nErrorID = nError;
pError->m_nLineNo = m_BasicLex.LineNo();
pError->m_strErrorDes = strError;
throw pError;
}
void CBasic::Parse(CString & strCode)
{
try
{
m_BasicLex.LoadCode(strCode);
////////////////////////////////////
help_scan_labels();
/////////////////////////////////////
m_BasicLex.Locate(0);
int nToken;
do{
nToken = m_BasicLex.NextToken();
switch(nToken)
{
case TT_INTEGER://���
exec_lable();
break;
case TT_WORD://��ֵ���
m_BasicLex.PushBack();
exec_assignment();
break;
case TT_KW_PRINT://��ӡ���
exec_print();
break;
case TT_KW_INPUT:
m_BasicLex.PushBack();
exec_default();
break;
case TT_KW_IF://IF
exec_if();
break;
case TT_KW_ENDIF://ENDIF
exec_endif();
break;
case TT_KW_FOR://FOR
exec_for();
break;
case TT_KW_NEXT://NEXT
exec_next();
break;
case TT_KW_GOSUB:
exec_gosub();//gosub
break;
case TT_KW_RETURN://return
exec_return();
break;
case TT_KW_GOTO://GOTO���
exec_goto();
break;
case TT_KW_END://END ���
m_BasicLex.PushBack();
exec_end();
case TT_EOF:
goto ex;
default://
Error(0,"��Ԥ�ڵ��п�ʼ!");
};
}while(nToken!=TT_EOF);
ex:;
}catch(_Error*pError)
{
CString ss;
ss.Format("��%d��:'%s' ",pError->m_nLineNo,pError->m_strErrorDes);
AfxMessageBox(ss);
delete pError;
}
}