Boost.Spirit.Qi optionalとvariant

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

便利べんり。