Boost Spirit x3:解析分隔字符串

Boost Spirit x3: parse delimited string

我正在用 Spirit X3 编写另一个无聊的计算器解析器,我遇到了一个问题:我定义了 2 个文字,"cos" 和 "cosh",每个都期望后跟一个数字。我写的规则是:

const std::string COS_TAG = "cos";
const std::string COSH_TAG = "cosh";
const auto cos = (COS_TAG > value)[math::cos_solver{}];
const auto cosh = (COSH_TAG > value)[math::cosh_solver{}];

(我知道语义动作不是首选方式,但我很懒惰)。 现在,解析 "cosh 3.5" 时的问题是:

expectation failure: expecting value here "cosh 3.5"
----------------------------------------------^-----

看起来解析器很急于使用第一个标记而不检查另一个标记。我已经通过使用这样的差异运算符使其工作:

const std::string COS_TAG = "cos";
const std::string COSH_TAG = "cosh";
const auto cos = ((x3::lit(COS_TAG) - COSH_TAG) > value)[math::cos_solver{}];
const auto cosh = (COSH_TAG > value)[math::cosh_solver{}];

有没有更好的方法?

因此,不是分隔字符串,而是检查标记边界。

Qi 存储库为此提供了 distinct,我想我可能已经在 X3 代码库中看过一次。会找的。

不管怎样,为了now/older versions/your的理解,这里有一些实现的方法:

  • 重新排序分支,如果你在 cos 之前匹配 cosh 你会得到你想要的行为,因为贪婪

  • 对您的标识符做出更笼统的断言:

    auto kw = [](auto p) {
         return x3::lexeme [ x3::as_parser(p) >> !x3::char_("a-zA-Z0-9_") ];
    };
    

    现在您可以使用 kw(COSH) 而不是 lit(COSH) 并确保它不匹配 coshida.