dlvhex  2.5.0
src/Printer.cpp
Go to the documentation of this file.
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: