Ich bin wirklich neu in Haskell zu analysieren, aber es macht meistens Sinn.Parsec: Überlappende Parser behandeln
Ich arbeite am Aufbau eines Templating-Programms, um das Parsen besser zu lernen; Vorlagen können Werte in {{ value }}
Notation interpolieren.
Hier ist meine aktuellen Parser,
data Template a = Template [Either String a]
data Directive = Directive String
templateFromFile :: FilePath -> IO (Either ParseError (Template Directive))
templateFromFile = parseFromFile templateParser
templateParser :: Parser (Template Directive)
templateParser = do
tmp <- template
eof
return tmp
template :: Parser (Template Directive)
template = Template <$> many (dir <|> txt)
where
dir = Right <$> directive
txt = Left <$> many1 (anyChar <* notFollowedBy directive)
directive :: Parser Directive
directive = do
_ <- string "{{"
txt <- manyTill anyChar (string "}}")
return $ Directive txt
Dann habe ich es auf eine Datei in etwa so aus:
{{ value }}
This is normal Text
{{ expression }}
wenn ich laufe diese templateFromFile "./template.txt"
mit erhalte ich die Fehlermeldung:
Left "./template.txt" (line 5, column 17):
unexpected Directive " expression "
Warum passiert das und wie kann ich es beheben?
Mein grundlegendes Verständnis ist, dass many1 (anyChar <* notFollowedBy directive)
alle Zeichen bis zum Beginn der nächsten Direktive greifen sollte, dann fehlschlagen und die Liste der Zeichen bis zu diesem Punkt zurückgeben sollte; dann sollte es zurückfallen auf die vorherige many
und sollte versuchen, dir
erneut zu analysieren und sollte erfolgreich sein; Es passiert jedoch offensichtlich etwas anderes. Ich bin Probleme haben herauszufinden, wie man Dinge zu analysieren zwischen andere Dinge, wenn die Parser meist überlappen.
Ich hätte gerne ein paar Tipps, wie man das alles idiomatisch strukturieren kann, bitte lassen Sie mich wissen, wenn ich etwas auf eine alberne Art mache. Prost! Vielen Dank für Ihre Zeit!
Sinn ergibt; Wie kann ich es am besten reparieren, um das zu tun, was ich erwarte? –
'txt = many1 (notFollowedBy directive *> anyChar)' ist die einfachste Lösung, obwohl es 'directive' zweimal pro Direktive ausführt. –