Question

Je suis en train d'utiliser fparsec pour analyser un langage de liste de tâches simples (les données de TaskPaper en fait) comme un simple analyseur Combinator exemple. Mais j'ai rencontré un bug, je ne peux pas sembler déchiffrer. Je suis nouveau à l'analyseur combinateurs et FParsec semble compter sur moi savoir parsec, mais je trouve l'insondable de la documentation parsec.

Les règles de la langue de papier tâche sont simples (j'ignore @tags pour l'instant)

  • Projets fin avec ':'
  • Les tâches sont commencent par '-'
  • Toute autre ligne de texte est une note de texte brut soit sur le projet ou la tâche

la chaîne "Projet 1: \ nCertains Note \ nProject 2:" devrait revenir de parseFile comme [ProjectName ( "Projet 1"); NoteText ( "Quelques remarques"); ProjectName ( "Projet 2")], mais à la place, je reçois [ProjectName ( "projet 1"); ProjectName ( "Quelques remarques \ nProject 2")]

Voici mon code d'analyse syntaxique.

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)

Edité

La syntaxe est tirée de la demande TaskPaper de Hogbay Software TaskPaper site Voici quelques exemples de la syntaxe

    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
Était-ce utile?

La solution

Je ne suis pas super à l'aise FParsec, mais celui-ci fonctionne:

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

imprime:

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

Je tester contre d'autres exemples.

BTW:. Les rares fois où j'ai utilisé FParsec j'ai préféré le style combinateur sur le style monadique

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top