Re: [挖坑不填是一种美德] Write Yourself a Scheme in 48 Hours/Parsing(三)

13 views
Skip to first unread message

Zoom.Quiet

unread,
Dec 15, 2008, 9:39:32 AM12/15/08
to ?????, idea.t...@gmail.com, haske...@googlegroups.com
2008/12/15 ????? <Marc...@gmail.com>:
> 上一节的时候我们讨论到了用附加的解释器组件扩展功能的方法。这一次我们再加些料。
> 首先,我们定义出Scheme语言中的一些类型:
>
>
> Haskell语言: Parsing 代码片段六
> 1 data LispVal = Atom String
> 2 | List [LispVal]
> 3 | DottedList [LispVal] LispVal
> 4 | Number Integer
> 5 | String String
> 6 | Bool Bool
>
>
> 事实上,Haskell里一切都可以看作是函数,data也不例外。千万不要拿这个东西去随便对应你以前见过的其它叫data的东西。事实上Haskell里的Type、Class、Instance和Data跟OO语言里的概念都完全不是一回事儿。如果你有学过近世代数,可以去看看上节里推荐的T1的那篇Monad教程。
>
>
>
> 这里,使用data,我们定义了 LispVal 可能的几种类型:
>
>
>
> Atom 是一个文本,它表示一个原子命名
> 若干 LispVal 的序列成为一个 List (注意 List 也是一种 data Lispval,所以这是一个递归的定义)
> . 联接列表和一个 LispVal 值,组成一个 DottedList
> Number 存储整数
> String 存储字符串
> Bool 存储逻辑值
>
>
>
>
> 因为Haskell的类型和构造器取自不同的命名空间,所以这里我们定义了与系统类型相同的String、Bool之类的类型,也不会靠成什么问题。类型和构造器都是PASCAL命名。
>
>
> 现在编写几个解释器函数。首先是字符串。字符串是一对双引号标记,包含若干文。
>
>
>
> Haskell语言: Parsing 代码片段七
> 1 parseString :: Parser LispVal
> 2 parseString = do char '"'
> 3 x <- many (noneOf "\"")
> 4 char '"'
> 5 return $ String x
>
>
>
>
> 这儿又出来一新的妖招:我们没用
>>>,而是用了一个do。这是为了可以取到引号之间的值,这里我们用了char和many两个解析工具。按作者的解释,通常不需要取得action返回值的时候(比如为了组合它们生成新的monad),使用>>,而需要取值并用于下一个action的时候,用
>>>= 或 do-notation。
>
>
> 取值完成以后,我们将其 return 为一个 LispVal
> 。抽象数据类型中的每个构造器也同样可以看作是一个函数:返回一个该类型的值。函数进行参数的式匹配的时候,也可以根据data来匹配。
>
>
> 内置函数 return 可以把我们的 LispVal 提升为一个Parser
> monad。每一行do代码虽然都要求是同一个类型,但是但是我们的字符串解析函数只是返回了一个 LispVal,这时候就靠 return
> 帮我们搞定这个类型封装啦。这样,整个 parseString action 就成为了一个 Parser LispVal。
>
>
> $只是括号的简写 return $ String x 等同于 return (String
> x),这个在Haskell的语法教程中都会有介绍。不过这里有特别提出,$是一个操作符,所以你能对一个函数做什么,就能对它做什么,传递、局部化等等。在这里,它相当于一个
> apply。
>
> Atom 就是一个原子语素,一个字母或符号,跟随若干数值或字母、符号之类的:
>
>
> Haskell语言: Parsing 代码片段八
> 1 parseAtom :: Parser LispVal
> 2 parseAtom = do first <- letter <|> symbol
> 3 rest <- many (letter <|> digit <|> symbol)
> 4 let atom = first:rest
> 5 return $ case atom of
> 6 "#t" -> Bool True
> 7 "#f" -> Bool False
> 8 otherwise -> Atom atom
>
>
>
> 这里出现了一个新的 Pasec combinator,选择运算符
> <|>。它尝试第一个parser,失败就尝试第二个。哪个成功就返回哪个parser的值。
>
> 读取语素的第一个字符以及其余部分后,我们需要把它们合在一起。let语法定义了一个atom变量,我们使用联接符:把它们联起来。如果不用:,还可以用
> [first] ++ rest。
>
> case是基本语句,语法书都讲得很明白,这里不多讨论了。
>
> 发芽网挂了……明天再继续吧……
>
用 paste 吧:稳定压倒一切!
http://paste.ubuntu.org.cn/

这些文章,最好整理到一个稳固的空间中:
http://groups.google.com/group/haskellcug/web

> --
> 挖坑爱好者 于 12/07/2008 04:33:00 上午 张贴在 挖坑不填是一种美德 上

--
http://zoomquiet.org
'''过程改进乃是催生可促生靠谱的人的组织!'''
Time is unimportant, only life important!

Zoom.Quiet

unread,
Dec 15, 2008, 9:50:28 AM12/15/08
to 刘鑫, haske...@googlegroups.com
2008/12/15 刘鑫 <marc...@gmail.com>:
> 悲愤的看到paste没有支持haskell……要不是muse最近没有时间配,用这个一招就横推了。
>
是也乎?没有注意到,,, Trac 都有 haskell 支持的哪,,,

Google 一个代码片段服务,支持 Haskell 的吧,,,

> 2008/12/15 Zoom. Quiet <zoom....@gmail.com>


>>
>> 用 paste 吧:稳定压倒一切!
>> http://paste.ubuntu.org.cn/
>>
>> 这些文章,最好整理到一个稳固的空间中:
>> http://groups.google.com/group/haskellcug/web
>>
>> > --
>> > 挖坑爱好者 于 12/07/2008 04:33:00 上午 张贴在 挖坑不填是一种美德 上

--
http://zoomquiet.org
'''过程改进乃是催生可促生靠谱的人的组织!'''
Free as in Freedom! 哲思自由软件社区:http://zeuux.org

Reply all
Reply to author
Forward
0 new messages