четверг, 29 ноября 2012 г.

Boost Spirit::Qi, разбор выражений с числом элементов, большим десяти

При попытке разобрать парсером Spirit::Qi выражение, в котором более десяти элементов, компилятор сообщает об ошибках вида error: '_10' is not a member of 'qi'. Продолжительные и нерегулярные :-) раскопки исходников Qi, а так же связанных с ним Phoenix-а и fusion-а, в конце концов привели к следующим определениям, которые нужно изменить в нужную для себя сторону:
#define PHOENIX_LIMIT                   20 /* Или сколько там надо их парсить... */
#define FUSION_MAX_VECTOR_SIZE          PHOENIX_LIMIT
#define BOOST_RESULT_OF_NUM_ARGS        PHOENIX_LIMIT

После их явного задания требуемые данные успешно распарсились в вектор кортежей:
namespace ph = boost::phoenix;
namespace qi = boost::spirit::qi;
using boost::spirit::ascii::space_type;
//--------------------------------------------------------------------------
typedef double ValueType;
typedef ValueType First;        static const size_t FirstIndex = 0;
typedef ValueType Second;       static const size_t SecondIndex = FirstIndex + 1;
typedef ValueType Third;        static const size_t ThirdIndex = SecondIndex + 1;
typedef ValueType Fourth;       static const size_t FourthIndex = ThirdIndex + 1;
typedef ValueType Fifth;        static const size_t FifthIndex = FourthIndex + 1;
typedef ValueType Sixth;        static const size_t SixthIndex = FifthIndex + 1;
typedef ValueType Seventh;      static const size_t SeventhIndex = SixthIndex + 1;
typedef ValueType Eight;        static const size_t EightIndex = SeventhIndex + 1;
typedef ValueType Ninth;        static const size_t NinthIndex = EightIndex + 1;
typedef ValueType Tenth;        static const size_t TenthIndex = NinthIndex + 1;
typedef ValueType Eleventh;     static const size_t EleventhIndex = TenthIndex + 1;
typedef ValueType Twelfth;      static const size_t TwelfthIndex = EleventhIndex + 1;
typedef bool Locked;            static const size_t LockedIndex = TwelfthIndex + 1;
//--------------------------------------------------------------------------
typedef std::tuple<First,Second,Third,Fourth,Fifth,Sixth,       \
                   Seventh,Eight,Ninth,Tenth,Eleventh,Twelfth,  \
                   Locked> Data;
typedef std::vector<Data> DataContainer;
//--------------------------------------------------------------------------
struct phoenix_make_tuple_impl
{ /* Tuple create adapter  */
  template <typename... Args>
  struct result
  {
    typedef std::tuple<Args...> type;
  };
  template <typename... Args>
  typename result<Args...>::type operator () (Args... args) const
  {
    return std::make_tuple(args...);
  }
};
ph::function<phoenix_make_tuple_impl> const phoenix_make_tuple = phoenix_make_tuple_impl();
//--------------------------------------------------------------------------
template <typename Iterator,typename Container> \
struct ParserGrammar : qi::grammar              \
<Iterator,Container(),qi::blank_type>           \
{
  typedef typename Container::value_type Value;
  ParserGrammar(Container& container) :         \
    ParserGrammar::base_type(start)
  {
    start = qi::lit("Data") >> qi::lit("=") >>     \
      containerData                                \
      [ph::push_back(ph::ref(container),qi::_1)] % \
      qi::eol;
    containerData =                                     \
      (first >> second >> third >> fourth >>            \
       fifth >> sixth >> seventh >> eight >>            \
       ninth >> tenth >> eleventh >> twelfth >>         \
       locked)                                          \
      [qi::_val = phoenix_make_tuple                    \
       (qi::_1,qi::_2,qi::_3,qi::_4,qi::_5,qi::_6,      \
        qi::_7,qi::_8,qi::_9,qi::_10,qi::_11,qi::_12,   \
        qi::_13)];
    first = second = third = fourth = fifth =         \
      sixth = seventh = eight = ninth = tenth =       \
      eleventh = twelfth = qi::double_;
    locked = qi::bool_;
    return;
  }
  qi::rule<Iterator,Container(), qi::blank_type> start;
  qi::rule<Iterator,Value(), qi::blank_type> containerData;
  qi::rule<Iterator,double()>                   \
    first,second,third,fourth,fifth,sixth,      \
    seventh,eight,ninth,tenth,eleventh,twelfth;
  qi::rule<Iterator, bool()> locked;
};
//--------------------------------------------------------------------------
const std::string dataString = "Data = 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 10.10 11.11 12.12\n\
10.10 20.20 30.30 40.40 50.50 60.60 70.70 80.80 90.90 100.100 110.110 120.120\n";