5

私は次の結果を理解しようとしています。テストケースコードは

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/spirit/home/support/context.hpp>
#include <boost/spirit/home/phoenix.hpp>
#include <boost/foreach.hpp>

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <vector>

namespace sp = boost::spirit;
namespace qi = boost::spirit::qi;
using namespace boost::spirit::ascii;

namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;

using phoenix::at_c;
using phoenix::push_back;
using phoenix::bind;

template <typename P>
void test_parser(
    char const* input, P const& p, bool full_match = true)
{
    using boost::spirit::qi::parse;

    char const* f(input);
    char const* l(f + strlen(f));
    if (parse(f, l, p) && (!full_match || (f == l)))
        std::cout << "ok" << std::endl;
    else
        std::cout << "fail" << std::endl;
}


int main() {

test_parser("+12345", qi::int_ ); //Ok
test_parser("+12345", qi::double_ - qi::int_ ); //failed, as expected
test_parser("+12345.34", qi::int_ );  // failed, as expected
test_parser("+12345.34", qi::double_ - qi::int_ );  //failed but it should be Ok!
};

ここでの動機は、数値「12345」を整数として、決して浮動小数点として一致させたいということです。'12345.34' は double_ に一致し、int_ には一致しませんが、逆の場合は当てはまりません。'12345' は、整数 (int_ ) と浮動小数点 (double_ ) の両方に一致します。double_ - int_ を試してみましたが、「12345」との一致に失敗しました。しかし、私の希望は、最後のテストケース '12345.34' が double_ - int_ に確実に一致することでしたが、結果は一致しませんでした。

なぜそうなのか、整数のみに一致するパーサーと浮動小数点のみに一致する別のパーサーを取得するにはどうすればよいですか (c のように、5.0 は浮動小数点として解釈されます)。

4

2 に答える 2

14

あなたの特定の例については、実際にはスペシャライゼーションの下のブーストスピリットのドキュメントに記載されていると思います. RealPolicies少し簡単にするために、整数ではなく実数のみを解析する簡単な「実数」パーサーを作成しました(または、少なくとも単純化された例では機能しました)。

template <typename T>
struct strict_real_policies : qi::real_policies<T>
{
    static bool const expect_dot = true;
};

qi::real_parser< double, strict_real_policies<double> > real;

これは、他のパーサー (int_ や double_ など) と同じように使用できます。以下を追加する必要があるかもしれません:

#include <boost/spirit/include/qi_numeric.hpp>

コンパイルするには。

于 2010-06-26T23:40:11.027 に答える
4

double-not-int の問題qi::double_ - qi::int_は、個々のパーサーが入力全体を一致させる必要がないことです。"+12345.34" の場合、qi::double_ は全体で一致し、qi::int は "+12345" で一致するため、一致しqi::double_ - qi::int_ません。差分演算子については、各パーサーを個別に適用し、入力の最初の部分でもそれぞれに有効な一致があるかどうかを検討してください。

qi::int_ の後に何らかの境界を要求することで、必要な動作を得ることができます。qi::int_ が float の最初の部分と一致する場合に続くのは、有効な float です (たとえば、"+12345.34" の qi::int_ は "+12345" と一致し、ストリームの次は ".34" のままになります)。したがって、float に対して否定的な先読みを行うことができます。

int_rule %= qi::int_ >> !qi::double_;

double_rule %= qi::double_ - int_rule; 

また

double_rule %= qi::double_ - (qi::int_ >> !qi::double_); 

!qi::double空白と eoi にも当てはまるので、これは標準形式ではかなり一般的であると思います。ただし、これは科学的表記法では機能しません。

于 2010-06-26T23:26:31.593 に答える