2016-06-19 6 views
3

私はint32_tまたはdoubleのいずれかを解析するパーサーを作成しようとしています。私はboost::variant<int32_t, double> パーサは12, 100, -42, 7のようなint型を解析するために成功したが、それはここで13.243, 42.7, 12.0 -10000.3ブーストスピリットx3 int32 | double_はdoubleを解析できません

などのダブルスの解析に失敗取り戻すことを期待

const auto int_or_double = boost::spirit::x3::int32 | boost::spirit::x3::double_; 

は生きている:私はこのパーサを書いた最初の試みとして、 demo

なぜこのパーサーはダブルに失敗するのですか?

答えて

5

問題はthis questionとよく似ています。

文法で最初に整数パーサーが発生する場合は、それが望ましいです。入力が"12.9"の場合、パーサはの文字部分を解析し、12になり、.で停止します。 あなたは二重のパーサは、整数1よりも優先されるように順序を逆にする必要がありlive example

:これは今"12.9"のために動作します

const auto double_or_int = boost::spirit::x3::double_ | boost::spirit::x3::int32; 

live example

しかし、二重のため、パーサも整数を解析すると、入力が"12"であっても常にdoubleを得る:live example

これを防ぐために、あなたは厳密ダブルパーサ必要があります。

boost::spirit::x3::real_parser<double, boost::spirit::x3::strict_real_policies<double> > const double_ = {}; 

live example

+0

「strict_real_policies」テンプレートについてはわかりませんでした – Exagon

1

を私が便利に聞こえること、のいずれかについてstrict_real_policiesを知りませんでした。

私はそうのように、一度、より直接的な方法でこれを回避働いていた:

(qi::int_ >> !lit('.') >> !lit('e') >> !lit('E')) | qi::float_ 

あなたはhttp://www.json.org/ 上のフロー・チャートを見て持っている場合は、これら3つの文字は、すべての法的な方法カバーしていることがわかります数はフロートとして解析される可能性があります。 (特に私の問題では)

+3

このアプローチは通常動作しますが、[this one](http://coliru.stacked-crooked .com/a/07be3ea0e2824259)それは失敗します。整数部分が決して失われないことが分かっているなら、私は '(int_ >>!char _(" .eE "))| float_'は等価で、(わずかに)騒音が少ないはずです。 – llonesmiz

+3

それはスキッパーを忘れているので、おそらく 'lexeme [int_ >>!char _(" .eE ")] |になるはずです。 double_' – sehe

+0

@sehe:私が働いていた文法では、すべてのスキッパーを無効にしました。完全なルールは実際には 'non_nil_value = true_ | false_ | (qi :: int_ >>!lit( '。')>>!lit( 'e')>>!lit( 'E'))| qi :: float_ | tstring_ | lua_string_ |テーブル; '。しかし、ええ、一般的に、私は 'lexeme'が関与すべきだと思います。 –

関連する問題