来自 boost Spirit 解析器的触发警告

2023-12-01

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

Edit:...可以报告位置问题

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

('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.我可以创建自己的回调吗?如何?

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我扩展了示例以显示您在评论中提到的一些不相关的挑战(位置、重复检查)。希望这可以帮助

这是一个简单的演示:看一下住在科利鲁(Word)

更新#2我什至让它(a)存储源信息而不是迭代器,(b)使其与浮点数(或任何其他公开的属性类型,实际上)一起“工作”。

请注意它是多么惊人的相似,s/Word/Number/, 基本上:住在 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;
}

Prints:

Warning: Near-identical entry 'NaN' at L:6
Warning: Near-identical entry '240001e-5' at L:7
parse success
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

来自 boost Spirit 解析器的触发警告 的相关文章

随机推荐

  • Django 模型中的任意类型数据

    我有一个模型 比如说 Item 我想在其上存储任意数量的属性 例如标题 描述 发布日期 我希望它们不仅仅是字符串 还有 python 类型 所以字符串 布尔值 日期时间等 我在这里有什么选择 由于所有值的数据库类型相同 因此具有单独的名称
  • 对 MERN Stack 等 Web 和 API 解决方案进行身份验证和授权的最佳方式是什么?

    我正在尝试找到实施授权的最佳方法 此时 我唯一需要的是一个简单的免费帐户 但稍后我可能会包含使用 Stripe 等支付系统的 高级 帐户的用户角色 我已经开始阅读和尝试 Auth0 但后来发现了一些其他方法可以做到这一点 Passport
  • Word 非数字中的 rmarkdown 方程是 q‌u‌e‌s‌t‌i‌on 标记

    在 RStudio 中 rmarkdown 方程符号未在 Word 中重现 当我点击Knit Word时 A pi r 2 在Word文档中变成这样 2 html pdf都没有问题 None
  • 如何影响 Shopware 6.4.13.0 中的模板加载顺序

    这与Shopware 6 插件按什么顺序加载 当覆盖不同插件中的模板时 加载顺序很重要并且取决于插件安装日期 我相信在最近的 Shopware 版本中可以以更好的方式解决这个问题 这是如何运作的 您可以从上一个版本开始添加getTempla
  • php 会话在 Android 应用程序中被破坏

    我正在android中构建一个登录应用程序 其中我点击一个url 带有用户名和密码 直到该部分它工作正常 但之后每当我点击一个url 一旦用户通过身份验证 它什么都不返回 即错误消息 例如请先登录 然而 它在非常相似的 iPhone 应用程
  • 更新面板中的按钮正在执行完整的回发?

    我正在遵循一个如何使用此处的更新面板的简单示例 http www asp net Ajax Documentation Live tutorials IntroductionUpdatePanel aspx 在更新面板之外 我有另一个 ht
  • 在 R 中动态子集调查设计对象

    我试图弄清楚如何动态地对调查设计对象进行子集化 我已经构建了循环来发送字符串 但不知道如何删除引号 因此 R 将其读取为调用 我想循环遍历这样的一些 尽管这显然会中断 因为 SUBSET VARIABLE in 4 需要是一个调用而不是一个
  • Java字节码与不同版本的Java兼容吗?

    如果我使用 Java 5 代码将应用程序编译为字节码 生成的 class 文件能够在 Java 1 4 下运行吗 如果后者可以工作并且我正在尝试在我的 Java 1 4 应用程序中使用 Java 5 框架 是否有有什么我应该注意的吗 Nop
  • JSP形式的空字段是null还是“”?

    当表单传递到 servlet 时 是空字段 还是 null 例如 在一个表单中 您将名字作为字段 将姓氏作为字段院长 名字 姓那么它在 servlet 中注册为什么呢 提前致谢 Dean 简单 如果参数名称存在 但值不存在 则它为空 如果参
  • Billingservice Android - 无签名

    我遵循了以下很棒的教程 http blog blundell apps com simple inapp billing payment 我已经完成了教程中所说的所有内容 并且已将所有内容重新阅读了 3 遍 但我仍然没有收到签名intent
  • 如何构建 SQL 查询来查找作为两个特定其他对象的父对象的对象?

    假设我有 2 个表 分别称为父表和子表 一个父母可以有 0 到多个孩子 一个孩子可以有 1 到多个父母 如何找到作为两个特定子元素的父元素的所有父元素 例如 假设我有父母 p a p b p c p d 和孩子 c a c b 它们的结构如
  • 连续训练多个序列模型会减慢速度

    我正在使用 Keras TensorFlow GPU 创建时间序列预测模型 我有 100 倍的时间序列 想为每个时间序列训练一个网络 连续运行几个时间序列很好 但一旦我运行 100 倍或 1000 倍 每个模型的训练时间就会缓慢增加 但肯定
  • 如何在java中设置jasper报表的边距?

    如何在java中设置jasper报表的边距 我有 reports jasper 带边距 但是打印时我必须更改边距 JasperPrint setTopMargins myMarginsValue 不起作用 I use JRPrintServ
  • 将字符串转换为元组并添加到元组

    我有一个这样的配置文件 rects rect1 2 2 10 10 rect2 12 8 2 10 我需要循环遍历这些值并将它们转换为元组 然后我需要制作一个元组的元组 例如 2 2 10 10 12 8 2 10 除了使用正则表达式或 i
  • 使用键盘快捷键触发 Silverlight Prism 命令

    有谁知道是否可以通过快捷方式触发 prism 命令 我的意思是我希望能够以声明方式定义命令与键盘快捷键的绑定 例如ClientUI does 有没有用于此目的的开源库 或者也许是代码示例 I found 这个问题但我不认为它回答了我的问题
  • 获取通用 List 中 T 的实际类型

    如何在运行时使用反射获取通用列表中 T 的实际类型 这取决于您到底要问什么 在泛型类型中编写代码时Blah
  • 将动态参数传递给注释

    我想知道是否有可能将动态值传递给注释属性 我知道注释不是为了修改而设计的 但我正在使用休眠过滤器在我的情况下 要放置的条件不是静态的 我认为唯一的解决方案是使用旨在读取和修改字节码的库 例如 Javassist 或ASM但如果有其他解决方案
  • 处理 tw:counturl addthis 插件中的 <

    我有一个 addthis 插件 用于显示我的 blogspot 博客中的推文总数 我这样用 如果我提到 tw counturl my specific blogger url gt 它会显示推文的确切数量 但问题是 在这种情况下我只能使用一
  • ASP.NET Core 6配置-不同环境下的不同数据库

    我想用不同的配置实现不同的数据库连接 即用于测试的测试和用于生产的演示 但遇到了困难 我实在不知道如何制作配置文件 更不知道如何制作连接的依赖 我有一个 用于测试目的 并且它可以工作 但我不知道如何随环境改变它 这正是他们拥有 launch
  • 来自 boost Spirit 解析器的触发警告

    如何在 boost Spirit 解析器中添加警告 Edit 可以报告位置问题 例如 如果我有一个整数解析器 0 gt gt oct int 我希望能够做这样的事情 0 gt gt oct 0 gt trigger warning nega