00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00026 #ifndef HH_SENF_Scheduler_Console_Parse_
00027 #define HH_SENF_Scheduler_Console_Parse_ 1
00028
00192
00193 #include <string>
00194 #include <vector>
00195 #include <boost/utility.hpp>
00196 #include <boost/scoped_ptr.hpp>
00197 #include <boost/range/iterator_range.hpp>
00198 #include <boost/iterator/iterator_facade.hpp>
00199 #include <boost/function.hpp>
00200 #include <senf/Utils/safe_bool.hh>
00201 #include <senf/Utils/Exception.hh>
00202
00203
00204
00205
00206 namespace senf {
00207 namespace console {
00208
00209 namespace detail { class FilePositionWithIndex; }
00210
00211 namespace detail { struct ParserAccess; }
00212
00220 class Token
00221 {
00222 public:
00223 enum TokenType {
00224 None = 0,
00225 PathSeparator = 0x0001,
00226 ArgumentGroupOpen = 0x0002,
00227 ArgumentGroupClose = 0x0004,
00228 DirectoryGroupOpen = 0x0008,
00229 DirectoryGroupClose = 0x0010,
00230 CommandTerminator = 0x0020,
00231 OtherPunctuation = 0x0040,
00232 BasicString = 0x0080,
00233 HexString = 0x0100,
00234 Word = 0x0200
00235 };
00236
00237 enum TokenGroup {
00238 ArgumentGrouper = ArgumentGroupOpen
00239 | ArgumentGroupClose,
00240
00241 DirectoryGrouper = DirectoryGroupOpen
00242 | DirectoryGroupClose,
00243
00244 Punctuation = DirectoryGroupOpen
00245 | DirectoryGroupClose
00246 | PathSeparator
00247 | CommandTerminator
00248 | OtherPunctuation,
00249
00250 String = BasicString
00251 | HexString,
00252
00253 SimpleArgument = Word
00254 | BasicString
00255 | HexString
00256 };
00257
00258 Token();
00259 Token(TokenType type, std::string token);
00261 Token(TokenType type, std::string token, detail::FilePositionWithIndex const & pos);
00263
00264
00265 std::string const & value() const;
00266
00268 TokenType type() const;
00269
00270 unsigned line() const;
00271 unsigned column() const;
00272 unsigned index() const;
00273
00274 bool is(unsigned tokens) const;
00275
00277 bool operator==(Token const & other) const;
00278 bool operator!=(Token const & other) const;
00279
00280 protected:
00281
00282 private:
00283 TokenType type_;
00284 std::string token_;
00285 unsigned line_;
00286 unsigned column_;
00287 unsigned index_;
00288 };
00289
00290 std::ostream & operator<<(std::ostream & os, Token const & token);
00291
00294 Token NoneToken();
00295
00298 Token PathSeparatorToken();
00299
00302 Token ArgumentGroupOpenToken();
00303
00306 Token ArgumentGroupCloseToken();
00307
00310 Token DirectoryGroupOpenToken();
00311
00314 Token DirectoryGroupCloseToken();
00315
00318 Token CommandTerminatorToken();
00319
00322 Token OtherPunctuationToken(std::string const & value);
00323
00326 Token BasicStringToken(std::string const & value);
00327
00330 Token HexStringToken(std::string const & value);
00331
00334 Token WordToken(std::string const & value);
00335
00349 class ParseCommandInfo
00350 {
00351 typedef std::vector<Token> Tokens;
00352 typedef std::vector<std::string> CommandPath;
00353
00354 public:
00355 class ArgumentIterator;
00356
00357 typedef CommandPath::const_iterator path_iterator;
00358 typedef Tokens::const_iterator token_iterator;
00359 typedef ArgumentIterator argument_iterator;
00360 typedef Tokens::size_type size_type;
00361
00362 typedef boost::iterator_range<path_iterator> CommandPathRange;
00363 typedef boost::iterator_range<argument_iterator> ArgumentsRange;
00364 typedef boost::iterator_range<token_iterator> TokensRange;
00365
00366 enum BuiltinCommand { NoBuiltin,
00367 BuiltinCD,
00368 BuiltinLS,
00369 BuiltinLL,
00370 BuiltinLR,
00371 BuiltinPUSHD,
00372 BuiltinPOPD,
00373 BuiltinEXIT,
00374 BuiltinHELP };
00375
00376 ParseCommandInfo();
00377
00378 BuiltinCommand builtin() const;
00379
00381 TokensRange commandPath() const;
00382
00388 ArgumentsRange arguments() const;
00389
00391 TokensRange tokens() const;
00392
00395 void clear();
00396 bool empty();
00397
00398 void builtin(BuiltinCommand builtin);
00399 void command(std::vector<Token> & commandPath);
00400
00401 void addToken(Token const & token);
00402
00407 protected:
00408
00409 private:
00410 struct MakeRange;
00411
00412 std::vector<Token> commandPath_;
00413 BuiltinCommand builtin_;
00414 Tokens tokens_;
00415 };
00416
00427 class ParseCommandInfo::ArgumentIterator
00428 : public boost::iterator_facade< ParseCommandInfo::ArgumentIterator,
00429 ParseCommandInfo::TokensRange,
00430 boost::bidirectional_traversal_tag,
00431 ParseCommandInfo::TokensRange >
00432 {
00433 public:
00434 ArgumentIterator();
00435 explicit ArgumentIterator(ParseCommandInfo::TokensRange::iterator i);
00436
00437 private:
00438 reference dereference() const;
00439 bool equal(ArgumentIterator const & other) const;
00440 void increment();
00441 void decrement();
00442
00443 mutable ParseCommandInfo::TokensRange::iterator b_;
00444 mutable ParseCommandInfo::TokensRange::iterator e_;
00445
00446 void setRange() const;
00447
00448 friend class boost::iterator_core_access;
00449 friend class ParseCommandInfo;
00450 };
00451
00457 struct SyntaxErrorException : public senf::Exception
00458 { explicit SyntaxErrorException(std::string const & msg = "syntax error")
00459 : senf::Exception(msg) {} };
00460
00493 class CheckedArgumentIteratorWrapper
00494 : boost::noncopyable,
00495 public boost::iterator_facade< CheckedArgumentIteratorWrapper,
00496 ParseCommandInfo::TokensRange,
00497 boost::forward_traversal_tag,
00498 ParseCommandInfo::TokensRange >,
00499 public senf::safe_bool<CheckedArgumentIteratorWrapper>
00500
00501 {
00502 typedef boost::iterator_facade< CheckedArgumentIteratorWrapper,
00503 ParseCommandInfo::TokensRange,
00504 boost::forward_traversal_tag,
00505 ParseCommandInfo::TokensRange > IteratorFacade;
00506
00507 public:
00508 explicit CheckedArgumentIteratorWrapper(
00509 ParseCommandInfo::ArgumentsRange const & range,
00510 std::string const & msg = "invalid number of arguments");
00512
00516 explicit CheckedArgumentIteratorWrapper(
00517 ParseCommandInfo::TokensRange const & range,
00518 std::string const & msg = "invalid number of arguments");
00520
00527 ~CheckedArgumentIteratorWrapper();
00528
00536 operator ParseCommandInfo::ArgumentIterator();
00538
00539 bool boolean_test() const;
00540 bool done() const;
00541
00542 void clear();
00543
00547 bool operator==(ParseCommandInfo::ArgumentIterator const & other) const;
00549 bool operator!=(ParseCommandInfo::ArgumentIterator const & other) const;
00551
00552 using IteratorFacade::operator++;
00553 ParseCommandInfo::ArgumentIterator operator++(int);
00554
00555 private:
00556 reference dereference() const;
00557 void increment();
00558
00559 ParseCommandInfo::ArgumentIterator i_;
00560 ParseCommandInfo::ArgumentIterator e_;
00561 std::string msg_;
00562
00563 friend class boost::iterator_core_access;
00564 };
00565
00569 std::ostream & operator<<(std::ostream & stream, ParseCommandInfo const & info);
00570
00586 class CommandParser
00587 : boost::noncopyable
00588 {
00589 public:
00590
00591
00592
00593 typedef boost::function<void (ParseCommandInfo const &)> Callback;
00594
00595
00597
00598
00599 CommandParser();
00600 ~CommandParser();
00601
00602
00603
00604
00605 void parse(std::string const & command, Callback cb);
00606 void parseFile(std::string const & filename, Callback cb);
00607
00610 void parseArguments(std::string const & arguments, ParseCommandInfo & info);
00612
00617 void parsePath(std::string const & path, ParseCommandInfo & info);
00619
00622 std::string::size_type parseIncremental(std::string const & commands, Callback cb);
00624
00633 static bool isSpecialChar(char ch);
00634 static bool isPunctuationChar(char ch);
00635 static bool isSpaceChar(char ch);
00636 static bool isInvalidChar(char ch);
00637 static bool isWordChar(char ch);
00638
00640 struct ParserErrorException : public SyntaxErrorException
00641 { explicit ParserErrorException(std::string const & msg) : SyntaxErrorException(msg) {} };
00642
00643 private:
00644 struct Impl;
00645 struct SetIncremental;
00646
00647 template <class Iterator>
00648 Iterator parseLoop(Iterator b, Iterator e, std::string const & source, Callback cb);
00649
00650 Impl & impl();
00651
00652 boost::scoped_ptr<Impl> impl_;
00653
00654 friend class SetIncremental;
00655 };
00656
00657 }}
00658
00659
00660 #include "Parse.cci"
00661
00662
00663 #endif
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674