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; }
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; }