Совместимость атрибутов правила

Я пытаюсь написать синтаксический анализатор, который считывает текстовый файл с объявлениями переменных и экземплярами и создает таблицу переменных, содержащую все объявленные переменные со связанными с ними значениями.

Файл выглядит следующим образом:

 int a = 18, b = 1+a*5;
 float test = rand(a);

Для этого я хотел бы использовать библиотеку синтаксического анализатора boost::spirit::qi, которая предоставляет синтаксический анализатор таблицы динамических символов, который может связать символ с изменяемым типом данных T. Недостатком предоставленного синтаксического анализатора таблицы символов является то, что он может связывать его символы только со значениями одного типа данных.

У меня есть следующий код:

 #include <boost/spirit/include/qi.hpp>
 #include <stdint.h>
 #include <string>
 template<typename VTYPE>
 struct VTable : boost::spirit::qi::symbols<char, VTYPE> {
      VTable() {} // empty
 };

 int main()
 {
      using boost::spirit::qi::rule;
      using boost::spirit::qi::space_type;

      VTable<int64_t> intDecs; VTable<double> floatDecs;
      rule<std::string::iterator, boost::variant<int64_t, double>() ,space_type> decs %= (!floatDecs >> intDecs) | floatDecs;
      return 0;
 }

Проблема заключается в одной строке перед оператором возврата. Атрибут в левой части «%=» явно несовместим с атрибутом в правой части (поскольку Visual Studio жалуется на этот код).

Мой вопрос, почему это так?

Когда я читал Documentation of Spirit::Qi, там говорилось следующее об атрибутах парсера:

  • Тип атрибута symbol‹Char, T> равен T.
    =>тип атрибута intDecs должен быть int64_t(), а тип атрибута floatDecs должен быть double()
  • Тип атрибута парсера !a не используется.
  • Если тип атрибута синтаксического анализатора X не используется, а анализатора Y — T, то тип атрибута синтаксического анализатора (X >> Y) — T.
    => тип атрибута (!floatDecs >> intDecs) должен быть int64_t ()
  • Если тип атрибута анализатора a — A, а анализатора b — B, то тип атрибута анализатора (a | b) — это boost::variant()
    тип атрибута (!floatDecs >> intDecs) | floatDecs) должен быть boost::variant()

person user1861174    schedule 13.01.2013    source источник


Ответы (1)


Я нашел источник, который предоставляет алгоритм для отображения атрибутов исходного парсера духа: "http://boost-spirit.com/home/2010/01/31/what-is-the-attribute-type-exposed- парсером/"

После некоторых модификаций я обнаружил, что атрибут

  • (!floatDecs >> intDecs) равно __int64 (думаю, это неудивительно!)
  • floatDecs имеет значение double (неудивительно) и
  • (!floatDecs >> intDecs) | floatDecs — это класс boost::variant‹_int64,double,struct boost::detail::variant::void,structboost::detail::variant::void_,struct boost::detail:: variant::void_,struct boost::detail::variant::void_,struct boost::detail::variant::void_,struct boost::detail::variant::void_,struct boost::detail::variant: :void_,struct boost::detail::variant::void_,struct boost::detail::variant::void_,struct boost::detail::variant::void_,struct boost::detail::variant::void_ ,struct boost::detail::variant::void_,struct boost::detail::variant::void_,struct boost::detail::variant::void_,struct boost::detail::variant::void_,struct boost::detail::variant::void_,struct boost::detail::variant::void_,struct boost::detail::variant::void_>

Для интересующихся алгоритмом:

#include <boost/spirit/include/qi.hpp>
#include <stdint.h>
#include <iostream>
#include <string>

template<typename VTYPE>
struct VTable : boost::spirit::qi::symbols<char, VTYPE> {
    VTable() {} // empty
};

template <typename Expr, typename Iterator = std::string::iterator>
struct attribute_of_parser {
    typedef typename boost::spirit::result_of::compile<boost::spirit::qi::domain, Expr>::type parser_expression_type;
    typedef typename boost::spirit::traits::attribute_of<parser_expression_type, boost::spirit::unused_type, Iterator>::type type;
};

template <typename T>
void display_attribute_of_parser(T const&)
{
    typedef typename attribute_of_parser<T>::type attribute_type;
    std::cout << typeid(attribute_type).name() << std::endl;
}

int main()
{
    using boost::spirit::qi::eps;
    using boost::spirit::qi::rule;
    using boost::spirit::qi::space_type;

    VTable<int64_t> intDecs; VTable<double> floatDecs;
    display_attribute_of_parser((!floatDecs >> intDecs));
    display_attribute_of_parser(floatDecs);
    display_attribute_of_parser((!floatDecs >> intDecs) | floatDecs);

    return 0;
}
person user1861174    schedule 13.01.2013