dlvhex
2.5.0
|
00001 /* dlvhex -- Answer-Set Programming with external interfaces. 00002 * Copyright (C) 2005-2007 Roman Schindlauer 00003 * Copyright (C) 2006-2015 Thomas Krennwallner 00004 * Copyright (C) 2009-2016 Peter Schüller 00005 * Copyright (C) 2011-2016 Christoph Redl 00006 * Copyright (C) 2015-2016 Tobias Kaminski 00007 * Copyright (C) 2015-2016 Antonius Weinzierl 00008 * 00009 * This file is part of dlvhex. 00010 * 00011 * dlvhex is free software; you can redistribute it and/or modify it 00012 * under the terms of the GNU Lesser General Public License as 00013 * published by the Free Software Foundation; either version 2.1 of 00014 * the License, or (at your option) any later version. 00015 * 00016 * dlvhex is distributed in the hope that it will be useful, but 00017 * WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with dlvhex; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00024 * 02110-1301 USA. 00025 */ 00026 00035 #ifdef HAVE_CONFIG_H 00036 #include "config.h" 00037 #endif // HAVE_CONFIG_H 00038 00039 #include "dlvhex2/Printer.h" 00040 #include "dlvhex2/Registry.h" 00041 00042 #include <cassert> 00043 00044 DLVHEX_NAMESPACE_BEGIN 00045 00046 void Printer::printmany(const std::vector<ID>& ids, const std::string& separator) 00047 { 00048 std::vector<ID>::const_iterator it = ids.begin(); 00049 if( it != ids.end() ) { 00050 print(*it); 00051 it++; 00052 while( it != ids.end() ) { 00053 out << separator; 00054 print(*it); 00055 it++; 00056 } 00057 } 00058 } 00059 00060 00061 namespace 00062 { 00063 bool isInfixBuiltin(IDAddress id) { 00064 return id <= ID::TERM_BUILTIN_DIV; 00065 } 00066 } 00067 00068 00069 void RawPrinter::print(ID id) 00070 { 00071 switch(id.kind & ID::MAINKIND_MASK) { 00072 case ID::MAINKIND_LITERAL: 00073 if(id.isNaf()) 00074 out << "not "; 00075 // continue with atom here! 00076 case ID::MAINKIND_ATOM: 00077 switch(id.kind & ID::SUBKIND_MASK) { 00078 case ID::SUBKIND_ATOM_ORDINARYG: 00079 out << registry->ogatoms.getByID(id).text; 00080 break; 00081 case ID::SUBKIND_ATOM_ORDINARYN: 00082 out << registry->onatoms.getByID(id).text; 00083 break; 00084 case ID::SUBKIND_ATOM_BUILTIN: 00085 { 00086 const BuiltinAtom& atom = registry->batoms.getByID(id); 00087 assert(atom.tuple.size() > 1); 00088 assert(atom.tuple[0].isBuiltinTerm()); 00089 if( isInfixBuiltin(atom.tuple[0].address) ) { 00090 if( atom.tuple.size() == 3 ) { 00091 // things like A < B 00092 print(atom.tuple[1]); 00093 out << " "; 00094 print(atom.tuple[0]); 00095 out << " "; 00096 print(atom.tuple[2]); 00097 } 00098 else { 00099 // things like A = B * C 00100 assert(atom.tuple.size() == 4); 00101 // for ternary builtins of the form (A = B * C) tuple contains 00102 // in this order: <*, B, C, A> 00103 print(atom.tuple[3]); 00104 out << " = "; 00105 print(atom.tuple[1]); 00106 out << " "; 00107 print(atom.tuple[0]); 00108 out << " "; 00109 print(atom.tuple[2]); 00110 } 00111 } 00112 else { 00113 print(atom.tuple[0]); 00114 out << "("; 00115 Tuple::const_iterator it = atom.tuple.begin() + 1; 00116 print(*it); 00117 it++; 00118 for(; it != atom.tuple.end(); ++it) { 00119 out << ","; 00120 print(*it); 00121 } 00122 out << ")"; 00123 } 00124 } 00125 break; 00126 case ID::SUBKIND_ATOM_AGGREGATE: 00127 { 00128 const AggregateAtom& atom = registry->aatoms.getByID(id); 00129 assert(atom.tuple.size() == 5); 00130 00131 // left operator (if any) 00132 if( atom.tuple[0] != ID_FAIL ) { 00133 assert(atom.tuple[1] != ID_FAIL); 00134 print(atom.tuple[0]); 00135 out << " "; 00136 print(atom.tuple[1]); 00137 out << " "; 00138 } 00139 else { 00140 assert(atom.tuple[1] == ID_FAIL); 00141 } 00142 00143 // aggregate predicate 00144 assert(atom.tuple[2] != ID_FAIL); 00145 // aggregation function 00146 print(atom.tuple[2]); 00147 out << " { "; 00148 if (atom.mvariables.size() > 0) { 00149 assert(atom.mvariables.size() == atom.mliterals.size()); 00150 // multiple symbolic sets 00151 for (int iss = 0; iss < atom.mvariables.size(); ++iss) { 00152 if (iss > 0) out << "; "; 00153 // variables 00154 printmany(atom.mvariables[iss], ","); 00155 out << " : "; 00156 // body 00157 printmany(atom.mliterals[iss], ","); 00158 } 00159 } 00160 else { 00161 // single symbolic set 00162 00163 // variables 00164 printmany(atom.variables, ","); 00165 out << " : "; 00166 // body 00167 printmany(atom.literals, ","); 00168 } 00169 out << " }"; 00170 00171 // right operator (if any) 00172 if( atom.tuple[3] != ID_FAIL ) { 00173 assert(atom.tuple[4] != ID_FAIL); 00174 out << " "; 00175 print(atom.tuple[3]); 00176 out << " "; 00177 print(atom.tuple[4]); 00178 } 00179 else { 00180 assert(atom.tuple[4] == ID_FAIL); 00181 } 00182 } 00183 break; 00184 case ID::SUBKIND_ATOM_EXTERNAL: 00185 { 00186 const ExternalAtom& atom = registry->eatoms.getByID(id); 00187 out << "&"; 00188 print(atom.predicate); 00189 out << "["; 00190 printmany(atom.inputs,","); 00191 out << "]("; 00192 printmany(atom.tuple,","); 00193 out << ")"; 00194 } 00195 break; 00196 case ID::SUBKIND_ATOM_MODULE: 00197 { 00198 const ModuleAtom& atom = registry->matoms.getByID(id); 00199 out << "@"; 00200 print(atom.predicate); 00201 out << "["; 00202 printmany(atom.inputs,","); 00203 out << "]::"; 00204 print(atom.outputAtom); 00205 } 00206 break; 00207 default: 00208 assert(false); 00209 } 00210 break; 00211 case ID::MAINKIND_TERM: 00212 switch(id.kind & ID::SUBKIND_MASK) { 00213 case ID::SUBKIND_TERM_VARIABLE: 00214 out << (id.isAnonymousVariable() && registry->terms.getByID(id).symbol != "_" ? "_" : "") << registry->terms.getByID(id).symbol; 00215 break; 00216 case ID::SUBKIND_TERM_CONSTANT: 00217 case ID::SUBKIND_TERM_NESTED: 00218 out << registry->terms.getByID(id).symbol; 00219 break; 00220 case ID::SUBKIND_TERM_PREDICATE: 00221 out << registry->preds.getByID(id).symbol; 00222 break; 00223 case ID::SUBKIND_TERM_INTEGER: 00224 out << id.address; 00225 break; 00226 case ID::SUBKIND_TERM_BUILTIN: 00227 out << ID::stringFromBuiltinTerm(id.address); 00228 break; 00229 default: 00230 assert(false); 00231 } 00232 break; 00233 case ID::MAINKIND_RULE: 00234 switch(id.kind & ID::SUBKIND_MASK) { 00235 case ID::SUBKIND_RULE_REGULAR: 00236 { 00237 const Rule& r = registry->rules.getByID(id); 00238 printmany(r.head, " v "); 00239 if( !r.body.empty() ) { 00240 out << " :- "; 00241 printmany(r.body, ", "); 00242 } 00243 out << "."; 00244 } 00245 break; 00246 case ID::SUBKIND_RULE_CONSTRAINT: 00247 { 00248 out << ":- "; 00249 const Rule& r = registry->rules.getByID(id); 00250 printmany(r.body, ", "); 00251 out << "."; 00252 } 00253 break; 00254 case ID::SUBKIND_RULE_WEAKCONSTRAINT: 00255 { 00256 out << ":~ "; 00257 const Rule& r = registry->rules.getByID(id); 00258 printmany(r.body, ", "); 00259 out << ". ["; 00260 print(r.weight); 00261 out << ":"; 00262 print(r.level); 00263 out << "]"; 00264 } 00265 break; 00266 case ID::SUBKIND_RULE_WEIGHT: 00267 { 00268 const Rule& r = registry->rules.getByID(id); 00269 printmany(r.head, " v "); 00270 if( !r.body.empty() ) { 00271 out << " :- "; 00272 out << r.bound.address << " "; 00273 for (uint32_t i = 0; i < r.body.size(); ++i) { 00274 out << (i > 0 ? ", " : ""); 00275 print(r.body[i]); 00276 out << "=" << r.bodyWeightVector[i].address; 00277 } 00278 } 00279 out << "."; 00280 } 00281 break; 00282 default: 00283 assert(false); 00284 } 00285 break; 00286 default: 00287 assert(false); 00288 } 00289 } 00290 00291 00292 std::string RawPrinter::toString(RegistryPtr reg, ID id) 00293 { 00294 std::stringstream ss; 00295 RawPrinter printer(ss, reg); 00296 printer.print(id); 00297 return ss.str(); 00298 } 00299 00300 00301 // remove the prefix 00302 // from m0___p1__q(a) to q(a) 00303 std::string RawPrinter::removeModulePrefix(const std::string& text) 00304 { 00305 std::string result; 00306 if (text.find(MODULEINSTSEPARATOR) == std::string::npos) { 00307 result = text; 00308 } 00309 else { 00310 result = text.substr(text.find(MODULEINSTSEPARATOR)+3); 00311 } 00312 return result.substr(result.find(MODULEPREFIXSEPARATOR)+2); 00313 } 00314 00315 00316 void RawPrinter::printWithoutPrefix(ID id) 00317 { 00318 switch(id.kind & ID::MAINKIND_MASK) { 00319 case ID::MAINKIND_ATOM: 00320 switch(id.kind & ID::SUBKIND_MASK) { 00321 case ID::SUBKIND_ATOM_ORDINARYG: 00322 out << removeModulePrefix(registry->ogatoms.getByID(id).text); 00323 break; 00324 default: 00325 assert(false); 00326 } 00327 break; 00328 default: 00329 assert(false); 00330 } 00331 } 00332 00333 00334 DLVHEX_NAMESPACE_END 00335 00336 // vim:expandtab:ts=4:sw=4: 00337 // mode: C++ 00338 // End: