dlvhex
2.5.0
|
00001 /* dlvhex -- Answer-Set Programming with external interfaces. 00002 * Copyright (C) 2005-2007 Roman Schindlauer 00003 * Copyright (C) 2006-2015 Thomas Krennwallner 00004 * Copyright (C) 2009-2016 Peter Schüller 00005 * Copyright (C) 2011-2016 Christoph Redl 00006 * Copyright (C) 2015-2016 Tobias Kaminski 00007 * Copyright (C) 2015-2016 Antonius Weinzierl 00008 * 00009 * This file is part of dlvhex. 00010 * 00011 * dlvhex is free software; you can redistribute it and/or modify it 00012 * under the terms of the GNU Lesser General Public License as 00013 * published by the Free Software Foundation; either version 2.1 of 00014 * the License, or (at your option) any later version. 00015 * 00016 * dlvhex is distributed in the hope that it will be useful, but 00017 * WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with dlvhex; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00024 * 02110-1301 USA. 00025 */ 00026 00034 #ifdef HAVE_CONFIG_H 00035 #include "config.h" 00036 #endif // HAVE_CONFIG_H 00037 00038 #include "dlvhex2/HexParser.h" 00039 #include "dlvhex2/ProgramCtx.h" 00040 #include "dlvhex2/HexGrammar.h" 00041 #include "dlvhex2/HexParserModule.h" 00042 #include "dlvhex2/fwd.h" 00043 00044 #include <boost/spirit/include/qi_parse.hpp> 00045 00046 #include <boost/scope_exit.hpp> 00047 #include <fstream> 00048 00049 //#include <unistd.h> 00050 00051 DLVHEX_NAMESPACE_BEGIN 00052 00053 HexParser::~HexParser() 00054 { 00055 } 00056 00057 00058 void ModuleHexParser::registerModule(HexParserModulePtr module) 00059 { 00060 modules.push_back(module); 00061 } 00062 00063 00064 void ModuleHexParser::parse(InputProviderPtr in, ProgramCtx& ctx) 00065 { 00066 assert(!!in); 00067 assert(!!ctx.registry()); 00068 00069 if( ctx.edb == 0 ) { 00070 // create empty interpretation using this context's registry 00071 ctx.edb.reset(new Interpretation(ctx.registry())); 00072 DBGLOG(DBG, " reset edb "); 00073 } 00074 else { 00075 DBGLOG(DBG, " not reset edb "); 00076 } 00077 00078 // put whole input from stream into a string 00079 // (an alternative would be the boost::spirit::multi_pass iterator 00080 // but this can be done later when the parser is updated to Spirit V2) 00081 WARNING("TODO incrementally read and parse this stream") 00082 std::ostringstream buf; 00083 buf << in->getAsStream().rdbuf(); 00084 std::string input = buf.str(); 00085 00086 // create grammar 00087 HexGrammarSemantics semanticsMgr(ctx); 00088 HexGrammar<HexParserIterator, HexParserSkipper> grammar(semanticsMgr); 00089 00090 // configure grammar with modules 00091 BOOST_FOREACH(HexParserModulePtr module, modules) { 00092 switch(module->getType()) { 00093 case HexParserModule::TOPLEVEL: 00094 grammar.registerToplevelModule(module->createGrammarModule()); 00095 break; 00096 case HexParserModule::BODYATOM: 00097 grammar.registerBodyAtomModule(module->createGrammarModule()); 00098 break; 00099 case HexParserModule::HEADATOM: 00100 grammar.registerHeadAtomModule(module->createGrammarModule()); 00101 break; 00102 case HexParserModule::TERM: 00103 grammar.registerTermModule(module->createGrammarModule()); 00104 break; 00105 default: 00106 LOG(ERROR,"unknown parser module type " << module->getType() << "!"); 00107 assert(false); 00108 break; 00109 } 00110 } 00111 00112 // prepare iterators 00113 HexParserIterator it_begin = input.begin(); 00114 HexParserIterator it_end = input.end(); 00115 00116 // parse 00117 HexParserSkipper skipper; 00118 DBGLOG(DBG,"starting to parse"); 00119 bool success = false; 00120 try 00121 { 00122 success = boost::spirit::qi::phrase_parse( 00123 it_begin, it_end, grammar, skipper); 00124 DBGLOG(DBG,"parsing returned with success=" << success); 00125 } 00126 catch(const boost::spirit::qi::expectation_failure<HexParserIterator>& e) { 00127 LOG(ERROR,"parsing returned with failure: expected '" << e.what_ << "'"); 00128 it_begin = e.first; 00129 } 00130 if( !success || it_begin != it_end ) { 00131 if( it_begin != it_end ) 00132 LOG(ERROR,"iterators not the same!"); 00133 00134 HexParserIterator it_displaybegin = it_begin; 00135 HexParserIterator it_displayend = it_begin; 00136 unsigned usedLeft = 0; 00137 while( usedLeft++ < 50 && 00138 it_displaybegin != input.begin() && 00139 *it_displaybegin != '\n' ) 00140 it_displaybegin--; 00141 if( *it_displaybegin == '\n' ) { 00142 it_displaybegin++; 00143 usedLeft--; 00144 } 00145 unsigned limitRight = 50; 00146 while( limitRight-- > 0 && 00147 it_displayend != it_end && 00148 *it_displayend != '\n' ) 00149 it_displayend++; 00150 LOG(ERROR,"unparsed '" << std::string(it_displaybegin, it_displayend) << "'"); 00151 LOG(ERROR,"---------" << std::string(usedLeft, '-') << "^"); 00152 throw SyntaxError("Could not parse complete input!"); 00153 } 00154 00155 // workaround: making IDs in idb unique 00156 WARNING("we should probably also do this for MLP, at the same time we should probably generalize MLP better") 00157 WARNING("we should use std::set<ID> for IDB") 00158 std::set<ID> uniqueidb(ctx.idb.begin(), ctx.idb.end()); 00159 ctx.idb.clear(); 00160 ctx.idb.insert(ctx.idb.end(), uniqueidb.begin(), uniqueidb.end()); 00161 } 00162 00163 00164 DLVHEX_NAMESPACE_END 00165 00166 #if 0 00167 void 00168 HexParserDriver::parse(std::istream& is, 00169 Program& program, 00170 AtomSet& EDB) throw (SyntaxError) 00171 { 00172 // put whole input from stream into a string 00173 // (an alternative would be the boost::spirit::multi_pass iterator 00174 // but it was not possible to setup/simply did not compile) 00175 std::ostringstream buf; 00176 buf << is.rdbuf(); 00177 std::string input = buf.str(); 00178 00179 HexGrammar grammar; 00180 typedef HexGrammarPTToASTConverter Converter; 00181 00182 Converter::iterator_t it_begin(input.c_str(), input.c_str()+input.size()); 00183 Converter::iterator_t it_end; 00184 00185 // parse ast 00186 boost::spirit::tree_parse_info<Converter::iterator_t, Converter::factory_t> info = 00187 boost::spirit::pt_parse<Converter::factory_t>( 00188 it_begin, it_end, grammar, boost::spirit::space_p); 00189 00190 // successful parse? 00191 if( !info.full ) 00192 throw SyntaxError("Could not parse complete input!", 00193 info.stop.get_position().line, this->source); 00194 00195 // if this is not ok, there is some bug and the following code will be incomplete 00196 assert(info.trees.size() == 1); 00197 00198 // create dlvhex AST from spirit parser tree 00199 Converter converter; 00200 converter.convertPTToAST(*info.trees.begin(), program, EDB); 00201 } 00202 00203 00204 void 00205 HexParserDriver::parse(const std::string& file, 00206 Program &program, 00207 AtomSet& EDB) throw (SyntaxError) 00208 { 00209 this->source = file; 00210 00211 std::ifstream ifs; 00212 00213 ifs.open(this->source.c_str()); 00214 00215 if (!ifs.is_open()) { 00216 throw SyntaxError("File " + this->source + " not found"); 00217 } 00218 00219 parse(ifs, program, EDB); 00220 00221 ifs.close(); 00222 } 00223 #endif 00224 00225 00226 // vim:expandtab:ts=4:sw=4: 00227 // mode: C++ 00228 // End: