Haskell/Parsec:如何使用 Text.Parsec.Indent 中的函数?

2023-12-28

我无法弄清楚如何使用其中的任何功能Text.Parsec.Indent http://hackage.haskell.org/packages/archive/indents/latest/doc/html/Text-Parsec-Indent.html模块提供的indents http://hackage.haskell.org/package/indents-0.3.3Haskell 的软件包,它是 Parsec 的一种附加组件。

所有这些功能都有什么作用?如何使用它们?

我能理解黑线鳕的简短描述withBlock,并且我找到了如何使用的示例withBlock, runIndentIndentParser type here http://spin.atomicobject.com/2012/03/16/using-text-parsec-indent-to-parse-an-indentation-sensitive-language-with-haskells-parsec-library/, here http://changaco.net/blog/parse-indented-tree/ and here https://stackoverflow.com/questions/15533730/haskell-parsec-indents-please-give-an-example-for-how-to-use-each-of-the-functi。我还可以理解四个解析器的文档indentBrackets和朋友 http://hackage.haskell.org/packages/archive/indents/latest/doc/html/Text-Parsec-Indent.html#g:4。但很多事情仍然让我困惑。

尤其:

  1. 有什么区别withBlock f a p and

    do aa <- a
       pp <- block p
       return f aa pp
    

    同样,有什么区别withBlock' a p and do {a; block p}

  2. 在函数族中indented和朋友 http://hackage.haskell.org/packages/archive/indents/latest/doc/html/Text-Parsec-Indent.html#g:3,什么是“参考水平”?也就是说,什么是“参考”?

  3. 再次,使用函数indented还有朋友们,它们该如何使用呢?除了withPos,看起来它们不带任何参数并且都是类型IParser ()(IParser 定义如下this http://spin.atomicobject.com/2012/03/16/using-text-parsec-indent-to-parse-an-indentation-sensitive-language-with-haskells-parsec-library/ or this https://stackoverflow.com/questions/15533730/haskell-parsec-indents-please-give-an-example-for-how-to-use-each-of-the-functi)所以我猜测他们所能做的就是产生或不产生错误,并且它们应该出现在do块,但我无法弄清楚细节。

    我至少找到了一些关于使用的例子withPos in the 源代码 http://hackage.haskell.org/packages/archive/indents/latest/doc/html/src/Text-Parsec-Indent.html,所以如果我盯着它看足够长的时间,我可能就能弄清楚。

  4. <+/> http://hackage.haskell.org/packages/archive/indents/latest/doc/html/Text-Parsec-Indent.html#v:-60--43--47--62-附带有用的描述“<+/>对缩进敏感的解析器来说是什么apis to monads”如果你想花几个时间来尝试理解这一点,这非常有用ap然后找出它与解析器的相似之处。另一个三个组合器 http://hackage.haskell.org/packages/archive/indents/latest/doc/html/Text-Parsec-Indent.html#g:5然后参考定义<+/>,让整个团队对于新人来说难以接近。

    我需要使用这些吗?我可以忽略它们并使用吗do反而?

  5. 普通的lexeme http://hackage.haskell.org/packages/archive/parsec/latest/doc/html/Text-Parsec-Token.html#v:lexeme组合器和whiteSpace http://hackage.haskell.org/packages/archive/parsec/latest/doc/html/Text-Parsec-Token.html#v:whiteSpaceParsec 的解析器会很乐意在多令牌构造中使用换行符,而不会抱怨。但在缩进风格的语言中,有时您希望停止解析词法结构,或者在一行被破坏并且下一行缩进量小于应有的量时抛出错误。我该如何以秒差距执行此操作?

  6. In the language http://www.cs.bris.ac.uk/software/next/status/lex.html我正在尝试解析,理想情况下,允许词法结构继续到下一行的规则应该取决于第一行末尾或下一行开头出现的标记。有没有一种简单的方法可以在秒差距中实现这一目标? (如果这很困难,那么这不是我现在需要关心的事情。)


所以,第一个提示是看一下IndentParser

type IndentParser s u a = ParsecT s u (State SourcePos) a

IE。它是ParsecT密切关注SourcePos http://hackage.haskell.org/packages/archive/parsec/3.1.2/doc/html/Text-Parsec-Pos.html#t%3aSourcePos,一个抽象容器,可用于访问当前的内容等column数字。因此,它可能将当前的“缩进级别”存储在SourcePos。这是我对“参考水平”含义的初步猜测。

简而言之,indents给你一种新的Parsec这是上下文敏感的,特别是对当前缩进敏感。我会不按顺序回答你的问题。


(2)“引用级别”是在该缩进级别开始的当前解析器上下文状态中引用的“信念”。为了更清楚,让我给出一些关于(3)的测试用例。

(3) 为了开始试验这些功能,我们将构建一个小型测试运行程序。它将使用我们提供的字符串运行解析器,然后解开内部State部分使用initialPos我们可以修改它。在代码中

import Text.Parsec
import Text.Parsec.Pos
import Text.Parsec.Indent
import Control.Monad.State

testParse :: (SourcePos -> SourcePos) 
          -> IndentParser String () a 
          -> String -> Either ParseError a
testParse f p src = fst $ flip runState (f $ initialPos "") $ runParserT p () "" src

(请注意,这是almost runIndent,除了我给了一个后门来修改initialPos.)

现在我们可以看一下indented。通过检查来源,我可以看出它做了两件事。首先,它会fail if the current SourcePos列号小于或等于存储在中的“引用级别”SourcePos 存储在State。其次,它有点神秘地更新了State SourcePos's line计数器(不是列计数器)是当前的。

据我了解,只有第一个行为很重要。我们可以在这里看到差异。

>>> testParse id indented ""
Left (line 1, column 1): not indented

>>> testParse id (spaces >> indented) "   "
Right ()

>>> testParse id (many (char 'x') >> indented) "xxxx"
Right ()

所以,为了有indented成功后,我们需要消耗足够的空白(或其他任何东西!)来将我们的列位置推出到“参考”列位置之外。否则,它会失败并显示“未缩进”。接下来的三个函数也存在类似的行为:same除非当前位置和参考位置在同一行,否则失败,sameOrIndented如果当前列严格小于参考列,则失败,除非它们位于同一行,并且checkIndent除非当前列和参考列匹配,否则失败。

withPos略有不同。这不仅仅是一个IndentParser, 这是一个IndentParser-combinator——它转换输入IndentParser进入一个认为“参考列”(SourcePos in the State)正是我们打电话时的位置withPos.

顺便说一句,这给了我们另一个提示。它让我们知道我们有权更改参考列。

(1) 现在我们来看看如何block and withBlock使用我们新的、较低级别的参考列运算符进行工作。withBlock是根据以下方面实施的block,所以我们将从block.

-- simplified from the actual source
block p = withPos $ many1 (checkIndent >> p)

So, block将“参考列”重置为当前列,然后至少消耗 1 次解析p只要每个列的缩进与新设置的“参考列”相同即可。现在我们可以看一下withBlock

withBlock f a p = withPos $ do
  r1 <- a
  r2 <- option [] (indented >> block p)
  return (f r1 r2)

因此,它将“参考列”重置为当前列,解析单个a解析,尝试解析indented block of ps,然后使用组合结果f。你的实现是almost正确,除了您需要使用withPos选择正确的“参考列”。

然后,一旦你有了withBlock, withBlock' = withBlock (\_ bs -> bs).

(5) So, indented和朋友正是执行此操作的工具:如果相对于选择的“参考位置”缩进不正确,它们将导致解析立即失败withPos.

(4) 是的,在你学会如何使用之前不要担心这些家伙Applicative style http://learnyouahaskell.com/for-a-few-monads-more#useful-monadic-functions解析基数Parsec。它通常是一种更干净、更快、更简单的指定解析方法。有时它们甚至更强大,但如果你明白Monad那么它们几乎总是完全等效的。

(6) 这就是症结所在。如果您可以使用以下命令描述您想要的缩进,那么到目前为止提到的工具只能导致缩进失败withPos。很快,我认为不可能指定withPos基于其他解析的成功或失败......所以你必须更深入地了解。幸运的是,这个机制使得IndentParser其工作是显而易见的——这只是一个内在的State单子包含SourcePos。您可以使用lift :: MonadTrans t => m a -> t m a操纵这个内部状态并设置“参考列”,只要你喜欢。

Cheers!

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

Haskell/Parsec:如何使用 Text.Parsec.Indent 中的函数? 的相关文章

  • ErrorT 已弃用,但 exceptT 不适合

    我有一个一元计算 在某些时候 由于单子模式匹配 它开始需要 MonadFail 约束 我的简单解决方法是使用以下命令运行它 fmap either error id runErrorT 然而哎呀 Deprecated Use Control
  • 为什么 Parsec 的 sepBy 停止并且不解析所有元素?

    我正在尝试解析一些逗号分隔的字符串 该字符串可能包含也可能不包含具有图像尺寸的字符串 例如 hello world 300x300 good bye world 我写了下面的小程序 import Text Parsec import qua
  • Haskell 中的实例声明

    我有这两个功能 primes sieve 2 where sieve p xs p sieve x x lt xs x mod p gt 0 isPrime number number 1 null x x lt takeWhile x g
  • 这个记忆的斐波那契函数是如何工作的?

    在我正在做的函数式编程课程的当前练习作业中 我们必须制作给定函数的记忆版本 为了解释记忆化 给出以下示例 fiblist fibm x x lt 0 fibm 0 0 fibm 1 1 fibm n fiblist n 1 fiblist
  • 如何手动推断表达式的类型

    给定 Haskell 函数 head filter fst 现在的问题是如何手动 手动 找到类型 如果我让 Haskell 告诉我我得到的类型 head filter fst Bool b gt Bool b 但我想了解仅使用所用函数的签名
  • 将数据类型设置为 Kind * -> * 这不是函子

    布伦特 约尔吉类型分类百科全书 https www haskell org haskellwiki Typeclassopedia给出以下练习 举一个类型的例子 gt 不能将其制成 的实例Functor 不使用undefined 请告诉我什
  • csv格式是常规语法还是上下文无关语法?

    我目前正在编写一个 csv 解析器 csv 格式的定义由下式给出RFC4180 https www rfc editor org rfc rfc4180这是由 ABNF 定义的 所以csv的定义绝对是上下文无关语法 不过我想知道csv是否是
  • 我应该在 Turtle 或 Foldl 包中使用折叠吗?

    我在使用 Turtle 时遇到了一些困难 直到盯着难以理解的错误消息几分钟后才意识到我使用了错误的fold功能 https hackage haskell org package turtle 1 5 8 docs Turtle Shell
  • 搜索重写规则

    有什么办法可以浏览或搜索重写规则吗 当我使用像这样的标志时 ddump rule firings or ddump rule rewrites我只是得到了触发的规则的名称以及它引起的重写 但没有得到实际的规则本身 理想情况下 我想通过 GH
  • 如何在 Visual Studio Code 中缩进/格式化所选代码?

    我想缩进 Visual Studio Code 中的特定代码部分 I read 如何在 Visual Studio Code 中设置代码格式 https stackoverflow com questions 29973357 它提供了缩进
  • 构建一个简单的解析器,能够使用 PyParse 解析不同的日期格式

    我正在构建一个简单的解析器 它接受如下查询 显示 fizi 从 2010 年 1 月 1 日到 2006 年 2 月 11 日的提交 到目前为止我有 class QueryParser object def parser self stmn
  • “Eta减少”并不总是在Haskell中举行?

    我发现我可以说 LANGUAGE RankNTypes f1 forall b b gt b gt forall c c gt c f1 f id f HLint 告诉我我可以在这里做 Eta 减少 但是 f2 forall b b gt
  • 如何在 Haskell 中安装库?

    我尝试使用控制 Monad Extra andM https hackage haskell org package extra 1 7 10 docs Control Monad Extra html import Control Mon
  • Haskell 中列表列表的笛卡尔积

    给定一个长度列表的列表x所有子列表的长度都相同y 输出y x长度列表x包含每个子列表中的一项 例子 x 3 y 2 1 2 3 4 5 6 Output 2 3 8不同的输出 1 3 5 1 4 5 1 3 6 1 4 6 2 3 5 2
  • python 3 argparse 调用函数

    我想在 python3 中创建一个类似命令行 类似 shell 的界面 Argparse 似乎负责解析和显示帮助 错误消息 根据argparse 的 python3 文档 https docs python org 3 5 library
  • 在Python中连续解析文件

    我正在编写一个脚本 该脚本使用 HTTP 流量行解析文件 并取出域 目前仅将它们打印到屏幕上 我正在使用 httpry 将流量连续写入文件 这是我用来删除域名的脚本 usr bin python import re input open r
  • 将 Java 字符串转换为 sql.Timestamp

    收到以下格式的字符串 YYYY MM DD HH MM SS NNNNNN 时间戳来自 DB2 数据库 我需要将其解析为 java sql Timestamp 并且不丢失任何精度 到目前为止 我一直无法找到现有的代码来解析远至微秒的数据 S
  • Haskell Stack 从 github 安装包依赖项

    是否可以使用 Haskell 堆栈从 github 安装软件包的版本 例如在一个 cabal or a stack yaml文件 如何在 git repo branch revision 上指向依赖项 对于堆栈 The 的文档stack y
  • Haskell:Data.Numbers.Primes 库在哪里?

    我尝试导入 Data Numbers Primes import Data Numbers Primes 伦哈斯克尔给了我 5 hs 1 8 Could not find module Data Numbers Primes Use v t
  • 如何使用Gson仅从Json反序列化某些特定字段?

    我有以下 JSON 字符串 channel bvmt initValues data value instrumentIds TN0007250012 TN0007500010 instruments mnemonic ADWYA marc

随机推荐