Qiで便利な演算子を2つ紹介。
ひとつは、値が0回もしくは1回のみ現れる、省略可能な値のパースに使用する単項の-演算子。
これはboost::optional
#include <iostream> #include <boost/spirit/include/qi.hpp> #include <boost/optional.hpp> #include <boost/optional/optional_io.hpp> void parse(const std::string& s) { namespace qi = boost::spirit::qi; typedef boost::optional<int> value_type; typedef qi::rule<std::string::const_iterator, value_type()> rule_type; const rule_type r = '(' >> -qi::int_ >> ')'; value_type result; if (!qi::parse(s.begin(), s.end(), r, result)) { std::cout << "failed" << std::endl; return; } std::cout << result << std::endl; } int main() { parse("(123)"); parse("()"); }
123 --
もうひとつは、数値か文字のどちらかが入る、というようなフィールドに使用する|演算子。
これはboost::variantを返してくれます。
#include <iostream> #include <boost/spirit/include/qi.hpp> #include <boost/variant.hpp> void parse(const std::string& s) { namespace qi = boost::spirit::qi; typedef boost::variant<int, char> value_type; typedef qi::rule<std::string::const_iterator, value_type()> rule_type; const rule_type r = qi::int_ | qi::char_; value_type result; if (!qi::parse(s.begin(), s.end(), r, result)) { std::cout << "failed" << std::endl; return; } std::cout << result << std::endl; } int main() { parse("123"); parse("x"); }
123 x
同じ型の場合はvariantではなく、値としてどちらかにマッチします。
#include <iostream> #include <boost/spirit/include/qi.hpp> #include <boost/variant.hpp> void parse(const std::string& s) { namespace qi = boost::spirit::qi; typedef char value_type; typedef qi::rule<std::string::const_iterator, value_type()> rule_type; const rule_type r = qi::alpha | qi::digit; value_type result; if (!qi::parse(s.begin(), s.end(), r, result)) { std::cout << "failed" << std::endl; return; } std::cout << result << std::endl; } int main() { parse("1"); parse("x"); parse("*"); }
1 x failed
便利べんり。