Boost.Spirit:解析期间设置子语法

2024-01-30

为了处理大量的编译时间和语法的重用,我将语法组成了几个按顺序调用的子语法。其中之一(称为:SETUP 语法)提供了解析器的一些配置(通过符号解析器),因此后面的子语法在逻辑上依赖于该语法(再次通过不同的符号解析器)。因此,在解析SETUP之后,需要更改以下子语法的符号解析器。

我的问题是,如何有效地解决这个问题,同时保持子语法之间的松散耦合?

目前我只看到两种可能性:

  • SETUP 语法的 on_success 处理程序可以完成这项工作,但这会引入相当多的耦合。
  • 设置完成后,将所有内容解析为字符串,构建一个新的解析器(根据更改后的符号)并在第二步中解析该字符串。这会留下相当多的开销。

我想要的是一个 on_before_parse 处理程序,它可以由任何需要在每次解析之前做一些工作的语法来实现。从我的角度来看,这会减少耦合,并且解析器的某些设置在其他情况下也可以派上用场。这样的事情可能吗?

Update:

抱歉,我太粗略了,这不是我的本意。

任务是使用一些关键字解析输入 I,例如#task1 and #task2。但在某些情况下,这些关键字需要不同,例如$$task1 and $$task2.

所以解析的文件将以

setup {
  #task1=$$task1
  #task2=$$task2
}

realwork {
  ...
}

一些代码草图:给定是一个主解析器,由几个(至少两个)解析器组成。

template<typename Iterator>
struct MainParser: qi::grammar<Iterator, Skipper<Iterator>> {

  MainParser() : MainParser::base_type(start) {
    start = setup >> realwork;
  }

  Setup<Iterator>    setup;
  RealWork<Iterator> realwork;

  qi::rule<Iterator, Skipper<Iterator> > start;
}

Setup and RealWork它们本身就是解析器(我上面的子解析器)。在设置部分期间,语法的某些关键字可能会改变,因此设置部分有一个qi::symbols<char, keywords>规则。一开始这些符号将包含#task1 and #task2。解析文件的第一部分后,它们包含$$task1 and $$task2.

由于关键字已更改,并且自RealWork需要解析 I,它需要了解新的关键字。所以我必须从Setup to RealWork在文件配对期间。

我看到的两种方法是:

  • 使Setup意识到RealWork并传输符号Setup to RealWork in the qi::on_success的处理程序Setup。 (坏,耦合)
  • 切换到两个解析步骤。start of MainParser看起来像

    start = setup >> unparsed_rest
    

    之后会有第二个解析器MainParser。示意图:

    SymbolTable Table;
    string Unparsed_Rest;
    MainParser.parse(Input, (Unparsed_Rest, Table));
    
    RealWordParser.setupFromAlteredSymbolTable(Table);
    RealWorkParser.parse(Unparsed_Rest);
    

    几个解析步骤的开销。

所以,到目前为止,属性还没有发挥作用。只需在解析时更改解析器即可处理多种输入文件。

我的希望是一个处理者qi::on_before_parse like qi::on_success。从这个想法来看,每次解析器开始解析输入时都会触发该处理程序。理论上只是在解析开始时的拦截,就像我们有拦截一样on_success and on_error.


可悲的是,您没有显示任何代码,并且您的描述有点......粗略。因此,这是一个相当通用的答案,它解决了我从您的问题中提取的一些要点:

关注点分离

听起来很像您需要将 AST 构建与转换/处理步骤分开。

解析器组成

当然你可以编写语法。只需按照您的规则编写语法,并以您希望的任何传统方式隐藏这些语法的实现(pImpl习语、const static 内部规则,只要符合要求即可)。

然而,组合通常不需要“事件”驱动元素:如果您觉得需要分两个阶段进行解析,在我看来,你只是在努力保持概述,但递归下降或 PEG 语法自然非常适合描述这样的语法swoop(或者如果你愿意的话,可以通过一次)。

但是,如果您发现

(a) 你的语法变得复杂
(b) 或者您希望能够根据运行时功能选择性地插入子语法

你可以考虑

  1. 纳比亚莱克技巧(我在我的文章中多次展示/提到过这一点)[标签:boost-spirit] 本网站上的答案 https://stackoverflow.com/search?q=user%3A85371+%5Bboost-spirit%5D+OR+%5Bboost-spirit-qi%5D
  2. 您可以动态构建规则(这并不容易推荐,因为您将陷入与复制 Proto 表达式树有关的致命陷阱,从而导致悬空引用)。我有时也会展示一些这样做的答案:

    • 从替代解析器表达式的可变参数列表生成 Spirit 解析器表达式 https://stackoverflow.com/questions/16177184/generating-spirit-parser-expressions-from-a-variadic-list-of-alternative-parser/16181550#16181550
    • C++ Boost qi 递归规则构建 https://stackoverflow.com/questions/17405500/c-boost-qi-recursive-rule-construction/17408206#17408206
    • Boost.Spirit.Qi:在解析时动态创建“差异”解析器 https://stackoverflow.com/questions/17000897/boost-spirit-qi-dynamically-create-difference-parser-at-parse-time/17003832#17003832

    重复:除非您知道如何检测 UB 并使用 Proto 修复问题,否则不要尝试此操作

希望这些事情可以帮助您走上正轨。如果没有,我建议你回来concrete问题。与“想法”相比,我更熟悉代码,因为想法often对你来说比对我来说更有意义。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Boost.Spirit:解析期间设置子语法 的相关文章

  • CLR 2.0 与 4.0 性能比较?

    如果在 CLR 4 0 下运行 为 CLR 2 0 编译的 NET 程序会运行得更快吗 应用程序配置
  • 适合初学者的良好调试器教程[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个好的初学者教程 在 C 中使用调试器 我感觉自己好像错过了很多 我知道怎么做 单步执行代码并查看局部变量 虽然这常常给我带来问
  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • 为什么pow函数比简单运算慢?

    从我的一个朋友那里 我听说 pow 函数比简单地将底数乘以它的指数的等价函数要慢 例如 据他介绍 include
  • 如何判断计算机是否已重新启动?

    我曾经使用过一个命令行 SMTP 邮件程序 作为试用版的限制 它允许您在每个 Windows 会话中最多接收 10 封电子邮件 如果您重新启动计算机 您可能还会收到 10 个以上 我认为这种共享软件破坏非常巧妙 我想在我的应用程序中复制它
  • 当一组凭据下的计划任务启动的进程在另一组凭据下运行另一个程序时,Windows 是否有限制

    所以我有一个简单的例子 其中我有应用程序 A 它对用户 X 本地管理员 有一些硬编码的凭据 然后它使用硬编码的绝对路径启动带有这些凭据的应用程序 B A 和 B 以及 dotnet 控制台应用程序 但是它们不与控制台交互 只是将信息写入文件
  • 从客户端访问 DomainService 中的自定义对象

    我正在使用域服务从 Silverlight 客户端的数据库中获取数据 在DomainService1 cs中 我添加了以下内容 EnableClientAccess public class Product public int produ
  • 对 std::vector 进行排序但忽略某个数字

    我有一个std vector
  • 告诉 Nancy 将枚举序列化为字符串

    Nancy 默认情况下在生成 JSON 响应时将枚举序列化为整数 我需要将枚举序列化为字符串 有一种方法可以通过创建来自定义 Nancy 的 JSON 序列化JavaScript 原始转换器 https github com NancyFx
  • 为什么可以通过ref参数修改readonly字段?

    考虑 class Foo private readonly string value public Foo Bar ref value private void Bar ref string value value hello world
  • C# 存档中的文件列表

    我正在创建一个 FileFinder 类 您可以在其中进行如下搜索 var fileFinder new FileFinder new string C MyFolder1 C MyFolder2 new string
  • 识别 Visual Studio 中的重载运算符 (c++)

    有没有办法使用 Visual Studio 快速直观地识别 C 中的重载运算符 在我看来 C 中的一大问题是不知道您正在使用的运算符是否已重载 Visual Studio 或某些第三方工具中是否有某些功能可以自动突出显示重载运算符或对重载运
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • 如何在 C 中安全地声明 16 位字符串文字?

    我知道已经有一个标准方法 前缀为L wchar t test literal L Test 问题是wchar t不保证是16位 但是对于我的项目 我需要16位wchar t 我还想避免通过的要求 fshort wchar 那么 C 不是 C
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • 打印大型 WPF 用户控件

    我有一个巨大的数据 我想使用 WPF 打印 我发现WPF提供了一个PrintDialog PrintVisual用于打印派生的任何 WPF 控件的方法Visual class PrintVisual只会打印一页 因此我需要缩放控件以适合页面
  • WebBrowser.Print() 等待完成。 。网

    我在 VB NET 中使用 WebBrowser 控件并调用 Print 方法 我正在使用 PDF 打印机进行打印 当调用 Print 时 它不会立即启动 它会等到完成整个子或块的运行代码 我需要确保我正在打印的文件也完整并继续处理该文件
  • 将数组作为参数传递

    如果我们修改作为方法内参数传递的数组的内容 则修改是在参数的副本而不是原始参数上完成的 因此结果不可见 当我们调用具有引用类型参数的方法时 会发生什么过程 这是我想问的代码示例 using System namespace Value Re
  • 实体框架中的“it”是什么

    如果以前有人问过这个问题 请原谅我 但我的任何搜索中都没有出现 它 我有两个数据库表 Person 和 Employee 对每个类型的表进行建模 例如 Employee is a Person 在我的 edmx 设计器中 我定义了一个实体
  • 是否可以在不连接数据库的情况下检索 MetadataWorkspace?

    我正在编写一个需要遍历实体框架的测试库MetadataWorkspace对于给定的DbContext类型 但是 由于这是一个测试库 我宁愿不连接到数据库 它引入了测试环境中可能无法使用的依赖项 当我尝试获取参考时MetadataWorksp

随机推荐

  • Android - 使用我的应用程序打开 Gmail 附件

    我需要使用我的应用程序打开具有自定义扩展名的文件 当文件位于我的 SD 卡中时 我可以使用 Intent 过滤器来执行此操作 如果文件作为 Gmail 附件发送 我还可以查看 下载 和 预览 按钮 但是 当我单击下载 预览按钮时 我收到消息
  • 删除某些内容后如何在 OS X Yosemite 上恢复 python?

    我想我之前是通过homebrew安装了python 这不是一个好主意 但我做到了 which python Library Frameworks Python framework Versions 2 7 bin python sudo r
  • 如何在标准 ML 中检查整数的以 2 为底的表示形式? [复制]

    这个问题在这里已经有答案了 我正在尝试在 SML 中实现重复平方算法 我希望它是尾递归的 目标是将所有 x k 相乘 其中 k 是 2 m 2 m 是 n 的二进制表示形式中的 1 例如 对于 x 25 计算 x 1 x 8 x 16 因为
  • 打印两次

    我出于教学目的编写了一个简单的程序 除了打印出名称和您选择的计算答案的部分之外 一切正常 if 语句似乎执行了两次 就好像它在前进之前向后退了一步 它将打印出 您想继续吗 但不会提示用户输入是 否 而是会再次打印出计算的答案 然后询问他们是
  • CodeDom:编译部分类

    我正在尝试编译文本文件中的代码以更改 WinForms 应用程序主窗体上的 TextBox 中的值 IE 将另一个带有方法的分部类添加到调用表单中 该表单有一个按钮 button1 和一个文本框 textBox1 文本文件中的代码是 thi
  • 错误:_handle onLaunch iOS 9 中的特定操作

    我在 iOS 9 上收到以下错误 UIApplication handleNonLaunchSpecificActions forScene withTransitionContext completion unhandled action
  • PHP - 将 MS Word 特殊字符(^l、^p、^s)更改为“,”

    所以我拥有的是一个 MS Word docx 文件 其中包含一些未真正排序的数据 示例输出 1 姓氏 名字 地址 城市 州邮政编码 通过执行 Ctrl Shift 我可以查看文件中存在的所有特殊字符 ETC 然后用 替换它们作为分隔符 然后
  • MDX SSAS - 最大测量日期

    只需要在多维数据集中的所有测量中获取最大日期即可 例如 DateID is a Dimention Measure First Measure Second Measure 如何获取列表MAX DateID 来自我的立方体中的所有措施 以下
  • 处理运行时创建的 OLEObject 命令按钮的事件

    我已经为这个问题苦苦挣扎了一段时间 我想做一些非常简单的事情 我想在运行时创建多个命令按钮 然后用一个过程处理这些命令按钮的事件 所以我构建了一个 withevents 类来处理自动化 但我的代码不起作用 当我运行 Test 时 会创建 C
  • 有没有办法将“a”标签链接取消设置为默认颜色

    我有一个 a 标签 它是另一个网页的正常链接 我想禁用默认链接外观 除非鼠标光标悬停在链接上 此时应恢复默认的正常链接外观 这是我到目前为止所尝试过的 HTML a href example com example a CSS a colo
  • ASP.NET MVC URL 生成性能

    ASP NET MVC 的一点基准测试 查看页面代码 public string Bechmark Func
  • 当您不知道列数时,使用所有列按顺序对矩阵进行排序

    我有一个从递归左连接动态生成的数据框 如何使用order当我事先不知道列数时应用到所有列的函数 我希望结果首先在第一列排序 然后在第二列排序 在下面的示例中 我有四列 set seed 123 A lt matrix rep 1 25 4
  • 直接上传图片到twitter

    我需要帮助在 Windows Phone 7 中将图像直接上传到 Twitter 我已经完成了 twitter 的 oauth 流程 也可以更新推文 但我无法使用 wp7 将图像上传到 twitter 我已经通过使用 Hammock Win
  • 如何在不加载程序集的情况下获取程序集的版本?

    大型程序的一个小功能会检查文件夹中的程序集 并用最新版本替换过时的程序集 为了实现这一点 它需要读取现有程序集文件的版本号 而不实际将这些程序集加载到执行进程中 我发现了以下内容在本文中 http blogs msdn com alejac
  • 相当于在MySQL中处理字符串的explode()

    在 MySQL 中 我希望能够搜索 31 7 当另一个值 7 31 我将使用什么语法来分解 MySQL 中的字符串 在 PHP 中 我可能会使用explode string 并将它们放在一起 MySQL 有没有办法做到这一点 背景 我正在处
  • 如何获取 gcloud 的 shell 命令完成(自动完成)?

    I tried both 1 the official Google installation for Ubuntu https cloud google com sdk docs install deb and 2 the one lin
  • 正则表达式验证错误

    我在正则表达式验证方面遇到问题 请参阅如果我将验证放在代码后面 例如 RegexValidator 0 9 MessageTemplateResourceName INVALID PHONE MessageTemplateResourceT
  • 如何在 Angular 8 中存储像 jwt token 这样的数据?是否有另一种使用本地存储或会话存储安全存储的方法?

    我正在使用 JWT 令牌来授权从 Angular 8 网站向我的 API 发出的请求 但是我应该在哪里存储这个用户看不到的令牌呢 我尝试过使用服务 但刷新页面后令牌丢失 您可以使用 cookie 来存储令牌 而不是本地存储或会话存储 但这并
  • 使用脚本编辑器将表情符号 unicode 从 Google 表格插入到电子邮件中

    我正在尝试使用脚本编辑器从谷歌表格中获取一些文本来发送电子邮件 该文本包含表情符号 unicode 但是 当发送电子邮件时 它会打印纯文本而不是显示 unicode 表情符号 我在电子邮件中看到的内容 9889 some text here
  • Boost.Spirit:解析期间设置子语法

    为了处理大量的编译时间和语法的重用 我将语法组成了几个按顺序调用的子语法 其中之一 称为 SETUP 语法 提供了解析器的一些配置 通过符号解析器 因此后面的子语法在逻辑上依赖于该语法 再次通过不同的符号解析器 因此 在解析SETUP之后