Boost Spirit x3:解析定界字符串

时间:2019-08-09 07:49:10

标签: boost boost-spirit eager

我正在用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{}];

有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

因此,请不要分隔字符串,而要检查令牌边界。

Qi存储库为此使用了distinct,我想我可能曾经在X3代码库中浏览过它。会寻找的。

无论如何,对于现在/较旧的版本/您的理解,这里有一些实现方法:

  • 对分支进行重新排序,如果在cosh之前匹配cos,则由于贪婪而获得所需的行为

  • 对您的标识符进行更一般的断言:

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

    现在可以使用lit(COSH)代替kw(COSH),并确保它与coshida不匹配。