c++ - 如何绕过贪婪的路?

标签 c++ boost-spirit boost-spirit-x3

我想解析一个可以包含“-”但既不以它开头也不以它结尾的字符串。

我希望这个解析器能工作:

auto const parser = alnum >> -(*(alnum | char_('-')) >> alnum);

但在我的测试输入“something”中,它只解析“so”而不会吃掉其余部分。

问题是中间位 *(alnum | char_('-')) 一直吃到最后(包括最后一个字符,所以整个可选括号失败)。

解释的方式和原因 herehere

我想知道的是,我怎样才能绕过它并制作这个解析器?

现场观看:http://coliru.stacked-crooked.com/a/833cc2aac7ba5e27

最佳答案

我个人会“积极地”写它:

auto const rule = raw [ lexeme [
    alnum >> *('-' >> alnum | alnum) >> !(alnum|'-') 
] ];

这使用

  • lexeme 处理空白意义,
  • raw 以避免必须主动匹配您想要作为输出一部分的每个字符(您只需要所有字符)。
  • '-' >> alnum 积极地 要求任何破折号后跟一个 alnum。请注意,这也禁止输入中的 "--" 。请参阅下面的VARIANT

Live On Coliru

#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <string>
#include <algorithm>

namespace x3 = boost::spirit::x3;

namespace parser {
    using namespace boost::spirit::x3;

    auto const rule = raw [ lexeme [
        alnum >> *('-' >> alnum | alnum) >> !(alnum|'-') 
    ] ];
}

int main() {
    struct test { std::string input; bool expected; };

    for (auto const t : {
            test { "some-where", true },
            test { " some-where", true },
            test { "some-where ", true },
            test { "s", true },
            test { " s", true },
            test { "s ", true },
            test { "-", false },
            test { " -", false },
            test { "- ", false },

            test { "some-", false },
            test { " some-", false },
            test { "some- ", false },

            test { "some--where", false },
            test { " some--where", false },
            test { "some--where ", false },
        })
    {
        std::string output;
        bool ok = x3::phrase_parse(t.input.begin(), t.input.end(), parser::rule, x3::space, output);
        if (ok != t.expected)
            std::cout << "FAILURE: '" << t.input << "'\t" << std::boolalpha << ok << "\t'" << output << "'\n";
    }
}

变体

为了也允许 some--thing 和类似的输入,我将 '-' 更改为 +lit('-') :

alnum >> *(+lit('-') >> alnum | alnum) >> !(alnum|'-') 

Live On Coliru

#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <string>
#include <algorithm>

namespace x3 = boost::spirit::x3;

namespace parser {
    using namespace boost::spirit::x3;

    auto const rule = raw [ lexeme [
        alnum >> *(+lit('-') >> alnum | alnum) >> !(alnum|'-') 
    ] ];
}

int main() {
    struct test { std::string input; bool expected; };

    for (auto const t : {
            test { "some-where", true },
            test { " some-where", true },
            test { "some-where ", true },
            test { "s", true },
            test { " s", true },
            test { "s ", true },
            test { "-", false },
            test { " -", false },
            test { "- ", false },

            test { "some-", false },
            test { " some-", false },
            test { "some- ", false },

            test { "some--where", true },
            test { " some--where", true },
            test { "some--where ", true },
        })
    {
        std::string output;
        bool ok = x3::phrase_parse(t.input.begin(), t.input.end(), parser::rule, x3::space, output);
        if (ok != t.expected)
            std::cout << "FAILURE: '" << t.input << "'\t" << std::boolalpha << ok << "\t'" << output << "'\n";
    }
}

关于c++ - 如何绕过贪婪的路?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38561300/

相关文章:

c++ - 在windows中获取文件大小

python - 如何在没有 XGBoost 库的情况下生成 XGBoost 输出?

C++ boost::spirit 解析嵌入式语言

c++ - 振奋 spirit 及相关零件

c++ - 无法使用 Boost Spirit X3 解析空的 C++ 结构

c++ - boost spirit x3 元组构造和隐式 unused_type

c++ - 处理模板列表的元函数

c++ - 为什么这个 OpenCV 代码什么都不做?

c++ - Boost Spirit 和抽象语法树设计

c++ - 使用转义序列处理为引用的字符串创建一个boost::spirit::x3解析器