dlvhex  2.1.0
include/dlvhex2/HexGrammar.tcc
Go to the documentation of this file.
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: