Форум программистов, компьютерный форум, киберфорум
Boost C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.85/13: Рейтинг темы: голосов - 13, средняя оценка - 4.85
 Аватар для DiffEreD
1458 / 795 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2

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

05.03.2015, 14:52. Показов 2581. Ответов 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
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.03.2015, 14:52
Ответы с готовыми решениями:

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

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

Json Spirit и VS2012
Прошу помощи у знающих. Необходимо прикрутить Json Spirit к Visual Studio 2012. Сам Json брал отсюда: ...

3
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
06.03.2015, 12:00
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
1458 / 795 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
06.03.2015, 17:43  [ТС]
Цитата Сообщение от 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
1458 / 795 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
09.03.2015, 02:06  [ТС]
Проблему с первого поста решил так:
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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
09.03.2015, 02:06
Помогаю со студенческими работами здесь

Thermalright True Spirit 90
Что думаете о Thermalright True Spirit 90 - отзывы о нем вроде очень хорошие, да и сам он не очень дорогой, около 830 руб)

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

Семантическое ядро
Уважаемые оптимизаторы, у меня вопрос про составление Семантического ядра, могли бы вы показать на конкретном примере как это сделать (с...

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

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


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

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru