Example #1
0
// note new return type, this now returns the bad block number, else 0 for success.
//
//  I also return -ve block numbers for errors between blocks. Eg if you read 3 good blocks, then find an unexpected
//		float in the script between blocks 3 & 4 then I return -3 to indicate the error is after that, but not block 4
//
int	CInterpreter::Interpret( CTokenizer *Tokenizer, CBlockStream *BlockStream, char *filename )
{
	CBlock		block;
	CToken		*token;
	int			type, blockLevel = 0, parenthesisLevel = 0;

	m_sCurrentFile	= filename;		// used during error reporting because you can't ask tokenizer for pushed streams
	
	m_tokenizer		= Tokenizer;
	m_blockStream	= BlockStream;

	m_iCurrentLine = m_tokenizer->GetCurLine();
	token = m_tokenizer->GetToEndOfLine(TK_STRING);		
	m_sCurrentLine = token->GetStringValue();	
	m_tokenizer->PutBackToken(token, false, NULL, true);
	
	m_iBadCBlockNumber = 0;

	while (m_tokenizer->GetRemainingSize() > 0)
	{
		token = m_tokenizer->GetToken( TKF_USES_EOL, 0 );
		type = token->GetType();

		switch ( type )
		{
		case TK_UNDEFINED:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;
			Error("%d : undefined token", type);
			return m_iBadCBlockNumber;
			break;

		case TK_EOF:
			break;

		case TK_EOL:
			// read the next line, then put it back
			token->Delete();
			m_iCurrentLine = m_tokenizer->GetCurLine();
			token = m_tokenizer->GetToEndOfLine(TK_STRING);			
			m_sCurrentLine = token->GetStringValue();				
			m_tokenizer->PutBackToken(token, false, NULL, true);
			break;
		
		case TK_CHAR:
		case TK_STRING:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;
			Error("syntax error : unexpected string");
			return m_iBadCBlockNumber;
			break;
		
		case TK_INT:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;		
			Error("syntax error : unexpected integer");
			return m_iBadCBlockNumber;
			break;
		
		case TK_FLOAT:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;
			Error("syntax error : unexpected float");
			return m_iBadCBlockNumber;
			break;
		
		case TK_IDENTIFIER:
			m_iBadCBlockNumber++;
			if (!GetID( (char *) token->GetStringValue() ))
			{
				token->Delete();
				return m_iBadCBlockNumber;
			}
			token->Delete();
			break;
		
		case TK_BLOCK_START:
			token->Delete();
			if (parenthesisLevel)
			{
				m_iBadCBlockNumber = -m_iBadCBlockNumber;
				Error("syntax error : brace inside parenthesis");
				return m_iBadCBlockNumber;
			}

			blockLevel++;
			break;

		case TK_BLOCK_END:
			token->Delete();
			if (parenthesisLevel)
			{
				m_iBadCBlockNumber = -m_iBadCBlockNumber;
				Error("syntax error : brace inside parenthesis");
				return m_iBadCBlockNumber;
			}
			
			block.Create( ID_BLOCK_END );
			m_blockStream->WriteBlock( &block );
			block.Free();

			blockLevel--;
			break;

		case TK_OPEN_PARENTHESIS:
			token->Delete();
			blockLevel++;
			parenthesisLevel++;
			break;

		case TK_CLOSED_PARENTHESIS:
			token->Delete();
			blockLevel--;
			parenthesisLevel--;

			if (parenthesisLevel<0)
			{
				m_iBadCBlockNumber = -m_iBadCBlockNumber;
				Error("syntax error : closed parenthesis with no opening match");
				return m_iBadCBlockNumber;
			}
			break;

		case TK_VECTOR_START:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;
			Error("syntax error : unexpected vector");
			return m_iBadCBlockNumber;
			break;

		case TK_VECTOR_END:
			token->Delete();
			m_iBadCBlockNumber = -m_iBadCBlockNumber;
			Error("syntax error : unexpected vector");
			return m_iBadCBlockNumber;
			break;
		}
	}

	if ( blockLevel )
	{
		m_iBadCBlockNumber = -m_iBadCBlockNumber;
		Error("error : open brace was not closed");
		return m_iBadCBlockNumber;
	}

	if ( parenthesisLevel )
	{
		m_iBadCBlockNumber = -m_iBadCBlockNumber;
		Error("error: open parenthesis");
		return m_iBadCBlockNumber;
	}

	//Release all the variable information, because it's already been written out
	FreeVars();

	m_iBadCBlockNumber = 0;
	return m_iBadCBlockNumber;	//true;
}