Я пытаюсь использовать fparsec для анализа простого языка списка задач (на самом деле данных из TaskPaper) в качестве простого примера комбинатора синтаксического анализа.Но я столкнулся с ошибкой, которую не могу разгадать.Я новичок в комбинаторах синтаксического анализа, и FParsec, кажется, полагается, что я знаю Parsec, но я нахожу документацию parsec непостижимой.
Правила языка заданий просты (я игнорирую @tags длясейчас)
- Проекты заканчиваются на ':'
- Задачи начинаются с '-'
- Любая другая строка текста представляет собой обычную текстовую заметку напроект или задача
Поэтому строка «Project 1: \ nSome note \ nProject 2:» должна возвращаться из parseFile как [ProjectName («Project 1»); NoteText («Some note»); ProjectName)(«Проект 2»)], но вместо этого я получаю [ProjectName («Проект 1»); ProjectName («Некоторая заметка \ nПроект 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 Некоторые примеры синтаксиса
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