我正在尝试将保尔森ML的代码转换为工作程序员第9章,为λ-Calculus编写解释器。 我想知道是否有人可以帮我翻译成Haskell。 我很难理解语法。
fun list ph = ph -- repeat ("," $-- ph) >> (op::);
fun pack ph = "(" $-- list ph --$")" >> #1
| empty;
答案 0 :(得分:2)
在将此代码移植到Haskell时,我看到了两个挑战:一个是重写组合器,因此它们使用 Either SyntaxError 类型而不是流控制的异常,另一个是保留ML的模块性函子。也就是说,编写一个解析器组合库,它是模块化的,它应该使用哪些关键字/符号/标记器。
虽然ML代码有两个ActionController
和functor Lexical (Keyword: KEYWORD) : LEXICAL
,但您可以从
functor Parsing (Lex: LEXICAL) : PARSE
ML代码使用类型 string 和 substring ,而Haskell的 String 实际上是 [Char] 。词法分析器函数看起来有点不同,因为ML的data Keyword = Keyword { alphas :: [String]
, symbols :: [String] }
data Token = Key String | Id String deriving (Show, Eq)
lex :: Keyword -> String -> [Token]
lex kw s = ...
where
alphaTok :: String -> Token
alphaTok a | a `elem` alphas kw = Key a
| otherwise = Id a
...
可能只是Haskell中的模式匹配String.getc
等。
Paulson的解析器有类型 [Token]→(τ,[Token])但允许例外。 Haskell解析器可以有类型 [Token]→E语法错误(τ,[Token]):
c : ss1
运营商newtype SyntaxError = SyntaxError String deriving Show
newtype Parser a = Parser { runP :: [Token] -> Either SyntaxError (a, [Token]) }
err :: String -> Either SyntaxError b
err msg = Left (SyntaxError msg)
,id
,$
,||
,!!
和--
需要新名称,因为它们与一堆相撞内置运算符和单行注释。名称的提示可以是:>>
,ident
,kw
,|||
和+++
。我最初会跳过实施>>>
运算符。
这两个组合器的实现方式略有不同,
!!
最后一些评论:
阅读论文Monadic Parsing in Haskell(Hutton,Meijer)。
您可能感兴趣的是Ken Friis Larsen的SimpleParse,这是一个教育解析器组合库,由Koen Claessen简化ReadP,因为它的源代码非常易于阅读。它们都是非确定性的。
如果您对Haskell中使用解析器组合器感兴趣,而不是移植一些老式的图书馆以获得学习体验,我建议您也看看Megaparsec(教程),Parsec的现代派。实施有点复杂。
这三个库中没有一个(SimpleParse,ReadP,Megaparsec)将lexing和解析分成两个独立的步骤。相反,他们只是构建小型的标记化解析器,隐含地使用无意义的空白。 (例如,请参阅SimpleParse中的token
combinator。)