在 Ruby 中使用 Parslet 的缩进敏感解析器?

2023-11-26

我正在尝试使用以下方法解析简单的缩进敏感语法ParsletRuby 中的库。

以下是我尝试解析的语法示例:

level0child0
level0child1
  level1child0
  level1child1
    level2child0
  level1child2

结果树看起来像这样:

[
  {
    :identifier => "level0child0",
    :children => []
  },
  {
    :identifier => "level0child1",
    :children => [
      {
        :identifier => "level1child0",
        :children => []
      },
      {
        :identifier => "level1child1",
        :children => [
          {
            :identifier => "level2child0",
            :children => []
          }
        ]
      },
      {
        :identifier => "level1child2",
        :children => []
      },
    ]
  }
]

我现在拥有的解析器可以解析嵌套级别 0 和 1 节点,但无法解析过去的节点:

require 'parslet'

class IndentationSensitiveParser < Parslet::Parser

  rule(:indent) { str('  ') }
  rule(:newline) { str("\n") }
  rule(:identifier) { match['A-Za-z0-9'].repeat.as(:identifier) }

  rule(:node) { identifier >> newline >> (indent >> identifier >> newline.maybe).repeat.as(:children) }

  rule(:document) { node.repeat }

  root :document

end

require 'ap'
require 'pp'

begin
  input = DATA.read

  puts '', '----- input ----------------------------------------------------------------------', ''
  ap input

  tree = IndentationSensitiveParser.new.parse(input)

  puts '', '----- tree -----------------------------------------------------------------------', ''
  ap tree

rescue IndentationSensitiveParser::ParseFailed => failure
  puts '', '----- error ----------------------------------------------------------------------', ''
  puts failure.cause.ascii_tree
end

__END__
user
  name
  age
recipe
  name
foo
bar

很明显,我需要一个动态计数器,它需要 3 个缩进节点来匹配嵌套级别 3 上的标识符。

如何以这种方式使用 Parslet 实现缩进敏感语法解析器?是否可以?


有几种方法。

  1. 通过将每一行识别为缩进和标识符的集合来解析文档,然后应用转换以根据缩进数重建层次结构。

  2. 使用捕获来存储当前缩进,并期望下一个节点包含该缩进以及更多内容以作为子项进行匹配(我没有深入研究这种方法,因为我想到了下一种方法)

  3. 规则只是方法。所以你可以将'node'定义为一个方法,这意味着你可以传递参数! (如下)

这可以让您定义node(depth)按照node(depth+1)。然而,这种方法的问题在于node方法不匹配字符串,它会生成一个解析器。所以递归调用永远不会完成。

这就是为什么dynamic存在。它返回一个解析器,直到它尝试匹配它时才解析,允许您现在可以毫无问题地递归。

请看下面的代码:

require 'parslet'

class IndentationSensitiveParser < Parslet::Parser

  def indent(depth)
    str('  '*depth)
  end

  rule(:newline) { str("\n") }

  rule(:identifier) { match['A-Za-z0-9'].repeat(1).as(:identifier) }

  def node(depth) 
    indent(depth) >> 
    identifier >> 
    newline.maybe >> 
    (dynamic{|s,c| node(depth+1).repeat(0)}).as(:children)
  end 

  rule(:document) { node(0).repeat }

  root :document
end

这是我最喜欢的解决方案。

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

在 Ruby 中使用 Parslet 的缩进敏感解析器? 的相关文章

  • 在 Rails 3.2 + SimpleForm 中显示嵌套表单有错误的字段

    我有一个Flight模型嵌套在一个FlightLog模型 AFlightLog可能包含许多航班 我使用 SimpleForm 进行引导安装 这样当验证失败时 可以用错误类包围带有错误的表单元素 问题是 即使触发了嵌套模型的验证 simple
  • 如何用水豚填充日期时间本地字段?

    我正在使用 Cocoon 添加记录 ID 看起来像workshop instance sessions attributes 1477654140 start time 目前 我正在遍历 DOM 并获取动态生成的 ID 这很好用 这样我就可
  • 如何在 .js 中的字符串中插入来自 ruby​​ 示例的变量[重复]

    这个问题在这里已经有答案了 在 ruby 中 您可以将变量插入到字符串中 如下所示 x sake puts I like x I like sake 例如 def what i like word I like word end 在 jav
  • GitHub API:标记提交所属(与 git describe --tag 并行)

    我正在使用 GitHub API 进行实验octokit https github com octokit octokit rb红宝石 我的目标是能够提取提交 SHA 所属的 标签 现在我可以使用命令行轻松地执行此操作 gt git des
  • 使用 TStringList 的分隔符解析字符串,似乎也解析空格(Delphi)

    我有一个简单的字符串 由某个字符分隔 比如说逗号 我应该能够创建一个 TStringList 并将其分隔符设置为逗号 然后将 DelimitedText 设置为我想要解析的文本 并且应该自动解析它 问题是 当我查看输出时 它还包含空格作为分
  • 使用 Javascript 解析文本

    我正在尝试使用 Javascript 来解析在文本框中输入的文本 这将结合各种用户生成的变量来创建随机活动 看看这个例子可能更有意义 一些示例输入可能是 Activity Home Out Home Read book for time C
  • 使用 R 读取和转换二进制原始数据

    我有一个file https drive google com file d 0BxMpk0nhnJy6SFhxd2xuMzJYYlk edit usp sharing其中包含原始 二进制数据和 ascii 它包含一个时间戳和一个代表速度的
  • 获取块参数个数

    我需要获取给定块所采用的参数数量 例如 foobar 1 2 3 a b c def foobar x y z block need to obtain number of arguments in block which would be
  • sleep 0 有特殊含义吗?

    我看到很多用法sleep 0在我的一个客户项目中 代码看起来像这样 while true sleep 0 end 阅读一些像这样的答案this https stackoverflow com questions 3727420 signif
  • 调用了 numberOfRowsInSection 但未调用 cellForRowAtIndexPath

    在我的表视图中节中的行数被调用两次但是cellForRowAtIndexPath不叫 我想在 tableView 中显示 Facebook 好友列表 如果 cellForRowAtIndexPath 调用我的问题就解决了 我在这里的数组中得
  • Rails 中的 PDF 导出

    我需要将包含一些图表的 HTML 页面导出为 PDF 有哪些好的 gem 可以做到这一点 PDFKit http railscasts com episodes 220 pdfkit http railscasts com episodes
  • 转储 YAML 时如何强制使用双引号?

    我有一个小脚本来自动化 YAML 文件中的一些操作 我读取原始 YAML 文件并将其转换为哈希 然后dump http ruby doc org stdlib 1 8 6 libdoc yaml rdoc YAML html method
  • Watir 更改 Mozilla Firefox 首选项

    我正在使用 Watir 运行 Ruby 脚本来自动执行一些操作 我正在尝试自动将一些文件保存到某个目录 因此 在我的 Mozilla 设置中 我将默认下载目录设置为桌面并选择自动保存文件 然而 当我开始运行脚本时 这些更改并未反映出来 似乎
  • Ruby 枚举器中的“break”与“raise StopIteration”

    如果我使用 Ruby Enumerators 来实现生成器和过滤器 generator Enumerator new do y x 0 loop do y lt lt x x 1 break if x gt CUTOFF end end l
  • Rails 控制台无法运行

    rbenv 红宝石版本 2 6 6 导轨版本 5 1 4 我正在较旧的代码库中工作 ruby 2 6 6 rails 5 4 1 这是我每天使用的代码库 我必须通过 rbenv 下载一个新的 ruby 版本作为单独的存储库 这样做在我的旧代
  • 拆分字符串以仅获取前 5 个字符

    我想去那个地点 var log src ap kernelmodule 10 001 100 但看起来我的代码必须处理 ap kernelmodule 10 002 100 ap kernelmodule 10 003 101 等 我想使用
  • Rails 3 在 Ruby 1.9.2 上初始化非常慢

    我使用 RVM 来管理环境 安装了 Ruby 1 9 2 p136 我认为是最新版本 和 Rails 3 创建了 gemset 并运行捆绑器 到目前为止一切正常 但 Rails 在运行命令 即生成 销毁 rake 等 时初始化速度非常慢 完
  • ruby 中的 #encode 和 #force_encoding 有什么区别?

    我真的不明白之间的区别 encode and force encoding在 Ruby 中String班级 我明白那个 kam force encoding UTF 8 将迫使 kam 是UTF 8编码 但是怎么样 encode encod
  • Rails/Nginx 中的超时——最佳实践

    我正在开发一个应该在 Nginx 服务器上运行的 Rails 应用程序 根据输入 应用程序可能需要很长时间来处理请求 或者在出现错误时挂起 因此我想防止进程永远运行 除了确保客户端收到超时信号的 Nginx 配置之外 我想我可能仍然需要确保
  • REXML - 如何提取单个元素

    我正在用 ruby 编写一些验收测试 其中涉及断言响应 XML 中值的存在 我的 XML 是这样的

随机推荐

  • 二叉树插入算法

    我最近完成了我正在从事的一个项目的二叉搜索树的实现 一切都很顺利 我学到了很多东西 然而 现在我需要实现一个常规的二叉树 由于某种原因 这让我感到困惑 我正在寻找一种方法来执行我的 InsertNode 功能 通常在 BST 中 您只需检查
  • 动态改变listview的分隔线高度?

    这个问题已被问到这里a link 我也想澄清一下问题 我有 10 个列表项Listview我想要拥有deviderheight每个列表项的不同之处就像第一个项目应该是setDividerheight 2 第二次setDividerheigh
  • Maven:在pom.xml中设置settings.xml位置?

    是否可以设置位置settings xml文件内的pom xml file 我知道你可以通过命令行输入来做到这一点mvn s location of settings xml 但我想知道是否可以将其设置在pom xml所以我不必继续通过命令行
  • 如何使用媒体源 API 将两个视频文件数据附加到源缓冲区?

    我有两个视频 名称为 v11 webm 和 v12 webm 我想要的是这两个视频应该无缝运行 没有任何间隙 我正在遵循将数据附加到源缓冲区的媒体源 api 方法 我指的是对此给出的演示link 我修改了该示例并删除了对视频进行分块的部分
  • 平滑算法

    我编写了这段代码来平滑曲线 它需要一个点旁边的 5 个点并将它们相加并求平均值 Smoothing void smoothing vector
  • 在 Google 地图上移动并显示驾驶摄像头视图

    我已经通过谷歌地图路由添加了当前位置 Routing routing new Routing Builder travelMode Routing TravelMode DRIVING key getResources getString
  • 对“initscr”Ncurses 的未定义引用

    我正在尝试编译我的项目并使用 lib ncurse 当编译器链接文件时我遇到了一些错误 这是我在 Makefile 中的标志行 W Wall Werror Wextra lncurses 我已经包含了 ncurses h 一些布局 prom
  • MySQL UPDATE 查询,其中 id 最高并且字段等于变量

    我正在尝试构建一个 MySQL 查询 该查询将更新表中 id 最高且名为 idSession 的字段等于 65 的行 它看起来像这样 UPDATE History SET state 0 WHERE id SELECT MAX id FRO
  • Windows.Security.Cryptography 和 Windows Phone 8 SDK?

    今天我安装了新的Windows Phone 8 SDK w8phone SDK 尝试包括我的一些基类 来自 Windows 8 应用程序 他们说相同的核心 但是哎呀 no Windows Security Cryptography 我用的是
  • PHP-时间减去时间到分钟

    在 php 中我有两次 11 00 00 和 12 45 00 我想以分钟为单位得出它们之间的差异 在本例中为 105 分钟 最好的方法是什么 谢谢你 干得好 strtotime 12 45 00 strtotime 11 00 00 60
  • 为什么变量的寿命不够长?

    考虑这个函数 它应该返回给定的文件扩展名Path pub fn get extension lt a gt path a Path gt Option lt a str gt let path str path as str unwrap
  • 使用 VBA 宏取消选择 Excel 工作簿中的所有复选框

    我有一本包含 100 多个复选框的工作簿 他们是表单控件复选框 我想一次性取消选择它们 这就是将它们设置为 false Sub clearcheck ActiveSheet CheckBoxes Value False End Sub 这适
  • 用Python 3.1制作一个可移植的(exe)?

    有没有办法为 python 应用程序制作可移植 独立的 exe 我读过有关 p2exe 的内容 但它不支持最新版本 我不愿意使用 2 6 因为我宁愿保留最新版本 也不愿担心 2 6 过时后会出现不兼容问题 cx freeze 对我有用 这是
  • 连接到 FCM 的应用程序未收到来自 AWS SNS 的通知

    我已将 Android 应用连接到 Google Firebase 云消息服务 FCM 如下所示本指南 我已经关注了这个答案设置 FCM 和之间的连接AWS SNS 我可以成功接收来自FCM控制台但不是来自AWS SNS 控制台 消息邮寄状
  • 从 javascript 到 java servlet 的 HTTP POST

    如何通过 JavaScript 将参数 POST 到 Java Servlet 这是我的 html 代码 它可以工作 div div
  • Prolog,带有条件子句的构建列表

    我需要使用序言 SWI 风格 来完成这项家庭作业 但有些事情我无法理解 例如 如果我想迭代一个列表并将其元素添加到另一个列表中 但只有当它们满足特定条件时 我将如何处理 我可以将它们全部添加 也可以不添加 但是如果我添加检查此条件的子句 则
  • 当.NET 中的另一个线程正在执行 Console.ReadLine 时,如何中止该线程? [复制]

    这个问题在这里已经有答案了 我的控制台应用程序正在执行一个完全致力于用户界面的线程 它花费大量时间阻塞Console ReadLine 此调用将时间花在 Windows 内部深处 不受 NET 框架的控制 我需要中止这个线程 然而 下面的代
  • C++ 中的异常处理在抛出“char const*”实例后调用终止

    错误 抛出 char const 实例后调用终止 终止应用程序需要运行时以不寻常的方式终止它 请联系应用程序的支持团队 我不确定执行此操作时是什么导致编译器崩溃 有任何想法吗 对编程有点陌生 include
  • 将 bytes 可迭代对象转换为 str 可迭代对象,其中每个值都是一行

    我有一个可迭代的bytes 例如 bytes iter b col 1 b c b ol 2 n1 b val b ue n 但通常这会not是硬编码的或一次性可用的 但由生成器提供 我想将其转换为可迭代的str行 其中换行符预先未知 但可
  • 在 Ruby 中使用 Parslet 的缩进敏感解析器?

    我正在尝试使用以下方法解析简单的缩进敏感语法ParsletRuby 中的库 以下是我尝试解析的语法示例 level0child0 level0child1 level1child0 level1child1 level2child0 lev