FPARSEC и синтаксис на основе разделителя

StackOverflow https://stackoverflow.com/questions/4252441

  •  27-09-2019
  •  | 
  •  

Вопрос

Я пытаюсь использовать FPARSEC для анализа простого языка списка TODO (данные из Taskaper фактически) в качестве простого примера комбинатора парсера. Но я столкнулся с ошибкой, я не могу голодать. Я новичок в комбинатора анализатора, а FPARSEC, кажется, полагается на меня, зная паршек, но я нахожу документацию Parsec Incrutable.

Правила языка бумаги задач просты (я уже игнорирую @TAGS)

  • Заканчивается проекты с «:»
  • Задачи начинаются с '-'
  • Любая другая линия текста - это простое текстовое примечание на проекте или задаче

Таким образом, строка «проект 1: NSOMET NPROJECT 2:» должен возвращаться из Parsefile в виде [ProjectName («Project 1»); NoteText («Некоторые примечание»); ProjectName («Проект 2»)], но вместо этого я Получить [ProjectName («Проект 1»); ProjectName («Некоторые примечание 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)

Отредактировано

Синтаксис берется из приложения Taskaper программного обеспечения Hogbay Taskaper сайтНекоторые примеры синтаксиса

 Проект 1: Описание проекта One -Task для проекта 1 -апоказательская задача для проекта 1 Подробнее для другой задачи - FInal Задача Перейти в магазин: -Буй яйца -Буй молоко
Это было полезно?

Решение

Я не супер свободно в 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