00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00026 #ifndef IH_SENF_Scheduler_Console_Parse_
00027 #define IH_SENF_Scheduler_Console_Parse_ 1
00028
00029
00030 #include <vector>
00031 #include <senf/config.hh>
00032
00033 #if HAVE_BOOST_SPIRIT_INCLUDE_CLASSIC_HPP
00034 # include <boost/spirit/include/classic.hpp>
00035 # include <boost/spirit/include/classic_grammar_def.hpp>
00036 # include <boost/spirit/include/classic_dynamic.hpp>
00037 # include <boost/spirit/include/phoenix1.hpp>
00038 #else
00039 # include <boost/spirit.hpp>
00040 # include <boost/spirit/utility/grammar_def.hpp>
00041 # include <boost/spirit/dynamic.hpp>
00042 # include <boost/spirit/phoenix.hpp>
00043 #endif
00044
00045 #include <senf/Utils/Phoenix.hh>
00046
00047
00048
00049 namespace senf {
00050 namespace console {
00051 namespace detail {
00052
00053 #if HAVE_BOOST_SPIRIT_INCLUDE_CLASSIC_HPP
00054 namespace boost_spirit = ::boost::spirit::classic;
00055 #else
00056 namespace boost_spirit = ::boost::spirit;
00057 #endif
00058
00059 #ifndef DOXYGEN
00060
00061 struct FilePositionWithIndex
00062 : public boost_spirit::file_position
00063 {
00064 int index;
00065
00066 FilePositionWithIndex(std::string const & file_ = std::string(),
00067 int line_ = 1, int column_ = 1, int index_ = 0)
00068 : boost_spirit::file_position (file_, line_, column_), index (index_)
00069 {}
00070
00071 bool operator==(const FilePositionWithIndex & fp) const
00072 {
00073 return boost_spirit::file_position::operator==(fp) && index == fp.index;
00074 }
00075 };
00076
00077 struct PositionOf {
00078 template <class A1> struct result { typedef FilePositionWithIndex type; };
00079 template <class A1> FilePositionWithIndex operator()(A1 & a1) { return a1.get_position(); }
00080 FilePositionWithIndex operator()(char const * a1) { return FilePositionWithIndex(); }
00081 };
00082
00083 ::phoenix::function<PositionOf> const positionOf;
00084
00085
00086
00087
00088 template <class ParseDispatcher>
00089 struct CommandGrammar : boost_spirit::grammar<CommandGrammar<ParseDispatcher> >
00090 {
00091
00092
00093
00094 enum { CommandParser, SkipParser, ArgumentsParser, PathParser };
00095
00096
00097
00098
00099 typedef Token::TokenType TokenType;
00100
00101 struct Context {
00102 std::string str;
00103 std::vector<Token> path;
00104 char ch;
00105 Token token;
00106 FilePositionWithIndex pos;
00107 };
00108
00109 Context & context;
00110
00111
00112
00113
00114 bool incremental;
00115
00116
00117
00118
00119 ParseDispatcher & dispatcher;
00120
00121
00122
00123
00124 static boost_spirit::chset<> special_p;
00125 static boost_spirit::chset<> punctuation_p;
00126 static boost_spirit::chset<> space_p;
00127 static boost_spirit::chset<> invalid_p;
00128 static boost_spirit::chset<> word_p;
00129 static boost_spirit::distinct_parser<> keyword_p;
00130
00131
00132
00133
00134 enum Errors {
00135 EndOfStatementExpected,
00136 PathExpected,
00137 ClosingParenExpected,
00138 QuoteExpected
00139 };
00140
00141
00142
00143 CommandGrammar(ParseDispatcher & d, Context & c)
00144 : context(c), incremental(false), dispatcher(d) {}
00145
00146 template <class Scanner>
00147 struct definition
00148 : public boost_spirit::grammar_def< boost_spirit::rule<Scanner>,
00149 boost_spirit::rule<Scanner>,
00150 boost_spirit::rule<Scanner>,
00151 boost_spirit::rule<Scanner> >
00152 {
00153 boost_spirit::rule<Scanner> command, path, argument, word, string, hexstring,
00154 word_or_string, token, punctuation, hexbyte, balanced_tokens, simple_argument,
00155 complex_argument, builtin, skip, statement, relpath, abspath, arguments,
00156 group_start, group_close, statement_end, opt_path;
00157
00158 definition(CommandGrammar const & self)
00159 {
00160 using namespace boost_spirit;
00161 using namespace ::phoenix;
00162 using namespace senf::phoenix;
00163 typedef ParseDispatcher PD;
00164
00165 actor< variable< char > > ch_ (self.context.ch);
00166 actor< variable< std::string > > str_ (self.context.str);
00167 actor< variable< std::vector<Token> > > path_ (self.context.path);
00168 actor< variable< Token > > token_ (self.context.token);
00169 actor< variable< FilePositionWithIndex > > pos_ (self.context.pos);
00170 actor< variable< ParseDispatcher > > d_ (self.dispatcher);
00171
00172 assertion<Errors> end_of_statement_expected (EndOfStatementExpected);
00173 assertion<Errors> path_expected (PathExpected);
00174 assertion<Errors> closing_paren_expected (ClosingParenExpected);
00175 assertion<Errors> quote_expected (QuoteExpected);
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 command
00216 = builtin >> end_of_statement_expected(statement_end)
00217 | group_close
00218 | ch_p(';')
00219 | statement
00220 ;
00221
00222 statement
00223 = path_expected(path) [ bind(&PD::beginCommand)(d_, path_) ]
00224 >> arguments
00225 >> end_of_statement_expected(
00226 ( group_start | statement_end )
00227 [ bind(&PD::endCommand)(d_) ]
00228 )
00229 ;
00230
00231 builtin
00232 = self.keyword_p("cd")
00233 >> path_expected(path)
00234 >> eps_p [ bind(&PD::builtin_cd)(d_, path_) ]
00235 | self.keyword_p("ls")
00236 >> ! path
00237 >> eps_p [ bind(&PD::builtin_ls)(d_, path_) ]
00238 | self.keyword_p("ll")
00239 >> ! path
00240 >> eps_p [ bind(&PD::builtin_ll)(d_, path_) ]
00241 | self.keyword_p("lr")
00242 >> ! path
00243 >> eps_p [ bind(&PD::builtin_lr)(d_, path_) ]
00244 | self.keyword_p("exit") [ bind(&PD::builtin_exit)(d_) ]
00245 | self.keyword_p("help")
00246 >> ! path
00247 >> eps_p [ bind(&PD::builtin_help)(d_, path_) ]
00248 ;
00249
00250 group_start
00251 = ch_p('{') [ bind(&PD::pushDirectory)(d_) ]
00252 ;
00253
00254 group_close
00255 = ch_p('}') [ bind(&PD::popDirectory)(d_) ]
00256 ;
00257
00258 arguments
00259 = * argument
00260 ;
00261
00262 argument
00263 = simple_argument [ bind(&PD::pushToken)(d_, token_) ]
00264 | balanced_tokens
00265 ;
00266
00267 simple_argument
00268 = string
00269 | hexstring
00270 | word
00271 ;
00272
00273 string
00274 = eps_p [ pos_ = positionOf(arg1) ][ clear(str_) ]
00275 >> lexeme_d
00276 [
00277 ch_p('"')
00278 >> * ( ( lex_escape_ch_p[ ch_ = arg1 ]
00279 - '"'
00280 ) [ str_ += ch_ ]
00281 )
00282 >> quote_expected(ch_p('"'))
00283 [ token_ = construct_<Token>(Token::BasicString,
00284 str_,
00285 pos_) ]
00286 ]
00287 ;
00288
00289 hexstring
00290 = eps_p [ pos_ = positionOf(arg1) ][ clear(str_) ]
00291 >> "x\""
00292 >> * ( hexbyte - ch_p('"') )
00293 >> quote_expected(ch_p('"'))
00294 [ token_ = construct_<Token>(Token::HexString,
00295 str_,
00296 pos_) ]
00297 ;
00298
00299 opt_path
00300 = ! path [ bind(&PD::beginCommand)(d_, path_) ]
00301 [ bind(&PD::endCommand)(d_) ]
00302 ;
00303
00304 path
00305 = eps_p [ clear(path_) ]
00306 >> relpath | abspath
00307 ;
00308
00309 relpath
00310 = ( word_or_string [ push_back(path_, token_) ]
00311 % +ch_p('/') )
00312 >> ( ! (+ch_p('/') ) [ push_back(path_, construct_<Token>()) ] )
00313 ;
00314
00315 abspath
00316 = (+ch_p('/')) [ push_back(path_, construct_<Token>()) ]
00317 >> ( relpath
00318 | eps_p [ push_back(path_, construct_<Token>()) ] )
00319 ;
00320
00321 balanced_tokens
00322 = eps_p [ pos_ = positionOf(arg1) ]
00323 >> ch_p('(') [ token_ = construct_<Token>(
00324 Token::ArgumentGroupOpen,
00325 "(",
00326 pos_) ]
00327 [ bind(&PD::pushToken)(d_, token_) ]
00328 >> * token
00329 >> eps_p [ pos_ = positionOf(arg1) ]
00330 >> closing_paren_expected(ch_p(')'))
00331 [ token_ = construct_<Token>(
00332 Token::ArgumentGroupClose,
00333 ")",
00334 pos_) ]
00335 [ bind(&PD::pushToken)(d_, token_) ]
00336 ;
00337
00338 token
00339 = simple_argument [ bind(&PD::pushToken)(d_, token_) ]
00340 | punctuation [ bind(&PD::pushToken)(d_, token_) ]
00341 | balanced_tokens
00342 ;
00343
00344 punctuation
00345 = eps_p [ pos_ = positionOf(arg1) ]
00346 >> (
00347 ch_p('/') [ token_ = construct_<Token>(
00348 Token::PathSeparator,
00349 "/") ]
00350 | ch_p('{') [ token_ = construct_<Token>(
00351 Token::DirectoryGroupOpen,
00352 "{") ]
00353 | ch_p('}') [ token_ = construct_<Token>(
00354 Token::DirectoryGroupClose,
00355 "}") ]
00356 | ch_p(';') [ token_ = construct_<Token>(
00357 Token::CommandTerminator,
00358 ";") ]
00359 | self.punctuation_p [ token_ = construct_<Token>(
00360 Token::OtherPunctuation,
00361 construct_<std::string>(1u, arg1),
00362 pos_) ]
00363 )
00364 ;
00365
00366 word
00367 = eps_p [ pos_ = positionOf(arg1) ]
00368 >> lexeme_d
00369 [
00370 (+ self.word_p) [ str_ = construct_<std::string>(arg1, arg2) ]
00371 ]
00372 >> eps_p [ token_ = construct_<Token>(
00373 Token::Word,
00374 str_,
00375 pos_) ]
00376 ;
00377
00378 word_or_string
00379 = word
00380 | string
00381 ;
00382
00383 hexbyte
00384 = uint_parser<char, 16, 2, 2>()
00385 [ push_back(str_, arg1) ]
00386 ;
00387
00388 statement_end
00389 = if_p(var(self.incremental)) [
00390 ch_p(';')
00391 ]
00392 .else_p [
00393 ch_p(';')
00394 | end_p
00395 ]
00396 ;
00397
00398 skip
00399 = self.space_p | comment_p('#')
00400 ;
00401
00402
00403
00404 start_parsers(
00405 command,
00406 skip,
00407 arguments,
00408 opt_path
00409 );
00410
00411 BOOST_SPIRIT_DEBUG_TRACE_RULE(command,1);
00412 BOOST_SPIRIT_DEBUG_TRACE_RULE(path,1);
00413 BOOST_SPIRIT_DEBUG_TRACE_RULE(argument,1);
00414 BOOST_SPIRIT_DEBUG_TRACE_RULE(word,1);
00415 BOOST_SPIRIT_DEBUG_TRACE_RULE(string,1);
00416 BOOST_SPIRIT_DEBUG_TRACE_RULE(hexstring,1);
00417 BOOST_SPIRIT_DEBUG_TRACE_RULE(token,1);
00418 BOOST_SPIRIT_DEBUG_TRACE_RULE(punctuation,1);
00419 BOOST_SPIRIT_DEBUG_TRACE_RULE(hexbyte,1);
00420 BOOST_SPIRIT_DEBUG_TRACE_RULE(balanced_tokens,1);
00421 BOOST_SPIRIT_DEBUG_TRACE_RULE(simple_argument,1);
00422 BOOST_SPIRIT_DEBUG_TRACE_RULE(complex_argument,1);
00423 BOOST_SPIRIT_DEBUG_TRACE_RULE(builtin,1);
00424 BOOST_SPIRIT_DEBUG_TRACE_RULE(commands,1);
00425 BOOST_SPIRIT_DEBUG_TRACE_RULE(block,1);
00426 BOOST_SPIRIT_DEBUG_TRACE_RULE(statement,1);
00427 BOOST_SPIRIT_DEBUG_TRACE_RULE(relpath,1);
00428 BOOST_SPIRIT_DEBUG_TRACE_RULE(abspath,1);
00429 }
00430 };
00431 };
00432
00433 template <class PD> boost_spirit::chset<> CommandGrammar<PD>::special_p (
00434 "/(){};\"");
00435 template <class PD> boost_spirit::chset<> CommandGrammar<PD>::punctuation_p (
00436 ",=");
00437 template <class PD> boost_spirit::chset<> CommandGrammar<PD>::space_p (
00438 " \t\n\r");
00439 template <class PD> boost_spirit::chset<> CommandGrammar<PD>::invalid_p (
00440 (boost_spirit::chset<>('\0') | boost_spirit::chset<>("\x01-\x20")) - space_p );
00441 template <class PD> boost_spirit::chset<> CommandGrammar<PD>::word_p (
00442 boost_spirit::anychar_p - special_p - punctuation_p - space_p - invalid_p);
00443 template <class PD> boost_spirit::distinct_parser<> CommandGrammar<PD>::keyword_p (
00444 word_p | boost_spirit::ch_p('/'));
00445
00446 #endif
00447
00448 }}}
00449
00450
00451 #endif
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462