網站首頁 編程語言 正文
rule規則
在 Boost.Spirit 中,解析器由規則組成。由于規則通常基于 Boost.Spirit 提供的解析器,因此沒有明顯的區別。例如, boost::spirit::ascii::digit 既可以是解析器,也可以是規則。通常,規則指的是更復雜的表達式,例如 qi::int_ % ','。
在迄今為止的所有示例中,規則都直接傳遞給 boost::spirit::qi::parse() 或 boost::spirit::qi::phrase_parse()。通過 boost::spirit::qi::rule,Boost.Spirit 提供了一個類來定義規則變量。例如,如果應該將規則存儲在類的成員變量中,則需要 boost::spirit::qi::rule。
Example11.13.Defining rules withboost::spirit::qi::rule
#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(); qi::rule<std::string::iterator, std::vector<int>(), ascii::space_type> values = qi::int_ % ','; std::vector<int> v; if (qi::phrase_parse(it, s.end(), values, ascii::space, v)) { std::ostream_iterator<int> out{std::cout, ";"}; std::copy(v.begin(), v.end(), out); } }
示例 11.13 的工作方式與示例 11.12 類似。如果您輸入多個以逗號分隔的整數,它們將用分號顯示。與前面的示例相比,解析器沒有直接傳遞給 boost::spirit::qi::phrase_parse(),而是在 boost::spirit::qi::rule 變量中定義。
boost::spirit::qi::rule 是一個類模板。唯一的強制參數是被解析字符串的迭代器類型。在示例中,還傳遞了另外兩個可選模板參數。
第二個模板參數是 std::vector<int>(),它是返回 std::vector<int> 類型向量且不需要參數的函數的簽名。該模板參數表示解析的屬性類型為int向量。
第三個模板參數是 boost::spirit::qi::phrase_parse() 使用的 skipper 的類型。在示例中,使用了船長 boost::spirit::ascii::space。該船長的類型可通過 boost::spirit::ascii::space_type 獲得,并作為模板參數傳遞給 boost::spirit::qi::rule。
如果您希望您的代碼獨立于平臺并使用 C++11 開發環境,您應該更喜歡 boost::spirit::qi::rule 而不是關鍵字 auto。如果值是用 auto 定義的,則該示例在 GCC 和 Clang 中可以正常工作。然而,在 Visual C++ 2013 中,只有第一個數字被解析并寫入標準輸出。
Example11.14.Nesting Rules
#include <boost/spirit/include/qi.hpp> #include <boost/variant.hpp> #include <string> #include <vector> #include <algorithm> #include <iostream> using namespace boost::spirit; struct print : public boost::static_visitor<> { template <typename T> void operator()(T t) const { std::cout << std::boolalpha << t << ';'; } }; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); qi::rule<std::string::iterator, boost::variant<int, bool>(), ascii::space_type> value = qi::int_ | qi::bool_; qi::rule<std::string::iterator, std::vector<boost::variant<int, bool>>(), ascii::space_type> values = value % ','; std::vector<boost::variant<int, bool>> v; if (qi::phrase_parse(it, s.end(), values, ascii::space, v)) { for (const auto &elem : v) boost::apply_visitor(print{}, elem); } }
Example11.14.Nesting Rules
#include <boost/spirit/include/qi.hpp> #include <boost/variant.hpp> #include <string> #include <vector> #include <algorithm> #include <iostream> using namespace boost::spirit; struct print : public boost::static_visitor<> { template <typename T> void operator()(T t) const { std::cout << std::boolalpha << t << ';'; } }; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); qi::rule<std::string::iterator, boost::variant<int, bool>(), ascii::space_type> value = qi::int_ | qi::bool_; qi::rule<std::string::iterator, std::vector<boost::variant<int, bool>>(), ascii::space_type> values = value % ','; std::vector<boost::variant<int, bool>> v; if (qi::phrase_parse(it, s.end(), values, ascii::space, v)) { for (const auto &elem : v) boost::apply_visitor(print{}, elem); } }
example11.14 定義了兩個規則,其中一個引用另一個:values 定義為 value % ',',value 設置為 qi::int_ | qi::bool_。 values 表示可以解析由逗號分隔的任意數量的值。 value 將值定義為整數或布爾值。總之,規則規定用逗號分隔的整數和布爾值可以按任何順序輸入。
為了存儲任意數量的值,提供了一個 std::vector 類型的容器。因為值的類型是 int 或 bool,所以需要一個可以存儲 int 或 bool 值的類。根據屬性類型和運算符的概述,必須使用來自 Boost.Variant 的類 boost::variant。
如果您啟動示例并輸入以逗號分隔的整數和布爾值,則這些值將寫入以分號分隔的標準輸出流。這是在 Boost.Variant 提供的函數 boost::apply_visitor() 的幫助下完成的。這個函數需要一個訪問者——在這個例子中是類 print 的一個對象。
請注意,布爾值必須輸入為 true 和 false。
語法
如果要解析復雜的格式,需要定義多個相互引用的規則,可以用 boost::spirit::qi::grammar 進行分組。
Example11.15.Grouping rules in a grammar
#include <boost/spirit/include/qi.hpp> #include <boost/variant.hpp> #include <string> #include <vector> #include <iostream> using namespace boost::spirit; template <typename Iterator, typename Skipper> struct my_grammar : qi::grammar<Iterator, std::vector<boost::variant<int, bool>>(), Skipper> { my_grammar() : my_grammar::base_type{values} { value = qi::int_ | qi::bool_; values = value % ','; } qi::rule<Iterator, boost::variant<int, bool>(), Skipper> value; qi::rule<Iterator, std::vector<boost::variant<int, bool>>(), Skipper> values; }; struct print : public boost::static_visitor<> { template <typename T> void operator()(T t) const { std::cout << std::boolalpha << t << ';'; } }; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); my_grammar<std::string::iterator, ascii::space_type> g; std::vector<boost::variant<int, bool>> v; if (qi::phrase_parse(it, s.end(), g, ascii::space, v)) { for (const auto &elem : v) boost::apply_visitor(print{}, elem); } }
示例 11.15 的工作方式與示例 11.14 類似:您可以按任何順序輸入整數和布爾值,并以逗號分隔。它們將以相同的順序寫入標準輸出流,但用分號分隔。該示例使用與前一個相同的規則——值和值。然而,這一次規則被分組在一個語法中。語法在一個名為 my_grammar 的類中定義,該類派生自 boost::spirit::qi::grammar。
my_grammar 和 boost::spirit::qi::grammar 都是類模板。 boost::spirit::qi::grammar 期望的模板參數與 boost::spirit::qi::rule 期望的模板參數相同。要解析的字符串的迭代器類型必須傳遞給 boost::spirit::qi::grammar。您還可以傳遞定義屬性類型和船長類型的函數的簽名。
在 my_grammar 中, boost::spirit::qi::rule 用于定義規則值和值。規則被定義為成員變量并在構造函數中初始化。
請注意,最外層的規則必須與 base_type 一起傳遞給基類的構造函數。這樣,Boost.Spirit 就知道哪個規則是語法的入口點。
一旦定義了語法,就可以像解析器一樣使用它。在示例 11.15 中,my_grammar 在 main() 中實例化以創建 g。然后將 g 傳遞給 boost::spirit::qi::phrase_parse()。
Example11.16.Storing parsed values in structures
#include <boost/spirit/include/qi.hpp> #include <boost/variant.hpp> #include <boost/fusion/include/adapt_struct.hpp> #include <string> #include <vector> #include <iostream> using namespace boost::spirit; typedef boost::variant<int, bool> int_or_bool; struct int_or_bool_values { int_or_bool first; std::vector<int_or_bool> others; }; BOOST_FUSION_ADAPT_STRUCT( int_or_bool_values, (int_or_bool, first) (std::vector<int_or_bool>, others) ) template <typename Iterator, typename Skipper> struct my_grammar : qi::grammar<Iterator, int_or_bool_values(), Skipper> { my_grammar() : my_grammar::base_type{values} { value = qi::int_ | qi::bool_; values = value >> ',' >> value % ','; } qi::rule<Iterator, int_or_bool(), Skipper> value; qi::rule<Iterator, int_or_bool_values(), Skipper> values; }; struct print : public boost::static_visitor<> { template <typename T> void operator()(T t) const { std::cout << std::boolalpha << t << ';'; } }; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); my_grammar<std::string::iterator, ascii::space_type> g; int_or_bool_values v; if (qi::phrase_parse(it, s.end(), g, ascii::space, v)) { print p; boost::apply_visitor(p, v.first); for (const auto &elem : v.others) boost::apply_visitor(p, elem); } }
示例 11.16 基于前面的示例,但需要至少兩個值。規則值定義為 value >> ',' >> value % ','。
values 中的第一個組件是 value,第二個是 value % ','。第一個組件解析的值必須存儲在 boost::variant 類型的對象中。第二個組件解析的值必須存儲在容器中。使用 int_or_bool_values,該示例提供了一個結構來存儲由規則值的兩個組件解析的值。
要將 int_or_bool_values 與 Boost.Spirit 一起使用,必須使用宏 BOOST_FUSION_ADAPT_STRUCT。該宏由 Boost.Fusion 提供。該宏可以將 int_or_bool_values 視為具有 int_or_bool 和 std::vector<int_or_bool> 類型的兩個值的元組。因為這個元組具有正確數量的正確類型的值,所以可以使用簽名 int_or_bool_values() 定義值。 values 將在 first 中存儲第一個解析值,在其他中存儲所有其他解析值。
int_or_bool_values 類型的對象作為屬性傳遞給 boost::spirit::qi::phrase_parse()。如果您啟動示例并輸入至少兩個以逗號分隔的整數或布爾值,則它們都存儲在屬性中并寫入標準輸出流。
解析器已從上一個示例中使用的內容進行了更改。如果值是用 value % ',' 定義的,則 int_or_bool_values 將只有一個成員變量,并且所有解析的值都可以存儲在一個向量中,如前面的示例所示。因此,int_or_bool_values 就像一個只有一個值的元組——Boost.Spirit 不支持。只有一個成員變量的結構將導致編譯器錯誤。該問題有多種解決方法。
練習
創建一個可以加減整數的解析器。解析器應該能夠處理像 1+2-5+8 這樣的輸入,并將結果(這里是 6)寫入標準輸出。
擴展您的解析器:它現在應該也支持浮點數。此外,應該可以使用分數。新的解析器應該能夠處理像 1.2+6/5-0.9 這樣的輸入,并且應該將結果(這里是 1.5)寫入標準輸出。
原文鏈接:https://yamagota.blog.csdn.net/article/details/127327728
相關推薦
- 2022-04-16 Redis命令處理過程源碼解析_Redis
- 2022-06-01 Androidstudio調用攝像頭拍照并保存照片_Android
- 2023-03-01 shell?sleep睡眠命令的具體使用_linux shell
- 2022-11-24 PyTorch?Dataset與DataLoader使用超詳細講解_python
- 2022-10-08 Pandas數據分析之pandas數據透視表和交叉表_python
- 2023-02-01 MongoDB?事務支持詳解_MongoDB
- 2023-02-04 詳解C++中存儲類的使用_C 語言
- 2022-03-20 C語言數據結構之鏈隊列的基本操作_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同步修改后的遠程分支