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 00042 #ifndef DLVHEX_HEX_GRAMMAR_TCC_INCLUDED 00043 #define DLVHEX_HEX_GRAMMAR_TCC_INCLUDED 00044 00045 #include "dlvhex2/PlatformDefinitions.h" 00046 #include "dlvhex2/ProgramCtx.h" 00047 #include "dlvhex2/Registry.h" 00048 #include "dlvhex2/Printer.h" 00049 #include "dlvhex2/ExtSourceProperties.h" 00050 00051 #include <algorithm> 00052 00053 #include <boost/spirit/include/qi.hpp> 00054 #include <boost/algorithm/string/predicate.hpp> 00055 #include <boost/lexical_cast.hpp> 00056 00057 DLVHEX_NAMESPACE_BEGIN 00058 00060 // Skipper ////////////////////////////////////////////////////// 00062 template<typename Iterator> 00063 HexParserSkipperGrammar<Iterator>::HexParserSkipperGrammar(): 00064 HexParserSkipperGrammar::base_type(ws) 00065 { 00066 using namespace boost::spirit; 00067 ws 00068 = ascii::space 00069 | qi::lexeme[ qi::char_('%') > *(qi::char_ - qi::eol) ]; 00070 00071 #ifdef BOOST_SPIRIT_DEBUG_WS 00072 BOOST_SPIRIT_DEBUG_NODE(ws); 00073 #endif 00074 } 00075 00076 00078 // HexGrammarBase semantic processors /////////////////////////// 00080 template<> 00081 struct sem<HexGrammarSemantics::termId> 00082 { 00083 void operator()(HexGrammarSemantics& mgr, const ID& source, ID& target) { 00084 target = source; 00085 } 00086 }; 00087 00088 template<> 00089 struct sem<HexGrammarSemantics::termFromCIdent> 00090 { 00091 void operator()(HexGrammarSemantics& mgr, const std::string& source, ID& target) { 00092 assert(!source.empty() && islower(source[0])); 00093 target = mgr.ctx.registry()->terms.getIDByString(source); 00094 if( target == ID_FAIL ) { 00095 Term term(ID::MAINKIND_TERM | ID::SUBKIND_TERM_CONSTANT, source); 00096 target = mgr.ctx.registry()->terms.storeAndGetID(term); 00097 } 00098 } 00099 }; 00100 00101 template<> 00102 struct sem<HexGrammarSemantics::termFromFunctionTerm> 00103 { 00104 void operator()(HexGrammarSemantics& mgr, const boost::fusion::vector2<const std::string, boost::optional<boost::optional<std::vector<ID> > > >& source, ID& target) { 00105 Term functionSymbol(ID::MAINKIND_TERM | ID::SUBKIND_TERM_CONSTANT, boost::fusion::at_c<0>(source)); 00106 ID fid = mgr.ctx.registry()->terms.getIDByString(functionSymbol.symbol); 00107 if (fid == ID_FAIL) fid = mgr.ctx.registry()->terms.storeAndGetID(functionSymbol); 00108 00109 std::vector<ID> args; 00110 args.push_back(fid); 00111 if (!!boost::fusion::at_c<1>(source) && !!boost::fusion::at_c<1>(source).get() ) { 00112 BOOST_FOREACH (ID id, boost::fusion::at_c<1>(source).get().get()) args.push_back(id); 00113 } 00114 00115 Term term(ID::MAINKIND_TERM | ID::SUBKIND_TERM_NESTED, args, mgr.ctx.registry()); 00116 target = mgr.ctx.registry()->terms.getIDByString(term.symbol); 00117 if (target == ID_FAIL) target = mgr.ctx.registry()->terms.storeAndGetID(term); 00118 } 00119 }; 00120 00121 template<> 00122 struct sem<HexGrammarSemantics::termFromRange> 00123 { 00124 void operator()(HexGrammarSemantics& mgr, const boost::fusion::vector2<ID, ID>& source, ID& target) { 00125 std::vector<ID> args; 00126 Term functionSymbol(ID::MAINKIND_TERM | ID::SUBKIND_TERM_CONSTANT, "range"); 00127 ID fid = mgr.ctx.registry()->terms.getIDByString(functionSymbol.symbol); 00128 if (fid == ID_FAIL) fid = mgr.ctx.registry()->terms.storeAndGetID(functionSymbol); 00129 args.push_back(fid); 00130 args.push_back(boost::fusion::at_c<0>(source)); 00131 args.push_back(boost::fusion::at_c<1>(source)); 00132 Term rangeTerm(ID::MAINKIND_TERM | ID::SUBKIND_TERM_NESTED | ID::PROPERTY_TERM_RANGE, args, mgr.ctx.registry()); 00133 target = mgr.ctx.registry()->terms.getIDByString(rangeTerm.symbol); 00134 if (target == ID_FAIL) target = mgr.ctx.registry()->terms.storeAndGetID(rangeTerm); 00135 } 00136 }; 00137 00138 template<> 00139 struct sem<HexGrammarSemantics::termFromInteger> 00140 { 00141 void operator()(HexGrammarSemantics& mgr, unsigned int source, ID& target) { 00142 target = ID::termFromInteger(source); 00143 if (source > mgr.ctx.maxint) mgr.ctx.maxint = source; // by default, set maxint to the largest number in the input 00144 } 00145 }; 00146 00147 template<> 00148 struct sem<HexGrammarSemantics::termFromString> 00149 { 00150 void operator()(HexGrammarSemantics& mgr, const std::string& source, ID& target) { 00151 assert(!source.empty() && source[0] == '"' && source[source.size()-1] == '"'); 00152 target = mgr.ctx.registry()->terms.getIDByString(source); 00153 if( target == ID_FAIL ) { 00154 Term term(ID::MAINKIND_TERM | ID::SUBKIND_TERM_CONSTANT, source); 00155 target = mgr.ctx.registry()->terms.storeAndGetID(term); 00156 } 00157 } 00158 }; 00159 00160 template<> 00161 struct sem<HexGrammarSemantics::termFromVariable> 00162 { 00163 void operator()(HexGrammarSemantics& mgr, const std::string& source, ID& target) { 00164 assert(!source.empty() && ((source[0] == '_' && source.size() == 1) || isupper(source[0]))); 00165 // special handling of anonymous variables 00166 IDKind addFlags = 0; 00167 if( source == "_" ) { 00168 addFlags |= ID::PROPERTY_VAR_ANONYMOUS; 00169 } 00170 // regular handling + flags 00171 target = mgr.ctx.registry()->terms.getIDByString(source); 00172 if( target == ID_FAIL ) { 00173 Term term(ID::MAINKIND_TERM | ID::SUBKIND_TERM_VARIABLE | addFlags, source); 00174 target = mgr.ctx.registry()->terms.storeAndGetID(term); 00175 } 00176 } 00177 }; 00178 00179 // helper method to prefix and store predicates 00180 void storePredicate(const std::string& oriPredName, int predArity, HexGrammarSemantics& mgr, ID& target) 00181 { 00182 std::string newPredName; 00183 // if ( mgr.mlpMode == 0 ) 00184 // { // ordinary encoding 00185 newPredName = oriPredName; 00186 // } 00187 // else 00188 // { // mlp encoding 00189 newPredName = mgr.ctx.registry()->moduleTable.getModuleName( mgr.ctx.registry()->moduleTable.getSize()-1 ) + MODULEPREFIXSEPARATOR + oriPredName; 00190 // } 00191 00192 target = mgr.ctx.registry()->preds.getIDByString(newPredName); 00193 if( target == ID_FAIL ) { 00194 Predicate predicate(ID::MAINKIND_TERM | ID::SUBKIND_TERM_PREDICATE, newPredName, predArity); 00195 target = mgr.ctx.registry()->preds.storeAndGetID(predicate); 00196 DBGLOG(DBG, "Preds stored: " << predicate << " got id: " << target); 00197 } 00198 else { 00199 DBGLOG(DBG, "Preds previously stored: " << newPredName << "/" << predArity << " got id: " << target); 00200 } 00201 } 00202 00203 00204 template<> 00205 struct sem<HexGrammarSemantics::predFromPredDecl> 00206 { 00207 void operator()( 00208 HexGrammarSemantics& mgr, 00209 const boost::fusion::vector2<const std::string&, unsigned int>& source, 00210 ID& target) { 00211 00212 const std::string& oriPredName = boost::fusion::at_c<0>(source); 00213 assert(!oriPredName.empty() && islower(oriPredName[0])); 00214 00215 unsigned int predArity = boost::fusion::at_c<1>(source); 00216 00217 std::string newPredName; 00218 newPredName = mgr.currentModuleName + MODULEPREFIXSEPARATOR + oriPredName; 00219 00220 target = mgr.ctx.registry()->preds.getIDByString(newPredName); 00221 if( target == ID_FAIL ) { 00222 Predicate predicate(ID::MAINKIND_TERM | ID::SUBKIND_TERM_PREDICATE, newPredName, predArity); 00223 target = mgr.ctx.registry()->preds.storeAndGetID(predicate); 00224 DBGLOG(DBG, "Preds stored: " << predicate << " got id: " << target); 00225 } 00226 else { 00227 DBGLOG(DBG, "Preds previously stored: " << newPredName << "/" << predArity << " got id: " << target); 00228 } 00229 00230 } 00231 }; 00232 00233 template<> 00234 struct sem<HexGrammarSemantics::predFromNameOnly> 00235 { 00236 void operator()( 00237 HexGrammarSemantics& mgr, 00238 const std::string& source, 00239 ID& target) { 00240 00241 assert(!source.empty() && islower(source[0])); 00242 if (mgr.mlpMode == 1) { 00243 // mlp encoding 00244 int predArity = -1; 00245 storePredicate(source, predArity, mgr, target); 00246 } 00247 else { 00248 // ordinary encoding 00249 target = mgr.ctx.registry()->terms.getIDByString(source); 00250 if( target == ID_FAIL ) { 00251 Term term(ID::MAINKIND_TERM | ID::SUBKIND_TERM_CONSTANT, source); 00252 target = mgr.ctx.registry()->terms.storeAndGetID(term); 00253 } 00254 } 00255 00256 } 00257 }; 00258 00259 template<> 00260 struct sem<HexGrammarSemantics::predFromString> 00261 { 00262 void operator()( 00263 HexGrammarSemantics& mgr, 00264 const std::string& source, 00265 ID& target) { 00266 00267 assert(!source.empty() && source[0] == '"' && source[source.size()-1] == '"'); 00268 00269 if (mgr.mlpMode == 1) { 00270 // mlp encoding 00271 const std::string& oriPredName = source; 00272 int predArity = -1; 00273 storePredicate(oriPredName, predArity, mgr, target); 00274 } 00275 else { 00276 // ordinary encoding 00277 target = mgr.ctx.registry()->terms.getIDByString(source); 00278 if( target == ID_FAIL ) { 00279 Term term(ID::MAINKIND_TERM | ID::SUBKIND_TERM_CONSTANT, source); 00280 target = mgr.ctx.registry()->terms.storeAndGetID(term); 00281 } 00282 } 00283 00284 } 00285 }; 00286 00287 template<> 00288 struct sem<HexGrammarSemantics::classicalAtomFromPrefix> 00289 { 00290 void createAtom(RegistryPtr reg, OrdinaryAtom& atom, ID& target) { 00291 // groundness 00292 DBGLOG(DBG,"checking groundness of tuple " << printrange(atom.tuple)); 00293 IDKind kind = 0; 00294 std::set<ID> var; 00295 BOOST_FOREACH(const ID& id, atom.tuple) { 00296 reg->getVariablesInID(id, var); 00297 kind |= id.kind; 00298 // make this sure to make the groundness check work 00299 // (if we add "builtin constant terms" like #supremum we might have to change the above statement) 00300 assert((id.kind & ID::SUBKIND_MASK) != ID::SUBKIND_TERM_BUILTIN); 00301 } 00302 const bool ground = !(kind & ID::SUBKIND_TERM_VARIABLE) && var.size() == 0; 00303 if( ground ) { 00304 atom.kind |= ID::SUBKIND_ATOM_ORDINARYG; 00305 target = reg->storeOrdinaryGAtom(atom); 00306 } 00307 else { 00308 atom.kind |= ID::SUBKIND_ATOM_ORDINARYN; 00309 target = reg->storeOrdinaryNAtom(atom); 00310 } 00311 DBGLOG(DBG,"stored atom " << atom << " which got id " << target); 00312 } 00313 00314 void operator()( 00315 HexGrammarSemantics& mgr, 00316 const boost::fusion::vector2<ID, boost::optional<boost::optional<std::vector<ID> > > >& source, 00317 ID& target) { 00318 RegistryPtr reg = mgr.ctx.registry(); 00319 OrdinaryAtom atom(ID::MAINKIND_ATOM); 00320 00321 // predicate 00322 const ID& idpred = boost::fusion::at_c<0>(source); 00323 atom.tuple.push_back(idpred); 00324 00325 // arguments 00326 if( (!!boost::fusion::at_c<1>(source)) && 00327 (!!(boost::fusion::at_c<1>(source).get())) ) { 00328 const Tuple& tuple = boost::fusion::at_c<1>(source).get().get(); 00329 atom.tuple.insert(atom.tuple.end(), tuple.begin(), tuple.end()); 00330 if ( mgr.mlpMode==1 ) mgr.ctx.registry()->preds.setArity(idpred, tuple.size()); 00331 } 00332 else { 00333 if ( mgr.mlpMode==1 ) mgr.ctx.registry()->preds.setArity(idpred, 0); 00334 } 00335 00336 createAtom(reg, atom, target); 00337 } 00338 }; 00339 00340 template<> 00341 struct sem<HexGrammarSemantics::classicalAtomFromTuple>: 00342 private sem<HexGrammarSemantics::classicalAtomFromPrefix> 00343 { 00344 void operator()( 00345 HexGrammarSemantics& mgr, 00346 const boost::fusion::vector2<ID, std::vector<ID> >& source, 00347 ID& target) { 00348 RegistryPtr reg = mgr.ctx.registry(); 00349 OrdinaryAtom atom(ID::MAINKIND_ATOM); 00350 00351 // predicate 00352 atom.tuple.push_back(boost::fusion::at_c<0>(source)); 00353 // arguments 00354 const Tuple& tuple = boost::fusion::at_c<1>(source); 00355 atom.tuple.insert(atom.tuple.end(), tuple.begin(), tuple.end()); 00356 00357 createAtom(reg, atom, target); 00358 } 00359 }; 00360 00361 template<> 00362 struct sem<HexGrammarSemantics::builtinTernaryInfix> 00363 { 00364 void operator()( 00365 HexGrammarSemantics& mgr, 00366 const boost::fusion::vector4< 00367 ID, ID, ID, ID 00368 >& source, 00369 ID& target) { 00370 BuiltinAtom atom(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_BUILTIN); 00371 atom.tuple.push_back(boost::fusion::at_c<2>(source)); 00372 atom.tuple.push_back(boost::fusion::at_c<1>(source)); 00373 atom.tuple.push_back(boost::fusion::at_c<3>(source)); 00374 atom.tuple.push_back(boost::fusion::at_c<0>(source)); 00375 00376 DBGLOG(DBG,"storing builtin atom " << atom); 00377 target = mgr.ctx.registry()->batoms.storeAndGetID(atom); 00378 DBGLOG(DBG,"builtin atom " << atom << " got id " << target); 00379 } 00380 }; 00381 00382 template<> 00383 struct sem<HexGrammarSemantics::builtinBinaryInfix> 00384 { 00385 void operator()( 00386 HexGrammarSemantics& mgr, 00387 const boost::fusion::vector3< 00388 ID, ID, ID 00389 >& source, 00390 ID& target) { 00391 BuiltinAtom atom(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_BUILTIN); 00392 atom.tuple.push_back(boost::fusion::at_c<1>(source)); 00393 atom.tuple.push_back(boost::fusion::at_c<0>(source)); 00394 atom.tuple.push_back(boost::fusion::at_c<2>(source)); 00395 00396 DBGLOG(DBG,"storing builtin atom " << atom); 00397 target = mgr.ctx.registry()->batoms.storeAndGetID(atom); 00398 DBGLOG(DBG,"builtin atom " << atom << " got id " << target); 00399 } 00400 }; 00401 00402 template<> 00403 struct sem<HexGrammarSemantics::builtinUnaryPrefix> 00404 { 00405 void operator()( 00406 HexGrammarSemantics& mgr, 00407 const boost::fusion::vector2< 00408 ID, ID 00409 >& source, 00410 ID& target) { 00411 BuiltinAtom atom(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_BUILTIN); 00412 atom.tuple.push_back(boost::fusion::at_c<0>(source)); 00413 atom.tuple.push_back(boost::fusion::at_c<1>(source)); 00414 00415 DBGLOG(DBG,"storing builtin atom " << atom); 00416 target = mgr.ctx.registry()->batoms.storeAndGetID(atom); 00417 DBGLOG(DBG,"builtin atom " << atom << " got id " << target); 00418 } 00419 }; 00420 00421 template<> 00422 struct sem<HexGrammarSemantics::builtinBinaryPrefix> 00423 { 00424 void operator()( 00425 HexGrammarSemantics& mgr, 00426 const boost::fusion::vector3< 00427 ID, ID, ID 00428 >& source, 00429 ID& target) { 00430 BuiltinAtom atom(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_BUILTIN); 00431 atom.tuple.push_back(boost::fusion::at_c<0>(source)); 00432 atom.tuple.push_back(boost::fusion::at_c<1>(source)); 00433 atom.tuple.push_back(boost::fusion::at_c<2>(source)); 00434 00435 DBGLOG(DBG,"storing builtin atom " << atom); 00436 target = mgr.ctx.registry()->batoms.storeAndGetID(atom); 00437 DBGLOG(DBG,"builtin atom " << atom << " got id " << target); 00438 } 00439 }; 00440 00441 template<> 00442 struct sem<HexGrammarSemantics::builtinTernaryPrefix> 00443 { 00444 void operator()( 00445 HexGrammarSemantics& mgr, 00446 const boost::fusion::vector4< 00447 ID, ID, ID, ID 00448 >& source, 00449 ID& target) { 00450 BuiltinAtom atom(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_BUILTIN); 00451 atom.tuple.push_back(boost::fusion::at_c<0>(source)); 00452 atom.tuple.push_back(boost::fusion::at_c<1>(source)); 00453 atom.tuple.push_back(boost::fusion::at_c<2>(source)); 00454 atom.tuple.push_back(boost::fusion::at_c<3>(source)); 00455 00456 DBGLOG(DBG,"storing builtin atom " << atom); 00457 target = mgr.ctx.registry()->batoms.storeAndGetID(atom); 00458 DBGLOG(DBG,"builtin atom " << atom << " got id " << target); 00459 } 00460 }; 00461 00462 template<> 00463 struct sem<HexGrammarSemantics::aggregateAtom> 00464 { 00465 void operator()( 00466 HexGrammarSemantics& mgr, 00467 const boost::fusion::vector3< 00468 // left term and left comparison operator 00469 boost::optional<boost::fusion::vector2<ID, ID> >, 00470 boost::fusion::vector2<ID,// aggregate function 00471 std::vector< // set of symbolic sets 00472 // variables and literals of the current symbolic set 00473 boost::fusion::vector2<std::vector<ID>, boost::optional<std::vector<ID> > > 00474 > 00475 >, 00476 // right comparison operator and right term 00477 boost::optional<boost::fusion::vector2<ID, ID> > 00478 >& source, 00479 ID& target) { 00480 AggregateAtom aatom(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_AGGREGATE); 00481 ID& leftTerm = aatom.tuple[0]; 00482 ID& leftComp = aatom.tuple[1]; 00483 ID& aggFunc = aatom.tuple[2]; 00484 ID& rightComp = aatom.tuple[3]; 00485 ID& rightTerm = aatom.tuple[4]; 00486 00487 // left term + operator 00488 if( !!boost::fusion::at_c<0>(source) ) { 00489 leftTerm = boost::fusion::at_c<0>( 00490 boost::fusion::at_c<0>(source).get()); 00491 leftComp = boost::fusion::at_c<1>( 00492 boost::fusion::at_c<0>(source).get()); 00493 } 00494 00495 // right term + operator 00496 if( !!boost::fusion::at_c<2>(source) ) { 00497 rightComp = boost::fusion::at_c<0>( 00498 boost::fusion::at_c<2>(source).get()); 00499 rightTerm = boost::fusion::at_c<1>( 00500 boost::fusion::at_c<2>(source).get()); 00501 } 00502 00503 WARNING("TODO throw iterator in syntax error and display it nicely (like expectation failure)") 00504 if( leftTerm == ID_FAIL && rightTerm == ID_FAIL ) 00505 throw SyntaxError("aggregate needs at least one term + comparison operator"); 00506 00507 // aggregation 00508 aggFunc = boost::fusion::at_c<0>(boost::fusion::at_c<1>(source)); 00509 00510 // symbolic set 00511 const std::vector<boost::fusion::vector2<std::vector<ID>, boost::optional<std::vector<ID> > > >& symbolicSets = boost::fusion::at_c<1>(boost::fusion::at_c<1>(source)); 00512 for (int currentSymbolicSet = 0; currentSymbolicSet < symbolicSets.size(); ++currentSymbolicSet) { 00513 const boost::fusion::vector2<std::vector<ID>, boost::optional<std::vector<ID> > >& symbolicSet = symbolicSets[currentSymbolicSet]; 00514 Tuple aggVariables = boost::fusion::at_c<0>(symbolicSet); 00515 Tuple aggBody = (!!boost::fusion::at_c<1>(symbolicSet) ? boost::fusion::at_c<1>(symbolicSet).get() : Tuple()); 00516 if (symbolicSets.size() > 1) { 00517 aatom.mvariables.push_back(aggVariables); 00518 aatom.mliterals.push_back(aggBody); 00519 } 00520 else { 00521 aatom.variables = aggVariables; 00522 aatom.literals = aggBody; 00523 } 00524 } 00525 00526 DBGLOG(DBG,"storing aggregate atom " << aatom); 00527 target = mgr.ctx.registry()->aatoms.storeAndGetID(aatom); 00528 DBGLOG(DBG,"stored aggregate atom " << aatom << " which got id " << target); 00529 } 00530 }; 00531 00532 template<> 00533 struct sem<HexGrammarSemantics::externalAtom> 00534 { 00535 void operator()( 00536 HexGrammarSemantics& mgr, 00537 const boost::fusion::vector4< 00538 ID, 00539 boost::optional<boost::optional<std::vector<ID> > >, 00540 boost::optional<boost::optional<std::vector<ID> > >, 00541 boost::optional<boost::optional<std::vector<std::vector<std::string> > > > 00542 >& source, 00543 ID& target) { 00544 ExternalAtom atom(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_EXTERNAL); 00545 00546 // predicate 00547 atom.predicate = boost::fusion::at_c<0>(source); 00548 00549 // inputs 00550 if( (!!boost::fusion::at_c<1>(source)) && 00551 (!!(boost::fusion::at_c<1>(source).get())) ) { 00552 atom.inputs = boost::fusion::at_c<1>(source).get().get(); 00553 } 00554 00555 // outputs 00556 if( (!!boost::fusion::at_c<2>(source)) && 00557 (!!(boost::fusion::at_c<2>(source).get())) ) { 00558 atom.tuple = boost::fusion::at_c<2>(source).get().get(); 00559 } 00560 00561 // properties 00562 if( (!!boost::fusion::at_c<3>(source)) && 00563 (!!(boost::fusion::at_c<3>(source).get())) ) { 00564 atom.prop.interpretProperties(mgr.ctx.registry(), atom, boost::fusion::at_c<3>(source).get().get()); 00565 } 00566 00567 DBGLOG(DBG,"storing external atom " << atom); 00568 target = mgr.ctx.registry()->eatoms.storeAndGetID(atom); 00569 DBGLOG(DBG,"external atom " << atom << " got id " << target); 00570 } 00571 }; 00572 00573 template<> 00574 struct sem<HexGrammarSemantics::extSourceProperty> 00575 { 00576 void operator()( 00577 HexGrammarSemantics& mgr, 00578 const boost::fusion::vector2< 00579 std::string, 00580 boost::optional<boost::optional<std::vector<std::string> > > >& source, 00581 std::vector<std::string>& target) { 00582 target.push_back(boost::fusion::at_c<0>(source)); 00583 if( (!!boost::fusion::at_c<1>(source)) && 00584 (!!(boost::fusion::at_c<1>(source).get())) ) { 00585 target.insert(target.end(), boost::fusion::at_c<1>(source).get().get().begin(), boost::fusion::at_c<1>(source).get().get().end()); 00586 } 00587 } 00588 }; 00589 00590 template<> 00591 struct sem<HexGrammarSemantics::mlpModuleAtom> 00592 { 00593 void operator()( 00594 HexGrammarSemantics& mgr, 00595 const boost::fusion::vector3< 00596 ID, 00597 boost::optional<boost::optional<std::vector<ID> > >, 00598 ID 00599 >& source, 00600 ID& target) { 00601 ModuleAtom atom(ID::MAINKIND_ATOM | ID::SUBKIND_ATOM_MODULE); 00602 00603 // predicate 00604 atom.predicate = boost::fusion::at_c<0>(source); 00605 00606 // get actual module name 00607 const std::string& predName = mgr.ctx.registry()->preds.getByID(atom.predicate).symbol; 00608 int n = predName.find(MODULEPREFIXSEPARATOR); 00609 atom.actualModuleName = predName.substr(n+2, predName.length()); 00610 00611 // inputs 00612 if( (!!boost::fusion::at_c<1>(source)) && 00613 (!!(boost::fusion::at_c<1>(source).get())) ) { 00614 atom.inputs = boost::fusion::at_c<1>(source).get().get(); 00615 } 00616 00617 // output 00618 atom.outputAtom = boost::fusion::at_c<2>(source); 00619 00620 ID atomNewID = mgr.ctx.registry()->matoms.getIDByElement(atom.predicate, atom.inputs, atom.outputAtom); 00621 if ( atomNewID == ID_FAIL ) { 00622 DBGLOG(DBG,"storing mlp Module atom " << atom); 00623 target = mgr.ctx.registry()->matoms.storeAndGetID(atom); 00624 DBGLOG(DBG,"mlp Module atom " << atom << " got id " << target); 00625 } 00626 else { 00627 DBGLOG(DBG,"previously stored mlp Module atom " << atom); 00628 target = atomNewID; 00629 DBGLOG(DBG,"mlp Module atom " << atom << " got (old) id " << target); 00630 } 00631 } 00632 }; 00633 00634 template<> 00635 struct sem<HexGrammarSemantics::bodyLiteral> 00636 { 00637 void operator()( 00638 HexGrammarSemantics& mgr, 00639 const boost::fusion::vector2< 00640 boost::optional<std::string>, 00641 dlvhex::ID 00642 >& source, 00643 ID& target) { 00644 bool isNaf = !!boost::fusion::at_c<0>(source); 00645 assert(boost::fusion::at_c<1>(source).isAtom()); 00646 target = ID::literalFromAtom(boost::fusion::at_c<1>(source), isNaf); 00647 } 00648 }; 00649 00650 template<> 00651 struct sem<HexGrammarSemantics::rule> 00652 { 00653 void operator()( 00654 HexGrammarSemantics& mgr, 00655 const boost::fusion::vector2< 00656 std::vector<dlvhex::ID>, 00657 boost::optional<std::vector<dlvhex::ID> > 00658 >& source, 00659 ID& target) { 00660 RegistryPtr reg = mgr.ctx.registry(); 00661 const Tuple& head = boost::fusion::at_c<0>(source); 00662 bool hasBody = !!boost::fusion::at_c<1>(source); 00663 00664 if( hasBody ) { 00665 // rule -> put into IDB 00666 const Tuple& body = boost::fusion::at_c<1>(source).get(); 00667 00668 Rule r(ID::MAINKIND_RULE | ID::SUBKIND_RULE_REGULAR, head, body); 00669 mgr.markExternalPropertyIfExternalBody(reg, r); 00670 mgr.markModulePropertyIfModuleBody(reg, r); 00671 // mark as disjunctive if required 00672 if( r.head.size() > 1 ) 00673 r.kind |= ID::PROPERTY_RULE_DISJ; 00674 target = reg->storeRule(r); 00675 } 00676 else { 00677 if( head.size() > 1 ) { 00678 // disjunctive fact -> create rule 00679 Rule r(ID::MAINKIND_RULE | ID::SUBKIND_RULE_REGULAR | ID::PROPERTY_RULE_DISJ, 00680 head, Tuple()); 00681 mgr.markExternalPropertyIfExternalBody(reg, r); 00682 mgr.markModulePropertyIfModuleBody(reg, r); 00683 target = reg->storeRule(r); 00684 } 00685 else { 00686 assert(head.size() == 1); 00687 00688 // if the only head atom uses a range, make a disjunction to force the reasoner to handle it as a rule 00689 const OrdinaryAtom& oatom = mgr.ctx.registry()->lookupOrdinaryAtom(head[0]); 00690 BOOST_FOREACH (ID arg, oatom.tuple) { 00691 if (arg.isRangeTerm()) { 00692 Tuple dhead; 00693 dhead.push_back(head[0]); 00694 dhead.push_back(head[0]); 00695 Rule r(ID::MAINKIND_RULE | ID::SUBKIND_RULE_REGULAR | ID::PROPERTY_RULE_DISJ, dhead, Tuple()); 00696 target = reg->storeRule(r); 00697 return; 00698 } 00699 } 00700 00701 // return ID of fact 00702 target = *head.begin(); 00703 } 00704 } 00705 } 00706 }; 00707 00708 template<> 00709 struct sem<HexGrammarSemantics::ruleVariableDisjunction> 00710 { 00711 void operator()( 00712 HexGrammarSemantics& mgr, 00713 const boost::fusion::vector3< 00714 dlvhex::ID, 00715 std::vector<dlvhex::ID>, 00716 boost::optional<std::vector<dlvhex::ID> > 00717 >& source, 00718 ID& target) { 00719 RegistryPtr reg = mgr.ctx.registry(); 00720 Tuple head; 00721 head.push_back(boost::fusion::at_c<0>(source)); 00722 const Tuple& headGuard = boost::fusion::at_c<1>(source); 00723 bool hasBody = !!boost::fusion::at_c<2>(source); 00724 00725 if( hasBody ) { 00726 // rule -> put into IDB 00727 Tuple body = boost::fusion::at_c<2>(source).get(); 00728 // body.insert(body.end(), headGuard.begin(), headGuard.end()); 00729 00730 Rule r(ID::MAINKIND_RULE | ID::SUBKIND_RULE_REGULAR, head, body, headGuard); 00731 if (r.headGuard.size() > 0) r.kind |= ID::PROPERTY_RULE_HEADGUARD; 00732 mgr.markExternalPropertyIfExternalBody(reg, r); 00733 mgr.markModulePropertyIfModuleBody(reg, r); 00734 // mark as disjunctive if required 00735 if( r.head.size() > 1 ) 00736 r.kind |= ID::PROPERTY_RULE_DISJ; 00737 target = reg->storeRule(r); 00738 } 00739 else { 00740 // in order to process the head guard we need to create a rule 00741 Tuple body; 00742 // body.insert(body.end(), headGuard.begin(), headGuard.end()); 00743 Rule r(ID::MAINKIND_RULE | ID::SUBKIND_RULE_REGULAR | ID::PROPERTY_RULE_DISJ, 00744 head, body, headGuard); 00745 if (r.headGuard.size() > 0) r.kind |= ID::PROPERTY_RULE_HEADGUARD; 00746 mgr.markExternalPropertyIfExternalBody(reg, r); 00747 mgr.markModulePropertyIfModuleBody(reg, r); 00748 target = reg->storeRule(r); 00749 } 00750 } 00751 }; 00752 00753 template<> 00754 struct sem<HexGrammarSemantics::constraint> 00755 { 00756 void operator()( 00757 HexGrammarSemantics& mgr, 00758 const std::vector<dlvhex::ID>& source, 00759 ID& target) { 00760 Rule r(ID::MAINKIND_RULE | ID::SUBKIND_RULE_CONSTRAINT); 00761 r.body = source; 00762 mgr.markExternalPropertyIfExternalBody(mgr.ctx.registry(), r); 00763 mgr.markModulePropertyIfModuleBody(mgr.ctx.registry(), r); 00764 ID existing = mgr.ctx.registry()->rules.getIDByElement(r); 00765 if( existing == ID_FAIL ) { 00766 target = mgr.ctx.registry()->storeRule(r); 00767 DBGLOG(DBG,"created constraint " << r << " with id " << target); 00768 } 00769 else 00770 target = existing; // ID_FAIL; 00771 } 00772 }; 00773 00774 template<> 00775 struct sem<HexGrammarSemantics::weakconstraint> 00776 { 00777 void operator()( 00778 HexGrammarSemantics& mgr, 00779 const boost::fusion::vector2< 00780 const std::vector<dlvhex::ID>&, 00781 const boost::optional<boost::fusion::vector2<ID, ID> >& >& source, 00782 ID& target) { 00783 Rule r(ID::MAINKIND_RULE | ID::SUBKIND_RULE_WEAKCONSTRAINT); 00784 r.body = boost::fusion::at_c<0>(source); 00785 r.weakconstraintVector.push_back(ID_FAIL); // DLV-style 00786 if (!!boost::fusion::at_c<1>(source)) { 00787 r.weight = boost::fusion::at_c<0>(boost::fusion::at_c<1>(source).get()); 00788 r.level = boost::fusion::at_c<1>(boost::fusion::at_c<1>(source).get()); 00789 } 00790 else { 00791 r.weight = ID::termFromInteger(1); 00792 r.level = ID::termFromInteger(1); 00793 } 00794 mgr.markExternalPropertyIfExternalBody(mgr.ctx.registry(), r); 00795 mgr.markModulePropertyIfModuleBody(mgr.ctx.registry(), r); 00796 ID existing = mgr.ctx.registry()->rules.getIDByElement(r); 00797 if( existing == ID_FAIL ) { 00798 target = mgr.ctx.registry()->storeRule(r); 00799 DBGLOG(DBG,"created weak constraint " << r << " with id " << target); 00800 } 00801 else 00802 target = existing; // ID_FAIL; 00803 } 00804 }; 00805 00806 template<> 00807 struct sem<HexGrammarSemantics::weakconstraintaspcore2> 00808 { 00809 void operator()( 00810 HexGrammarSemantics& mgr, 00811 const boost::fusion::vector4< 00812 const std::vector<dlvhex::ID>&, 00813 const ID&, 00814 const boost::optional<ID>&, 00815 const boost::optional<std::vector<ID> > >& source, 00816 ID& target) { 00817 00818 Rule r(ID::MAINKIND_RULE | ID::SUBKIND_RULE_WEAKCONSTRAINT); 00819 r.body = boost::fusion::at_c<0>(source); 00820 r.weight = boost::fusion::at_c<1>(source); 00821 if (!!boost::fusion::at_c<2>(source)){ 00822 r.level = boost::fusion::at_c<2>(source).get(); 00823 }else{ 00824 r.level = ID::termFromInteger(1); 00825 } 00826 00827 // ASP-Core-2-style 00828 if (!!boost::fusion::at_c<3>(source)) { 00829 r.weakconstraintVector = boost::fusion::at_c<3>(source).get(); 00830 } 00831 00832 mgr.markExternalPropertyIfExternalBody(mgr.ctx.registry(), r); 00833 mgr.markModulePropertyIfModuleBody(mgr.ctx.registry(), r); 00834 ID existing = mgr.ctx.registry()->rules.getIDByElement(r); 00835 if( existing == ID_FAIL ) { 00836 target = mgr.ctx.registry()->storeRule(r); 00837 DBGLOG(DBG,"created weak constraint " << r << " with id " << target); 00838 } 00839 else 00840 target = existing; // ID_FAIL; 00841 } 00842 }; 00843 00844 template<> 00845 struct sem<HexGrammarSemantics::addMLPModuleName> 00846 { 00847 void operator()( 00848 HexGrammarSemantics& mgr, 00849 const std::string& source, 00850 std::string& target) { 00851 mgr.mlpMode = 1; 00852 mgr.currentModuleName = source; 00853 target = source; 00854 } 00855 }; 00856 00857 template<> 00858 struct sem<HexGrammarSemantics::addMLPModuleHeader> 00859 { 00860 void operator()( 00861 HexGrammarSemantics& mgr, 00862 const boost::fusion::vector2< 00863 const std::string&, 00864 boost::optional<boost::optional<std::vector<ID> > > 00865 >& source, 00866 const boost::spirit::unused_type& target) { 00867 // take care module name 00868 // const std::string& mlpModuleName = boost::fusion::at_c<0>(source); 00869 const std::string& mlpModuleName = mgr.currentModuleName; 00870 Module module(mlpModuleName, mgr.ctx.registry()->inputList.size(), mgr.ctx.edbList.size(), mgr.ctx.idbList.size()); 00871 mgr.ctx.registry()->moduleTable.storeAndGetAddress(module); 00872 00873 // get and insert input list 00874 // resize +1 to handle if the input list is empty (because it's optional) 00875 mgr.ctx.registry()->inputList.resize(mgr.ctx.registry()->inputList.size()+1); 00876 // formal input predicates 00877 if( (!!boost::fusion::at_c<1>(source)) && 00878 (!!(boost::fusion::at_c<1>(source).get())) ) { 00879 mgr.ctx.registry()->inputList.back() = boost::fusion::at_c<1>(source).get().get(); 00880 } 00881 00882 // extend edbList, idbList for the mlp module body 00883 mgr.ctx.edbList.resize(mgr.ctx.edbList.size()+1); 00884 mgr.ctx.edbList.back().reset(new Interpretation(mgr.ctx.registry())); 00885 mgr.ctx.idbList.resize(mgr.ctx.idbList.size()+1); 00886 } 00887 }; 00888 00889 WARNING("look at spirit mailing list 'optimizing parsing of large input'") 00890 00891 template<> 00892 struct sem<HexGrammarSemantics::add> 00893 { 00894 void operator()( 00895 HexGrammarSemantics& mgr, 00896 const dlvhex::ID& source, 00897 const boost::spirit::unused_type& target) { 00898 RegistryPtr reg = mgr.ctx.registry(); 00899 assert(source != ID_FAIL); 00900 if( source.isAtom() ) { 00901 // fact -> put into EDB 00902 if( !source.isOrdinaryGroundAtom() ) 00903 throw SyntaxError( 00904 "fact '"+reg->onatoms.getByID(source).text+"' not safe!"); 00905 00906 if ( mgr.mlpMode == 0 ) { 00907 // ordinary encoding 00908 mgr.ctx.edb->setFact(source.address); 00909 } 00910 else { 00911 // mlp encoding 00912 mgr.ctx.edbList.back()->setFact(source.address); 00913 } 00914 DBGLOG(DBG,"added fact with id " << source << " to edb"); 00915 } 00916 else if( source.isRule() ) { 00917 if ( mgr.mlpMode == 0 ) { 00918 // ordinary encoding 00919 mgr.ctx.idb.push_back(source); 00920 } 00921 else { 00922 // mlp encoding 00923 mgr.ctx.idbList.back().push_back(source); 00924 } 00925 DBGLOG(DBG,"added rule with id " << source << " to idb"); 00926 } 00927 else { 00928 // something bad happened if we get no rule and no atom here 00929 assert(false); 00930 } 00931 } 00932 }; 00933 00934 template<> 00935 struct sem<HexGrammarSemantics::ignoreAndWarnIfNotFail> 00936 { 00937 void operator()( 00938 HexGrammarSemantics&, // mgr, 00939 const dlvhex::ID& source, 00940 // target) 00941 const boost::spirit::unused_type&) { 00942 if( source != ID_FAIL ) { 00943 LOG(WARNING,"ignoring ID " << source); 00944 } 00945 } 00946 }; 00947 00948 template<> 00949 struct sem<HexGrammarSemantics::maxint> 00950 { 00951 void operator()( 00952 HexGrammarSemantics& mgr, 00953 uint32_t source, 00954 // target) 00955 const boost::spirit::unused_type& ) { 00956 mgr.ctx.maxint = source; 00957 } 00958 }; 00959 00961 // HexGrammarBase /////////////////////////////////////////////// 00963 template<typename Iterator, typename Skipper> 00964 HexGrammarBase<Iterator, Skipper>:: 00965 HexGrammarBase(HexGrammarSemantics& sem): 00966 sem(sem) 00967 { 00968 namespace qi = boost::spirit::qi; 00969 namespace ascii = boost::spirit::ascii; 00970 typedef HexGrammarSemantics Sem; 00971 00972 cident 00973 = qi::lexeme[ ascii::lower >> *(ascii::alnum | qi::char_('_')) ]; 00974 string 00975 = qi::lexeme[ qi::char_('"') >> 00976 *( qi::string("\\\"") 00977 | qi::as_string[qi::char_ - (qi::char_('"') | qi::eol)] 00978 ) >> qi::char_('"') ]; 00979 variable 00980 = qi::string("_") // this can be qi::char_('_') in boost 1.44 ... boost 1.46 00981 | qi::lexeme[ ascii::upper >> *(ascii::alnum | qi::char_('_')) ]; 00982 posinteger 00983 = qi::ulong_; 00984 primitiveTerm 00985 = cident [ Sem::termFromCIdent(sem) ] 00986 | string [ Sem::termFromString(sem) ] 00987 | variable [ Sem::termFromVariable(sem) ] 00988 | posinteger [ Sem::termFromInteger(sem) ]; 00989 term 00990 = termExt [ Sem::termId(sem) ] // termId is a workaround: for some reason the value of the subexpression must be explicitly copied, otherwise term evaluates to ID_FAIL 00991 | ( cident >> qi::lit('(') >> -terms >> qi::lit(')') > qi::eps ) [ Sem::termFromFunctionTerm(sem) ] 00992 | (primitiveTerm >> qi::lit("..") >> primitiveTerm) [ Sem::termFromRange(sem) ] 00993 | primitiveTerm [ Sem::termId(sem) ]; 00994 00995 // allow backtracking over terms (no real need to undo the semantic actions == id registrations) 00996 terms 00997 = (term > qi::eps) % qi::lit(','); 00998 pred 00999 = cident [ Sem::predFromNameOnly(sem) ]; 01000 preds 01001 = (pred > qi::eps) % qi::lit(','); 01002 01003 // if we have this, we can easily extend this to higher order using a module 01004 classicalAtomPredicate 01005 = cident [ Sem::predFromNameOnly(sem) ] 01006 // module for higher order adds a variable here 01007 | string [ Sem::predFromString(sem) ]; 01008 01009 classicalAtom 01010 = ( 01011 classicalAtomPredicate >> -(qi::lit('(') > -terms >> qi::lit(')')) > qi::eps 01012 ) [ Sem::classicalAtomFromPrefix(sem) ] 01013 | ( 01014 qi::lit('(') > classicalAtomPredicate > qi::lit(',') > terms >> qi::lit(')') > qi::eps 01015 ) [ Sem::classicalAtomFromTuple(sem) ]; 01016 builtinOpsUnary.add 01017 ("#int", ID::termFromBuiltin(ID::TERM_BUILTIN_INT)); 01018 builtinOpsBinary.add 01019 ("=", ID::termFromBuiltin(ID::TERM_BUILTIN_EQ)) 01020 ("==", ID::termFromBuiltin(ID::TERM_BUILTIN_EQ)) 01021 ("!=", ID::termFromBuiltin(ID::TERM_BUILTIN_NE)) 01022 ("<>", ID::termFromBuiltin(ID::TERM_BUILTIN_NE)) 01023 ("<", ID::termFromBuiltin(ID::TERM_BUILTIN_LT)) 01024 ("<=", ID::termFromBuiltin(ID::TERM_BUILTIN_LE)) 01025 (">", ID::termFromBuiltin(ID::TERM_BUILTIN_GT)) 01026 (">=", ID::termFromBuiltin(ID::TERM_BUILTIN_GE)) 01027 ("#succ", ID::termFromBuiltin(ID::TERM_BUILTIN_SUCC)); 01028 builtinOpsTernary.add 01029 ("*", ID::termFromBuiltin(ID::TERM_BUILTIN_MUL)) 01030 ("+", ID::termFromBuiltin(ID::TERM_BUILTIN_ADD)) 01031 ("-", ID::termFromBuiltin(ID::TERM_BUILTIN_SUB)) 01032 ("/", ID::termFromBuiltin(ID::TERM_BUILTIN_DIV)) 01033 ("#mod", ID::termFromBuiltin(ID::TERM_BUILTIN_MOD)); 01034 builtinOpsAgg.add 01035 ("#count", ID::termFromBuiltin(ID::TERM_BUILTIN_AGGCOUNT)) 01036 ("#min", ID::termFromBuiltin(ID::TERM_BUILTIN_AGGMIN)) 01037 ("#max", ID::termFromBuiltin(ID::TERM_BUILTIN_AGGMAX)) 01038 ("#sum", ID::termFromBuiltin(ID::TERM_BUILTIN_AGGSUM)) 01039 ("#times", ID::termFromBuiltin(ID::TERM_BUILTIN_AGGTIMES)) 01040 ("#avg", ID::termFromBuiltin(ID::TERM_BUILTIN_AGGAVG)) 01041 ("#any", ID::termFromBuiltin(ID::TERM_BUILTIN_AGGANY)); 01042 builtinAtom 01043 = (term >> qi::lit('=') >> term >> builtinOpsTernary >> term > qi::eps) 01044 [ Sem::builtinTernaryInfix(sem) ] 01045 | (term >> builtinOpsBinary >> term > qi::eps) 01046 [ Sem::builtinBinaryInfix(sem) ] 01047 | (builtinOpsUnary >> qi::lit('(') > term > qi::lit(')')) 01048 [ Sem::builtinUnaryPrefix(sem) ] 01049 | (builtinOpsBinary >> qi::lit('(') > term > qi::lit(',') > term > qi::lit(')')) 01050 [ Sem::builtinBinaryPrefix(sem) ] 01051 | (builtinOpsTernary >> qi::lit('(') > term > qi::lit(',') > term > qi::lit(',') > term > qi::lit(')')) 01052 [ Sem::builtinTernaryPrefix(sem) ]; 01053 symbolicSet 01054 = (terms > -(qi::lit(':') > (bodyLiteral % (qi::char_(',') | qi::char_(';')))) > qi::eps); 01055 aggregateTerm 01056 = builtinOpsAgg > qi::lit('{') > (symbolicSet % qi::lit(';')) > qi::lit('}'); 01057 aggregateAtom 01058 // aggregate range or only left or only right part of it 01059 // (the semantics handler has to rule out that no binop exists) 01060 = ( 01061 -(term >> builtinOpsBinary) >> 01062 aggregateTerm >> 01063 -(builtinOpsBinary >> term) > qi::eps 01064 ) [ Sem::aggregateAtom(sem) ]; 01065 externalAtomPredicate 01066 = cident [ Sem::termFromCIdent(sem) ]; 01067 01068 externalAtom 01069 = ( 01070 qi::lit('&') > externalAtomPredicate > 01071 -(qi::lit('[') > -terms >> qi::lit(']')) > qi::eps > 01072 -(qi::lit('(') > -terms >> qi::lit(')')) > qi::eps > 01073 -(qi::lit('<') > -externalAtomProperties >> qi::lit('>')) > qi::eps 01074 ) [ Sem::externalAtom(sem) ]; 01075 01076 externalAtomPropertyString 01077 = qi::lexeme[ (ascii::alnum >> *(ascii::alnum) > qi::eps) ]; 01078 01079 externalAtomProperty 01080 = (externalAtomPropertyString > -(externalAtomPropertyString % qi::eps) > qi::eps) [ Sem::extSourceProperty(sem) ]; 01081 01082 externalAtomProperties 01083 = (externalAtomProperty > qi::eps) % qi::lit(','); 01084 01085 mlpModuleAtomPredicate 01086 = cident [ Sem::predFromNameOnly(sem) ]; 01087 01088 mlpModuleAtom 01089 = ( 01090 // for module predicate 01091 qi::lit('@') > mlpModuleAtomPredicate > 01092 // for input 01093 -(qi::lit('[') > -preds >> qi::lit(']')) > qi::eps > 01094 // for output 01095 qi::lit(':') > qi::lit(':') > classicalAtom > qi::eps 01096 ) [ Sem::mlpModuleAtom(sem) ]; 01097 01098 predDecl 01099 = (cident > qi::lit('/') > qi::ulong_)[ Sem::predFromPredDecl(sem) ]; 01100 01101 predList 01102 = (predDecl > qi::eps) % qi::lit(','); 01103 01104 mlpModuleName 01105 = cident [ Sem::addMLPModuleName(sem) ]; 01106 01107 mlpModuleHeader 01108 = ( qi::lit("#module") >>// #module 01109 // module name 01110 qi::lit('(') > mlpModuleName > 01111 // predicate list 01112 -( qi::lit(',') > qi::lit('[') > -predList >> qi::lit(']') ) > qi::eps > 01113 qi::lit(')') > qi::eps > qi::lit('.') > qi::eps 01114 ) [ Sem::addMLPModuleHeader(sem) ]; 01115 01116 bodyAtom 01117 = bodyAtomExt 01118 | classicalAtom 01119 | externalAtom 01120 | mlpModuleAtom 01121 | builtinAtom 01122 | aggregateAtom; 01123 01124 bodyLiteral 01125 = ( 01126 #if BOOST_VERSION >= 104600 01127 -qi::hold[ qi::lexeme[qi::string("not") >> qi::omit[ascii::space]] ] >> 01128 #else 01129 - qi::lexeme[qi::string("not") >> qi::omit[ascii::space]] >> 01130 #endif 01131 bodyAtom 01132 ) [ Sem::bodyLiteral(sem) ]; 01133 01134 headAtom 01135 = headAtomExt 01136 | classicalAtom; 01137 01138 rule 01139 = ( 01140 (headAtom % qi::no_skip[*ascii::space >> qi::char_('v') >> ascii::space]) >> 01141 -( 01142 qi::lit(":-") > 01143 (bodyLiteral % (qi::char_(',') | qi::char_(';'))) 01144 ) >> 01145 qi::lit('.') 01146 ) [ Sem::rule(sem) ] 01147 | ( 01148 headAtom >> qi::lit(':') >> (bodyLiteral % qi::char_(',')) >> 01149 -( 01150 qi::lit(":-") > 01151 (bodyLiteral % (qi::char_(',') | qi::char_(';'))) 01152 ) >> 01153 qi::lit('.') 01154 ) [ Sem::ruleVariableDisjunction(sem) ]; 01155 constraint 01156 = ( 01157 qi::lit(":-") >> 01158 (bodyLiteral % (qi::char_(',') | qi::char_(';'))) >> 01159 qi::lit('.') 01160 ) [ Sem::constraint(sem) ]; 01161 weakconstraint 01162 = ( 01163 qi::lit(":~") >> 01164 (bodyLiteral % (qi::char_(',') | qi::char_(';'))) >> 01165 qi::lit('.') >> 01166 qi::lit("[") >> term >> -(qi::lit("@") >> term) >> -(qi::lit(',') >> (term % qi::char_(','))) >> qi::lit("]") 01167 ) [ Sem::weakconstraintaspcore2(sem) ] 01168 | ( 01169 qi::lit(":~") >> 01170 (bodyLiteral % (qi::char_(',') | qi::char_(';'))) >> 01171 qi::lit('.') >> 01172 -(qi::lit("[") >> term >> qi::lit(":") >> term >> qi::lit("]")) 01173 ) [ Sem::weakconstraint(sem) ]; 01174 toplevelBuiltin 01175 = (qi::lit("#maxint") > qi::lit('=') > qi::ulong_ >> qi::lit('.') > qi::eps) 01176 [ Sem::maxint(sem) ]; 01177 toplevel 01178 = (toplevelExt > qi::eps) 01179 [ Sem::ignoreAndWarnIfNotFail(sem) ] 01180 | (rule > qi::eps) 01181 [ Sem::add(sem) ] 01182 | (constraint > qi::eps) 01183 [ Sem::add(sem) ] 01184 | (weakconstraint > qi::eps) 01185 [ Sem::add(sem) ] 01186 | (mlpModuleHeader > qi::eps) 01187 | (toplevelBuiltin > qi::eps); 01188 // the root rule 01189 start 01190 = *(toplevel); 01191 01192 // TODO will weak constraints go into toplevelExt? 01193 // TODO namespaces go into toplevelExt 01194 toplevelExt 01195 = qi::eps(false); 01196 bodyAtomExt 01197 = qi::eps(false); 01198 // TODO action atoms go into HeadAtomExt 01199 headAtomExt 01200 = qi::eps(false); 01201 termExt 01202 = qi::eps(false); 01203 01204 #ifdef BOOST_SPIRIT_DEBUG 01205 BOOST_SPIRIT_DEBUG_NODE(start); 01206 BOOST_SPIRIT_DEBUG_NODE(toplevel); 01207 BOOST_SPIRIT_DEBUG_NODE(toplevelBuiltin); 01208 BOOST_SPIRIT_DEBUG_NODE(cident); 01209 BOOST_SPIRIT_DEBUG_NODE(string); 01210 BOOST_SPIRIT_DEBUG_NODE(variable); 01211 BOOST_SPIRIT_DEBUG_NODE(posinteger); 01212 BOOST_SPIRIT_DEBUG_NODE(term); 01213 BOOST_SPIRIT_DEBUG_NODE(primitiveTerm); 01214 BOOST_SPIRIT_DEBUG_NODE(externalAtom); 01215 BOOST_SPIRIT_DEBUG_NODE(externalAtomPredicate); 01216 BOOST_SPIRIT_DEBUG_NODE(externalAtomPropertyString); 01217 BOOST_SPIRIT_DEBUG_NODE(externalAtomProperty); 01218 BOOST_SPIRIT_DEBUG_NODE(externalAtomProperties); 01219 BOOST_SPIRIT_DEBUG_NODE(mlpModuleAtom); 01220 BOOST_SPIRIT_DEBUG_NODE(mlpModuleAtomPredicate); 01221 BOOST_SPIRIT_DEBUG_NODE(classicalAtomPredicate); 01222 BOOST_SPIRIT_DEBUG_NODE(classicalAtom); 01223 BOOST_SPIRIT_DEBUG_NODE(builtinAtom); 01224 BOOST_SPIRIT_DEBUG_NODE(symbolicSet); 01225 BOOST_SPIRIT_DEBUG_NODE(aggregateAtom); 01226 BOOST_SPIRIT_DEBUG_NODE(bodyAtom); 01227 BOOST_SPIRIT_DEBUG_NODE(bodyLiteral); 01228 BOOST_SPIRIT_DEBUG_NODE(headAtom); 01229 BOOST_SPIRIT_DEBUG_NODE(rule); 01230 BOOST_SPIRIT_DEBUG_NODE(constraint); 01231 BOOST_SPIRIT_DEBUG_NODE(weakconstraint); 01232 BOOST_SPIRIT_DEBUG_NODE(terms); 01233 BOOST_SPIRIT_DEBUG_NODE(aggregateTerm); 01234 BOOST_SPIRIT_DEBUG_NODE(toplevelExt); 01235 BOOST_SPIRIT_DEBUG_NODE(bodyAtomExt); 01236 BOOST_SPIRIT_DEBUG_NODE(headAtomExt); 01237 BOOST_SPIRIT_DEBUG_NODE(termExt); 01238 #endif 01239 } 01240 01241 01242 WARNING("TODO more efficient than " rule = rule.copy() | *module " could be something else (see comments below)") 01243 // this could be a separate list for each type and a | b | c | d alternatives (have to be coded for each number of arguments) 01244 // this could be something not yet existing, see spirit-general mailinglist Sat, Jul 9, 2011 Vol 62, Issue 6 01245 01248 template<typename Iterator, typename Skipper> 01249 void 01250 HexGrammarBase<Iterator, Skipper>:: 01251 registerToplevelModule( 01252 HexParserModuleGrammarPtr module) 01253 { 01254 // remember the pointer (own it) 01255 modules.push_back(module); 01256 toplevelExt = *module | toplevelExt.copy(); 01257 } 01258 01259 01262 template<typename Iterator, typename Skipper> 01263 void 01264 HexGrammarBase<Iterator, Skipper>:: 01265 registerBodyAtomModule( 01266 HexParserModuleGrammarPtr module) 01267 { 01268 // remember the pointer (own it) 01269 modules.push_back(module); 01270 bodyAtomExt = *module | bodyAtomExt.copy(); 01271 } 01272 01273 01276 template<typename Iterator, typename Skipper> 01277 void 01278 HexGrammarBase<Iterator, Skipper>:: 01279 registerHeadAtomModule( 01280 HexParserModuleGrammarPtr module) 01281 { 01282 // remember the pointer (own it) 01283 modules.push_back(module); 01284 headAtomExt = *module | headAtomExt.copy(); 01285 } 01286 01287 01290 template<typename Iterator, typename Skipper> 01291 void 01292 HexGrammarBase<Iterator, Skipper>:: 01293 registerTermModule( 01294 HexParserModuleGrammarPtr module) 01295 { 01296 // remember the pointer (own it) 01297 modules.push_back(module); 01298 termExt = *module | termExt.copy(); 01299 } 01300 01301 01302 DLVHEX_NAMESPACE_END 01303 #endif // DLVHEX_HEX_GRAMMAR_TCC_INCLUDED 01304 01305 01306 // vim:expandtab:ts=4:sw=4: 01307 // mode: C++ 01308 // End: