dlvhex  2.5.0
src/Term.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 
00034 #ifdef HAVE_CONFIG_H
00035 #include "config.h"
00036 #endif                           // HAVE_CONFIG_H
00037 
00038 #include "dlvhex2/Term.h"
00039 #include "dlvhex2/Logger.h"
00040 #include "dlvhex2/Printhelpers.h"
00041 #include "dlvhex2/Interpretation.h"
00042 #include "dlvhex2/Registry.h"
00043 #include "dlvhex2/Printer.h"
00044 #include "dlvhex2/PluginInterface.h"
00045 #include "dlvhex2/OrdinaryAtomTable.h"
00046 
00047 #include <boost/foreach.hpp>
00048 #include <map>
00049 
00050 DLVHEX_NAMESPACE_BEGIN
00051 
00052 Term::Term(IDKind kind, const std::vector<ID>& arguments, RegistryPtr reg): kind(kind), arguments(arguments)
00053 {
00054     assert(ID(kind,0).isTerm());
00055     assert(arguments.size() > 0);
00056 
00057     updateSymbolOfNestedTerm(reg.get());
00058 }
00059 
00060 
00061 void Term::updateSymbolOfNestedTerm(Registry* reg)
00062 {
00063     std::stringstream ss;
00064     if ((kind & ID::PROPERTY_MASK) == ID::PROPERTY_TERM_RANGE) {
00065         // range terms are printed without function symbol and parantheses
00066         ss << arguments[1].address;
00067         ss << "..";
00068         ss << arguments[2].address;
00069     }else{
00070         ss << reg->terms.getByID(arguments[0]).symbol;
00071         if (arguments.size() > 1) {
00072             ss << "(";
00073             for (uint32_t i = 1; i < arguments.size(); ++i) {
00074                 ss << (i > 1 ? "," : "");
00075                 if (arguments[i].isIntegerTerm()) {
00076                     ss << arguments[i].address;
00077                 }
00078                 else {
00079                     ss << reg->terms.getByID(arguments[i]).symbol;
00080                 }
00081             }
00082             ss << ")";
00083         }
00084     }
00085     symbol = ss.str();
00086 }
00087 
00088 
00089 // restores the hierarchical structure of a term from a string representation
00090 void Term::analyzeTerm(RegistryPtr reg)
00091 {
00092 
00093     // get token: function name and arguments
00094     bool quoted = false;
00095     bool primitive = true;
00096     int nestedcount = 0;
00097     int start = 0;
00098     int end = symbol.length();
00099     std::vector<std::string> tuple;
00100     //DBGLOG(DBG,"Analyzing Term '" << symbol << "'");
00101     for (int pos = 0; pos < end; ++pos) {
00102         if (symbol[pos] == '\"' &&
00103             (pos == 0 || symbol[pos-1] != '\\')) quoted = !quoted;
00104         if (symbol[pos] == '(' && !quoted ) {
00105             if (nestedcount == 0) {
00106                 primitive = false;
00107                 tuple.push_back(symbol.substr(start, pos - start));
00108                 start = pos + 1;
00109                 // eliminate closing bracket
00110                 assert(symbol[end-1] == ')');
00111                 end--;
00112             }
00113             nestedcount++;
00114         }
00115         if (symbol[pos] == ')' && !quoted) {
00116             nestedcount--;
00117         }
00118         if (symbol[pos] == ',' && !quoted && nestedcount == 1) {
00119             tuple.push_back(symbol.substr(start, pos - start));
00120             start = pos + 1;
00121         }
00122         if (pos == end - 1) {
00123             tuple.push_back(symbol.substr(start, pos - start + 1));
00124         }
00125     }
00126     // we did not find a ( -> it is primitive, or
00127     // we came into (, increased by one, and eliminated the closing )
00128     // therefore if it is not primitive we must leave the loop at 1
00129     assert(primitive || nestedcount == 1);
00130     #ifndef NDEBUG
00131     {
00132         std::stringstream ss;
00133         ss << "Term tuple: ";
00134         bool first = true;
00135         BOOST_FOREACH (std::string str, tuple) {
00136             if (!first) ss << ", ";
00137             first = false;
00138             ss << str;
00139         }
00140         DBGLOG(DBG, ss.str());
00141     }
00142     #endif
00143 
00144     // convert tuple of strings to terms
00145     arguments.clear();
00146     if (primitive) {
00147         // no arguments
00148         if (islower(symbol[0]) || symbol[0] == '\"') kind |= ID::SUBKIND_TERM_CONSTANT;
00149         if (isupper(symbol[0])) kind |= ID::SUBKIND_TERM_VARIABLE;
00150     }
00151     else {
00152         BOOST_FOREACH (std::string str, tuple) {
00153             Term t(ID::MAINKIND_TERM, str);
00154             t.analyzeTerm(reg);
00155             if (t.arguments[0] == ID_FAIL) {
00156                 if (islower(t.symbol[0]) || t.symbol[0] == '\"') t.kind |= ID::SUBKIND_TERM_CONSTANT;
00157                 if (isupper(t.symbol[0])) t.kind |= ID::SUBKIND_TERM_VARIABLE;
00158             }
00159             else {
00160                 t.kind |= ID::SUBKIND_TERM_NESTED;
00161             }
00162             ID tid = reg->storeTerm(t);
00163             arguments.push_back(tid);
00164         }
00165         kind |= ID::SUBKIND_TERM_NESTED;
00166     }
00167 }
00168 
00169 
00170 DLVHEX_NAMESPACE_END
00171 
00172 // vim:expandtab:ts=4:sw=4:
00173 // mode: C++
00174 // End: