gpt4 book ai didi

c++ - 来自 boost spirit 解析器的触发警告

转载 作者:行者123 更新时间:2023-11-30 01:57:02 24 4
gpt4 key购买 nike

我如何在 boost spirit 解析器中添加警告。

编辑: ...可以报告位置问题

例如,如果我有一个整数解析器:

('0' >> oct)
| int_

我希望能够做这样的事情:

('0' >> oct)
| "-0" --> trigger warning("negative octal values are not supported, it will be interpreted as negative decimal value and the leading 0 will be ignored")
| int_

最佳答案

Q. Can I create my own callback? How?

A. 当然可以。您通常在 C++ 中使用的任何方式(或查看 Boost Signal2 和/或 Boost Log)

parser(std::function<bool(std::string const& s)> callback) 
: parser::base_type(start),
callback(callback)
{
using namespace qi;

start %=
as_string[+graph]
[ _pass = phx::bind(callback, _1) ]
% +space
;

BOOST_SPIRIT_DEBUG_NODES((start));
}

如您所见,您甚至可以让处理程序决定是应忽略警告还是导致匹配失败。


更新 #1 我扩展了示例以显示您在评论中提到的一些不相关的挑战(位置、重复检查)。希望这有帮助

这里有一个简单的演示:看吧 Live on Coliru (Word)

更新 #2 我什至让它 (a) 存储源信息而不是迭代器,(b) 让它与 float (或任何其他公开的属性类型,真的).

注意它是多么的相似,s/Word/Number/,基本上是: Live On Coliru (Number)

#define BOOST_RESULT_OF_USE_DECLTYPE // needed for gcc 4.7, not clang++
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <functional>

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;

// okay, so you want position reporting (actually unrelated):
#include <boost/spirit/include/support_line_pos_iterator.hpp>
using It = boost::spirit::line_pos_iterator<std::string::const_iterator>;

// AST type that represents a Number 'token' (with source and location
// information)
struct Number
{
double value;
size_t line_pos;
std::string source;

explicit Number(double value = 0.0, boost::iterator_range<It> const& range = {})
:
value(value),
line_pos(get_line(range.begin())),
source(range.begin(), range.end())
{}

bool operator< (const Number& other) const { return (other.value - value) > 0.0001; }
};

// the exposed attribute for the parser:
using Words = std::set<Number>;

// the callback signature for our warning; you could make it more like
// `on_error` so it takes the iterators directly, but again, I'm doing the
// simple thing for the dmeo
using Callback = std::function<bool(Number const& s)>;

template <typename It>
struct parser : qi::grammar<It, Words()>
{
parser(Callback warning)
: parser::base_type(start),
warning(warning)
{
using namespace qi;
auto check_unique = phx::end(_val) == phx::find(_val, _1);

word =
raw [ double_ [ _a = _1 ] ] [ _val = phx::construct<Number>(_a, _1) ]
;

start %=
- word [ _pass = check_unique || phx::bind(warning, _1) ]
% +space
>> eoi
;
}

private:
Callback warning;
qi::rule<It, Number(), qi::locals<double> > word;
qi::rule<It, Words()> start;
};

int main(int argc, const char *argv[])
{
// parse command line arguments
const auto flags = std::set<std::string> { argv+1, argv+argc };
const bool fatal_warnings = end(flags) != flags.find("-Werror");

// test input
const std::string input("2.4 2.7 \n\n\n-inf \n\nNaN 88 -2.40001 \n3.14 240001e-5\n\ninf");

// warning handler
auto warning_handler = [&](Number const& w) {
std::cerr << (fatal_warnings?"Error":"Warning")
<< ": Near-identical entry '" << w.source << "' at L:" << w.line_pos << "\n";
return !fatal_warnings;
};

// do the parse
It f(begin(input)), l(end(input));
bool ok = qi::parse(f, l, parser<It>(warning_handler));

// report results
if (ok) std::cout << "parse success\n";
else std::cerr << "parse failed\n";
if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";

// exit code
return ok? 0 : 255;
}

打印:

Warning: Near-identical entry 'NaN' at L:6
Warning: Near-identical entry '240001e-5' at L:7
parse success

关于c++ - 来自 boost spirit 解析器的触发警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19216119/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com