Console: Refactor argument parsing into iterator
[senf.git] / Console / Parse.hh
index 1dc7498..8c2ab32 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef HH_Parse_
 #define HH_Parse_ 1
 
-/** \defgroup console_parser The console/config parser
+/** \defgroup console_parser The parser
 
     The console/config library defines a simple language used to interact with the console or to
     configure the application.  The parser is not concerned about interpreting commands or
 #include <boost/utility.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <boost/range/iterator_range.hpp>
+#include <boost/iterator/iterator_facade.hpp>
 #include <boost/function.hpp>
 
 //#include "Parse.mpp"
@@ -214,24 +215,64 @@ namespace console {
     class ArgumentToken
     {
     public:
+        enum TokenType { 
+            PathSeparator       = 0x0001,
+            ArgumentGroupOpen   = 0x0002,
+            ArgumentGroupClose  = 0x0004,
+            DirectoryGroupOpen  = 0x0008,
+            DirectoryGroupClose = 0x0010,
+            CommandTerminator   = 0x0020,
+            OtherPunctuation    = 0x0040,
+            BasicString         = 0x0080,
+            HexString           = 0x0100,
+            Word                = 0x0200
+        };
+
+        enum TokenGroup {
+            ArgumentGrouper     = ArgumentGroupOpen 
+                                | ArgumentGroupClose,
+
+            DirectoryGrouper    = DirectoryGroupOpen 
+                                | DirectoryGroupClose,
+
+            Punctuation         = DirectoryGroupOpen 
+                                | DirectoryGroupClose 
+                                | PathSeparator 
+                                | CommandTerminator 
+                                | OtherPunctuation,
+
+            String              = BasicString 
+                                | HexString,
+
+            SimpleArgument      = Word 
+                                | BasicString 
+                                | HexString
+        };
+        
         std::string const & value() const; ///< String value of token
                                         /**< This value is properly unquoted */
 
+        TokenType type() const;         ///< Token type
+
+        bool is(unsigned tokens) const; ///< Check, whether tokens type matches \a tokens
+                                        /**< \a tokens is a bit-mask of token types to check. */
+
     protected:
 
     private:
-        explicit ArgumentToken(std::string token);
+        ArgumentToken(TokenType type, std::string token);
 
+        TokenType type_;
         std::string token_;
 
         friend class detail::ParserAccess;
     };
 
-    /** \brief Console command
+    /** \brief Single parsed console command
 
         Every command parsed is returned in a ParseCommandInfo instance. This information is purely
         taken from the parser, no semantic information is attached at this point, the config/console
-        is not involved in any why. ParseCommandInfo consist of
+        node tree is not involved in any why. ParseCommandInfo consist of
         
         \li the type of command: built-in or normal command represented by a possibly relative path
             into the command tree.
@@ -244,19 +285,13 @@ namespace console {
     {
         typedef std::vector<ArgumentToken> Tokens;
         typedef std::vector<std::string> CommandPath;
-        
+        class ArgumentIterator; 
+
     public:
         typedef CommandPath::const_iterator path_iterator;
         typedef Tokens::const_iterator token_iterator;
-        typedef boost::iterator_range<token_iterator> argument_value_type;
-
-
-    private:
-        typedef std::vector<argument_value_type> Arguments;
-
-    public:
-        typedef Arguments::const_iterator argument_iterator;
-        typedef Arguments::size_type size_type;
+        typedef ArgumentIterator argument_iterator;
+        typedef Tokens::size_type size_type;
 
         typedef boost::iterator_range<path_iterator> CommandPathRange;
         typedef boost::iterator_range<argument_iterator> ArgumentsRange;
@@ -279,9 +314,9 @@ namespace console {
                                              constitutes one path element. If the first element is
                                              empty, the path is an absolute path, otherwise it is
                                              relative. If the last element is an empty string, the
-                                             path ends in a '/' char. */
+                                             path ends with a '/' char. */
         ArgumentsRange arguments() const; ///< Command arguments
-                                        /**< The returned range contains one token range for each
+                                        /**< The returned range contains one TokensRange for each
                                              argument. */
         TokensRange tokens() const;     ///< All argument tokens
                                         /**< The returned range contains \e all argument tokens in a
@@ -292,26 +327,42 @@ namespace console {
         void init();
         void setBuiltin(BuiltinCommand builtin);
         void setCommand(std::vector<std::string> & commandPath);
-        void startArgument();
-        void endArgument();
         void addToken(ArgumentToken const & token);
-        void finalize();
 
         struct MakeRange;
 
         std::vector<std::string> commandPath_;
-
-        typedef std::pair<Tokens::size_type, Tokens::size_type> TempArgumentRange;
-        typedef std::vector<TempArgumentRange> TempArguments;
-
         BuiltinCommand builtin_;
         Tokens tokens_;
-        Arguments arguments_;
-        TempArguments tempArguments_;
 
         friend class detail::ParserAccess;
     };
 
+    class ParseCommandInfo::ArgumentIterator
+        : public boost::iterator_facade< ParseCommandInfo::ArgumentIterator, 
+                                         ParseCommandInfo::TokensRange,
+                                         boost::bidirectional_traversal_tag,
+                                         ParseCommandInfo::TokensRange >
+    {
+        ArgumentIterator();
+
+    private:
+        ArgumentIterator(ParseCommandInfo::TokensRange::iterator i);
+
+        reference dereference() const;
+        bool equal(ArgumentIterator const & other) const;
+        void increment();
+        void decrement();
+
+        mutable ParseCommandInfo::TokensRange::iterator b_;
+        mutable ParseCommandInfo::TokensRange::iterator e_;
+
+        void setRange() const;
+
+        friend class boost::iterator_core_access;
+        friend class ParseCommandInfo;
+    };
+
     /**< \brief Output ParseCommandInfo instance
          \related ParseCommandInfo
       */