Pregunta

Estoy intentando utilizar fparsec para analizar un sencillo lenguaje de lista de tareas (los datos de TaskPaper en realidad) como un ejemplo sencillo analizador combinador. Pero me he encontrado un bug me parece que no puede descifrar. Soy nuevo en combinadores de analizadores sintácticos y FParsec parece confiar en mí sabiendo Parsec, pero estoy encontrando el inescrutable documentación parsec.

Las reglas de la lengua de papel tareas son simples (estoy ignorando @tags por ahora)

  • Los proyectos terminan con un ':'
  • Las tareas se inician con '-'
  • Cualquier otra línea de texto es una nota de texto sin formato a cada proyecto o tarea

Así que la cadena "Proyecto 1: \ nAlgunos nota \ nProject 2:" se apartase de parseFile como [Proyecto ( "Proyecto 1"); NoteText ( "Algunos nota"); Nombre proyecto ( "Proyecto 2")], pero en cambio, recibo [Proyecto ( "Proyecto 1"); Nombre proyecto ( "Algunos señalan \ nProject 2")]

A continuación se muestra el código del analizador.

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)

Editado

La sintaxis es tomada de la aplicación de TaskPaper Hogbay Software TaskPaper página web Algunos ejemplos de la sintaxis

    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
¿Fue útil?

Solución

No soy muy fluido en FParsec, pero este funciona:

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"]

Me había prueba contra otros ejemplos.

Por cierto:. Las pocas veces que he usado FParsec he preferido el estilo combinador sobre el estilo monádico

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top