在Haskell中将一个完整的String转换为int和单词作为解释器

时间:2014-09-29 22:59:52

标签: haskell

我正在尝试在Haskell中编写一个Forth解释器。有许多子问题和类别可以实现这一点,但是,我正在尝试完成最基本的步骤,并且我已经在不同的方法中使用了一段时间。我想要的简单输入案例是"25 12 +" -> [37]。我并不担心Forth中的列表是从Haskell向后的,但我确实想尝试适应输入字符串的可扩展性,所以我使用Maybe,好像有错误,我我会做Nothing

我首先尝试使用Prelude的words函数将输入字符串分解为“单词”列表。从那里我使用Prelude的reads函数将其转换为元组(Int,String)列表。所以这很好用,直到我得到一个命令“word”,例如示例问题中的char +

那么如何解析/解释字符串的命令到我可以使用的东西呢? 我是否创建了一个包含所有Forth命令或特殊字符的新数据结构? (假设这个,我如何将它从字符串格式转换为该数据类型?)

需要其他任何东西,请问。我很感激帮助这个想法。

1 个答案:

答案 0 :(得分:2)

read本质上是一个非常简单的字符串解析器。您可能需要考虑学习使用解析器组合库,例如Parsec,而不是对其进行调整。

有许多关于解析器组合器的不同教程,因此您可能需要在他们点击之前进行一些阅读。'但是,this tutorial中的第一个示例与您的问题密切相关。

import Text.Parsec
import Text.Parsec.String

play :: String -> Either ParseError Integer
play s = parse pmain "parameter" s

pmain :: Parser Integer
pmain = do
  x <- pnum `chainl1` pplus
  eof
  return x

pnum = read `fmap` many1 digit

pplus = char '+' >> return (+)

它是一个评估任意长列表的简单解析器:

*Main> play "1+2+3+4+5"
Right 15

它还会产生有用的解析错误:

*Main> play "1+2+3+4+5~"
Left "parameter" (line 1, column 10):
    unexpected '~'
    expecting digit, "+" or end of input

如果你能理解这个简单的解析器,你应该能够找出如何使它适应你的特定问题(参考the documentation for Text.Parsec.Combinator中的通用组合子列表)。最初需要花费的时间比使用read要长一些,但使用正确的解析库可以更容易地实现解析Forth的全语法的最终目标。