dlvhex  2.5.0
src/MLPSyntaxChecker.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/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: