Utils/Logger: Remove dependency on libboost_datetime
[senf.git] / Console / Parse.ih
index 2f7c80d..5129197 100644 (file)
@@ -42,6 +42,11 @@ namespace senf {
 namespace console {
 namespace detail {
 
+#ifndef DOXYGEN
+
+    ///////////////////////////////////////////////////////////////////////////
+    // append_a
+
     struct append_action
     {
         template <class T, class Value>
@@ -56,16 +61,15 @@ namespace detail {
     template <class T>
     inline boost::spirit::ref_value_actor<T, append_action> 
     append_a(T & ref)
-    {
-        return boost::spirit::ref_value_actor<T, append_action>(ref);
-    }
+    { return boost::spirit::ref_value_actor<T, append_action>(ref); }
     
     template <class T, class Value>
     inline boost::spirit::ref_const_ref_actor<T, Value, append_action> 
     append_a(T & ref, Value const & value)
-    {
-        return boost::spirit::ref_const_ref_actor<T, Value, append_action>(ref, value);
-    }
+    { return boost::spirit::ref_const_ref_actor<T, Value, append_action>(ref, value); }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Grammar
 
     template <class ParseDispatcher>
     struct CommandGrammar : boost::spirit::grammar<CommandGrammar<ParseDispatcher> >
@@ -78,10 +82,21 @@ namespace detail {
         ///////////////////////////////////////////////////////////////////////////
         // The parse context (variables needed while parsing)
 
+        typedef ArgumentToken::TokenType TokenType;
+
         struct Context {
             std::string str;
             std::vector<std::string> path;
             char ch;
+            TokenType type;
+            
+            // OUCH ... This is sooooo stupid .. push_back_a and assign_a take their 
+            // arguments by const-reference and STORE the REFERENCE ... they do NOT accept
+            // literal values !!!!!! 
+            static const TokenType BasicString;
+            static const TokenType HexString;
+            static const TokenType Word;
+            static const std::string EmptyString;
         };
 
         Context & context;
@@ -114,6 +129,10 @@ namespace detail {
         Dispatch_actor dispatch(Callback cb, Arg const & arg) const
             { return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher), arg)); }
 
+        template <class Callback, class Arg1, class Arg2>
+        Dispatch_actor dispatch(Callback cb, Arg1 const & arg1, Arg2 const & arg2) const
+            { return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher), arg1, arg2)); }
+
         ///////////////////////////////////////////////////////////////////////////
 
         CommandGrammar(ParseDispatcher & d, Context & c) 
@@ -136,7 +155,8 @@ namespace detail {
                 special_p ("/(){};"),
 
                 // Characters which are returned as punctuation tokens
-                punctuation_p (",="),
+                // (only allowed within '()')
+                punctuation_p (",=/{};"),
 
                 // Whitespace characters
                 space_p (" \t\n\r"),
@@ -163,7 +183,7 @@ namespace detail {
                 // Syntax summary:
                 // This is EBNF with some minor tweaks to accommodate C++ syntax
                 //
-                //   * and +    precede their argument
+                //   * and +    like EBNF but they precede their argument
                 //   >>         is followed by
                 //   !          optional
                 //   a % b      match any number of a's separated by b
@@ -188,7 +208,7 @@ namespace detail {
                 //
                 // Aligned to the right at column 50 are semantic actions.
                 //
-                // For clarity, I have used 'ch_p' explicitly throughout even though it is auxiliary
+                // For clarity, I have used 'ch_p' explicitly throughout even though it is optional
                 // in most cases.
                 //
                 // More info is in the Boost.Spirit documentation
@@ -208,11 +228,16 @@ namespace detail {
                       >> path
                       >> eps_p                    [ self.dispatch(&PD::builtin_cd,
                                                                   boost::ref(self.context.path)) ]
-                    |    keyword_p("ls") 
+                    |    keyword_p("ls")
                       >> ! path
                       >> eps_p                    [ self.dispatch(&PD::builtin_ls,
                                                                   boost::ref(self.context.path)) ]
                     |    keyword_p("exit")        [ self.dispatch(&PD::builtin_exit) ]
+                    
+                    |    keyword_p("help")
+                      >> ! path
+                      >> eps_p                    [ self.dispatch(&PD::builtin_help,
+                                                                  boost::ref(self.context.path)) ]
                     ;
 
                 block
@@ -232,6 +257,7 @@ namespace detail {
 
                 argument
                     =    simple_argument          [ self.dispatch(&PD::pushArgument, 
+                                                                  boost::ref(self.context.type),
                                                                   boost::ref(self.context.str)) ]
                     |    complex_argument
                     ;
@@ -250,6 +276,8 @@ namespace detail {
 
                 string                  // Returns value in context.str
                     =    eps_p                    [ clear_a(self.context.str) ]
+                      >> eps_p                    [ assign_a(self.context.type, 
+                                                             self.context.BasicString) ]
                       >> lexeme_d
                          [
                              ch_p('"')
@@ -264,6 +292,8 @@ namespace detail {
 
                 hexstring               // Returns value in context.str
                     =    eps_p                    [ clear_a(self.context.str) ]
+                      >> eps_p                    [ assign_a(self.context.type, 
+                                                             self.context.HexString) ]
                       >> confix_p( "x\"", * hexbyte, '"' )
                     ;
 
@@ -273,16 +303,17 @@ namespace detail {
                     ;
 
                 relpath
-                    =    (   word                 [ push_back_a(self.context.path) ] 
+                    =    (   word                 [ push_back_a(self.context.path) ]
                            % ch_p('/') )
-                      >> ( ! ch_p('/')            [ push_back_a(self.context.path,"") ] )
+                      >> ( ! ch_p('/')            [ push_back_a(self.context.path,
+                                                                self.context.EmptyString) ] )
                     ;
 
                 abspath
-                    =    ch_p('/')                [ push_back_a(self.context.path, "") ]
-                      >> ! (    (   word          [ push_back_a(self.context.path) ] 
-                                  % ch_p('/') )
-                             >> ( ! ch_p('/')     [ push_back_a(self.context.path,"") ] ) )
+                    =    ch_p('/')                [ push_back_a(self.context.path,
+                                                                self.context.EmptyString) ]
+                      >> ( relpath
+                         | eps_p                  [ push_back_a(self.context.path, "") ] )
                     ;
 
                 balanced_tokens 
@@ -292,7 +323,8 @@ namespace detail {
                     ;
 
                 token
-                    =    simple_argument          [ self.dispatch(&PD::pushWord, 
+                    =    simple_argument          [ self.dispatch(&PD::pushWord,
+                                                                 boost::ref(self.context.type), 
                                                                   boost::ref(self.context.str)) ]
                     |    punctuation              [ self.dispatch(&PD::pushPunctuation,
                                                                   boost::ref(self.context.str)) ]
@@ -304,7 +336,12 @@ namespace detail {
                     ;
 
                 word                    // Returns value in context.str
-                    =    lexeme_d[ + word_p ]     [ assign_a(self.context.str) ]
+                    =    lexeme_d
+                         [
+                             eps_p                [ assign_a(self.context.type,
+                                                            self.context.Word) ]
+                          >> (+ word_p)           [ assign_a(self.context.str) ]
+                         ]
                     ;
 
                 hexbyte
@@ -345,6 +382,23 @@ namespace detail {
         };
     };
 
+    template <class ParseDispatcher>
+    ArgumentToken::TokenType const CommandGrammar<ParseDispatcher>::Context::BasicString (
+        ArgumentToken::BasicString);
+
+    template <class ParseDispatcher>
+    ArgumentToken::TokenType const CommandGrammar<ParseDispatcher>::Context::HexString(
+        ArgumentToken::HexString);
+
+    template <class ParseDispatcher>
+    ArgumentToken::TokenType const CommandGrammar<ParseDispatcher>::Context::Word(
+        ArgumentToken::Word);
+
+    template <class ParseDispatcher>
+    std::string const CommandGrammar<ParseDispatcher>::Context::EmptyString;
+
+#endif
+
 }}}
 
 ///////////////////////////////ih.e////////////////////////////////////////