我试图使用fparsec分析的一种简单的待办列表语言(数据从TaskPaper实际上)作为一个简单的分析器组合的例子。但我遇到了一个错误我不能似乎难题。我是新来的组合子分析器和FParsec似乎要依靠我知道秒差距,但我找到秒差距的文件难以理解的.

规则的任务纸语言是简单的(我忽略@的标签现在)

  • 项目结束与':'
  • 任务开始'-'
  • 任何其他线路的文本是一个普通的文本注意关于该项目或任务

所以string"项目1: Some注意 Project2:"应当返回自parseFile作[项目名称("项目1");NoteText("有的注意");项目名称("项目2")],但是,我获得[项目名称("项目1");项目名称("某些注意 Project2")]

下面是我析程序的代码。

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软件的TaskPaper应用程序 TaskPaper网站 一些实例中的语法

    Project 1:
    Description of Project One
    -task for project 1
    -another task for project 1
    details for another task
    -final task

    Go to store:
    -buy eggs
    -buy milk
有帮助吗?

解决方案

我不是超级流利FParsec,但这一工作:

let newline = pchar '\n'
let notNewLine = noneOf "\n"
let allTillEOL = manyChars notNewLine

let parseProject = 
    let r = manyCharsTill (noneOf ":\n") (pchar ':')
    r |>> ProjectName

let parseTask = 
    let r = skipChar '-' >>. allTillEOL
    r |>> TaskText

let parseNote = allTillEOL |>> NoteText

let parseLine = parseTask <|> attempt parseProject <|> parseNote
let parseFile = sepBy parseLine newline

let a = run parseFile "Project 1:\nSome note\nProject 2:\n-One Task"
match a with
| Success (a,b,c) -> printfn "%A" a
| Failure (a,b,c) -> printfn "failed: %s" a

打印出:

[ProjectName "Project 1"; NoteText "Some note"; ProjectName "Project 2"; TaskText "One Task"]

我会试验它对其他的例子。

顺便说一句:的几次我用FParsec我首选的组合的风格元的风格。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top