Boost spirit get the whole match as a string

社会主义新天地 提交于 2021-02-07 07:08:50

问题


I'm trying to define my own grammar using boost spirit framework and I'm defining such a matching rule:

value = (
        char_('"') >>
        (*qi::lexeme[
                char_('\\') >> char_('\\') |
                char_('\\') >> char_('"')  |
                graph - char_('"') |
                char_(' ')
        ])[some_func] >>
        char_('"')
);

I'd like to assing an action - some_func - to the part of it, and pass the whole matching string as a parameter. But unfortunately I will get something like vector<boost::variant<boost::fusion::vector2 ..a lot of stuff...)...> . Can I somehow get the whole data as a char*, std::string or even void* with size?


回答1:


Look at qi::as_string:

Output of demo program:

DEBUG: 'some\\"quoted\\"string.'
parse success

To be honest, it looks like you are really trying to parse 'verbatim' strings with possible escape chars. In the respect, the use of lexeme seem wrong (the spaces get eaten). If you want to see samples of escaped string parsing, see e.g.

  • Boost Spirit Implement small one-line DSL on a server application (for this style)
  • Compiling a simple parser with Boost.Spirit (for escaping by duplication)
  • Parsing escaped strings with boost spirit
  • Parse quoted strings with boost::spirit

A simple rearrangement that I think could be made, at least might look like:

  value = qi::lexeme [ 
          char_('"') >>
          qi::as_string [
           *(
                 string("\\\\") 
               | string("\\\"") 
               | (graph | ' ') - '"'
            )
          ] [some_func(_1)] >>
          char_('"')
      ];

Note however that you could simply declare the rule without a skipper and drop the lexeme alltogether: http://liveworkspace.org/code/1oEhei$0

Code (live on liveworkspace)

#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi    = boost::spirit::qi;
namespace phx   = boost::phoenix;

struct some_func_t 
{
    template <typename> struct result { typedef void type; };
    template <typename T> 
        void operator()(T const& s) const
        {
            std::cout << "DEBUG: '" << s << "'\n";
        }
};

template <typename It, typename Skipper = qi::space_type>
    struct parser : qi::grammar<It, Skipper>
{
    parser() : parser::base_type(value)
    {
        using namespace qi;
        // using phx::bind; using phx::ref; using phx::val;

        value = (
                 char_('"') >>
                     qi::as_string
                     [
                         (*qi::lexeme[
                          char_('\\') >> char_('\\') |
                          char_('\\') >> char_('"')  |
                          graph - char_('"') |
                          char_(' ')
                          ])
                     ] [some_func(_1)] >>
                 char_('"')
            );
        BOOST_SPIRIT_DEBUG_NODE(value);
    }

  private:
    qi::rule<It, Skipper> value;
    phx::function<some_func_t> some_func;
};

bool doParse(const std::string& input)
{
    typedef std::string::const_iterator It;
    auto f(begin(input)), l(end(input));

    parser<It, qi::space_type> p;

    try
    {
        bool ok = qi::phrase_parse(f,l,p,qi::space);
        if (ok)   
        {
            std::cout << "parse success\n";
        }
        else      std::cerr << "parse failed: '" << std::string(f,l) << "'\n";

        if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
        return ok;
    } catch(const qi::expectation_failure<It>& e)
    {
        std::string frag(e.first, e.last);
        std::cerr << e.what() << "'" << frag << "'\n";
    }

    return false;
}

int main()
{
    bool ok = doParse("\"some \\\"quoted\\\" string.\"");
    return ok? 0 : 255;
}


来源:https://stackoverflow.com/questions/14992295/boost-spirit-get-the-whole-match-as-a-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!