سؤال

أحاول استخدام FPARSEC لتحليل لغة قائمة بسيطة (البيانات من Passionpaper بالفعل) كمثال Combinator Simple. لكنني واجهت خطأ لا يمكنني أن أبدو فيه. أنا جديد على Combinators Parser ويبدو أن FPARSEC يعتمد علي معرفة Parsec ، لكنني أجد وثائق Parsec غامضة.

قواعد لغة ورقة المهمة بسيطة (أنا أتجاهل tags في الوقت الحالي)

  • تنتهي المشاريع بـ ":"
  • تبدأ المهام بـ "-"
  • أي سطر آخر من النص هو مذكرة نصية واضحة على المشروع أو المهمة

لذا ، يجب أن تعود السلسلة "Project 1: nsome note nproject 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 موقع ورقة العملبعض الأمثلة على بناء الجملة

    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
هل كانت مفيدة؟

المحلول

أنا لست بطلاقة فائقة في 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 لقد فضلت نمط combinator على نمط الأحادي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top