Beispiel #1
0
bool Parser::Parse(const std::vector<Token>& inTokens, Node **outParseTree)
{
    Node* rootNode = new Node(kNodeType_Root);
    unsigned int tokenCount = inTokens.size();

    int scopeLevel = 0;
    bool inComment = false;
    TextureNode* currentTextureNode = nullptr;
    OperationNode* currentOperationNode = nullptr;

    for(unsigned int index = 0; index < tokenCount; ++index)
    {
        const Token& currentToken = inTokens[index];
        switch(currentToken.GetType())
        {
            case kToken_ScopeBegin:
            {
                if( !inComment )
                {
                    // We're opening a new texture scope so it shouldn't be null
                    assert( currentTextureNode != nullptr );

                    scopeLevel++;
                }
                break;
            }
            case kToken_ScopeEnd:
            {
                if( !inComment )
                {
                    // We're closing a texture scope so it shouldn't be null
                    assert( currentTextureNode != nullptr );
                    scopeLevel--;

                    rootNode->InsertNode( currentTextureNode );
                    currentTextureNode = nullptr;
                }
                break;
            }
            case kToken_CommentBegin:
            {
                assert( !inComment );
                inComment = true;
                break;
            }
            case kToken_CommentEnd:
            {
                assert( inComment );
                inComment = false;
                break;
            }
            case kToken_Terminator:
            {
                if( !inComment )
                {
                    // Terminate the operation
                    assert( currentOperationNode != nullptr );
                    assert( currentTextureNode != nullptr );

                    currentTextureNode->InsertNode( currentOperationNode );
                    currentOperationNode = nullptr;
                }
                break;
            }
            case kToken_Identifier:
            {
                if( !inComment )
                {
                    // Start a new texture if we're not in one
                    if( currentTextureNode == nullptr )
                    {
                        IdentifierTokenData* tokenData = static_cast<IdentifierTokenData*>(currentToken.GetData());

                        assert( tokenData->GetValue().compare( "Texture" ) == 0 );

                        // Free the data here. This means the tokens are one time use
                        delete tokenData;

                        currentTextureNode = new TextureNode( "Undefined" );
                    }
                    else
                    {
                        // We're still looking for a name
                        if( currentTextureNode->GetName().compare( "Undefined") == 0 )
                        {
                            IdentifierTokenData* tokenData = static_cast<IdentifierTokenData*>(currentToken.GetData());

                            // Make sure no one tries to name it "Undefined"
                            assert( tokenData->GetValue().compare( "Undefined" ) != 0 );

                            currentTextureNode->SetName( tokenData->GetValue() );

                            // Free the data here. This means the tokens are one time use
                            delete tokenData;

                            // We also need width height and pixel depth
                            assert( index + 3 < tokenCount );
                            assert( inTokens[index+1].GetType() == kToken_Number );
                            assert( inTokens[index+2].GetType() == kToken_Number );
                            assert( inTokens[index+3].GetType() == kToken_Number );

                            NumberTokenData* widthData = static_cast<NumberTokenData*>(inTokens[index+1].GetData());
                            NumberTokenData* heightData = static_cast<NumberTokenData*>(inTokens[index+2].GetData());
                            NumberTokenData* pixelDepthData = static_cast<NumberTokenData*>(inTokens[index+3].GetData());

                            currentTextureNode->SetWidth( widthData->GetValue() );
                            currentTextureNode->SetHeight( heightData->GetValue() );
                            currentTextureNode->SetPixelDepth( pixelDepthData->GetValue() );

                            delete widthData;
                            delete heightData;
                            delete pixelDepthData;
                        }
                        else
                        {
                            // We're looking for operations now.
                            assert( currentOperationNode == nullptr );

                            IdentifierTokenData* tokenData = static_cast<IdentifierTokenData*>(currentToken.GetData());
                            currentOperationNode = new OperationNode( tokenData->GetValue() );

                            // Free the data here. This means the tokens are one time use
                            delete tokenData;
                        }
                    }
                }
                break;
            }
            case kToken_Number:
            {
                if( !inComment )
                {
                    // Add arguments to the operation
                    if( currentOperationNode != nullptr )
                    {
                        NumberTokenData* tokenData = static_cast<NumberTokenData*>(currentToken.GetData());
                        currentOperationNode->AddArgument( tokenData->GetValue() );

                        // Free the data here. This means the tokens are one time use
                        delete tokenData;
                    }
                }
                break;
            }

            case kToken_Undefined:
            default:
            {
                std::cout << "Error! Undefined token encountered!" << std::endl;
                delete rootNode;
                return false;
            }
        }
    }

    *outParseTree = rootNode;
    return true;
}