qi::hold
@Andrzejによって正しく言及されているように、それについての1つの方法です
役立つかもしれないいくつかの観察と、より良い解決策があると思います。
ポイントは、Spirit は設計上、属性の「一時」ストレージを必要としないということです。実際、そもそも属性がコピー可能であると想定することはできません。これがここでの理由です (すべてを単一の std::vector<> に解析し、パーサー ステップごとにコピーすることを想像してみてください)。
より本質的なレベルでは、ここで逆になっているのは属性の処理ではなく、パーサー式自体のように見えます。意図を述べることができず、数値表現を扱うあらゆる種類の複雑さを招きます...本当にそうすべきではありません。
それに対する私の見解は
rule<std::string::iterator, std::string()> zeroTo255, alternatively;
alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];
ご覧のとおり、Spirit に数値を解析させ、実際には範囲を確認するだけです。これは、最初にやりたかったことです。
典型的ではない 2 番目の点は、ルールがstd::string
属性を公開しているという事実unsigned char
です。
これが意識的な設計上の決定であると仮定すると、
- 否定先読み (
!parser
) - 属性には影響しません
- 正先読み (
&parser
) - 属性には影響しません
qi::as_string
、qi::raw
、qi::lexeme
および_qi::no_skip
- セマンティック アクション (自動ルールに依存しないでください)
元のルールを最小限に変更すると、次のようになります。
zeroTo255 = raw [
("25" >> char_("0-5"))
| ('2' >> char_("0-4") >> digit)
| ('1' >> digit >> digit)
| (char_("1-9") >> digit)
| digit
];
qi::hold
これは、_hold_ing 属性値のパフォーマンス上の欠点ではなく、使用するコードとほぼ同じ効果があります。
お役に立てれば。
完全なサンプル: http://liveworkspace.org/code/4v4CQW$0で公開:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
int main()
{
using namespace qi;
rule<std::string::iterator, std::string()> zeroTo255, alternatively;
zeroTo255 = raw [
("25" >> char_("0-5"))
| ('2' >> char_("0-4") >> digit)
| ('1' >> digit >> digit)
| (char_("1-9") >> digit)
| digit
];
alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];
for (auto& input : std::vector<std::string> { "255", "249", "178", "30", "4" })
{
std::string output;
std::cout << "zeroTo255:\t" << std::boolalpha
<< parse(std::begin(input), std::end(input), zeroTo255, output)
<< ": " << output << std::endl;
output.clear();
std::cout << "alternatively:\t" << std::boolalpha
<< parse(std::begin(input), std::end(input), alternatively, output)
<< ": " << output << std::endl;
}
}
出力
zeroTo255: true: 255
alternatively: true: 255
zeroTo255: true: 249
alternatively: true: 249
zeroTo255: true: 178
alternatively: true: 178
zeroTo255: true: 30
alternatively: true: 30
zeroTo255: true: 4
alternatively: true: 4