2

ブーストスピリットパーサーに警告を追加する方法。

編集: ...それは位置の問題を報告する可能性があります

たとえば、整数パーサーがある場合:

('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_
4

1 に答える 1

5

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サンプルを拡張して、コメントで言及した無関係な課題 (位置、重複チェック) のいくつかを示しました。お役に立てれば

簡単なデモンストレーションを次に示します。Coliru でのライブをご覧ください ( Word)

更新 #2 (a) イテレータの代わりにソース情報を格納し、(b) フロート (または実際には他の公開された属性タイプ) で「機能」するようにしました。

奇妙に似ていることに注意してください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
于 2013-10-08T06:40:42.177 に答える