2010-11-23 2 views
1

Я пытаюсь использовать fparsec для синтаксического анализа простого списка языков списка дел (данных из TaskPaper) в качестве простого примера комбинатор синтаксического анализатора. Но я столкнулся с проблемой, с которой я не могу разобраться. Я новичок в комбинаторах парсеров, и FParsec, похоже, полагается на меня, зная Parsec, но я считаю документацию parsec непостижимой.Синтаксис FParsec и синтаксиса на основе разделителя

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

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

так строка «Проект 1: \ Nsome примечание \ nProject 2:» должен вернуться из parseFile как [Projectname («Проект 1»); NoteText («Некоторая заметка»); ProjectName («Projec t 2 ")], но вместо этого я получаю [ProjectName (« Project 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) 

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

Синтаксис берется из приложения TaskPaper Hogbay Software, TaskPaper website Некоторые примеры синтаксиса

 
    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 
+0

Я запустил код и получил `[NoteText" Proje "]` – 2010-11-23 03:40:29

+0

Можете ли вы разместить некоторые репрезентативные образцы этого формата? – 2010-11-23 03:43:30

ответ

3

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

Я бы проверить его на других примерах.

BTW: несколько раз я использовал FParsec. Я предпочитал стиль комбинатора над монадическим стилем.