返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++BoostSpirit入门教程
  • 701
分享到

C++BoostSpirit入门教程

C++BoostSpiritC++Spirit 2022-11-16 00:11:29 701人浏览 薄情痞子
摘要

目录一、Boost.Spirit库介绍二、boost::spirit::qi::parse()解析格式三、解析器一、Boost.Spirit库介绍 本章介绍库 Boost.Spiri

一、Boost.Spirit库介绍

本章介绍库 Boost.Spirit。 Boost.Spirit 用于开发文本格式的解析器。例如,您可以使用 Boost.Spirit 开发解析器来加载配置文件。 Boost.Spirit 也可以用于二进制格式,尽管它在这方面的用处有限。

Boost.Spirit 简化了解析器的开发,因为格式是用规则描述的。规则定义格式的外观——其余的由 Boost.Spirit 完成。您可以将 Boost.Spirit 与正则表达式进行比较,因为它可以让您处理复杂的过程——正则表达式的模式搜索和 Boost.Spirit 的解析——而无需编写代码来实现该过程。

Boost.Spirit 期望使用解析表达式语法 (PEG) 来描述规则。 PEG 与扩展巴库斯-瑙尔形式 (EBNF) 有关。即使您不熟悉这些语言,本章中的示例也足以帮助您入门

Boost.Spirit 有两个版本。第一个版本称为 Spirit.Classic。这个版本不应该再使用了。当前版本是 2.5.2。这是本章介绍的版本。

从 2.x 版本开始,Boost.Spirit 可用于生成生成器和解析器。解析器读取文本格式,生成器编写它们。 Boost.Spirit 中用于开发解析器的组件称为 Spirit.Qi。 Spirit.Karma 是用于开发生成器的组件。命名空间被相应地划分:用于开发解析器的类和函数可以在 boost::spirit::qi 中找到,用于开发生成器的类和函数可以在 boost::spirit::karma 中找到。

除了 Spirit.Qi 和 Spirit.Karma,该库还包含一个名为 Spirit.Lex 的组件,可用于开发词法分析器。

本章的重点是开发解析器。示例主要使用来自 boost::spirit 和 boost::spirit::qi 的类和函数。对于这些类和函数,包含头文件 boost/spirit/include/qi.hpp 就足够了。

如果您不想包含像 boost/spirit/include/qi.hpp 这样的主头文件,您可以单独包含来自 boost/spirit/include/ 的头文件。仅包含此目录中的头文件很重要。 boost/spirit/include/ 是用户界面。其他目录中的头文件可以在新的库版本中更改。

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

Boost.Spirit 提供 boost::spirit::qi::parse() 和 boost::spirit::qi::phrase_parse() 来解析格式。

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()。这个函数需要两个被解析字符串的迭代器和一个解析器。该示例使用由 Boost.Spirit 提供的解析器 boost::spirit::ascii::digit。这是几个字符分类解析器之一。这些解析器测试字符是否属于某个类。 boost::spirit::ascii::digit 测试字符是否为 0 到 9 之间的数字。

该示例传递从 std::cin 读取的字符串的迭代器。请注意,开始迭代器没有直接传递给 boost::spirit::qi::parse()。它存储在变量 it 中,然后传递给 boost::spirit::qi::parse()。这样做是因为 boost::spirit::qi::parse() 可能会修改迭代器。

如果您键入一个数字,然后按 Enter,该示例将显示 true。如果您输入两位数然后回车,则输出将为真,后跟第二位数字。如果你输入一个字母然后回车,输出将是假的,然后是字母。

例 11.1 中使用的解析器 boost::spirit::ascii::digit 只测试一个字符以查看它是否是数字。如果第一个字符是数字,boost::spirit::qi::parse() 返回 true,否则返回 false。 boost::spirit::qi::parse() 的返回值表示解析器是否成功。

boost::spirit::qi::parse() 如果您输入多个数字,也会返回 true。因为解析器 boost::spirit::ascii::digit 只测试第一个字符,所以它会在这样的字符串上成功。第一个之后的所有数字都将被忽略。

为了让您确定可以成功解析多少字符串,boost::spirit::qi::parse() 更改了它的迭代器。调用 boost::spirit::qi::parse() 后,它指向最后一个解析成功后的字符。如果输入多个数字,则指第二个数字。如果您只输入一位数字,则它等于 s 的结束迭代器。如果你输入一个字母,它指的是那个字母。

boost::spirit::qi::parse() 不会忽略空格。如果运行示例 11.1 并输入空格,则会显示 false。 boost::spirit::qi::parse() 测试第一个输入的字符,即使该字符是空格。如果你想忽略空格,使用 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() 类似,但需要另一个名为 skipper 的参数。船长是应该被忽略的字符的解析器。示例 11.2 使用 boost::spirit::ascii::space,一个字符分类解析器来检测空格,作为船长。

boost::spirit::ascii::space 丢弃空格作为分隔符。如果您开始该示例并输入一个空格后跟一个数字,则显示为 true。与前面的示例不同,解析器 boost::spirit::ascii::digit 不应用于空格,而是应用于不是空格的第一个字符。

请注意,此示例忽略了任意数量的空格。因此,如果您输入多个空格后跟一个数字, boost::spirit::qi::phrase_parse() 将返回 true。

与 boost::spirit::qi::parse() 一样,boost::spirit::qi::phrase_parse() 修改了作为第一个参数传递的迭代器。这样,您就知道解析器能够成功工作到字符串多远。示例 11.2 跳过成功解析字符后出现的空格。如果您输入一个数字后跟一个空格,然后是一个字母,迭代器将引用该字母,而不是它前面的空格。如果您希望迭代器引用空间,请将 boost::spirit::qi::skip_flag::dont_postskip 作为另一个参数传递给 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() 以告诉解析器不要跳过在成功解析数字之后但在第一个不成功数字之前出现的空格解析的字符。如果你输入一个数字后跟一个空格再跟一个字母,它指的是调用 boost::spirit::qi::phrase_parse() 之后的空格。

标志 boost::spirit::qi::skip_flag::postskip 是默认值,如果 boost::spirit::qi::skip_flag::dont_postskip 和 boost::spirit::qi::skip_flag 都不是,则使用该标志: :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() 接受迭代器到一个宽字符串。示例 11.4 与前面的示例类似,只是使用了宽字符串。

Boost.Spirit 还支持来自 c++11 标准库的字符串类型 std::u16string 和 std::u32string。

三、解析器

本节说明如何定义解析器。您通常从 Boost.Spirit 访问现有的解析器——例如 boost::spirit::ascii::digit 或 boost::spirit::ascii::space。通过组合解析器,您可以解析更复杂的格式。该过程类似于定义正则表达式,它们也是由基本构建块构建的。

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 测试是否输入了两个数字。 boost::spirit::qi::phrase_parse() 仅在两个数字连续时才返回 true。空格被忽略。

与前面的示例一样, boost::spirit::ascii::digit 用于识别数字。因为 boost::spirit::ascii::digit 只测试一个字符,所以解析器使用了两次来测试两位数字的输入。要连续两次使用 boost::spirit::ascii::digit,必须使用运算符。 Boost.Spirit 为解析器重载 operator>>。使用 ascii::digit >> ascii::digit 创建了一个解析器,用于测试字符串是否包含两个数字。

如果您运行该示例并输入两位数,则会显示 true。如果您只输入一位数字,该示例将显示为 false。

请注意,如果您在两位数之间输入空格,该示例也会显示 true。无论在解析器中使用运算符 operator>> 的任何位置,都允许使用被船长忽略的字符。因为示例 11.5 使用 boost::spirit::ascii::space 作为跳过符,所以您可以在两个数字之间输入任意数量的空格。

如果您希望解析器仅在两个数字之间没有空格的情况下才接受它们,请使用 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]。现在, boost::spirit::qi::phrase_parse() 仅在数字之间没有空格时才返回 true。

boost::spirit::qi::lexeme 是可以改变解析器行为的几个指令之一。如果你想禁止在使用 operator>> 时会被船长忽略的字符,你可以使用 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 定义了一个解析器,它至少需要一个数字。这种语法,特别是加号 (+),类似于正则表达式中使用的语法。加号标识一个字符或字符组,该字符或字符组预计在字符串中至少出现一次。如果您启动示例并输入至少一位数字,则会显示 true。数字是否由空格分隔并不重要。如果解析器应该只接受没有空格的数字,请再次使用 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 需要一个整数。 boost::spirit::qi::int_ 是一个可以识别正整数和负整数的数值解析器。与 boost::spirit::ascii::digit 不同,boost::spirit::qi::int_ 可以将多个字符(例如 +1 或 -23)识别为整数。

Boost.Spirit 提供了额外的逻辑解析器。 boost::spirit::qi::float_、boost::spirit::qi::double_ 和 boost::spirit::qi::bool_ 是可以读取浮点数和布尔值的数值解析器。使用 boost::spirit::qi::eol,您可以测试行尾字符。 boost::spirit::qi::byte_ 和 boost::spirit::qi::Word 可用于读取一个或两个字节。 boost::spirit::qi::word 和其他二进制解析器识别平台的字节顺序并进行相应的解析。如果要基于特定的字节序进行解析,无论平台如何,都可以使用 boost::spirit::qi::little_word 和 boost::spirit::qi::big_word 等解析器。

到此这篇关于C++ Boost Spirit入门教程的文章就介绍到这了,更多相关C++ Boost Spirit内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++BoostSpirit入门教程

本文链接: https://lsjlt.com/news/173076.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C++BoostSpirit入门教程
    目录一、Boost.Spirit库介绍二、boost::spirit::qi::parse()解析格式三、解析器一、Boost.Spirit库介绍 本章介绍库 Boost.Spiri...
    99+
    2022-11-16
    C++ Boost Spirit C++ Spirit
  • C#中Linq的入门教程
    一、LINQ的体系结构 语言集成查询 (LINQ) (C#) | Microsoft 官方文档 LINQ总共包括五个部分:  程序集命名空间描述LINQ to Object...
    99+
    2024-04-02
  • C++教程(超长最全入门)
    目录1、C++简介1.1 起源1.2 应用范围1.3 C++和C2、开发工具3、基本语法3.1 注释3.2关键字3.3标识符4、数据类型4.1基本数据类型4.2 数据类型在不同系统中...
    99+
    2023-05-18
    C++教程
  • Python爬虫入门教程 1-100 C
    简介 你好,当你打开这个文档的时候,我知道,你想要的是什么! Python爬虫,如何快速的学会Python爬虫,是你最期待的事情,可是这个事情应该没有想象中的那么容易,况且你的编程底子还不一定好,这套课程,没有你想要的Python基础,没...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • node.js入门教程
    Node是个啥?   写个东西还是尽量面面俱到吧,所以有关基本概念的东西我也从网上选择性的拿了些下来,有些地方针对自己的理解有所改动,对这些概念性的东西有过了解的可选择跳过这段。   1.Node 是一个服...
    99+
    2022-06-04
    入门教程 node js
  • Navicat入门教程
    本篇内容主要讲解“Navicat入门教程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Navicat入门教程”吧!一、 连接使用 1.1 连接数据库打...
    99+
    2024-04-02
  • ECharts入门教程
    Echart 官网:https://echarts.apache.org/zh/index.html下载页面:https://echarts.apache.org/zh/downlo...
    99+
    2024-04-02
  • ECMAScript6入门教程
    目录你的浏览器支持ES吗?ES 6 新特性汇总(一图全览)1. let、const 和 block 作用域2. 箭头函数(Arrow Functions)3. 函数参数默认值4. S...
    99+
    2024-04-02
  • HTML5 入门教程
    本篇内容主要讲解“HTML5 入门教程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“HTML5 入门教程”吧!JavaScript作为一种弱类型语言,最大的特点就是动态类型。也就是说不用提前声明...
    99+
    2023-06-09
  • Flask 入门教程
    Flask 入门教程 一、Flask简单使用 1、准备环境 硬件:Windows 7+python 3.6+安装软件:pycharm安装(社区版)、python环境安装 2、简单的Flask应用 本地...
    99+
    2023-10-07
    flask python 后端
  • Lighttpd入门教程
    Lighttpd入门教程 概述入门教程安装配置静态文件服务动态文件服务 虚拟主机SSL启动服务器日志模块总结lighthttpd使用场景和原理使用场景原理 概述 Lightt...
    99+
    2023-09-04
    服务器 linux ubuntu
  • maven3 入门教程
    Maven库: http://repo2.maven.org/maven2/ Maven依赖查询: http://mvnrepository.com/ Maven常用命令:  1. 创建Maven的普通java项目:  ...
    99+
    2023-01-31
    入门教程
  • Jmeter入门教程
    目录一、下载二、安装三、运行四、一个简单的压测实例五、如何查看系统负载何性能瓶颈jemter简介 jmeter是apache公司基于java开发的一款开源压力测试工具,体积小,功能全...
    99+
    2024-04-02
  • IPv6入门教程
    本篇文章主要从基础概念、IPv6的相关网络工具、关于移动应用在IPv6和IPv4网络环境中自动降级机制的研究等三个方面介绍了IPv6的入门教程。前言众所周知,32位的IPv4地址已经基本耗尽(这里的耗尽只是说的分配完了,实际上有相当一部分并...
    99+
    2023-06-03
  • pgpool-II 入门教程
    欢迎阅读 pgpool-II 入门教程。从本教程中,你将学会如何安装,设置 pgpool-II 以及使用 pgpool-II 运行并行查询和复制。我们假设你已经知道PostgreSQL的基础操作,所以如果...
    99+
    2016-11-03
    pgpool-II 入门教程
  • python jupyter入门教程
    目录1.jupyter2.jupyter基础操作2.1windows更新pip库2.2jupyter安装2.3初次启动jupyter2.4设置密码进入jupyter3.创建一个jupyter文本4.jupyter文本...
    99+
    2022-06-02
    python jupyter入门 python jupyter
  • python pygame入门教程
    目录一、安装二、第一个代码实例三、绘制一个矩形框四、绘制矩形框的进阶版本五、绘制一条直线六、绘制一条弧线一、安装 在 cmd 命令中输入: pip install pygame 即可安装成功了 二、第一个代码实例 代...
    99+
    2022-06-02
    python pygame pygame入门教程
  • nodejs教程之入门
    前言 再不学nodeJs,我们就老了......在HTML5大浪袭来的时候,很多先辈就开始了NodeJs之旅,而那时我还在做服务器端的程序 后来转成前端,和梯队的距离已经很大了,因为我会服务器端语言,还干了...
    99+
    2022-06-04
    入门 教程 nodejs
  • Android RecylerView入门教程
    今年Google I/0大会,Google开放了两个全新的视图:RecyclerView和CardView。这篇文章会提供关于RecylerView的简介。 RecylerVi...
    99+
    2022-06-06
    教程 Android
  • Python Qt5 入门教程
    Python Qt5 入门教程 Python Qt5是一个强大的GUI工具包,可以用来设计各种桌面应用程序,包括图形用户界面、数据库应用程序等。本教程将带你入门Python Qt5,从安装开始到图形界面的设计以及常见的控件和事件。 安装...
    99+
    2023-08-31
    python ubuntu linux Qt5
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作