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 base_node_->unallocateChildren(); 00084 delete base_node_; 00085 00086 throw ParserException(error); 00087 } 00088 } 00089 00095 bool Parser::eliminateFilenames(Node* n) 00096 { 00097 if(n->value != "") 00098 { 00099 return true; 00100 } 00101 for(unsigned int i = 0 ; i < n->elements.size() ; i++) 00102 { 00103 if(n->elements[i]->tag == "filename") 00104 { 00105 if(!n->elements[i]->checkForFilename(n->tag)) 00106 { 00107 std::string error = 00108 std::string("STDR parser : ") + n->tag + std::string(" has a \ 00109 filename of wrong type specified\n") + 00110 std::string("\nError was in line ") + SSTR( n->file_row ) + 00111 std::string(" of file '") + n->file_origin + std::string("'"); 00112 throw ParserException(error); 00113 } 00114 Node* child = n->elements[i]->elements[0]; 00115 n->elements.erase(n->elements.begin() + i); 00116 for(unsigned int j = 0 ; j < child->elements.size() ; j++) 00117 { 00118 child->elements[j]->increasePriority() ; 00119 n->elements.push_back(child->elements[j]); 00120 } 00121 return false; 00122 } 00123 else 00124 { 00125 try 00126 { 00127 if(!eliminateFilenames(n->elements[i])) 00128 { 00129 return false; 00130 } 00131 } 00132 catch(ParserException ex) 00133 { 00134 throw ex; 00135 } 00136 } 00137 } 00138 return true; 00139 } 00140 00146 void Parser::mergeNodesValues(Node* n) 00147 { 00149 bool pure_values = true; 00150 for(unsigned int i = 0 ; i < n->elements.size() ; i++) 00151 { 00152 if(n->elements[i]->value == "") 00153 { 00154 pure_values = false; 00155 break; 00156 } 00157 } 00158 00159 if(pure_values) 00160 { 00162 if(n->elements.size() <= 1) 00163 { 00164 return; 00165 } 00166 00168 int min_priority = n->elements[0]->priority; 00169 unsigned int index = 0; 00170 for(unsigned int i = 1 ; i < n->elements.size() ; i++) 00171 { 00172 if(n->elements[i]->priority < min_priority) 00173 { 00174 min_priority = n->elements[i]->priority; 00175 index = i; 00176 } 00177 } 00178 Node* proper_child = n->elements[index]; 00179 n->elements.clear(); 00180 n->elements.push_back(proper_child); 00181 } 00182 else 00183 { 00184 for(unsigned int i = 0 ; i < n->elements.size() ; i++) 00185 { 00186 mergeNodesValues(n->elements[i]); 00187 } 00188 } 00189 } 00190 00196 bool Parser::mergeNodes(Node* n) 00197 { 00198 if(n->value != "") 00199 { 00200 return true; 00201 } 00202 for(unsigned int i = 0 ; i < n->elements.size() ; i++) 00203 { 00205 if(n->elements[i]->value != "") 00206 { 00207 continue; 00208 } 00209 std::string tag = n->elements[i]->tag; 00210 00212 if(Specs::non_mergable_tags.find(tag) == Specs::non_mergable_tags.end()) 00213 { 00214 std::vector<int> num = n->getTag(tag); 00215 00217 if(num.size() != 1) 00218 { 00219 for(int i = num.size()-1 ; i > 0 ; i --) 00220 { 00222 for (unsigned int j = 0 ; 00223 j < n->elements[num[i]]->elements.size() ; j++) 00224 { 00225 n->elements[num[0]]->elements.push_back( 00226 n->elements[num[i]]->elements[j]); 00227 } 00228 n->elements.erase(n->elements.begin() + num[i]); 00229 } 00230 return false; 00231 } 00232 } 00233 00234 if(!mergeNodes(n->elements[i])) 00235 { 00236 return false; 00237 } 00238 } 00239 return true; 00240 } 00241 } 00242