00001 /****************************************************************************** 00002 STDR Simulator - Simple Two DImensional Robot Simulator 00003 Copyright (C) 2013 STDR Simulator 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 3 of the License, or 00007 (at your option) any later version. 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 You should have received a copy of the GNU General Public License 00013 along with this program; if not, write to the Free Software Foundation, 00014 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00015 00016 Authors : 00017 * Manos Tsardoulias, etsardou@gmail.com 00018 * Aris Thallas, aris.thallas@gmail.com 00019 * Chris Zalidis, zalidis@gmail.com 00020 ******************************************************************************/ 00021 00022 #include "stdr_parser/stdr_parser.h" 00023 00024 namespace stdr_parser 00025 { 00026 00028 Node* Parser::base_node_ = new Node(); 00029 00034 Parser::Parser(void) 00035 { 00036 00037 } 00038 00044 void Parser::parse(std::string file_name) 00045 { 00046 Parser::base_node_ = new Node(); 00047 Parser::base_node_->tag = "STDR_Parser_Root_Node"; 00048 00049 // Must destroy prev tree 00050 try 00051 { 00052 if(file_name.find(".xml") != std::string::npos) 00053 { 00054 XmlParser::parse(file_name,base_node_); 00055 } 00056 else if(file_name.find(".yaml") != std::string::npos) 00057 { 00058 YamlParser::parse(file_name,base_node_); 00059 } 00060 //~ base_node_->printParsedXml(base_node_,""); 00061 Validator::parseMergableSpecifications(); 00062 00063 while(!eliminateFilenames(base_node_)); 00064 while(!mergeNodes(base_node_)); 00065 mergeNodesValues(base_node_); 00066 00067 Validator::validate(file_name, base_node_); 00068 00070 //~ base_node_->printParsedXml(base_node_,""); 00071 } 00072 catch(ParserException ex) 00073 { 00074 throw ex; 00075 } 00076 catch(YAML::ParserException& e) 00077 { 00078 std::string error = 00079 std::string("Failed to load file '") + 00080 file_name + std::string("'") + 00081 std::string("\nError was '") + std::string(e.what()); 00082 00083 delete base_node_; 00084 00085 throw ParserException(error); 00086 } 00087 } 00088 00094 bool Parser::eliminateFilenames(Node* n) 00095 { 00096 if(n->value != "") 00097 { 00098 return true; 00099 } 00100 for(unsigned int i = 0 ; i < n->elements.size() ; i++) 00101 { 00102 if(n->elements[i]->tag == "filename") 00103 { 00104 if(!n->elements[i]->checkForFilename(n->tag)) 00105 { 00106 std::string error = 00107 std::string("STDR parser : ") + n->tag + std::string(" has a \ 00108 filename of wrong type specified\n") + 00109 std::string("\nError was in line ") + SSTR( n->file_row ) + 00110 std::string(" of file '") + n->file_origin + std::string("'"); 00111 throw ParserException(error); 00112 } 00113 Node* child = n->elements[i]->elements[0]; 00114 n->elements.erase(n->elements.begin() + i); 00115 for(unsigned int j = 0 ; j < child->elements.size() ; j++) 00116 { 00117 child->elements[j]->increasePriority() ; 00118 n->elements.push_back(child->elements[j]); 00119 } 00120 return false; 00121 } 00122 else 00123 { 00124 try 00125 { 00126 if(!eliminateFilenames(n->elements[i])) 00127 { 00128 return false; 00129 } 00130 } 00131 catch(ParserException ex) 00132 { 00133 throw ex; 00134 } 00135 } 00136 } 00137 return true; 00138 } 00139 00145 void Parser::mergeNodesValues(Node* n) 00146 { 00148 bool pure_values = true; 00149 for(unsigned int i = 0 ; i < n->elements.size() ; i++) 00150 { 00151 if(n->elements[i]->value == "") 00152 { 00153 pure_values = false; 00154 break; 00155 } 00156 } 00157 00158 if(pure_values) 00159 { 00161 if(n->elements.size() <= 1) 00162 { 00163 return; 00164 } 00165 00167 int min_priority = n->elements[0]->priority; 00168 unsigned int index = 0; 00169 for(unsigned int i = 1 ; i < n->elements.size() ; i++) 00170 { 00171 if(n->elements[i]->priority < min_priority) 00172 { 00173 min_priority = n->elements[i]->priority; 00174 index = i; 00175 } 00176 } 00177 Node* proper_child = n->elements[index]; 00178 n->elements.clear(); 00179 n->elements.push_back(proper_child); 00180 } 00181 else 00182 { 00183 for(unsigned int i = 0 ; i < n->elements.size() ; i++) 00184 { 00185 mergeNodesValues(n->elements[i]); 00186 } 00187 } 00188 } 00189 00195 bool Parser::mergeNodes(Node* n) 00196 { 00197 if(n->value != "") 00198 { 00199 return true; 00200 } 00201 for(unsigned int i = 0 ; i < n->elements.size() ; i++) 00202 { 00204 if(n->elements[i]->value != "") 00205 { 00206 continue; 00207 } 00208 std::string tag = n->elements[i]->tag; 00209 00211 if(Specs::non_mergable_tags.find(tag) == Specs::non_mergable_tags.end()) 00212 { 00213 std::vector<int> num = n->getTag(tag); 00214 00216 if(num.size() != 1) 00217 { 00218 for(int i = num.size()-1 ; i > 0 ; i --) 00219 { 00221 for (unsigned int j = 0 ; 00222 j < n->elements[num[i]]->elements.size() ; j++) 00223 { 00224 n->elements[num[0]]->elements.push_back( 00225 n->elements[num[i]]->elements[j]); 00226 } 00227 n->elements.erase(n->elements.begin() + num[i]); 00228 } 00229 return false; 00230 } 00231 } 00232 00233 if(!mergeNodes(n->elements[i])) 00234 { 00235 return false; 00236 } 00237 } 00238 return true; 00239 } 00240 } 00241