Frage

Ich versuche FParsec zu verwenden, um eine einfache ToDo-Liste Sprache (die Daten aus Taskpaper tatsächlich) als einfaches Parser combinator Beispiel zu analysieren. Aber ich habe in einen Fehler laufen ich nicht herauszubekommen scheinen kann. Ich bin neu in Parser Kombinatoren und FParsec scheint auf mich zu wissen, Parsec zu verlassen, aber ich bin der Parsec Dokumentation unergründlich zu finden.

Die Regeln der Aufgabe Papier Sprache einfach sind (ich ignoriere @tags jetzt) ??

  • Projekte enden mit einem ':'
  • Die Aufgaben werden beginnen mit '-'
  • Jede andere Textzeile ist eine Nur-Text Hinweis auf entweder das Projekt oder eine Aufgabe

So die Zeichenfolge "Projekt 1: \ nEinige note \ nProject 2:" von parseFile zurückkehren sollte als [Projektname ( "Projekt 1"); Notetext ( "Some Note"); Projektnamen ( "Projekt 2")], aber stattdessen ich [Projektname ( "Projekt 1"); Projektname ( "Some Note \ nProject 2")]

Unten ist mein Parsercode.

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)

Edited

Die Syntax von Hogbay Software Taskpaper Anwendung genommen wird Taskpaper Website Einige Beispiele für die Syntax

    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
War es hilfreich?

Lösung

Ich bin nicht super fließend FParsec, aber diese funktioniert:

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

druckt:

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

ich es gegen andere Beispiele testen würde.

BTW:. Die wenigen Male, die ich FParsec ich verwendet habe, habe die combinator Stil über monadischen Stil bevorzugt

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top