4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief Parse non-inline non-template implementation */
31 #include <boost/iterator/transform_iterator.hpp>
32 #include <boost/spirit/iterator/file_iterator.hpp>
33 #include "../Utils/Exception.hh"
35 //#include "Parse.mpp"
37 ///////////////////////////////cc.p////////////////////////////////////////
45 struct ParseDispatcher
47 ParseCommandInfo * info_;
48 CommandParser::Callback cb_;
51 BindInfo( ParseDispatcher & d, ParseCommandInfo & info, CommandParser::Callback cb)
52 : dispatcher (d) { dispatcher.info_ = &info; dispatcher.cb_ = cb; }
53 ~BindInfo() { dispatcher.info_ = 0; dispatcher.cb_ = 0; }
55 ParseDispatcher & dispatcher;
58 void beginCommand(std::vector<Token> & command)
60 info_->command(command); }
65 void pushToken(Token const & token)
66 { info_->addToken(token); }
68 void builtin_cd(std::vector<Token> & path)
70 info_->builtin(ParseCommandInfo::BuiltinCD);
71 setBuiltinPathArg(path);
74 void builtin_ls(std::vector<Token> & path)
76 info_->builtin(ParseCommandInfo::BuiltinLS);
77 setBuiltinPathArg(path);
80 void pushDirectory(std::vector<Token> & path)
82 info_->builtin(ParseCommandInfo::BuiltinPUSHD);
83 setBuiltinPathArg(path);
88 info_->builtin(ParseCommandInfo::BuiltinPOPD);
93 info_->builtin(ParseCommandInfo::BuiltinEXIT);
96 void builtin_help(std::vector<Token> & path)
98 info_->builtin(ParseCommandInfo::BuiltinHELP);
99 setBuiltinPathArg(path);
102 void setBuiltinPathArg(std::vector<Token> & path)
104 pushToken(ArgumentGroupOpenToken());
105 for (std::vector<Token>::const_iterator i (path.begin());
106 i != path.end(); ++i)
108 pushToken(ArgumentGroupCloseToken());
116 ///////////////////////////////////////////////////////////////////////////
117 // senf::console::Token
119 prefix_ std::ostream & senf::console::operator<<(std::ostream & os, Token const & token)
121 static char const * tokenTypeName[] = {
125 "ArgumentGroupClose",
126 "DirectoryGroupOpen",
127 "DirectoryGroupClose",
133 // The real table is:
134 // static const int bitPosition[32] = {
135 // 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
136 // 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 };
137 // However, we have replaced all values > sizeof(tokenTypeName) with 0
138 static const int bitPosition[32] = {
139 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 4, 8,
140 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 6, 0, 5, 10, 9 };
141 os << tokenTypeName[ token.type()
142 ? bitPosition[((token.type() & -token.type()) * 0x077CB531UL) >> 27]+1
150 ///////////////////////////////////////////////////////////////////////////
151 // senf::console::ParseCommandInfo
153 prefix_ std::ostream & senf::console::operator<<(std::ostream & stream,
154 ParseCommandInfo const & info)
156 if (info.builtin() == ParseCommandInfo::NoBuiltin) {
157 ParseCommandInfo::TokensRange::const_iterator i (info.commandPath().begin());
158 ParseCommandInfo::TokensRange::const_iterator const i_end (info.commandPath().end());
161 stream << i->value();
162 if ( ++i != i_end ) stream << "/";
168 char const * builtins[] = { "", "cd", "ls", "pushd", "popd", "exit", "help" };
169 stream << "builtin-" << builtins[info.builtin()];
172 ParseCommandInfo::ArgumentsRange args (info.arguments());
173 for (ParseCommandInfo::argument_iterator i (args.begin()); i != args.end(); ++i) {
174 ParseCommandInfo::token_iterator j (i->begin());
176 if ( j != i->end() ) {
178 stream << "'" << j->value() << "'";
179 if ( ++j != i->end() ) stream << ' ';
189 ///////////////////////////////////////////////////////////////////////////
190 // senf::console::ParseCommandInfo::ArgumentIterator
192 prefix_ void senf::console::ParseCommandInfo::ArgumentIterator::setRange()
195 if (b_->is(Token::ArgumentGroupOpen)) {
199 if (e_->is(Token::ArgumentGroupOpen))
201 else if (e_->is(Token::ArgumentGroupClose)) {
212 prefix_ void senf::console::ParseCommandInfo::ArgumentIterator::decrement()
216 if (b_->is(Token::ArgumentGroupClose)) {
219 if (b_->is(Token::ArgumentGroupClose))
221 else if (b_->is(Token::ArgumentGroupOpen)) {
231 ///////////////////////////////////////////////////////////////////////////
232 // senf::console::CommandParser
236 struct senf::console::CommandParser::Impl
238 typedef detail::CommandGrammar<detail::ParseDispatcher> Grammar;
240 detail::ParseDispatcher dispatcher;
241 Grammar::Context context;
244 Impl() : dispatcher(), context(), grammar(dispatcher, context) {}
249 prefix_ senf::console::CommandParser::CommandParser()
253 prefix_ senf::console::CommandParser::~CommandParser()
256 prefix_ bool senf::console::CommandParser::parse(std::string command, Callback cb)
258 ParseCommandInfo info;
259 detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info, cb);
260 return boost::spirit::parse( command.begin(), command.end(),
261 impl().grammar.use_parser<Impl::Grammar::CommandParser>(),
262 impl().grammar.use_parser<Impl::Grammar::SkipParser>()
266 prefix_ bool senf::console::CommandParser::parseFile(std::string filename, Callback cb)
268 ParseCommandInfo info;
269 detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info, cb);
270 boost::spirit::file_iterator<> i (filename);
271 if (!i) throw SystemException(ENOENT SENF_EXC_DEBUGINFO);
272 boost::spirit::file_iterator<> const i_end (i.make_end());
274 return boost::spirit::parse( i, i_end,
275 impl().grammar.use_parser<Impl::Grammar::CommandParser>(),
276 impl().grammar.use_parser<Impl::Grammar::SkipParser>()
280 prefix_ bool senf::console::CommandParser::parseArguments(std::string arguments,
281 ParseCommandInfo & info)
283 detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info, 0);
284 return boost::spirit::parse( arguments.begin(), arguments.end(),
285 impl().grammar.use_parser<Impl::Grammar::ArgumentsParser>(),
286 impl().grammar.use_parser<Impl::Grammar::SkipParser>()
290 ///////////////////////////////cc.e////////////////////////////////////////
292 //#include "Parse.mpp"
298 // comment-column: 40
299 // c-file-style: "senf"
300 // indent-tabs-mode: nil
301 // ispell-local-dictionary: "american"
302 // compile-command: "scons -u test"