" />

欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++ Boost Spirit入門教程

 更新時(shí)間:2022年11月11日 08:38:18   作者:無(wú)水先生  
Boost是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱。Boost庫(kù)是一個(gè)可移植、提供源代碼的C++庫(kù),作為標(biāo)準(zhǔn)庫(kù)的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開(kāi)發(fā)引擎之一,是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱

一、Boost.Spirit庫(kù)介紹

本章介紹庫(kù) Boost.Spirit。 Boost.Spirit 用于開(kāi)發(fā)文本格式的解析器。例如,您可以使用 Boost.Spirit 開(kāi)發(fā)解析器來(lái)加載配置文件。 Boost.Spirit 也可以用于二進(jìn)制格式,盡管它在這方面的用處有限。

Boost.Spirit 簡(jiǎn)化了解析器的開(kāi)發(fā),因?yàn)楦袷绞怯靡?guī)則描述的。規(guī)則定義格式的外觀——其余的由 Boost.Spirit 完成。您可以將 Boost.Spirit 與正則表達(dá)式進(jìn)行比較,因?yàn)樗梢宰屇幚韽?fù)雜的過(guò)程——正則表達(dá)式的模式搜索和 Boost.Spirit 的解析——而無(wú)需編寫代碼來(lái)實(shí)現(xiàn)該過(guò)程。

Boost.Spirit 期望使用解析表達(dá)式語(yǔ)法 (PEG) 來(lái)描述規(guī)則。 PEG 與擴(kuò)展巴庫(kù)斯-瑙爾形式 (EBNF) 有關(guān)。即使您不熟悉這些語(yǔ)言,本章中的示例也足以幫助您入門。

Boost.Spirit 有兩個(gè)版本。第一個(gè)版本稱為 Spirit.Classic。這個(gè)版本不應(yīng)該再使用了。當(dāng)前版本是 2.5.2。這是本章介紹的版本。

從 2.x 版本開(kāi)始,Boost.Spirit 可用于生成生成器和解析器。解析器讀取文本格式,生成器編寫它們。 Boost.Spirit 中用于開(kāi)發(fā)解析器的組件稱為 Spirit.Qi。 Spirit.Karma 是用于開(kāi)發(fā)生成器的組件。命名空間被相應(yīng)地劃分:用于開(kāi)發(fā)解析器的類和函數(shù)可以在 boost::spirit::qi 中找到,用于開(kāi)發(fā)生成器的類和函數(shù)可以在 boost::spirit::karma 中找到。

除了 Spirit.Qi 和 Spirit.Karma,該庫(kù)還包含一個(gè)名為 Spirit.Lex 的組件,可用于開(kāi)發(fā)詞法分析器。

本章的重點(diǎn)是開(kāi)發(fā)解析器。示例主要使用來(lái)自 boost::spirit 和 boost::spirit::qi 的類和函數(shù)。對(duì)于這些類和函數(shù),包含頭文件 boost/spirit/include/qi.hpp 就足夠了。

如果您不想包含像 boost/spirit/include/qi.hpp 這樣的主頭文件,您可以單獨(dú)包含來(lái)自 boost/spirit/include/ 的頭文件。僅包含此目錄中的頭文件很重要。 boost/spirit/include/ 是用戶界面。其他目錄中的頭文件可以在新的庫(kù)版本中更改。

二、boost::spirit::qi::parse()解析格式

Boost.Spirit 提供 boost::spirit::qi::parse() 和 boost::spirit::qi::phrase_parse() 來(lái)解析格式。

Example11.1.Usingboost::spirit::qi::parse()

#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::parse(it, s.end(), ascii::digit);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

例 11.1 引入了 boost::spirit::qi::parse()。這個(gè)函數(shù)需要兩個(gè)被解析字符串的迭代器和一個(gè)解析器。該示例使用由 Boost.Spirit 提供的解析器 boost::spirit::ascii::digit。這是幾個(gè)字符分類解析器之一。這些解析器測(cè)試字符是否屬于某個(gè)類。 boost::spirit::ascii::digit 測(cè)試字符是否為 0 到 9 之間的數(shù)字。

該示例傳遞從 std::cin 讀取的字符串的迭代器。請(qǐng)注意,開(kāi)始迭代器沒(méi)有直接傳遞給 boost::spirit::qi::parse()。它存儲(chǔ)在變量 it 中,然后傳遞給 boost::spirit::qi::parse()。這樣做是因?yàn)?boost::spirit::qi::parse() 可能會(huì)修改迭代器。

如果您鍵入一個(gè)數(shù)字,然后按 Enter,該示例將顯示 true。如果您輸入兩位數(shù)然后回車,則輸出將為真,后跟第二位數(shù)字。如果你輸入一個(gè)字母然后回車,輸出將是假的,然后是字母。

例 11.1 中使用的解析器 boost::spirit::ascii::digit 只測(cè)試一個(gè)字符以查看它是否是數(shù)字。如果第一個(gè)字符是數(shù)字,boost::spirit::qi::parse() 返回 true,否則返回 false。 boost::spirit::qi::parse() 的返回值表示解析器是否成功。

boost::spirit::qi::parse() 如果您輸入多個(gè)數(shù)字,也會(huì)返回 true。因?yàn)榻馕銎?boost::spirit::ascii::digit 只測(cè)試第一個(gè)字符,所以它會(huì)在這樣的字符串上成功。第一個(gè)之后的所有數(shù)字都將被忽略。

為了讓您確定可以成功解析多少字符串,boost::spirit::qi::parse() 更改了它的迭代器。調(diào)用 boost::spirit::qi::parse() 后,它指向最后一個(gè)解析成功后的字符。如果輸入多個(gè)數(shù)字,則指第二個(gè)數(shù)字。如果您只輸入一位數(shù)字,則它等于 s 的結(jié)束迭代器。如果你輸入一個(gè)字母,它指的是那個(gè)字母。

boost::spirit::qi::parse() 不會(huì)忽略空格。如果運(yùn)行示例 11.1 并輸入空格,則會(huì)顯示 false。 boost::spirit::qi::parse() 測(cè)試第一個(gè)輸入的字符,即使該字符是空格。如果你想忽略空格,使用 boost::spirit::qi::phrase_parse() 而不是 boost::spirit::qi::parse()。

Example11.2.Usingboost::spirit::qi::phrase_parse()

#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(), ascii::digit, ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

boost::spirit::qi::phrase_parse() 的工作方式與 boost::spirit::qi::parse() 類似,但需要另一個(gè)名為 skipper 的參數(shù)。船長(zhǎng)是應(yīng)該被忽略的字符的解析器。示例 11.2 使用 boost::spirit::ascii::space,一個(gè)字符分類解析器來(lái)檢測(cè)空格,作為船長(zhǎng)。

boost::spirit::ascii::space 丟棄空格作為分隔符。如果您開(kāi)始該示例并輸入一個(gè)空格后跟一個(gè)數(shù)字,則顯示為 true。與前面的示例不同,解析器 boost::spirit::ascii::digit 不應(yīng)用于空格,而是應(yīng)用于不是空格的第一個(gè)字符。

請(qǐng)注意,此示例忽略了任意數(shù)量的空格。因此,如果您輸入多個(gè)空格后跟一個(gè)數(shù)字, boost::spirit::qi::phrase_parse() 將返回 true。

與 boost::spirit::qi::parse() 一樣,boost::spirit::qi::phrase_parse() 修改了作為第一個(gè)參數(shù)傳遞的迭代器。這樣,您就知道解析器能夠成功工作到字符串多遠(yuǎn)。示例 11.2 跳過(guò)成功解析字符后出現(xiàn)的空格。如果您輸入一個(gè)數(shù)字后跟一個(gè)空格,然后是一個(gè)字母,迭代器將引用該字母,而不是它前面的空格。如果您希望迭代器引用空間,請(qǐng)將 boost::spirit::qi::skip_flag::dont_postskip 作為另一個(gè)參數(shù)傳遞給 boost::spirit::qi::phrase_parse()。

Example11.3.phrase_parse()withboost::spirit::qi::skip_flag::dont_postskip

#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(), ascii::digit, ascii::space,
    qi::skip_flag::dont_postskip);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.3 將 boost::spirit::qi::skip_flag::dont_postskip 傳遞給 boost::spirit::qi::phrase_parse() 以告訴解析器不要跳過(guò)在成功解析數(shù)字之后但在第一個(gè)不成功數(shù)字之前出現(xiàn)的空格解析的字符。如果你輸入一個(gè)數(shù)字后跟一個(gè)空格再跟一個(gè)字母,它指的是調(diào)用 boost::spirit::qi::phrase_parse() 之后的空格。

標(biāo)志 boost::spirit::qi::skip_flag::postskip 是默認(rèn)值,如果 boost::spirit::qi::skip_flag::dont_postskip 和 boost::spirit::qi::skip_flag 都不是,則使用該標(biāo)志: :postskip 已指定。

Example11.4.boost::spirit::qi::phrase_parse()with wide strings

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::wstring s;
  std::getline(std::wcin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(), ascii::digit, ascii::space,
    qi::skip_flag::dont_postskip);
  std::wcout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::wcout << std::wstring{it, s.end()} << '\n';
}

boost::spirit::qi::parse() 和 boost::spirit::qi::phrase_parse() 接受迭代器到一個(gè)寬字符串。示例 11.4 與前面的示例類似,只是使用了寬字符串。

Boost.Spirit 還支持來(lái)自 C++11 標(biāo)準(zhǔn)庫(kù)的字符串類型 std::u16string 和 std::u32string。

三、解析器

本節(jié)說(shuō)明如何定義解析器。您通常從 Boost.Spirit 訪問(wèn)現(xiàn)有的解析器——例如 boost::spirit::ascii::digit 或 boost::spirit::ascii::space。通過(guò)組合解析器,您可以解析更復(fù)雜的格式。該過(guò)程類似于定義正則表達(dá)式,它們也是由基本構(gòu)建塊構(gòu)建的。

Example11.5.A parser for two consecutive digits

#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(), ascii::digit >> ascii::digit,
    ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.5 測(cè)試是否輸入了兩個(gè)數(shù)字。 boost::spirit::qi::phrase_parse() 僅在兩個(gè)數(shù)字連續(xù)時(shí)才返回 true。空格被忽略。

與前面的示例一樣, boost::spirit::ascii::digit 用于識(shí)別數(shù)字。因?yàn)?boost::spirit::ascii::digit 只測(cè)試一個(gè)字符,所以解析器使用了兩次來(lái)測(cè)試兩位數(shù)字的輸入。要連續(xù)兩次使用 boost::spirit::ascii::digit,必須使用運(yùn)算符。 Boost.Spirit 為解析器重載 operator>>。使用 ascii::digit >> ascii::digit 創(chuàng)建了一個(gè)解析器,用于測(cè)試字符串是否包含兩個(gè)數(shù)字。

如果您運(yùn)行該示例并輸入兩位數(shù),則會(huì)顯示 true。如果您只輸入一位數(shù)字,該示例將顯示為 false。

請(qǐng)注意,如果您在兩位數(shù)之間輸入空格,該示例也會(huì)顯示 true。無(wú)論在解析器中使用運(yùn)算符 operator>> 的任何位置,都允許使用被船長(zhǎng)忽略的字符。因?yàn)槭纠?11.5 使用 boost::spirit::ascii::space 作為跳過(guò)符,所以您可以在兩個(gè)數(shù)字之間輸入任意數(shù)量的空格。

如果您希望解析器僅在兩個(gè)數(shù)字之間沒(méi)有空格的情況下才接受它們,請(qǐng)使用 boost::spirit::qi::parse() 或指令 boost::spirit::qi::lexeme。

Example11.6.Parsing character by character withboost::spirit::qi::lexeme

#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::lexeme[ascii::digit >> ascii::digit], ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.6 使用解析器 qi::lexeme[ascii::digit >> ascii::digit]?,F(xiàn)在, boost::spirit::qi::phrase_parse() 僅在數(shù)字之間沒(méi)有空格時(shí)才返回 true。

boost::spirit::qi::lexeme 是可以改變解析器行為的幾個(gè)指令之一。如果你想禁止在使用 operator>> 時(shí)會(huì)被船長(zhǎng)忽略的字符,你可以使用 boost::spirit::qi::lexeme。

Example11.7.Boost.Spirit rules similar to regular expressions

#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(), +ascii::digit, ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

例 11.7 用 +ascii::digit 定義了一個(gè)解析器,它至少需要一個(gè)數(shù)字。這種語(yǔ)法,特別是加號(hào) (+),類似于正則表達(dá)式中使用的語(yǔ)法。加號(hào)標(biāo)識(shí)一個(gè)字符或字符組,該字符或字符組預(yù)計(jì)在字符串中至少出現(xiàn)一次。如果您啟動(dòng)示例并輸入至少一位數(shù)字,則會(huì)顯示 true。數(shù)字是否由空格分隔并不重要。如果解析器應(yīng)該只接受沒(méi)有空格的數(shù)字,請(qǐng)?jiān)俅问褂?boost::spirit::qi::lexeme。

Example11.8.Numeric 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_, ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.8 需要一個(gè)整數(shù)。 boost::spirit::qi::int_ 是一個(gè)可以識(shí)別正整數(shù)和負(fù)整數(shù)的數(shù)值解析器。與 boost::spirit::ascii::digit 不同,boost::spirit::qi::int_ 可以將多個(gè)字符(例如 +1 或 -23)識(shí)別為整數(shù)。

Boost.Spirit 提供了額外的邏輯解析器。 boost::spirit::qi::float_、boost::spirit::qi::double_ 和 boost::spirit::qi::bool_ 是可以讀取浮點(diǎn)數(shù)和布爾值的數(shù)值解析器。使用 boost::spirit::qi::eol,您可以測(cè)試行尾字符。 boost::spirit::qi::byte_ 和 boost::spirit::qi::word 可用于讀取一個(gè)或兩個(gè)字節(jié)。 boost::spirit::qi::word 和其他二進(jìn)制解析器識(shí)別平臺(tái)的字節(jié)順序并進(jìn)行相應(yīng)的解析。如果要基于特定的字節(jié)序進(jìn)行解析,無(wú)論平臺(tái)如何,都可以使用 boost::spirit::qi::little_word 和 boost::spirit::qi::big_word 等解析器。

到此這篇關(guān)于C++ Boost Spirit入門教程的文章就介紹到這了,更多相關(guān)C++ Boost Spirit內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論