Problems with grammar

2019-07-08 02:34发布

I need to parse an expression and I'm using boost :: spirit, the expression must have the form (@anything but @ followed of the string .PV@), and I am using the following grammar

P = S >> "." >> V;

S = ch_p('@') >> +~ch_p('@');

V = str_p(".PV@");

but does not work me, could you tell me where is the error. I need do it with a grammar and I am using namespace boost::spirit

1条回答
来,给爷笑一个
2楼-- · 2019-07-08 02:45

Update For completeness adding the regex approach (see at the bottom)

In spirit V2 I'd suggest the simpler

    P = S >> V;
    S = '@' >> +(char_ - '@' - V);
    V = ".PV@";

Assuming that you didn't mean a double . to be required. See a test program Live On Coliru.

Also, note the confix parser in the spirit repository, which could do this slightly more succinctly:

confix('@', ".PV@")[+(char_ - '@' - ".PV@")]

See that Live On Coliru as well.

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/repository/include/qi_confix.hpp>

namespace qi = boost::spirit::qi;
using boost::spirit::repository::confix;

int main()
{
    std::string const input("@anything but &at; followed of the string .PV@");
    std::string parsed;

    auto f(input.begin()), l(input.end());
    bool ok = qi::parse(
            f, l,
            confix('@', ".PV@") [+(qi::char_ - '@' - ".PV@")],
            parsed);

    if (ok)   std::cout << "parse success\ndata: " << parsed           << "\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? 0 : 255;
}

Output:

parse success
data: anything but &at; followed of the string

Regex Approach

Depending on your use case, you could use a regular expression as has been pointed out in comments. See a simple demo Live On Coliru

#include <boost/regex.hpp>
using boost::regex;

int main()
{
    std::string const input("@anything but &at; followed of the string .PV@");

    boost::smatch matches;
    if(regex_search(input, matches, regex("@(.*?)\\.PV@")))
        std::cout << "Parse success, match string: '" << matches[1] << "'\n";
}

Bear in mind,

  • Boost Regex is not header only, so you incur the library dependency if you don't already use it
  • std::regex is not ready on any compiler/platform I know of
查看更多
登录 后发表回答