dlvhex  2.5.0
include/dlvhex2/HexGrammar.tcc
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 
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: