X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Utils%2FConsole%2FParse.ih;h=d99e168f24c02f82c40ccc7c51970aa3a61aeb5f;hb=a1fdb7bb122f0b05be809a922d4b7ef5e125fa67;hp=afb4b78c2d9e29bfa728d3ebc3413c4caee46739;hpb=958bdb52c39fa39f4ef91cafd9628bcb4f85a03c;p=senf.git diff --git a/Utils/Console/Parse.ih b/Utils/Console/Parse.ih index afb4b78..d99e168 100644 --- a/Utils/Console/Parse.ih +++ b/Utils/Console/Parse.ih @@ -28,6 +28,7 @@ // Custom includes #include +#include "../../config.hh" #include #include #include @@ -42,6 +43,30 @@ namespace detail { #ifndef DOXYGEN + struct FilePositionWithIndex + : public boost::spirit::file_position + { + int index; + + FilePositionWithIndex(std::string const & file_ = std::string(), + int line_ = 1, int column_ = 1, int index_ = 0) + : boost::spirit::file_position (file_, line_, column_), index (index_) + {} + + bool operator==(const FilePositionWithIndex & fp) const + { + return boost::spirit::file_position::operator==(fp) && index == fp.index; + } + }; + + struct PositionOf { + template struct result { typedef FilePositionWithIndex type; }; + template FilePositionWithIndex operator()(A1 & a1) { return a1.get_position(); } + FilePositionWithIndex operator()(char const * a1) { return FilePositionWithIndex(); } + }; + + ::phoenix::function const positionOf; + /////////////////////////////////////////////////////////////////////////// // Grammar @@ -51,7 +76,7 @@ namespace detail { /////////////////////////////////////////////////////////////////////////// // Start rules - enum { CommandParser, SkipParser, ArgumentsParser }; + enum { CommandParser, SkipParser, ArgumentsParser, PathParser }; /////////////////////////////////////////////////////////////////////////// // The parse context (variables needed while parsing) @@ -63,6 +88,7 @@ namespace detail { std::vector path; char ch; Token token; + FilePositionWithIndex pos; }; Context & context; @@ -77,12 +103,21 @@ namespace detail { ParseDispatcher & dispatcher; + ////////////////////////////////////////////////////////////////////////// + // charachter sets + + static boost::spirit::chset<> special_p; + static boost::spirit::chset<> punctuation_p; + static boost::spirit::chset<> space_p; + static boost::spirit::chset<> invalid_p; + static boost::spirit::chset<> word_p; + static boost::spirit::distinct_parser<> keyword_p; + /////////////////////////////////////////////////////////////////////////// // Errors enum Errors { EndOfStatementExpected, - GroupOrArgumentsExpected, PathExpected, ClosingParenExpected, QuoteExpected @@ -97,53 +132,29 @@ namespace detail { struct definition : public boost::spirit::grammar_def< boost::spirit::rule, 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, 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; - - definition(CommandGrammar const & self) : - - // Characters with a special meaning within the parser - special_p ("/(){};\""), - - // Additional characters which are returned as punctuation tokens - // (only allowed within '()'). - punctuation_p (",="), - - // Whitespace characters - space_p (" \t\n\r"), - - // Invalid characters: All chars below \x20 (space) which are not space_p - // (don't put a \0 in the chset<> argument *string* ...) - invalid_p ( (boost::spirit::chset<>('\0') - | boost::spirit::chset<>("\x01-\x20")) - space_p ), - - // Valid word characters - word_p ( - boost::spirit::anychar_p - special_p - punctuation_p - space_p - invalid_p), - - // Keywords must not be followed by a word char or '/' - keyword_p ( word_p | boost::spirit::ch_p('/') ) + statement_end, opt_path; + definition(CommandGrammar const & self) { 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); + 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< FilePositionWithIndex > > pos_ (self.context.pos); + actor< variable< ParseDispatcher > > d_ (self.dispatcher); assertion end_of_statement_expected (EndOfStatementExpected); - assertion group_or_arguments_expected (GroupOrArgumentsExpected); assertion path_expected (PathExpected); assertion closing_paren_expected (ClosingParenExpected); assertion quote_expected (QuoteExpected); @@ -190,38 +201,39 @@ namespace detail { = builtin >> end_of_statement_expected(statement_end) | group_close | ch_p(';') // Ignore empty commands - | path_expected(path) - >> group_or_arguments_expected( group_start | statement ) + | statement + ; + + statement + = path_expected(path) [ bind(&PD::beginCommand)(d_, path_) ] + >> arguments + >> end_of_statement_expected( + ( group_start | statement_end ) + [ bind(&PD::endCommand)(d_) ] + ) ; builtin - = keyword_p("cd") + = self.keyword_p("cd") >> path_expected(path) >> eps_p [ bind(&PD::builtin_cd)(d_, path_) ] - | keyword_p("ls") + | self.keyword_p("ls") >> ! path >> eps_p [ bind(&PD::builtin_ls)(d_, path_) ] - | keyword_p("exit") [ bind(&PD::builtin_exit)(d_) ] - | keyword_p("help") + | self.keyword_p("exit") [ bind(&PD::builtin_exit)(d_) ] + | self.keyword_p("help") >> ! path >> eps_p [ bind(&PD::builtin_help)(d_, path_) ] ; group_start - = ch_p('{') [ bind(&PD::pushDirectory)(d_, path_) ] + = ch_p('{') [ bind(&PD::pushDirectory)(d_) ] ; group_close = ch_p('}') [ bind(&PD::popDirectory)(d_) ] ; - statement - = eps_p [ bind(&PD::beginCommand)(d_, path_) ] - >> arguments - >> end_of_statement_expected(statement_end) - [ bind(&PD::endCommand)(d_) ] - ; - arguments = * argument ; @@ -238,7 +250,7 @@ namespace detail { ; string // Returns value in context.token - = eps_p [ clear(str_) ] + = eps_p [ pos_ = positionOf(arg1) ][ clear(str_) ] >> lexeme_d [ ch_p('"') @@ -248,17 +260,24 @@ namespace detail { ) >> quote_expected(ch_p('"')) [ token_ = construct_(Token::BasicString, - str_) ] + str_, + pos_) ] ] ; hexstring // Returns value in context.token - = eps_p [ clear(str_) ] + = eps_p [ pos_ = positionOf(arg1) ][ clear(str_) ] >> "x\"" >> * ( hexbyte - ch_p('"') ) >> quote_expected(ch_p('"')) [ token_ = construct_(Token::HexString, - str_) ] + str_, + pos_) ] + ; + + opt_path + = ! path [ bind(&PD::beginCommand)(d_, path_) ] + [ bind(&PD::endCommand)(d_) ] ; path // Returns value in context.path @@ -279,15 +298,19 @@ namespace detail { ; balanced_tokens - = ch_p('(') [ token_ = construct_( + = eps_p [ pos_ = positionOf(arg1) ] + >> ch_p('(') [ token_ = construct_( Token::ArgumentGroupOpen, - "(") ] + "(", + pos_) ] [ bind(&PD::pushToken)(d_, token_) ] >> * token + >> eps_p [ pos_ = positionOf(arg1) ] >> closing_paren_expected(ch_p(')')) [ token_ = construct_( Token::ArgumentGroupClose, - ")") ] + ")", + pos_) ] [ bind(&PD::pushToken)(d_, token_) ] ; @@ -298,31 +321,37 @@ namespace detail { ; punctuation // Returns value in 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)) ] + = eps_p [ pos_ = positionOf(arg1) ] + >> ( + ch_p('/') [ token_ = construct_( + Token::PathSeparator, + "/") ] + | ch_p('{') [ token_ = construct_( + Token::DirectoryGroupOpen, + "{") ] + | ch_p('}') [ token_ = construct_( + Token::DirectoryGroupClose, + "}") ] + | ch_p(';') [ token_ = construct_( + Token::CommandTerminator, + ";") ] + | self.punctuation_p [ token_ = construct_( + Token::OtherPunctuation, + construct_(1u, arg1), + pos_) ] + ) ; word // Returns value in context.token - = lexeme_d + = eps_p [ pos_ = positionOf(arg1) ] + >> lexeme_d [ - (+ word_p) [ str_ = construct_(arg1, arg2) ] + (+ self.word_p) [ str_ = construct_(arg1, arg2) ] ] >> eps_p [ token_ = construct_( Token::Word, - str_) ] + str_, + pos_) ] ; hexbyte @@ -341,7 +370,7 @@ namespace detail { ; skip - = space_p | comment_p('#') + = self.space_p | comment_p('#') ; /////////////////////////////////////////////////////////////////// @@ -349,7 +378,8 @@ namespace detail { start_parsers( command, // CommandParser skip, // SkipParser - arguments // ArgumentsParser + arguments, // ArgumentsParser + opt_path // PathParser ); BOOST_SPIRIT_DEBUG_TRACE_RULE(command,1); @@ -374,6 +404,19 @@ namespace detail { }; }; + template boost::spirit::chset<> CommandGrammar::special_p ( + "/(){};\""); + template boost::spirit::chset<> CommandGrammar::punctuation_p ( + ",="); + template boost::spirit::chset<> CommandGrammar::space_p ( + " \t\n\r"); + template boost::spirit::chset<> CommandGrammar::invalid_p ( + (boost::spirit::chset<>('\0') | boost::spirit::chset<>("\x01-\x20")) - space_p ); + template boost::spirit::chset<> CommandGrammar::word_p ( + boost::spirit::anychar_p - special_p - punctuation_p - space_p - invalid_p); + template boost::spirit::distinct_parser<> CommandGrammar::keyword_p ( + word_p | boost::spirit::ch_p('/')); + #endif }}}