23 #include <boost/iterator/transform_iterator.hpp> 24 #include <senf/config.hh> 26 #include <boost/spirit/include/classic_file_iterator.hpp> 27 #include <boost/spirit/include/classic_position_iterator.hpp> 42 struct ParseDispatcher
44 ParseCommandInfo * info_;
47 BindInfo( ParseDispatcher & d, ParseCommandInfo & info)
48 : dispatcher (d) { dispatcher.info_ = &info; }
49 ~BindInfo() { dispatcher.info_ = 0; }
51 ParseDispatcher & dispatcher;
54 void beginCommand(std::vector<Token> & command)
56 info_->command(command); }
61 void pushToken(Token
const & token)
62 { info_->addToken(token); }
64 void builtin_cd(std::vector<Token> & path)
67 setBuiltinPathArg(path); }
69 void builtin_ls(std::vector<Token> & path)
72 setBuiltinPathArg(path); }
74 void builtin_ll(std::vector<Token> & path)
77 setBuiltinPathArg(path); }
79 void builtin_lr(std::vector<Token> & path)
82 setBuiltinPathArg(path); }
97 void builtin_help(std::vector<Token> & path)
100 setBuiltinPathArg(path); }
105 void setBuiltinPathArg(std::vector<Token> & path)
107 info_->command(path);
124 detail::FilePositionWithIndex
const & pos)
125 : type_(type), token_ (token), line_ (pos.line), column_ (pos.column), index_ (pos.index)
131 static char const * tokenTypeName[] = {
135 "ArgumentGroupClose",
136 "DirectoryGroupOpen",
137 "DirectoryGroupClose",
149 static const int bitPosition[32] = {
150 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 9,
151 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 7, 0, 6, 0, 10 };
153 os << tokenTypeName[ token.
type()
154 ? bitPosition[(((token.
type() & -token.
type()) * 0x077CB531UL) >> 27) & 31]
169 ParseCommandInfo::TokensRange::const_iterator i (info.
commandPath().begin());
170 ParseCommandInfo::TokensRange::const_iterator
const i_end (info.
commandPath().end());
173 stream << i->value();
174 if ( ++i != i_end ) stream <<
"/";
180 char const * builtins[] = { 0,
"cd",
"ls",
"lr",
"pushd",
"popd",
"exit",
"help" };
181 stream <<
"builtin-" << builtins[info.
builtin()];
188 if ( j != i->end() ) {
190 stream <<
"'" << j->value() <<
"'";
191 if ( ++j != i->end() ) stream <<
' ';
204 prefix_ void senf::console::ParseCommandInfo::ArgumentIterator::setRange()
224 prefix_ void senf::console::ParseCommandInfo::ArgumentIterator::decrement()
248 struct senf::console::CommandParser::Impl
250 typedef detail::CommandGrammar<detail::ParseDispatcher> Grammar;
252 detail::ParseDispatcher dispatcher;
253 Grammar::Context context;
256 Impl() : dispatcher(), context(), grammar(dispatcher, context) {}
263 template <
class Error>
264 void throwParserError(Error
const & err)
266 static char const * msg [] = {
"end of statement expected",
270 senf::console::detail::FilePositionWithIndex pos (err.where.get_position());
272 <<
"\nat " << pos.file <<
":" << pos.line <<
":" << pos.column;
282 class position_policy<senf::console::detail::FilePositionWithIndex>
283 :
public position_policy<file_position>
286 typedef position_policy<file_position> Base;
288 void next_line(senf::console::detail::FilePositionWithIndex & pos)
290 Base::next_line(pos);
294 void next_char(senf::console::detail::FilePositionWithIndex & pos)
296 Base::next_char(pos);
300 void tabulation(senf::console::detail::FilePositionWithIndex & pos)
302 Base::tabulation(pos);
319 template <
class Iterator>
320 prefix_ Iterator senf::console::CommandParser::parseLoop(Iterator npb, Iterator npe,
321 std::string
const & source,
Callback cb)
323 typedef detail::boost_spirit::position_iterator<
324 Iterator, detail::FilePositionWithIndex> PositionIterator;
325 PositionIterator b (npb, npe, source);
326 PositionIterator e (npe, npe, source);
328 detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info);
329 detail::boost_spirit::parse_info<PositionIterator> result;
333 b, e, * impl().grammar.use_parser<Impl::Grammar::SkipParser>());
340 impl().grammar.use_parser<Impl::Grammar::CommandParser>(),
341 impl().grammar.use_parser<Impl::Grammar::SkipParser>());
343 catch (detail::boost_spirit::parser_error<Impl::Grammar::Errors, PositionIterator> & ex) {
344 if (impl().grammar.incremental && ex.where == e)
347 throwParserError(ex);
350 SENF_ASSERT( result.hit,
"Internal parser failure (error handling broken?)" );
356 detail::FilePositionWithIndex pos (result.stop.get_position());
357 ex <<
"\nat " << pos.file <<
":" << pos.line <<
":" << pos.column;
366 parseLoop(command.begin(), command.end(),
"<unknown>", cb);
374 if (stat( filename.c_str(), &statBuf) != 0)
376 if (statBuf.st_size == 0)
return;
377 detail::boost_spirit::file_iterator<> i (filename);
386 detail::boost_spirit::file_iterator<>
const i_end (i.make_end());
387 parseLoop(i, i_end, filename, cb);
393 typedef detail::boost_spirit::position_iterator<
394 std::string::const_iterator, detail::FilePositionWithIndex> PositionIterator;
395 PositionIterator b (arguments.begin(), arguments.end(), std::string(
"<unknown>"));
396 PositionIterator e (arguments.end(), arguments.end(), std::string(
"<unknown>"));
397 detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info);
398 detail::boost_spirit::parse_info<PositionIterator> result;
401 impl().grammar.use_parser<Impl::Grammar::ArgumentsParser>(),
402 impl().grammar.use_parser<Impl::Grammar::SkipParser>() );
404 catch (detail::boost_spirit::parser_error<Impl::Grammar::Errors, PositionIterator> & ex) {
405 throwParserError(ex);
408 detail::FilePositionWithIndex pos (result.stop.get_position());
410 <<
"\nat " << pos.file <<
":" << pos.line <<
":" << pos.column;
417 typedef detail::boost_spirit::position_iterator<
418 std::string::const_iterator, detail::FilePositionWithIndex> PositionIterator;
419 PositionIterator b (path.begin(), path.end(), std::string(
"<unknown>"));
420 PositionIterator e (path.end(), path.end(), std::string(
"<unknown>"));
421 detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info);
422 detail::boost_spirit::parse_info<PositionIterator> result;
425 impl().grammar.use_parser<Impl::Grammar::PathParser>(),
426 impl().grammar.use_parser<Impl::Grammar::SkipParser>() );
428 catch (detail::boost_spirit::parser_error<Impl::Grammar::Errors, PositionIterator> & ex) {
429 throwParserError(ex);
432 detail::FilePositionWithIndex pos (result.stop.get_position());
434 <<
"\nat " << pos.file <<
":" << pos.line <<
":" << pos.column;
441 parser_.impl().grammar.incremental =
true;
445 parser_.impl().grammar.incremental =
false;
455 return std::distance( commands.begin(),
456 parseLoop(commands.begin(), commands.end(),
"<unknown>", cb) );
464 return Impl::Grammar::special_p().test(ch);
469 return Impl::Grammar::punctuation_p().test(ch);
474 return Impl::Grammar::space_p().test(ch);
479 return Impl::Grammar::invalid_p().test(ch);
484 return Impl::Grammar::word_p().test(ch);
Exception thrown when the parser detects an error.
boost::iterator_range< argument_iterator > ArgumentsRange
std::string::size_type parseIncremental(std::string const &commands, Callback cb)
Incremental parse.
Token()
Create empty token.
unspecified_keyword_type parser
Argument parser.
Tokens::const_iterator token_iterator
void clear()
Clear all data members.
void parse(std::string const &command, Callback cb)
Parse string.
static bool isInvalidChar(char ch)
Check, if ch is an invalid character.
boost::function< void(ParseCommandInfo const &)> Callback
Iterator parsing argument groups.
static bool isWordChar(char ch)
Check, if ch is a word character.
bool empty()
true, if the data is empty
void parseFile(std::string const &filename, Callback cb)
Parse file.
std::ostream & operator<<(std::ostream &os, Token const &token)
Single parsed console command.
TokensRange commandPath() const
Command path.
SetIncremental(CommandParser &parser)
void parse(ParseCommandInfo::TokensRange const &tokens, Type &out)
Parse token range.
TokenType type() const
Token type.
BuiltinCommand builtin() const
Command type.
std::string const & value() const
String value of token.
static bool isSpecialChar(char ch)
Check, if ch is a special character.
#define SENF_ASSERT(x, comment)
ArgumentsRange arguments() const
Command arguments.
#define SENF_EXC_DEBUGINFO
void parseArguments(std::string const &arguments, ParseCommandInfo &info)
Parse arguments.
static bool isPunctuationChar(char ch)
Check, if ch is a punctuation character.
void parsePath(std::string const &path, ParseCommandInfo &info)
Parse path.
static bool isSpaceChar(char ch)
Check, if ch is a space character.