Форум программистов, компьютерный форум, киберфорум
Наши страницы
Boost C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
DiffEreD
1442 / 779 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
1

Spirit::qi - семантическое действие

05.03.2015, 14:52. Просмотров 1119. Ответов 3
Метки нет (Все метки)

Суть - парсим значения в мапу (ключ, значение), после, есть правило expr, которое должно парсить примерно такой текст: val1 = val2 + val3;. val2 и val3 должны быть ключами в мапе. Надо результируючей переменной типа int присвоить значения из map[val2], map[val3]. Вот, пока такой код написал. Но он пока не компилируется.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <utility>
#include <boost/phoenix/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/repository/include/qi_confix.hpp>
#include <boost/fusion/include/std_pair.hpp>
 
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
 
using map_t = std::map<std::string, int>;
using pair_t = std::pair<std::string, int>;
 
struct map_value
{
   typedef int result_type;
 
   template <typename Map>
   int operator() (const Map& m, const std::string& key) const
   {
      if (m.find(key) != m.end()) return m.at(key);
      else return 0;
   }
};
 
phx::function<map_value> get_map_val = map_value();
 
//grammar:
/*
 * val1 = 42;
 * val2 = 84;
 * val2 = 0;
 * val1 = val2 + val3;
 * val2 = val2 - val3;
*/
template <typename Iterator>
struct my_grammar : qi::grammar<Iterator, map_t(), int(), qi::space_type>
{
   my_grammar(const map_t& map_var) : my_grammar::base_type(pairs)
   {
      pairs = pair % pair >> ';';
      pair  = key >> '=' >> value;
      key   = (qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_'));
      value = qi::int_;
 
      // qi::_val это int
      // qi::_val надо присвоить то, что есть key в нашей map_var : map_var[key]
      expr = key >> '=' >> key[qi::_val = get_map_val(map_var, qi::_1)]
            >> *('+' >> key[qi::_val += get_map_val(map_var, qi::_1)]
            | '-' >> key[qi::_val -= get_map_val(map_var, qi::_1)]);
   }
 
   qi::rule<Iterator, map_t(), int(), qi::space_type> pairs;
   qi::rule<Iterator, pair_t(), qi::space_type> pair;
   qi::rule<Iterator, std::string()> key;
   qi::rule<Iterator, int()> value;
 
   qi::rule<Iterator, int()> expr;
};
 
int main()
{
   std::string expr;
   map_t map;
   int res = 0;
 
   while (true)
   {
      std::cout << "Enter expr: ";
      std::getline(std::cin, expr);
      std::string::iterator  begin = expr.begin(), end   = expr.end();
      my_grammar<std::string::iterator> gr(map);
      qi::phrase_parse(begin, end, gr, qi::space, map, res);
 
      for (const auto& p : map)
         std::cout << p.first << " " << p.second << "\n";
      std::cout << "res = " << res << "\n";
   }
}
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.03.2015, 14:52
Ответы с готовыми решениями:

boost::spirit
Пишу парсер на спирите. Задаюсь вопросом как нормально сделать примерно такое lexeme Где...

Производительность boost::spirit::qi
#include &lt;iostream&gt; #include &lt;sstream&gt; #include &lt;chrono&gt; #include...

Spirit не видит юникод символы
Здавствуйте форумчане. Необходимо разобрать строку и заполнить полученными данными структуру....

Spirit::qi - не обновляются данные в грамматике
Есть такой код простой грамматики, которая парсит данные в std::map&lt;std::string, int&gt;. При...

Spirit qi. записать результат парсинга с пробелами
Привет всем ! при использование парсинга spirit::qi возникнул такой вопрос ... при вызове функции ...

3
ForEveR
В астрале
Эксперт С++
8003 / 4761 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
06.03.2015, 12:00 2
DiffEreD, Большинство ошибок убираются просто удалением явного влючения феникса, уже есть в спирите. Остаются ошибки с операторами.

Добавлено через 21 минуту
Можно сделать операции через функторы.

C++
1
2
3
4
5
6
7
8
9
10
11
struct add_val
{
   typedef void result_type;
 
   void operator () (int& result, const int& v) const
   {
      result += v;
   }
};
 
phx::function<add_val> add_value = add_val();
Но меня дико смущает вызов phrase_parse.
0
DiffEreD
1442 / 779 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
06.03.2015, 17:43  [ТС] 3
Цитата Сообщение от ForEveR Посмотреть сообщение
Большинство ошибок убираются просто удалением явного влючения феникса
Сделал так:
C++
1
2
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/phoenix.hpp>
- ошибки не исчезли. Ну да ладно. Может начнем с простого, если всеже интересно помочь. А то я видимо не понимаю сути. Вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <string>
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
 
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
 
template <typename Iterator>
struct my_grammar : qi::grammar<Iterator, std::string()>
{
   my_grammar(int& res) : my_grammar::base_type(start)
   {
      start = *qi::alpha; // только буквы
       // атрибут парсера qi::int_ int - я хочу присвоить этот int переменной res
      int_r = start >> qi::int_[phx::ref(res) = qi::_1];
   }
 
   qi::rule<Iterator, std::string()> start;
   qi::rule<Iterator, int()> int_r;
};
 
int main()
{
   std::string expr, str_res;
   int res = 0;
 
   while (true)
   {
      std::cout << "Enter expr: ";
      std::getline(std::cin, expr);
      std::string::iterator  begin = expr.begin(), end = expr.end();
      my_grammar<std::string::iterator> gr(res);
      qi::parse(begin, end, gr, str_res);
 
      std::cout << "str_res = " << str_res << "\n";
      std::cout << "res = " << res << "\n";
   }
}
Ввод:
Enter expr: hello42
str_res = hello
res = 0 <-- почему res не 42?
Enter expr:
Добавлено через 39 минут
Ну, и еще. Вот разные грамматики: одна для string, одна для int.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
template <typename Iterator>
struct string_grammar : qi::grammar<Iterator, std::string()>
{
   string_grammar() : string_grammar::base_type(start)
   {
      start = *qi::alpha; // только буквы
   }
 
   qi::rule<Iterator, std::string()> start;
};
 
int main()
{
   std::string expr, str_res;
 
   while (true)
   {
      std::cout << "Enter expr: ";
      std::getline(std::cin, expr);
      std::string::iterator  begin = expr.begin(), end = expr.end();
      string_grammar<std::string::iterator> gr;
      qi::parse(begin, end, gr, str_res);
 
      std::cout << "str_res = " << str_res << "\n";
   }
}
Ввод:
Enter expr: hello
str_res = hello
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
template <typename Iterator>
struct int_grammar : qi::grammar<Iterator, int()>
{
   int_grammar() : int_grammar::base_type(start)
   {
      start = qi::int_; // только int
   }
 
   qi::rule<Iterator, int()> start;
};
 
int main()
{
   std::string expr;
   int res = 0;
 
   while (true)
   {
      std::cout << "Enter expr: ";
      std::getline(std::cin, expr);
      std::string::iterator  begin = expr.begin(), end = expr.end();
      int_grammar<std::string::iterator> gr;
      qi::parse(begin, end, gr, res);
 
      //std::cout << "str_res = " << str_res << "\n";
      std::cout << "res = " << res << "\n";
   }
}
Ввод:
Enter expr: 42
res = 42
Они работают. Но, если я хочу парсить и строку и числа, то у меня возникает ошибка компиляции:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
template <typename Iterator>
struct string_int_grammar : qi::grammar<Iterator, std::string(), int()>
{
   string_int_grammar() : string_int_grammar::base_type(str_r)
   {
      str_r = *qi::alpha; // только буквы
      int_r = qi::int_; // только int
   }
 
   qi::rule<Iterator, std::string(), int()> str_r;
   qi::rule<Iterator, int()> int_r;
};
 
int main()
{
   std::string expr, str_res;
   int res = 0;
 
   while (true)
   {
      std::cout << "Enter expr: ";
      std::getline(std::cin, expr);
      std::string::iterator  begin = expr.begin(), end = expr.end();
      string_int_grammar<std::string::iterator> gr;
      qi::parse(begin, end, gr, str_res, res);
 
      std::cout << "str_res = " << str_res << "\n";
      std::cout << "res = " << res << "\n";
   }
}
Добавлено через 5 минут
Собственно, как грамматику заставить парсить данные в несколько разных сущостней?
0
DiffEreD
1442 / 779 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
09.03.2015, 02:06  [ТС] 4
Проблему с первого поста решил так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <string>
#include <map>
#include <utility>
#include <boost/phoenix/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
 
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
 
using map_t = std::map<std::string, int>;
using pair_t = std::pair<std::string, int>;
 
struct insert_impl
{
   template <typename T>
   struct result
   {
      typedef void type;
   };
 
   template <typename Container, typename Arg>
   void operator() (Container & container, const Arg & p) const
   {
      container[p.first] = p.second;
   }
};
 
phx::function<insert_impl> const insert = insert_impl();
 
////////////////////////////////////////////////////////
 
struct get_val_impl
{
   template <typename T>
   struct result
   {
      typedef typename pair_t::second_type type;
   };
 
   template <typename Container, typename Arg>
   typename pair_t::second_type
   operator() (Container & container, const Arg & key) const
   {
      if (container.find(key) != container.end()) return container[key];
      else
         return 0;
   }
};
 
phx::function<get_val_impl> const get_val = get_val_impl();
 
//grammar:
/*
 * Value : int
 * Key : string
 * Pair : Key = Value | Oper
 * Pairs : Pair ;
 * Oper : Key +|- Key
*/
template <typename Iterator>
struct my_grammar : qi::grammar<Iterator, map_t(), qi::space_type>
{
   my_grammar(map_t& map) : my_grammar::base_type(pairs)
   {
      pairs = pair[insert(phx::ref(qi::_val), qi::_1)] >> ';';
      pair  = key >> '=' >> (value | oper);
      key   = (qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_'));
      value = qi::int_;
 
      oper = key[qi::_val = get_val(phx::ref(map), qi::_1)]
            >> *('+' >> key[qi::_val += get_val(phx::ref(map), qi::_1)]
            | '-' >> key[qi::_val += get_val(phx::ref(map), qi::_1)]);
   }
 
   qi::rule<Iterator, map_t(), qi::space_type> pairs;
   qi::rule<Iterator, pair_t(), qi::space_type> pair;
   qi::rule<Iterator, std::string()> key;
   qi::rule<Iterator, int()> value;
   qi::rule<Iterator, int(), qi::space_type> oper;
};
 
int main()
{
   std::string expr;
   map_t map;
 
   while (true)
   {
      std::cout << "Enter expr: ";
      std::getline(std::cin, expr);
      std::string::iterator  begin = expr.begin(), end   = expr.end();
      my_grammar<std::string::iterator> gr(map);
      qi::phrase_parse(begin, end, gr, qi::space, map);
 
      for (const auto& p : map)
         std::cout << p.first << " " << p.second << "\n";
   }
}
Добавлено через 7 минут
Ввод:
Enter expr: a=42
a 42
Enter expr: b=42
a 42
b 42
Enter expr: c=a+b
a 42
b 42
c 84
2
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.03.2015, 02:06

Boost::Spirit. Разбор конфигурационного файла
Есть конфигурационный файл, содержащий текстовое описание данных. Каждая запись конфигурационного...

Метапрограммирование в boost::proto (boost::spirit)
В библиотеке boost:: proto есть такой код calculator&lt;proto::terminal&lt;placeholder&lt;0&gt; &gt;::type&gt;...

Трансивер Spirit-ON TR24A
Может кому попадались такие http://kosmodrom.som.ua/data/tr24a.php цена очень низкая, скорость...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru