从升压精神分析器触发警报 [英] trigger warning from boost spirit parser

查看:130
本文介绍了从升压精神分析器触发警报的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我怎么能在提振精神解析器添加警告。

编辑: ...这可能与位置报告问题

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

 ('0'>> 10月)
| int_

我希望能够做这样的事:

 ('0'>> 10月)
| -0 - >触发警告(负八进制值不支持,这将是PTED为否定十进制值与前导0间$ P $将忽略)
| int_


解决方案

  

问:我创造我自己的回调?怎么样?


一个。确定。任何方式你通常做它在C ++(或看升压第二信号和/或升压日志)

 解析器(的std ::功能<布尔(标准::字符串常量和放大器; S)>回调)
    :分析器:: base_type(开始),
      回调(回调)
{
    使用命名空间补气;    启动(%)=
        as_string [+图]
            [_pass = PHX ::绑定(回调,_1)]
        %+空格
        ;    BOOST_SPIRIT_DEBUG_NODES((开始));
}

正如你所看到的,你甚至可以使处理决定警告是否应该被忽略或导致了比赛的失败。


更新#1 我已经延长了样品展示一些你在评论中提到的无关的挑战(位置,重复检查)。希望这有助于

下面是一个简单的例子:看到它的 住在Coliru(

更新#2 我已经连上了(一)存储源的信息,而不是迭代器,(b)以它的工作花车(或其他任何暴露的属性类型,真的)。

请注意它是多么惊人地相似, S /字/数字/ ,基本上是:住在Coliru(编号

 的#define BOOST_RESULT_OF_USE_DECLTYPE //需要GCC 4.7,不铛++
#定义BOOST_SPIRIT_USE_PHOENIX_V3
#包括LT&;升压/精神/有/ qi.hpp>
#包括LT&;升压/精神/有/ phoenix.hpp>
#包括LT&;升压/精神/有/ phoenix_stl.hpp>
的#include<功能>命名空间补气=的boost ::精神::补气;
命名空间PHX =提振::凤;//好了,你想要的位置报告(实际上是不相关的):
#包括LT&;升压/精神/有/ support_line_pos_iterator.hpp>
使用它=的boost ::精神:: line_pos_iterator<的std ::字符串::为const_iterator取代;这再次presents // AST键入数字令牌(带有源和位置
//信息)
结构号码
{
    双重价值;
    为size_t line_pos;
    标准::字符串来源;    明确数(双值= 0.0,提振:: iterator_range的<它>常量和放大器;范围= {})
        :
          值(值),
          line_pos(get_line(range.begin())),
          源(range.begin(),range.end())
    {}    布尔运算符< (常量数字与安培;其他){const的回报(other.value - 值)> 0.0001; }
};//解析器暴露的属性:
用字=的std ::设为<号码取代;//为我们的警告回调签名;你可以使它更像
//`on_error`所以它直接将迭代器,但同样,我做的
//为dmeo简单的事情
使用回调=的std ::功能<布尔(数字常量和放大器; S)取代;模板< TYPENAME它>
    结构解析器:补气::语法<它,字()>
{
    解析器(回拨警告)
        :分析器:: base_type(开始),
          (报警)
    {
        使用命名空间补气;
        汽车check_unique = PHX ::端(_val)== PHX ::发现(_val,_1);    字=
               生[double_ [_a = _1] [_val = PHX ::构建<数字与GT;(_一,_1)]
               ;        启动(%)=
                - 字[_pass = check_unique || PHX ::绑定(警告,_1)]
               %+空格
               >> EOI
               ;
    }  私人的:
    回拨警告;
    齐::规则<它,号码(),齐::当地人<双> >字;
    齐::规则<它,字()>开始;
};INT主(INT ARGC,为const char * argv的[])
{
    //解析命令行参数
    常量汽车标志=的std ::设为<标准::字符串> {ARGV + 1,+ ARGV ARGC};
    !常量布尔fatal_warnings =结束(标志)= flags.find( - Werror);    //测试输入
    常量的std ::字符串输入(2.4 2.7 \\ n \\ n \\ n-INF \\ n \\ nNaN 88 -2.40001 \\ n3.14 240001e-5 \\ n \\ ninf);    //警告处理
    汽车warning_handler = [&安培](数字常量和放大器; W){
        的std :: CERR<< (?fatal_warnings错误:警告)
                  << :近乎相同的条目'<< w.source<< '在L:<< w.line_pos<< \\ n;
        返回fatal_warnings!;
    };    //做解析
    它F(开始(输入)),L(端(输入));
    布尔OK =齐::解析(F,L,解析器<它>(warning_handler));    //报告结果
    如果(OK)的std ::法院LT&;< 解析成功\\ n;
    其他的std :: CERR<< 解析失败\\ n;
    如果(F = L!)的std :: CERR<< 尾随未解析:'<<标准::字符串(F,L)LT;< '\\ n;    //退出code
    返回OK? 0:255;
}

打印:

 警告:为L近乎相同的条目'楠:6
警告:近乎相同的条目'240001e-5'在L:7
解析成功

How I can add warnings in boost spirit parser.

Edit: ... that could report the issue with position

For example if I have an integer parser:

('0' >> oct)
| int_

I would like to be able to do something like this:

('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. Sure. Any way you'd normally do it in C++ (or look at Boost Signal2 and/or 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));
}

As you can see, you can even make the handler decide whether the warning should be ignored or cause the match to fail.


UPDATE #1 I've extended the sample to show some of the unrelated challenges you mentioned in the comments (position, duplicate checking). Hope this helps

Here's a simple demonstration: see it Live on Coliru (Word)

UPDATE #2 I've even made it (a) store the source information instead of the iterators, (b) made it "work" with floats (or any other exposed attribute type, really).

Note how uncannily similar it is, s/Word/Number/, basically: 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;
}

Prints:

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

这篇关于从升压精神分析器触发警报的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆