Haskell 学习function parsers

近来一直在看haskell发现函数式编程还是挺好玩的.参考资料是`Learn You a Haskell`和`Programing in Haskell`,第一本书前部分有中文翻译版,看了3-四遍有点感觉.后面还没看,第二本有视频,有对应的ppt习题.第二本不厚就1百多页.看到第八章时郁闷了.function parsers.就是语法分析,不过这边实现的还是比较简单的书中实现了+*() 的解析,习题要自己写-/的解析.

来来回回看了几遍,记下学习过程吧(可能有些不太正确)..

--type Parser = String->Tree

--type Parser = String->(Tree,String)

--type Parser = String->[(Tree,String)]

type Parser a= String ->[(a,String)]

这里是定义了一个类型Parser,第一次是直接将 String转为Tree,但是不可能一次全部转换所以就保留了后面的String(第二种),但是肯能第一次都转换错了,所以要表示错误结果,可以使用Maybe类型但是这边使用的列表,错误时就直接转为空列表,正确就转为`一元`的列表(第三种),转换时不可能总是转为Tree于是这里就泛型了下 用a表示可以转换后的类型

1.基本Parser

return :: a->Parser a

return v = \inp->[(v,inp)]  -- return v inp = [(v,inp)](也可以这样写)

--sample: return 1 "abc"  = [(1,"abc")]

return 是永远返回v值的Parser(不太好讲) 

failure::Parser a

failure = \inp -> []

failure永远是返回[]类型是Parser 的类型

item::Parser Char

item = \inp -> case inp of

          []->[]

          (x:xs)-[(x,xs)]

item读入String 并返回第一个 Char 如果String为空则失败

parse ::Parser a -> String->[(a,String)]

parse p inp = p inp

parse是讲Parser 类型变为可输出(不太懂,但是值了Parser a输出是有错误的,如 failure a 虽然是[]但是不可输出)

2.序列检测

(>=)Parser a->Parser b->Parser (a,b)

p >>= f = \inp -> case parse p inp of

            []->[]

            [(v,out)] -> parse (f v) out

p的类型是Parse a 

f的类型是Parse b 如果p发生错误 则返回[] 否则 再由f检测(这个也不懂)

p::Parser (Char,Char)

p = do x<- item

    item        (或者 z<-item)

    y<-item

    return (x,y)

p的作用是将[x1,x2,x3..]中 x1,x3检测出来,如果发生错误则返回[] 

sample:parse p "abcdef"

    [(('a','c'),"def")] --检测出结果 为Parser (Char,Char)

    parse p "ab"

    []                    --有误

3.选择

(+++)::Parser a->Parser a->Parser a

p +++ q = \inp -> case parse  p inp of

          [] -> parse q inp

          [(v,out)]->[(v,out)]

这个是如果p Parser成功的话就返回p Parser的结果否则返回q Parser的结果.有点类似于 ?:表达式

4.派森原语 (derived primitives)

sat ::(Char->Bool)->Parser Char

sat p = do x<- item

      if p x then return x else failture

主要是获取一次字符并测试.

可以通过对一些常用的char 类型检测 如isDigit之类的需要提前导入 Data.Char包

digit ::Parser Char

digit = sat isDigit 

letter ::Parser Char

letter = sat isAlpha

char ::Char -> Parser Char

char x = sat (==x)

...

many ::Parser a->Parser [a]

many p = many1 p +++ return []

many1 ::Parser a -> [a]

many1 p = do v<-p

        vs<- many p

        return (v:vs)

many 和 many1类似与正则表达式中的?和+p来测试序列直到测试失败为止.

many允许失败 但是many1不允许失败

many 和 many1可以进行获取一段String中前面指定的格式如

parse (many digit) "123abc" -- [("123","abc")]

ident::Parser String

ident = do x<- lower;xs<- many alphaunm return (x:xs) --Haskell中的标识符开始字母是小写的

space ::Parse

space = do many (sat isSpace) return ()  --吞掉中间的空格

 

Sample :parse ident "abc def"

           ["abc"," def"]

第二次检测前就可以先使用space讲def前的" "吞掉

 

string ::String ->Parser String

string [] = return []

string (x:xs) = do char x

          string xs

          return (x:xs)

(这个不太懂)虽然例子简单 parse (string "abc") "abcdef" = [("abc","def")]

5.Handling spacing 不知道怎么翻译

token ::Parser a->Parser a

token p = do space

      v<- p

      space

      return v

这边才到了词法分析(o(︶︿︶)o 真多)

identifier ::Parse String

identifier = token ident 

natural ::Parse Int

natural = token nat

symbol ::String Parser String

symbol xs = token (string xs) //这边才用了string 就是用来测试标识符的

如 p::Parser [Int]

p = do symbol "["

    n<- natural

    ns <- many (do symbol ","

            natural)

    symbol "]"

    return (n:ns)

p是用来检测如[1,2,3]的列表的 [] 或者错误的 列表都会定义为错

 

还有一些,现在的基本工具只能做到词法分析,语法分析下次再写 睡觉先ZZzz.

posted @ 2012-05-02 21:43 zhuangzhuang1988 阅读(...) 评论(...) 编辑 收藏