我正在尝试使用 fparsec 来解析一个简单的待办事项列表语言(实际上是来自 TaskPaper 的数据)作为一个简单的解析器组合器示例。但是我遇到了一个我似乎无法解开的错误。我是解析器组合器的新手,FParsec 似乎依赖于我了解 Parsec,但我发现 parsec 文档难以理解。
任务论文语言的规则很简单(我现在忽略@tags)
- 项目以“:”结尾
- 任务以“-”开头
- 任何其他文本行都是项目或任务上的纯文本注释
所以字符串 "Project 1:\nSome note\nProject 2:" 应该从 parseFile 作为 [ProjectName("Project 1");NoteText("Some note");ProjectName("Project 2")] 返回,但相反,我get [ProjectName("Project 1");ProjectName("Some note\nProject 2")]
下面是我的解析器代码。
open FParsec.Primitives
open FParsec.CharParsers
type ProjectAst = ProjectName of string
| TaskText of string
| NoteText of string
let asString (x:char list) :string =
x
|> List.map (fun y -> y.ToString())
|> String.concat ""
let makeNote x = NoteText(asString x)
let parseProject =
parse { let! s = many (noneOf ":\n\r\c")
do! skipChar ':'
return ProjectName( asString s ) }
let parseTask =
parse { do! skipChar '-'
let! s = many (noneOf "\n\r\c")
return TaskText( asString s) }
let parseNote = many (noneOf "\n\r\c") |>> makeNote
let parseLine = parseTask <|> (attempt parseProject) <|> parseNote
let parseFile = sepBy parseLine (many1 whitespace)
已编辑
语法取自 Hogbay Software 的 TaskPaper 应用程序TaskPaper 网站 一些语法示例
项目一: 项目一说明 - 项目 1 的任务 - 项目 1 的另一个任务 另一个任务的详细信息 -最终任务 去商店: - 买鸡蛋 - 买牛奶