namespace console {
namespace detail {
+#ifndef DOXYGEN
+
+ ///////////////////////////////////////////////////////////////////////////
+ // append_a
+
struct append_action
{
template <class T, class Value>
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> >
///////////////////////////////////////////////////////////////////////////
// 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;
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)
special_p ("/(){};"),
// Characters which are returned as punctuation tokens
- punctuation_p (",="),
+ // (only allowed within '()')
+ punctuation_p (",=/{};"),
// Whitespace characters
space_p (" \t\n\r"),
// 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
//
// 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
>> 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
argument
= simple_argument [ self.dispatch(&PD::pushArgument,
+ boost::ref(self.context.type),
boost::ref(self.context.str)) ]
| complex_argument
;
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('"')
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, '"' )
;
;
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, "") ]
+ = ch_p('/') [ push_back_a(self.context.path,
+ self.context.EmptyString) ]
>> ( relpath
| eps_p [ push_back_a(self.context.path, "") ] )
;
;
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)) ]
;
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
};
};
+ 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////////////////////////////////////////