単純なパーサー コンビネーターの例として、fparsec を使用して単純な todo リスト言語 (実際には TaskPaper のデータ) を解析しようとしています。しかし、私はパズルを解くことができないように見えるバグに遭遇しました。私はパーサー コンビネータを初めて使用し、FParsec は私が Parsec を知っていることに依存しているようですが、パーセックのドキュメントは不可解です。
課題用紙言語のルールは単純です (今のところ @tags は無視しています)
- プロジェクトは「:」で終わります
- タスクは「-」で始まります
- その他のテキスト行は、プロジェクトまたはタスクに関するプレーン テキストのメモです。
したがって、文字列 "Project 1:\nSome note\nProject 2:" は parseFile から [ProjectName("Project 1");NoteText("Some note");ProjectName("Project 2")] として返されるはずですが、代わりに、 get [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)
編集済み
構文は、Hogbay Software の TaskPaper アプリケーションTaskPaper の Web サイトから引用され ています 構文の例
プロジェクト 1: プロジェクトワンの説明 -プロジェクト 1 のタスク -プロジェクト 1 の別のタスク 別のタスクの詳細 ・最終課題 店に行く: ・卵を買う ・牛乳を買う