我正在用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{}];
有更好的方法吗?
答案 0 :(得分:2)
因此,请不要分隔字符串,而要检查令牌边界。
Qi存储库为此使用了distinct
,我想我可能曾经在X3代码库中浏览过它。会寻找的。 p>
无论如何,对于现在/较旧的版本/您的理解,这里有一些实现方法:
对分支进行重新排序,如果在cosh
之前匹配cos
,则由于贪婪而获得所需的行为
对您的标识符进行更一般的断言:
auto kw = [](auto p) {
return x3::lexeme [ x3::as_parser(p) >> !x3::char_("a-zA-Z0-9_") ];
};
现在可以使用lit(COSH)
代替kw(COSH)
,并确保它与coshida
不匹配。