Parsec

Parsec是一个词法及语法分析器。

匹配字符与字符串

Prelude Text.Parsec> parseTest anyChar "a"
'a'
Prelude Text.Parsec> parseTest (char 'a') "a"
'a'
Prelude Text.Parsec> parseTest (satisfy (=='a')) "a"
'a'
Prelude Text.Parsec> parseTest (oneOf "abc") "a"
'a'
Prelude Text.Parsec> parseTest (string "a") "a"
"a"
  • anyChar 匹配任意字符
  • char c 匹配特定字符 c
  • satisfy p 匹配谓词 p
  • oneOf s 匹配字符串 s 中的任意字符
  • string s 匹配特定字符串 s

匹配0次,1次或多次

Prelude Text.Parsec> parseTest (many digit) "3"
"3"
Prelude Text.Parsec> parseTest (many digit) ""
""
Prelude Text.Parsec> parseTest (many1 digit) ""
parse error at (line 1, column 1):
unexpected end of input
expecting digit
Prelude Text.Parsec> parseTest (many1 digit) "3"
"3"
Prelude Text.Parsec> parseTest (many1 digit) "34"
"34"
Prelude Text.Parsec> parseTest (many digit) "34"
"34"
  • many 匹配0次1次或多次
  • many1 匹配1次或多次
  • digit 匹配数字

在 Parser Monad 中改变返回值类型

Prelude Text.Parsec Text.Parsec.String> num = do{ n <- many1 digit; return $ read n } :: Parser Integer
Prelude Text.Parsec Text.Parsec.String> parseTest num "123"
123

忽略空白

Prelude Text.Parsec Text.Parsec.String> whitespace = Control.Monad.void $ many $ oneOf " \n\t" :: Parser ()
Prelude Text.Parsec Text.Parsec.String> parseTest (whitespace >> anyChar) " a"
'a'
Prelude Text.Parsec Text.Parsec.String> lexeme = (\p -> whitespace >> p) :: Parser a -> Parser a
Prelude Text.Parsec Text.Parsec.String> parseTest (lexeme anyChar) " a"
'a'

sequence 和 choice

Prelude Text.Parsec Text.Parsec.String> parseTest (sequence [anyChar, anyChar]) "ab"
"ab"
Prelude Text.Parsec Text.Parsec.String> parseTest (anyChar >> anyChar) "ab"
'b'
Prelude Text.Parsec Text.Parsec.String> parseTest (choice [anyChar, digit]) "a"
'a'
Prelude Text.Parsec Text.Parsec.String> parseTest (choice [anyChar, digit]) "3"
'3'
Prelude Text.Parsec Text.Parsec.String> parseTest (anyChar <|> digit) "a"
'a'
Prelude Text.Parsec Text.Parsec.String> parseTest (anyChar <|> digit) "3"
'3'
  • sequence 匹配并且,与 (>>) 操作符有所不同。
  • choice 匹配或者,也可用 (<|>) 操作符

使用 try 来回溯

Prelude Text.Parsec Text.Parsec.String> parseTest (sequence [char 'a', char 'b'] <|> sequence [char 'a', char 'c']) "ac"
parse error at (line 1, column 2):
unexpected "c"
expecting "b"
Prelude Text.Parsec Text.Parsec.String> parseTest (try (sequence [char 'a', char 'b']) <|> sequence [char 'a', char 'c']) "ac"
"ac"
Prelude Text.Parsec Text.Parsec.String> parseTest (string "ab" <|> string "ac") "ac"
parse error at (line 1, column 1):
unexpected "c"
expecting "ab"
Prelude Text.Parsec Text.Parsec.String> parseTest (try (string "ab") <|> string "ac") "ac"
"ac"
  • 当 choice 的成员parser由多个parser组成时,该成员的某一部分parser成功某一部分parser失败将会导致该成员匹配失败,从而失去匹配其他成员parser的机会。
  • 此时应该使用 try 来强制回溯。

参考链接

Intro to Parsing with Parsec in Haskell

Haskell语言学习笔记(41)Parsec(1)的更多相关文章

  1. Haskell语言学习笔记(88)语言扩展(1)

    ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...

  2. Haskell语言学习笔记(79)lambda演算

    lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...

  3. Haskell语言学习笔记(69)Yesod

    Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...

  4. Haskell语言学习笔记(20)IORef, STRef

    IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...

  5. Haskell语言学习笔记(39)Category

    Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...

  6. Haskell语言学习笔记(43)Parsec(2)

    组合子 1 Prelude Text.Parsec Text.Parsec.String> parseTest (count 3 (char 'a')) "aaa" &quo ...

  7. Haskell语言学习笔记(57)Parsec(4)

    Parser 类型 data ParsecT s u m a type Parsec s u = ParsecT s u Identity type Parser = Parsec String () ...

  8. Haskell语言学习笔记(46)Parsec(3)

    Applicative Parsing 使用 Applicative 式的 Parser. 包括使用 (<$>), (<*>), (<$), (<*), (*> ...

  9. Haskell语言学习笔记(72)Free Monad

    安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...

随机推荐

  1. vue 文件中的注释

    在每个代码块内,注释的时候,需要使用各自语言的注释语法去注释(HTML.CSS.JavaScript.Jade 等).在文件最顶部注释的时候用HTML的注释语法:<!- 在这里写注释的内容 -- ...

  2. jquery操作select大全详解

    每一次操作select的时候,总是要出来翻一下资料,不如自己总结一下,以后就翻这里了. 比如<select class="selector"></select&g ...

  3. ML(4): 决策树分类

    决策树(Decision Tree)是用于分类和预测的主要技术,它着眼于从一组无规则的事例推理出决策树表示形式的分类规则,采用自顶向下的递归方式,在决策树的内部节点进行属性值的比较,并根据不同属性判断 ...

  4. Hadoop专业解决方案-第13章 Hadoop的发展趋势

    一.前言: 非常感谢Hadoop专业解决方案群:313702010,兄弟们的大力支持,在此说一声辛苦了,经过两周的努力,已经有啦初步的成果,目前第13章 Hadoop的发展趋势小组已经翻译完成,在此对 ...

  5. PAT 乙级 1038 统计同成绩的学生C++版

    1038. 统计同成绩学生(20) 时间限制 250 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 本题要求读入N名学生的成绩,将 ...

  6. 【转载】如何在 Github 上发现优秀的开源项目?

    之前发过一系列有关 GitHub 的文章,有同学问了,GitHub 我大概了解了,Git 也差不多会使用了,但是还是搞不清 GitHub 如何帮助我的工作,怎么提升我的工作效率? 问到点子上了,Git ...

  7. shell脚本判断语句和循环语句

    if判断语句 exit跳出判读语句 不加exit的结果 read -n(不换行) 判断是否输入的是数字 read age[[ $age =~ ^[0-9]+$ ]]if [ $? -ne 0 ]; t ...

  8. [UE4]acotor放置4*4列表

    // Number of blocks const int32 NumBlocks = Size * Size; // Loop to spawn each block ; BlockIndex< ...

  9. 组件Slate教程 & UMG widget构造初始化函数中获取其内部组件

    转自:http://aigo.iteye.com/blog/2296218 目的:在自定义的Widget初始化完毕后,获取其内部的button.combo等UMG组件的C++指针. 这里我们新建了一个 ...

  10. javascript cookie操作.

    给cookie追加name: document.cookie="name="+escape("我叫钢蛋");//这里可以不写secape,这样写会更加的安全., ...