X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Console%2FParse.ih;h=dbdf89ef527083eb42862ecf37698c056f5fb408;hb=42f556b7d7c8f210c5919fcb298b0dccdae568e3;hp=0de5ade57303844225c4b82ed7e99cee97ed63e4;hpb=2d5a1fd2cef2d84e16226a7336948f524fbb71c6;p=senf.git diff --git a/Console/Parse.ih b/Console/Parse.ih index 0de5ade..dbdf89e 100644 --- a/Console/Parse.ih +++ b/Console/Parse.ih @@ -28,13 +28,11 @@ // Custom includes #include -#include #include #include -#include -#include -#include -#include +#include +#include +#include "../Utils/Phoenix.hh" ///////////////////////////////ih.p//////////////////////////////////////// @@ -45,30 +43,6 @@ namespace detail { #ifndef DOXYGEN /////////////////////////////////////////////////////////////////////////// - // append_a - - struct append_action - { - template - void act(T & ref, Value const & value) const - { ref += T(1, value); } - - template - void act(T & ref, Iterator const & f, Iterator const & l) const - { ref += T(f,l); } - }; - - template - inline boost::spirit::ref_value_actor - append_a(T & ref) - { return boost::spirit::ref_value_actor(ref); } - - template - inline boost::spirit::ref_const_ref_actor - append_a(T & ref, Value const & value) - { return boost::spirit::ref_const_ref_actor(ref, value); } - - /////////////////////////////////////////////////////////////////////////// // Grammar template @@ -77,60 +51,47 @@ namespace detail { /////////////////////////////////////////////////////////////////////////// // Start rules - enum { CommandParser, SkipParser }; + enum { CommandParser, SkipParser, ArgumentsParser }; /////////////////////////////////////////////////////////////////////////// // The parse context (variables needed while parsing) + typedef Token::TokenType TokenType; + struct Context { std::string str; - std::vector path; + std::vector path; char ch; + Token token; }; Context & context; /////////////////////////////////////////////////////////////////////////// - // Dispatching semantic actions + // Configuration - ParseDispatcher & dispatcher; + bool incremental; - struct Dispatch_actor - { - Dispatch_actor(boost::function fn_) : fn (fn_) {} - - template - void operator()(Value const & value) const - { fn(); } - - template - void operator()(Iterator const & f, Iterator const & l) const - { fn(); } - - boost::function fn; - }; - - template - Dispatch_actor dispatch(Callback cb) const - { return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher))); } + /////////////////////////////////////////////////////////////////////////// + // Dispatching semantic actions - template - Dispatch_actor dispatch(Callback cb, Arg const & arg) const - { return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher), arg)); } + ParseDispatcher & dispatcher; /////////////////////////////////////////////////////////////////////////// CommandGrammar(ParseDispatcher & d, Context & c) - : context(c), dispatcher(d) {} + : context(c), incremental(false), dispatcher(d) {} template struct definition : public boost::spirit::grammar_def< boost::spirit::rule, + boost::spirit::rule, boost::spirit::rule > { boost::spirit::rule command, path, argument, word, string, hexstring, token, punctuation, hexbyte, balanced_tokens, simple_argument, complex_argument, builtin, - skip, commands, block, statement, relpath, abspath; + skip, statement, relpath, abspath, arguments, group_start, group_close, + statement_end; boost::spirit::chset<> special_p, punctuation_p, space_p, invalid_p, word_p; boost::spirit::distinct_parser<> keyword_p; @@ -139,7 +100,8 @@ namespace detail { // Characters with a special meaning within the parser special_p ("/(){};"), - // Characters which are returned as punctuation tokens + // Additional characters which are returned as punctuation tokens + // (only allowed within '()'). punctuation_p (",="), // Whitespace characters @@ -159,19 +121,29 @@ namespace detail { { using namespace boost::spirit; + using namespace ::phoenix; + using namespace senf::phoenix; typedef ParseDispatcher PD; + actor< variable< char > > ch_ (self.context.ch); + actor< variable< std::string > > str_ (self.context.str); + actor< variable< std::vector > > path_ (self.context.path); + actor< variable< Token > > token_ (self.context.token); + actor< variable< ParseDispatcher > > d_ (self.dispatcher); + /////////////////////////////////////////////////////////////////// // Spirit grammar // // Syntax summary: // This is EBNF with some minor tweaks to accommodate C++ syntax // - // * and + like EBNF but they precede their argument - // >> is followed by - // ! optional - // a % b match any number of a's separated by b - // a - b match a but not b + // * a any number of a's + // + a at least one a + // ! a an optional a + // a >> b a followed by b + // a | b a or b + // a % b any number of a's separated by b's + // a - b a but not b // // Beside this, we use some special parsers (ch_p, eps_p, confix_p, lex_escape_ch_p, // keyword_p, comment_p) and directives (lexeme_d), however, the parser should be @@ -197,127 +169,153 @@ namespace detail { // // More info is in the Boost.Spirit documentation - commands - = * command - ; - command - = builtin >> (ch_p(';') | end_p) - | path >> ( block | statement ) + = builtin >> statement_end + | path >> ( group_start | statement ) + | group_close | ch_p(';') // Ignore empty commands ; builtin = keyword_p("cd") >> path - >> eps_p [ self.dispatch(&PD::builtin_cd, - boost::ref(self.context.path)) ] + >> eps_p [ bind(&PD::builtin_cd)(d_, path_) ] | keyword_p("ls") >> ! path - >> eps_p [ self.dispatch(&PD::builtin_ls, - boost::ref(self.context.path)) ] - | keyword_p("exit") [ self.dispatch(&PD::builtin_exit) ] + >> eps_p [ bind(&PD::builtin_ls)(d_, path_) ] + | keyword_p("exit") [ bind(&PD::builtin_exit)(d_) ] | keyword_p("help") >> ! path - >> eps_p [ self.dispatch(&PD::builtin_help, - boost::ref(self.context.path)) ] + >> eps_p [ bind(&PD::builtin_help)(d_, path_) ] ; - block - = ch_p('{') [ self.dispatch(&PD::pushDirectory, - boost::ref(self.context.path)) ] - >> * command - >> ch_p('}') [ self.dispatch(&PD::popDirectory) ] + group_start + = ch_p('{') [ bind(&PD::pushDirectory)(d_, path_) ] + ; + + group_close + = ch_p('}') [ bind(&PD::popDirectory)(d_) ] ; statement - = eps_p [ self.dispatch(&PD::beginCommand, - boost::ref(self.context.path)) ] - >> * argument - >> (ch_p(';') | end_p) - >> eps_p [ self.dispatch(&PD::endCommand) ] + = eps_p [ bind(&PD::beginCommand)(d_, path_) ] + >> arguments + >> statement_end [ bind(&PD::endCommand)(d_) ] + ; + + arguments + = * argument ; argument - = simple_argument [ self.dispatch(&PD::pushArgument, - boost::ref(self.context.str)) ] - | complex_argument + = simple_argument [ bind(&PD::pushToken)(d_, token_) ] + | balanced_tokens ; - simple_argument // All these return their value in context.str + simple_argument // All these return their value in context.token = string | hexstring | word ; - complex_argument // Argument consists of multiple tokens - = ch_p('(') [ self.dispatch(&PD::openGroup) ] - >> * token - >> ch_p(')') [ self.dispatch(&PD::closeGroup) ] - ; - - string // Returns value in context.str - = eps_p [ clear_a(self.context.str) ] + string // Returns value in context.token + = eps_p [ clear(str_) ] >> lexeme_d [ ch_p('"') - >> * ( ( lex_escape_ch_p[ assign_a(self.context.ch) ] + >> * ( ( lex_escape_ch_p[ ch_ = arg1 ] - '"' - ) [ append_a(self.context.str, - self.context.ch) ] + ) [ str_ += ch_ ] ) - >> ch_p('"') + >> ch_p('"') [ token_ = construct_(Token::BasicString, + str_) ] ] ; - hexstring // Returns value in context.str - = eps_p [ clear_a(self.context.str) ] + hexstring // Returns value in context.token + = eps_p [ clear(str_) ] >> confix_p( "x\"", * hexbyte, '"' ) + [ token_ = construct_(Token::HexString, + str_) ] ; path // Returns value in context.path - = eps_p [ clear_a(self.context.path) ] + = eps_p [ clear(path_) ] >> relpath | abspath ; relpath - = ( word [ push_back_a(self.context.path) ] + = ( word [ push_back(path_, token_) ] % ch_p('/') ) - >> ( ! ch_p('/') [ push_back_a(self.context.path,"") ] ) + >> ( ! ch_p('/') [ push_back(path_, construct_()) ] ) ; abspath - = ch_p('/') [ push_back_a(self.context.path, "") ] + = ch_p('/') [ push_back(path_, construct_()) ] >> ( relpath - | eps_p [ push_back_a(self.context.path, "") ] ) + | eps_p [ push_back(path_, construct_()) ] ) ; balanced_tokens - = ch_p('(') [ self.dispatch(&PD::pushPunctuation, "(") ] + = ch_p('(') [ token_ = construct_( + Token::ArgumentGroupOpen, + "(") ] + [ bind(&PD::pushToken)(d_, token_) ] >> * token - >> ch_p(')') [ self.dispatch(&PD::pushPunctuation, ")") ] + >> ch_p(')') [ token_ = construct_( + Token::ArgumentGroupClose, + ")") ] + [ bind(&PD::pushToken)(d_, token_) ] ; token - = simple_argument [ self.dispatch(&PD::pushWord, - boost::ref(self.context.str)) ] - | punctuation [ self.dispatch(&PD::pushPunctuation, - boost::ref(self.context.str)) ] + = simple_argument [ bind(&PD::pushToken)(d_, token_) ] + | punctuation [ bind(&PD::pushToken)(d_, token_) ] | balanced_tokens ; punctuation // Returns value in context.str - = punctuation_p [ assign_a(self.context.str) ] + = ch_p('/') [ token_ = construct_( + Token::PathSeparator, + "/") ] + | ch_p('{') [ token_ = construct_( + Token::DirectoryGroupOpen, + "{") ] + | ch_p('}') [ token_ = construct_( + Token::DirectoryGroupClose, + "}") ] + | ch_p(';') [ token_ = construct_( + Token::CommandTerminator, + ";") ] + | punctuation_p [ token_ = construct_( + Token::OtherPunctuation, + construct_(1u, arg1)) ] ; - word // Returns value in context.str - = lexeme_d[ + word_p ] [ assign_a(self.context.str) ] + word // Returns value in context.token + = lexeme_d + [ + (+ word_p) [ str_ = construct_(arg1, arg2) ] + ] + >> eps_p [ token_ = construct_( + Token::Word, + str_) ] ; hexbyte = uint_parser() - [ append_a(self.context.str) ] + [ push_back(str_, arg1) ] + ; + + statement_end + = if_p(var(self.incremental)) [ + ch_p(';') + ] + .else_p [ + ch_p(';') + | end_p + ] ; skip @@ -327,8 +325,9 @@ namespace detail { /////////////////////////////////////////////////////////////////// start_parsers( - commands, // CommandParser - skip // SkipParser + command, // CommandParser + skip, // SkipParser + arguments // ArgumentsParser ); BOOST_SPIRIT_DEBUG_TRACE_RULE(command,1); @@ -353,8 +352,6 @@ namespace detail { }; }; - - #endif }}}