Ejemplo n.º 1
0
APLValue* APLreader::readAPLvector(int size)
{
    skipNewlines();

    // if at end of list, make new vector
    if (*p_ == ')')
    {
        p_++;
        return new APLValue(size);
    }

    // else we better have a digit, save it and get the rest
    int sign = 1;
    if (*p_ == '-')
    {
        sign = -1;
        p_++;
    }

    if (!isdigit(*p_))
    {
        error("ill formed apl vector constant");
    }

    int val = sign* readInteger();
    APLValue* newval = readAPLvector(size + 1);
    newval->atPut(size, val);

    return newval;
}
Ejemplo n.º 2
0
Expression* APLreader::readExpression()
{
    // see if it is a scalar value
    if ((*p_ == '-') && isdigit(*(p_ + 1)))
    {
        p_++;
        return readAPLscalar(-readInteger());
    }

    if (isdigit(*p_))
    {
        return readAPLscalar(readInteger());
    }

    // see if it is a vector constant
    if (*p_ == '(')
    {
        p_++;
        skipNewlines();
        if (isdigit(*p_))
        {
            return readAPLvector(0);
        }
        return readList();
    }

    // else default
    return LispReader::readExpression();
}
    ConcreteNodeListPtr ScriptParser::parse(const ScriptTokenListPtr &tokens)
    {
        // MEMCATEGORY_GENERAL because SharedPtr can only free using that category
        ConcreteNodeListPtr nodes(OGRE_NEW_T(ConcreteNodeList, MEMCATEGORY_GENERAL)(), SPFM_DELETE_T);

        enum{READY, OBJECT};
        uint32 state = READY;

        ConcreteNode *parent = 0;
        ConcreteNodePtr node;
        ScriptToken *token = 0;
        ScriptTokenList::iterator i = tokens->begin(), end = tokens->end();
        while(i != end)
        {
            token = (*i).get();

            switch(state)
            {
            case READY:
                if(token->type == TID_WORD)
                {
                    if(token->lexeme == "import")
                    {
                        node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                        node->token = token->lexeme;
                        node->file = token->file;
                        node->line = token->line;
                        node->type = CNT_IMPORT;

                        // The next token is the target
                        ++i;
                        if(i == end || ((*i)->type != TID_WORD && (*i)->type != TID_QUOTE))
                            OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 
                                Ogre::String("expected import target at line ") + 
                                    Ogre::StringConverter::toString(node->line),
                                "ScriptParser::parse");
                        ConcreteNodePtr temp(OGRE_NEW ConcreteNode());
                        temp->parent = node.get();
                        temp->file = (*i)->file;
                        temp->line = (*i)->line;
                        temp->type = (*i)->type == TID_WORD ? CNT_WORD : CNT_QUOTE;
                        if(temp->type == CNT_QUOTE)
                            temp->token = (*i)->lexeme.substr(1, token->lexeme.size() - 2);
                        else
                            temp->token = (*i)->lexeme;
                        node->children.push_back(temp);

                        // The second-next token is the source
                        ++i;
                        ++i;
                        if(i == end || ((*i)->type != TID_WORD && (*i)->type != TID_QUOTE))
                            OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 
                                Ogre::String("expected import source at line ") + 
                                    Ogre::StringConverter::toString(node->line),
                                "ScriptParser::parse");
                        temp = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                        temp->parent = node.get();
                        temp->file = (*i)->file;
                        temp->line = (*i)->line;
                        temp->type = (*i)->type == TID_WORD ? CNT_WORD : CNT_QUOTE;
                        if(temp->type == CNT_QUOTE)
                            temp->token = (*i)->lexeme.substr(1, (*i)->lexeme.size() - 2);
                        else
                            temp->token = (*i)->lexeme;
                        node->children.push_back(temp);

                        // Consume all the newlines
                        i = skipNewlines(i, end);

                        // Insert the node
                        if(parent)
                        {
                            node->parent = parent;
                            parent->children.push_back(node);
                        }
                        else
                        {
                            node->parent = 0;
                            nodes->push_back(node);
                        }
                        node = ConcreteNodePtr();
                    }
                    else if(token->lexeme == "set")
                    {
                        node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                        node->token = token->lexeme;
                        node->file = token->file;
                        node->line = token->line;
                        node->type = CNT_VARIABLE_ASSIGN;

                        // The next token is the variable
                        ++i;
                        if(i == end || (*i)->type != TID_VARIABLE)
                            OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 
                                Ogre::String("expected variable name at line ") + 
                                    Ogre::StringConverter::toString(node->line),
                                "ScriptParser::parse");
                        ConcreteNodePtr temp(OGRE_NEW ConcreteNode());
                        temp->parent = node.get();
                        temp->file = (*i)->file;
                        temp->line = (*i)->line;
                        temp->type = CNT_VARIABLE;
                        temp->token = (*i)->lexeme;
                        node->children.push_back(temp);

                        // The next token is the assignment
                        ++i;
                        if(i == end || ((*i)->type != TID_WORD && (*i)->type != TID_QUOTE))
                            OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 
                                Ogre::String("expected variable value at line ") + 
                                    Ogre::StringConverter::toString(node->line),
                                "ScriptParser::parse");
                        temp = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                        temp->parent = node.get();
                        temp->file = (*i)->file;
                        temp->line = (*i)->line;
                        temp->type = (*i)->type == TID_WORD ? CNT_WORD : CNT_QUOTE;
                        if(temp->type == CNT_QUOTE)
                            temp->token = (*i)->lexeme.substr(1, (*i)->lexeme.size() - 2);
                        else
                            temp->token = (*i)->lexeme;
                        node->children.push_back(temp);

                        // Consume all the newlines
                        i = skipNewlines(i, end);

                        // Insert the node
                        if(parent)
                        {
                            node->parent = parent;
                            parent->children.push_back(node);
                        }
                        else
                        {
                            node->parent = 0;
                            nodes->push_back(node);
                        }
                        node = ConcreteNodePtr();
                    }
                    else
                    {
                        node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                        node->file = token->file;
                        node->line = token->line;
                        node->type = token->type == TID_WORD ? CNT_WORD : CNT_QUOTE;
                        if(node->type == CNT_QUOTE)
                            node->token = token->lexeme.substr(1, token->lexeme.size() - 2);
                        else
                            node->token = token->lexeme;

                        // Insert the node
                        if(parent)
                        {
                            node->parent = parent;
                            parent->children.push_back(node);
                        }
                        else
                        {
                            node->parent = 0;
                            nodes->push_back(node);
                        }

                        // Set the parent
                        parent = node.get();

                        // Switch states
                        state = OBJECT;

                        node = ConcreteNodePtr();
                    }
                }
                else if(token->type == TID_RBRACKET)
                {
                    // Go up one level if we can
                    if(parent)
                        parent = parent->parent;

                    node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                    node->token = token->lexeme;
                    node->file = token->file;
                    node->line = token->line;
                    node->type = CNT_RBRACE;

                    // Consume all the newlines
                    i = skipNewlines(i, end);

                    // Insert the node
                    if(parent)
                    {
                        node->parent = parent;
                        parent->children.push_back(node);
                    }
                    else
                    {
                        node->parent = 0;
                        nodes->push_back(node);
                    }

                    // Move up another level
                    if(parent)
                        parent = parent->parent;

                    node = ConcreteNodePtr();
                }
                break;
            case OBJECT:
                if(token->type == TID_NEWLINE)
                {
                    // Look ahead to the next non-newline token and if it isn't an {, this was a property
                    ScriptTokenList::iterator next = skipNewlines(i, end);
                    if(next == end || (*next)->type != TID_LBRACKET)
                    {
                        // Ended a property here
                        if(parent)
                            parent = parent->parent;
                        state = READY;
                    }
                }
                else if(token->type == TID_COLON)
                {
                    node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                    node->token = token->lexeme;
                    node->file = token->file;
                    node->line = token->line;
                    node->type = CNT_COLON;

                    // The following token are the parent objects (base classes).
                    // Require at least one of them.

                    ScriptTokenList::iterator j = i + 1;
                    j = skipNewlines(j, end);
                    if(j == end || ((*j)->type != TID_WORD && (*j)->type != TID_QUOTE)) {
                        OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 
                            Ogre::String("expected object identifier at line ") + 
                                    Ogre::StringConverter::toString(node->line),
                            "ScriptParser::parse");
                    }

                    while(j != end && ((*j)->type == TID_WORD || (*j)->type == TID_QUOTE))
                    {
                        ConcreteNodePtr tempNode = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                        tempNode->token = (*j)->lexeme;
                        tempNode->file = (*j)->file;
                        tempNode->line = (*j)->line;
                        tempNode->type = (*j)->type == TID_WORD ? CNT_WORD : CNT_QUOTE;
                        tempNode->parent = node.get();
                        node->children.push_back(tempNode);
                        ++j;
                    }

                    // Move it backwards once, since the end of the loop moves it forwards again anyway
                    i = --j;

                    // Insert the node
                    if(parent)
                    {
                        node->parent = parent;
                        parent->children.push_back(node);
                    }
                    else
                    {
                        node->parent = 0;
                        nodes->push_back(node);
                    }
                    node = ConcreteNodePtr();
                }
                else if(token->type == TID_LBRACKET)
                {
                    node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                    node->token = token->lexeme;
                    node->file = token->file;
                    node->line = token->line;
                    node->type = CNT_LBRACE;

                    // Consume all the newlines
                    i = skipNewlines(i, end);

                    // Insert the node
                    if(parent)
                    {
                        node->parent = parent;
                        parent->children.push_back(node);
                    }
                    else
                    {
                        node->parent = 0;
                        nodes->push_back(node);
                    }

                    // Set the parent
                    parent = node.get();

                    // Change the state
                    state = READY;

                    node = ConcreteNodePtr();
                }
                else if(token->type == TID_RBRACKET)
                {
                    // Go up one level if we can
                    if(parent)
                        parent = parent->parent;

                    // If the parent is currently a { then go up again
                    if(parent && parent->type == CNT_LBRACE && parent->parent)
                        parent = parent->parent;

                    node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                    node->token = token->lexeme;
                    node->file = token->file;
                    node->line = token->line;
                    node->type = CNT_RBRACE;

                    // Consume all the newlines
                    i = skipNewlines(i, end);

                    // Insert the node
                    if(parent)
                    {
                        node->parent = parent;
                        parent->children.push_back(node);
                    }
                    else
                    {
                        node->parent = 0;
                        nodes->push_back(node);
                    }

                    // Move up another level
                    if(parent)
                        parent = parent->parent;

                    node = ConcreteNodePtr();
                    state = READY;
                }
                else if(token->type == TID_VARIABLE)
                {
                    node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                    node->token = token->lexeme;
                    node->file = token->file;
                    node->line = token->line;
                    node->type = CNT_VARIABLE;

                    // Insert the node
                    if(parent)
                    {
                        node->parent = parent;
                        parent->children.push_back(node);
                    }
                    else
                    {
                        node->parent = 0;
                        nodes->push_back(node);
                    }
                    node = ConcreteNodePtr();
                }
                else if(token->type == TID_QUOTE)
                {
                    node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                    node->token = token->lexeme.substr(1, token->lexeme.size() - 2);
                    node->file = token->file;
                    node->line = token->line;
                    node->type = CNT_QUOTE;

                    // Insert the node
                    if(parent)
                    {
                        node->parent = parent;
                        parent->children.push_back(node);
                    }
                    else
                    {
                        node->parent = 0;
                        nodes->push_back(node);
                    }
                    node = ConcreteNodePtr();
                }
                else if(token->type == TID_WORD)
                {
                    node = ConcreteNodePtr(OGRE_NEW ConcreteNode());
                    node->token = token->lexeme;
                    node->file = token->file;
                    node->line = token->line;
                    node->type = CNT_WORD;

                    // Insert the node
                    if(parent)
                    {
                        node->parent = parent;
                        parent->children.push_back(node);
                    }
                    else
                    {
                        node->parent = 0;
                        nodes->push_back(node);
                    }
                    node = ConcreteNodePtr();
                }
                break;
            }

            ++i;
        }

        return nodes;
    }