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