Introduction
In my recent project I needed a smart and light application language , so I wrote MyBasic a custom-BASIC language interpreter, in about 3 days. I think MyBasic has a lot of shortcuts and it is enough for my requirements. From time to time I got code from CodeProject and so now I would like to share my code with you.
Details
This interpreter uses Zoly Farkas's CStringTokenizer as it's tokenizer but it does not work for 16-bit character sets, for example Chinese, and the interpreter needs to locate tokens in any place of the source code. Therefore I made some changes to CStringTokenizer as you can see below :
void Locate(int nLocation);
int GetLocation(){ return m_iPChar;}
void LoadCode(CString &strCode);
private:
inline int GetChar()
{
if(m_iChar == m_sString.GetLength())
return -1;
else
return (unsigned char)m_sString[m_iChar++];
}
CStringTokenizer::CStringTokenizer()
{
m_bEolIsSignificant = FALSE;
m_bSlSlComments = TRUE;
m_bSlStComments = TRUE;
m_bPascalComments = TRUE;
Locate(0);
ResetSyntax();
WordChars('a','z');
WordChars('A','Z');
WordChars(128,255);
QuoteChar('"');
QuoteChar('\'');
WhiteSpaceChars(0,' ');
ParseNumbers();
}
void CStringTokenizer::LoadCode(CString &strCode)
{
m_sString = strCode;
m_sString += -1;
}
void CStringTokenizer::Locate(int nLocation)
{
m_bPushedBack = FALSE;
m_iLineNo = 1; // the first line
m_iChar = nLocation;
m_iPChar= nLocation;
m_peekc = ' ';
}
In the main loop the interpreter gets the keywords one by one and calls the function accordingly, that's all.
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:
exec_if();
break;
case TT_KW_ENDIF:
exec_endif();
break;
case TT_KW_FOR:
exec_for();
break;
case TT_KW_NEXT:
exec_next();
break;
case TT_KW_GOSUB:
exec_gosub();
break;
case TT_KW_RETURN:
exec_return();
break;
case TT_KW_GOTO:
exec_goto();
break;
case TT_KW_END:
m_BasicLex.PushBack();
exec_end();
case TT_EOF:
goto ex;
default:
Error(0,"not except begin of line !");
};
}while(nToken!=TT_EOF);
ex:;
Custom-BASIC keywords
The keywords Custom-BASIC language interpreter supports.
PRINT
IF
THEN
ENDIF
FOR
NEXT
TO
GOTO
GOSUB
RETURN
END
Sample BASIC program
PRINT "Hello world!\r\nHello to all of you!"
FOR X=1 To 2
FOR Y=1 To 2
PRINT "X=",X,"Y=",Y
NEXT
NEXT
A = 12.5*2+(100+100)-2^2+4/6
PRINT A
IF A >= 0 THEN
GOTO 100
ENDIF
PRINT "..."
100 PRINT "GOTO 100"
200 PRINT "GOTO 200..."
GOSUB 300
END
300 PRINT "GOSUB 300"
RETURN
How to use the code
Include header file in your project and use like this :
#include "Basic.h"
public:
CBasic m_Basic;
CString strCode(pBuffer);
m_Basic.Init();
m_Basic.Parse(strCode);
Conclusion
All comments and feedback and criticism are welcome. I hope someone can benefit from my interpreter.