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/MLPSyntaxChecker.h" 00040 00041 DLVHEX_NAMESPACE_BEGIN 00042 00043 MLPSyntaxChecker::MLPSyntaxChecker(ProgramCtx& ctx1) 00044 { 00045 ctx = ctx1; 00046 } 00047 00048 00049 // get the arity of the predicate 00050 int MLPSyntaxChecker::getArity(std::string predName) 00051 { 00052 return ctx.registry()->preds.getByString(predName).arity; 00053 } 00054 00055 00056 // get the arity of predicate idp 00057 int MLPSyntaxChecker::getArity(ID idp) 00058 { 00059 if (idp.isTerm()==false) { 00060 return -2; 00061 } 00062 return ctx.registry()->preds.getByID(idp).arity; 00063 } 00064 00065 00066 // s = "p1.p2" will return "p1" 00067 std::string MLPSyntaxChecker::getStringBeforeSeparator(const std::string& s) 00068 { 00069 int n=s.find(MODULEPREFIXSEPARATOR); 00070 return s.substr(0, n); 00071 } 00072 00073 00074 // s = "p1.p2" will return "p2" 00075 std::string MLPSyntaxChecker::getStringAfterSeparator(const std::string& s) 00076 { 00077 int n=s.find(MODULEPREFIXSEPARATOR); 00078 return s.substr(n+2, s.length()); 00079 } 00080 00081 00082 // for example: 00083 // module = p1.p2 00084 // tuple = (q1) 00085 // moduleFullName = p1.p2 00086 // moduleToCall = p2 00087 bool MLPSyntaxChecker::verifyPredInputsArityModuleCall(ID module, Tuple tuple) 00088 { 00089 // get the module to call 00090 std::string moduleFullName = ctx.registry()->preds.getByID(module).symbol; 00091 std::string moduleToCall = getStringAfterSeparator(moduleFullName); 00092 00093 // get the module that is called 00094 const Module& moduleCalled = ctx.registry()->moduleTable.getModuleByName(moduleToCall); 00095 if ( moduleCalled == MODULE_FAIL ) { 00096 DBGLOG(ERROR,"[MLPSyntaxChecker::verifyPredInputsArityModuleCall] Error: Module '" << moduleToCall << "' not found"); 00097 return false; 00098 } 00099 00100 // get the predicate inputs of the module that is being called 00101 // ModuleHeaderTable::PredSetIndexBySequenced& predSetIndex = predInputs.get<ModuleHeaderTable::bySequenced>(); 00102 // ModuleHeaderTable::PredSetIteratorBySequenced itp = predSetIndex.begin(); 00103 Tuple inputList = ctx.registry()->inputList.at(moduleCalled.inputList); 00104 Tuple::const_iterator itp = inputList.begin(); 00105 00106 // predArity1 = for predicate arity in module call input 00107 // predArity2 = for predicate arity in module header that is being called 00108 int predArity1; 00109 00110 Tuple::const_iterator it = tuple.begin(); 00111 while ( it != tuple.end() ) { 00112 predArity1 = getArity(*it); 00113 if ( predArity1 != -1 ) { 00114 if (itp==inputList.end()) { 00115 DBGLOG(ERROR,"[MLPSyntaxChecker::verifyPredInputsArityModuleCall] Error: Too many predicate inputs in '@" << getStringAfterSeparator(moduleFullName) << "' in module '" << getStringBeforeSeparator(moduleFullName) << "'"<< std::endl); 00116 return false; 00117 } 00118 00119 if (predArity1 != ctx.registry()->preds.getByID(*itp).arity) { 00120 DBGLOG(ERROR,"[MLPSyntaxChecker::verifyPredInputsArityModuleCall] Error: Mismatch predicate inputs arity '" << getStringAfterSeparator(ctx.registry()->preds.getByID(*it).symbol) << "' when calling '@" << getStringAfterSeparator(moduleFullName) << "' in module '" << getStringBeforeSeparator(moduleFullName) << "' " << std::endl); 00121 return false; 00122 } 00123 } 00124 it++; 00125 itp++; 00126 } 00127 if (itp!=inputList.end()) { 00128 DBGLOG(ERROR,"[MLPSyntaxChecker::verifyPredInputsArityModuleCall] Error: Need more predicate inputs in '@" << getStringAfterSeparator(moduleFullName) << "' in module '" << getStringBeforeSeparator(moduleFullName) << "' " << std::endl); 00129 return false; 00130 } 00131 00132 DBGLOG(INFO,"[MLPSyntaxChecker::verifyPredInputsArityModuleCall] Verifying predicate inputs in module call '@" << getStringAfterSeparator(moduleFullName) << "' in module '" << getStringBeforeSeparator(moduleFullName) << "' succeeded"); 00133 return true; 00134 00135 } 00136 00137 00138 bool MLPSyntaxChecker::verifyPredOutputArityModuleCall(ID module, ID outputAtom) 00139 { 00140 // get the module to call 00141 std::string moduleFullName = ctx.registry()->preds.getByID(module).symbol; 00142 std::string moduleToCall = getStringAfterSeparator(moduleFullName); 00143 00144 // get the arity of the outputAtom in the module Call 00145 OrdinaryAtom oa = ctx.registry()->lookupOrdinaryAtom(outputAtom); 00146 int arity1 = oa.tuple.size()-1; 00147 00148 std::string predFullName = ctx.registry()->preds.getByID(oa.tuple.front()).symbol; 00149 std::string predName = getStringAfterSeparator(predFullName); 00150 std::string predNewName = moduleToCall + MODULEPREFIXSEPARATOR + predName; 00151 int arity2 = getArity(ctx.registry()->preds.getIDByString(predNewName)); 00152 // std::string predName = ctx.registry()->preds.getByID(oa.tuple.front()).symbol; 00153 // int arity2 = getArity(ctx.registry()->preds.getIDByString(predName)); 00154 00155 if (arity1 == arity2) { 00156 DBGLOG(INFO,"[MLPSyntaxChecker::verifyPredInputsArityModuleCall] Verifying predicate output of module call '@" << getStringAfterSeparator(moduleFullName) << "' in module '" << getStringBeforeSeparator(moduleFullName) << "' succeeded"); 00157 return true; 00158 } 00159 else { 00160 DBGLOG(ERROR,"[MLPSyntaxChecker::verifyPredInputsArityModuleCall] Error: Verifying predicate output '" << predName << "' of module call '@" << getStringAfterSeparator(moduleFullName) << "' in module '" << getStringBeforeSeparator(moduleFullName) << "' failed" << std::endl); 00161 return false; 00162 } 00163 } 00164 00165 00166 bool MLPSyntaxChecker::verifyAllModuleCalls() 00167 { 00168 ModuleAtomTable::AddressIterator it, it_end; 00169 boost::tie(it, it_end) = ctx.registry()->matoms.getAllByAddress(); 00170 while (it!=it_end) { 00171 ModuleAtom ma = *it; 00172 // Verifying pred Inputs 00173 if (verifyPredInputsArityModuleCall(ma.predicate, ma.inputs) == false) { 00174 DBGLOG(ERROR,"[MLPSyntaxChecker::verifyAllModuleCall] Error: Verifying predicates input and output for all module calls failed in " << ma << std::endl); 00175 return false; 00176 } 00177 // Verifying pred Ouput 00178 if (verifyPredOutputArityModuleCall(ma.predicate, ma.outputAtom) == false) { 00179 DBGLOG(ERROR,"[MLPSyntaxChecker::verifyAllModuleCall] Error: Verifying predicates input and output for all module calls failed in " << ma << std::endl); 00180 return false; 00181 } 00182 it++; 00183 } 00184 DBGLOG(INFO,"[MLPSyntaxChecker::verifyAllModuleCall] Verifying predicates input and output for all module calls succeeded"); 00185 return true; 00186 } 00187 00188 00189 bool MLPSyntaxChecker::verifySyntax() 00190 { 00191 bool result = verifyAllModuleCalls(); 00192 // successful verification? 00193 if( result == false ) 00194 throw FatalError("MLP syntax error"); 00195 return result; 00196 } 00197 00198 00199 DLVHEX_NAMESPACE_END 00200 00201 00202 // vim:expandtab:ts=4:sw=4: 00203 // mode: C++ 00204 // End: