::boost::spirit:+alnum_p和连字符

::boost::spirit: +alnum_p and hyphen

本文关键字:连字符 +alnum boost spirit      更新时间:2023-10-16

现在我有了这个提升::精神模式:

        str_p("url(") >> !( str_p("'") | str_p(""") ) >> ("#") >>
        ((+alnum_p)[assign_a(o_rPaintUri)] >> 
        !( str_p("'") | str_p(""") ) >> str_p(")")

这可以很好地解析像url(#myRadialGradient)这样的东西,但是如果有像url(#my-RadialGradient4)这样的连字符,它就不起作用了。我试过(+alnum_p | '-')[assign_a(o_rPaintUri)]之类的东西,但它不起作用。

有人知道怎么做吗?

感谢

这是精神经典(又名v1.x)。
PS没有线索,但你可以尝试(+(alnum_p | ch_p('-')))而不是(+alnum_p | '-')

你应该进入本世纪,使用Spirit V2(大约十年前它取代了v1):

Spirit V2

在Coliru上直播

#include <boost/spirit/include/qi.hpp>
int main() {
    for (std::string const sample : {
            "url(#myRadialGradient)",
            "url(#my-RadialGradient4)",
            "url('#my-RadialGradient4')",
            "url("#my-RadialGradient4")",
            })
    {
        std::cout << " -- parsing '" << sample << "'n";
        std::string o_rPaintUri;
        bool ok;
        {
            using namespace boost::spirit::qi;
            ok = parse(sample.begin(), sample.end(),
                    "url(" >> -char_("'"") >> "#" >> +(alnum|char_('-')) >> -char_("'"") >> ")",
                    o_rPaintUri);
        }
        if (ok)
            std::cout << "Parsed: '" << o_rPaintUri << "'n";
        else
            std::cout << "Parse failedn";
    }
}

打印

-- parsing 'url(#myRadialGradient)'
Parsed: 'myRadialGradient'
-- parsing 'url(#my-RadialGradient4)'
Parsed: 'my-RadialGradient4'
-- parsing 'url('#my-RadialGradient4')'
Parsed: ''my-RadialGradient4''
-- parsing 'url("#my-RadialGradient4")'
Parsed: '"my-RadialGradient4"'

Spirit X3

相同,但将qi替换为x3。我建议进行一些改进:

  • 现在支持引号中的任何字符(除了引号字符)
  • 现在期望所有语法元素并报告有用的错误

在Coliru上直播

#include <boost/spirit/home/x3.hpp>
#include <boost/exception/all.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
int main() {
    for (std::string const sample : {
            "url(#myRadialGradient)",
            "url(#my-RadialGradient4)",
            "url('#my-RadialGradient4')",
            "url("#my-RadialGradient4")",
            // extra
            "url('#my-RadialGradient4")",
            "url('#my-Radial_Gradient4')",
            "url('#my-Radial_Gradient4'",
            "url(oops)",
            "url('oops')",
            "url("oops")",
            "oops",
            })
    {
        std::cout << " -- parsing " << sample << "n";
        std::string o_rPaintUri;
        bool ok = false;
        try {
            using namespace x3;
            auto q = [](auto quote) { return quote > as_parser('#') > *(char_ - quote) > quote; };
            auto u = rule<struct url, std::string> { "#anchor|'#anchor'|"#anchor"" } // FOR ERROR INFO ONLY
                   = q("'") | q('"') | '#' >> *~char_(')');
            ok = parse(sample.begin(), sample.end(), eps > "url(" > u > ")", o_rPaintUri);
            if (ok)
                std::cout << "Parsed: '" << o_rPaintUri << "'n";
            else
                std::cout << "Parse failedn";
        } catch (x3::expectation_failure<std::string::const_iterator> const& e) {
            std::cout << "    Error: '" << std::string(e.where(), sample.end()) << "', expecting " << e.which() << "n";
        }
    }
}

打印

-- parsing url(#myRadialGradient)
Parsed: 'myRadialGradient'
-- parsing url(#my-RadialGradient4)
Parsed: 'my-RadialGradient4'
-- parsing url('#my-RadialGradient4')
Parsed: 'my-RadialGradient4'
-- parsing url("#my-RadialGradient4")
Parsed: 'my-RadialGradient4'
-- parsing url('#my-RadialGradient4")
    Error: '', expecting "'"
-- parsing url('#my-Radial_Gradient4')
Parsed: 'my-Radial_Gradient4'
-- parsing url('#my-Radial_Gradient4'
    Error: '', expecting ')'
-- parsing url(oops)
    Error: 'oops)', expecting #anchor|'#anchor'|"#anchor"
-- parsing url('oops')
    Error: 'oops')', expecting '#'
-- parsing url("oops")
    Error: 'oops")', expecting '#'
-- parsing oops
    Error: 'oops', expecting "url("