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 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: