網站首頁 編程語言 正文
一、行動
到目前為止,本章中的示例只檢測到兩件事:解析器是否成功以及解析器在哪里結束。但是,解析器通常以某種方式處理數據,正如您將在下一個示例中看到的那樣。
Example11.9.Linking actions with parsers
#include <boost/spirit/include/qi.hpp> #include <string> #include <iostream> using namespace boost::spirit; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); bool match = qi::phrase_parse(it, s.end(), qi::int_[([](int i){ std::cout << i << '\n'; })], ascii::space); std::cout << std::boolalpha << match << '\n'; if (it != s.end()) std::cout << std::string{it, s.end()} << '\n'; }
示例 11.9 使用 boost::spirit::qi::int_ 解析一個整數,然后將該整數寫入標準輸出。這就是為什么一個動作與 boost::spirit::qi::int_ 相關聯。動作是應用解析器時調用的函數或函數對象。鏈接是使用運算符 operator[] 完成的,它被 boost::spirit::qi::int_ 和其他解析器重載。示例 11.9 使用 lambda 函數作為操作,該操作需要一個 int 類型的唯一參數并將其寫入標準輸出。
如果您啟動示例 11.9 并輸入一個數字,則會顯示該數字。
傳遞給動作的參數類型取決于解析器。例如, boost::spirit::qi::int_ 轉發一個 int 值,而 boost::spirit::qi::float_ 傳遞一個 float 值。
Example11.10.Boost.Spirit with Boost.Phoenix
#define BOOST_SPIRIT_USE_PHOENIX_V3 #include <boost/spirit/include/qi.hpp> #include <boost/phoenix/phoenix.hpp> #include <string> #include <iostream> using namespace boost::spirit; using boost::phoenix::ref; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); int i; bool match = qi::phrase_parse(it, s.end(), qi::int_[ref(i) = qi::_1], ascii::space); std::cout << std::boolalpha << match << '\n'; if (match) std::cout << i << '\n'; if (it != s.end()) std::cout << std::string{it, s.end()} << '\n'; }
示例 11.10 使用 Boost.Phoenix 將使用 boost::spirit::qi::int_ 解析的 int 值存儲在 i 中。如果 boost::spirit::qi::phrase_parse() 返回 true,則將 i 寫入標準輸出。
這個例子在包含來自 Boost.Spirit 的頭文件之前定義了宏 BOOST_SPIRIT_USE_PHOENIX_V3。此宏選擇 Boost.Phoenix 的第三個和當前版本。這很重要,因為 Boost.Phoenix 是從 Boost.Spirit 派生的,而 Boost.Spirit 包含 Boost.Phoenix 的第二個版本。如果未定義 BOOST_SPIRIT_USE_PHOENIX_V3,則 Boost.Phoenix 的第二個版本將包含在 Boost.Spirit 頭文件中,第三個版本將包含在 boost/phoenix/phoenix.hpp 中。不同的版本會導致編譯器錯誤。
請注意如何詳細定義 lambda 函數。 boost::phoenix::ref() 創建對變量 i 的引用。但是,占位符 _1 不是來自 Boost.Phoenix,而是來自 Boost.Spirit。這很重要,因為 boost::spirit::qi::_1 提供了對具有通常預期類型的??解析值的訪問——示例 11.10 中的 int。如果 lambda 函數使用 boost::phoenix::placeholders::arg1,編譯器會報錯,因為 boost::phoenix::placeholders::arg1 不代表 int;它將基于 Boost.Spirit 中的另一種類型,并且需要提取 int 值。
二、屬性
操作是處理解析值的一種選擇。另一種選擇是將對象傳遞給 boost::spirit::qi::parse() 或 boost::spirit::qi::phrase_parse() 用于存儲解析值。這些對象稱為屬性。它們的類型必須與解析器的類型相匹配。
您已經在上一節中使用過屬性。傳遞給動作的參數也是屬性。每個解析器都有一個屬性。例如,解析器 boost::spirit::qi::int_ 具有 int 類型的屬性。在以下示例中,屬性不會作為參數傳遞給函數。相反,解析后的值存儲在屬性中,可以在 boost::spirit::qi::parse() 或 boost::spirit::qi::phrase_parse() 返回后處理。
Example11.11.Storing anint
value in an attribute
#include <boost/spirit/include/qi.hpp> #include <string> #include <iostream> using namespace boost::spirit; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); int i; if (qi::phrase_parse(it, s.end(), qi::int_, ascii::space, i)) std::cout << i << '\n'; }
示例 11.11 使用解析器 boost::spirit::qi::int_。解析后的 int 值存儲在變量 i 中。 i 作為另一個參數傳遞給 boost::spirit::qi::phrase_parse(),因此成為解析器 boost::spirit::qi::int_ 的一個屬性。 如果您啟動示例 11.11 并輸入一個數字,該數字將被寫入標準輸出流。
Example11.12.Storing severalint
values in an attribute
#include <boost/spirit/include/qi.hpp> #include <string> #include <vector> #include <iterator> #include <algorithm> #include <iostream> using namespace boost::spirit; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); std::vector<int> v; if (qi::phrase_parse(it, s.end(), qi::int_ % ',', ascii::space, v)) { std::ostream_iterator<int> out{std::cout, ";"}; std::copy(v.begin(), v.end(), out); } }
示例 11.12 使用了一個用 qi::int_ % ',' 定義的解析器。解析器接受由逗號分隔的任意數量的整數。像往常一樣忽略空格。
因為解析器可以返回多個 int 值,所以屬性的類型必須支持存儲多個 int 值。該示例傳遞一個向量。如果您開始該示例并輸入多個以逗號分隔的整數,則這些整數將寫入以分號分隔的標準輸出流。
除了向量,您還可以傳遞其他類型的容器,例如 std::list。Boost.Spirit 文檔描述了哪些屬性類型必須與哪些運算符一起使用。
原文鏈接:https://yamagota.blog.csdn.net/article/details/127327582
相關推薦
- 2022-09-27 Python?Matplotlib繪制扇形圖標簽重疊問題解決過程_python
- 2023-09-12 linux配置固定ip
- 2022-07-04 反向傳播BP學習算法Gradient?Descent的推導過程_相關技巧
- 2023-11-19 如何將電腦復制的內容粘貼進MobaXterm?如何復制粘貼
- 2022-09-16 一文詳解Python中復合語句的用法_python
- 2022-06-17 docker修改容器配置文件的3種方法總結_docker
- 2022-10-22 Go語言同步等待組sync.WaitGroup結構體對象方法詳解_Golang
- 2022-12-27 C++實現STL迭代器萃取的示例代碼_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支