parsing - 如何根据输出消耗的数据量使该解析代码变得懒惰?

标签 parsing haskell

有人知道如何使代码变得惰性和非严格,以便在解析输入数据时生成 AST 树吗?目前使用的列表输入是从左到右读取的,但是是反向构造的。因此我不得不在两个地方使用“reverse”。

type Program = [Instruction]
data Instruction = Next | Prev | Plus | Minus | Print | Loop [Instruction] deriving Show

parse :: String -> Program
parse ys = reverse exps where
        (exps, _) = parse' ys []
        parse' [] is     = (is, [])
        parse' (x:xs) is = case x of
                            '>' -> parse' xs (Next:is)
                            '<' -> parse' xs (Prev:is)
                            '+' -> parse' xs (Plus:is)
                            '-' -> parse' xs (Minus:is)
                            '.' -> parse' xs (Print:is)
                            '[' -> parse' after $ Loop (reverse inside):is where (inside, after) = parse' xs []
                            ']' -> (is, xs)
                            _   -> parse' xs is

最佳答案

如果您希望它是惰性的,那么您的函数需要返回如下所示的值:

instr1 : instr2 : ... : <thunk>

哪里<thunk>是其余的计算。对我来说,这表明您的函数应该如下所示:

parse [] = []
parse (x:xs) = instr : parse xs
  where instr = ...

不知道你是故意的还是无意的,但是那个辅助parse'带有额外参数的函数(在其中累积结果)正是您用来从严格语言中获得性能的模式(如果它支持尾部调用消除)。尾递归实际上是这里的敌人!

带有累加器的尾递归函数几乎必然是非惰性的,因为直到您达到基本情况并决定如何处理最终累加器值时,才能知道输出的第一个“部分”。因此,在处理整个输入时,要求输出的消费者必须等待,并且整个输出必须缓冲在内存中。

惰性递归代码最明显的秘诀是让您的函数返回应用于某些字段的数据构造函数(在本例中为 : ),其中您的递归调用存储在一个(或多个)田野。这允许使用者在要求递归调用的输出之前检查构造函数和您生成的任何其他字段。

这也意味着,如果您正在编写一个生成递归数据类型的递归函数,并且希望它是惰性的,那么您通常最终会在返回类型的结构之后构建函数 - 这正是递归使用者通常镜像的方式它们的输入类型的结构。例如。原型(prototype)列表生成器需要一个返回 [] 的案例。和一个返回 something : recursiveCall 的案例.

关于parsing - 如何根据输出消耗的数据量使该解析代码变得懒惰?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29357656/

相关文章:

c++ - 这个正则表达式是否足以删除 C++ 多行注释?

haskell - 为使用 Maybe 的新类型创建任意实例

python - Beautiful Soup 解析 url 以获取另一个 urls 数据

c++ - 如何停止 Spirit Qi 'repeat' 解析器中的字符串连接?

compiler-construction - 在哪里可以获得学习EBNF的 Material ?

jquery - 如何在不将 &quot 转换为 "的情况下获取元素的内容?

parsing - 如何从 Parsec 中的 optional 解析器中检索值?

haskell - 是否有惰性 `ByteString` 的参数版本?

haskell - 我如何计算 Haskell 中元组的元素?

haskell - 函数可以在非空类型构造函数上参数化多态吗?