Click here to Skip to main content
15,884,537 members
Articles / Containers / Virtual Machine

Building a Programming Language: Part II (Adding Conditions, Loop and Blocks to BrainLess)

Rate me:
Please Sign up or sign in to vote.
4.75/5 (15 votes)
11 Oct 2013LGPL311 min read 56.8K   1.6K   66  
In this article, we will discuss implementing conditional statements, loops and blocks.
/*
Author : Shakti Misra
All are welcome to use these files, distribute, modify and release. But This notice should be included.
This software is given as is, for use and modification.
*/

#include "Interpreter.h"

#define START_RESTORE_PT( a ) const long a( m_lex.setRestorePoint() )
#define END_RESTORE_PT( a ) 

void Interpreter::interpreteScript()//Main routine to start script interpretation. this is semantic analysis or meaning findout method.
{
    m_lex.getNextToken();
    while( eTokenOver != m_lex.getCurrentToken() )
    {enmTokens tok = m_lex.getCurrentToken();//shakti del
        Sentence();
    }
}

void Interpreter::Block()
{
    /*
    A block is of the form #B(BlockName)[BlockContent]
    */
    char szBlockName[ARR_SIZE_128] = {0};

    if(eLeftParen == m_lex.getNextToken())
    {
        int iIndex = 0;

        while( (eCharVal == m_lex.getNextToken()) && (iIndex < ARR_SIZE_128) )
        {
            szBlockName[iIndex++] = (char)m_lex.getAttribVal();
        }

        if((iIndex > ARR_SIZE_128) || isBlankOrNull(szBlockName))
        {
            printf("invalid block name [%s]", szBlockName);//TODO proper error handling
        }
    }
}

void Interpreter::Sentence()
{
/*    while(eTokenOver != m_lex.getNextToken())
    {*/enmTokens tok = m_lex.getCurrentToken();//shakti del
        switch(m_lex.getCurrentToken())
        {//Based on the tokens choose the path.
        case eRdAndStrVal:
            m_tapeVirtualMachine.getCharAndStore();break;
        case eCharVal:break;//TODO
/*        case eBackSlash:
            compareWithNext();break;
            */
        case eDspCurVal:
            m_tapeVirtualMachine.displayChar();break;
        case eIncrContent:
            m_tapeVirtualMachine.incrementContent();break;
        case eDecrContent:
            m_tapeVirtualMachine.decrementContent();break;
        case eAddWithNext:
            m_tapeVirtualMachine.addWithNext();break;
        case eSubNext:
            m_tapeVirtualMachine.substractFromNext();break;
        case eStarChar:
            m_tapeVirtualMachine.moveHeadForeward();break;
        case eLeftAngleBracket:
            m_tapeVirtualMachine.moveHeadBackward();break;
        case eLessThan:// \<
        case eGreaterThan:// \>
        case eEquality:// \=
            compareWithNextBoolean();break;
        case eCompareGeneral://\<>
            compareWithNext();break;
        case eExclaimationMark:
            intDisplayContent();break;
        case eIF://IF(\<)[]FI
            IFBlock();break;
        case eBlock://#B(BlockName)[]
            Block();break;
        case eDO://DO()
            DOLoop();break;
        default:
            exit(0);break;//TODO error handling
        }
        m_lex.getNextToken();//Advance the token
    /*}*/
}

void Interpreter::DOLoop()
{
    if(m_lex.getNextToken() == eLeftParen)
    {
        const long resStartPoint( m_lex.setRestorePoint() );
        m_lex.getNextToken();
        long resEndPoint(-666);//Making it to some imaginary negative number. Else it will be again set when EOF is found.
        enmTokens tok = m_lex.getCurrentToken();//Shakti del
        while( 
            (!(HEX_1 ^ m_tapeVirtualMachine.getFlagRegister()))
            )
        {
            while(
                (m_lex.getCurrentToken() != eTokenOver)/* &&
                (m_lex.getCurrentToken() != eRightParen)*/
                )
            {   tok = m_lex.getCurrentToken();//shakti del
                Sentence();
                tok = m_lex.getCurrentToken();//shakti del
                if(m_lex.getCurrentToken() == eRightParen)
                {
                    if(-666 == resEndPoint)
                        resEndPoint = m_lex.setRestorePoint();
                    break;
                }
            }
            m_lex.positionToRestorePoint(resStartPoint);
            tok = m_lex.getNextToken();//Shakti del tok only
        }

        m_lex.positionToRestorePoint(resEndPoint);
    }
}

void Interpreter::intDisplayContent()
{   //When we are in this function we know that it was due to ![eExclaimationMark] that this function is called.
    //So check for eLeftSqrParen eIntNumber eRightSqrParen structure.
    switch(m_lex.getNextToken())//The tokens group eExclaimationMark eLeftSqrParen eIntNumber eRightSqrParen is a valid token.
    {
    case eLeftSqrParen:
        int len(0);
        if(eIntNumber == m_lex.getNextToken())
        {
           len = (int)m_lex.getAttribVal();
        }
        if(eRightSqrParen == m_lex.getNextToken())
        {
            m_tapeVirtualMachine.displayMultiChar(len);
        }
    }
}

void Interpreter::compareWithNextBoolean()
{
    compareWithNext();
    
    const ulong flagVal = m_tapeVirtualMachine.getFlagRegister();
    bool valSet = false;

    switch( m_lex.getCurrentToken() )
    {
    case eLessThan:
        if(!(flagVal ^ HEX_1))
        {
            m_tapeVirtualMachine.setFlagRegister(HEX_1);
            valSet = true;
        }
        break;
    case eGreaterThan:
        if(!(flagVal ^ HEX_2))
        {
            m_tapeVirtualMachine.setFlagRegister(HEX_1);
            valSet = true;
        }
        break;
    case eEquality:
        if(!(flagVal ^ HEX_3))
        {
            m_tapeVirtualMachine.setFlagRegister(HEX_1);
            valSet = true;
        }
        break;
    }

    if( !valSet )
    {
        m_tapeVirtualMachine.setFlagRegister(HEX_0);
    }
}

void Interpreter::IFBlock()
{
    if(eLeftParen == m_lex.getNextToken())
    {
        switch(m_lex.getNextToken())
        {
        case eLessThan:// \<
        case eGreaterThan:// \>
        case eEquality:// \=
            compareWithNextBoolean();
            if( (m_lex.getNextToken() == eRightParen) && (m_lex.getNextToken() == eLeftSqrParen) )
            {
                const ulong val = m_tapeVirtualMachine.getFlagRegister();//shakti del
                enmTokens tok = m_lex.getNextToken();//shakti del tok
                do
                {tok = m_lex.getCurrentToken();//Shakti del
                    
                    if(!(HEX_1 ^ m_tapeVirtualMachine.getFlagRegister()))
                    {
                        Sentence();
                    }
                    else/* if(HEX_1 & m_tapeVirtualMachine.getFlagRegister())*/
                    {
                        ;//NULL while to eat up all characters till we get ]. NULL Statement()
                    }
                }while( (m_lex.getNextToken() != eFI) && (m_lex.getCurrentToken() != eTokenOver) );
            }
            else
            {
                //set error TODO
            }
            break;
        default:
            //set error TODO
            break;
        }
    }
    else
    {
        //set error - TODO
    }
}

void Interpreter::compareWithNext()
{
    if(m_tapeVirtualMachine.getCurrentHeadValue() < m_tapeVirtualMachine.getNthPosValFrmHead(1))
    {
        m_tapeVirtualMachine.setFlagRegister(HEX_1);
    }
    else if(m_tapeVirtualMachine.getCurrentHeadValue() > m_tapeVirtualMachine.getNthPosValFrmHead(1))
    {
        m_tapeVirtualMachine.setFlagRegister(HEX_2);
    }
    else
    {
        m_tapeVirtualMachine.setFlagRegister(HEX_3);
    }
}

bool Interpreter::isBlankOrNull(const char* str)
{
    //For now only check string len, TODO check for blank too
    return (strlen(str) > 0)? true : false;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Architect
India India
I like to explore different aspects of technology. Try new things, and get delighted. My interests are programming language, and Imaging. But its not hard to work on other things also. Algorithms delight me over a coffee break.

I basically code in C++, but JAVA is not so alien for me. I know few scripting languages also. Basically I feel that knowing a programing language is just a matter of getting introduced to it.

For my other articles check my blog on homepage:

http://brainlesslabs.com/

https://github.com/BrainlessLabsInc

http://www.luxrender.net/en_GB/authors_contributors - SMISRA

Comments and Discussions