From 51fe35c60f5a560c32c5ee26c4317d7858ac7fde Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Tue, 9 Jan 2024 07:24:41 +0100 Subject: [PATCH] Simple generic parsing functions for common searched elements. --- src/Main.purs | 4 +++ src/Parser.purs | 70 +++++++++++++++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/Main.purs b/src/Main.purs index e37aedb..ae48c38 100644 --- a/src/Main.purs +++ b/src/Main.purs @@ -47,6 +47,10 @@ main = do Just (Tuple x y) -> show x <> " " <> show y Nothing -> "failed" + log $ "parsing 'fic' in 'fiction' (string): " <> case parse (string "fic") "fiction" of + Just (Tuple x y) -> show x <> " " <> show y + Nothing -> "failed" + -- JUST WORKS -- isffound $ parse isf "fable" -- isffound $ parse isf "f" diff --git a/src/Parser.purs b/src/Parser.purs index 79d96c6..7aaf11a 100644 --- a/src/Parser.purs +++ b/src/Parser.purs @@ -5,14 +5,14 @@ import Prelude import Data.Array as A import Data.Maybe (Maybe(..)) import Data.Tuple (Tuple(..)) -import Data.String.CodeUnits (uncons, toCharArray, fromCharArray) +import Data.String.CodeUnits (singleton, uncons, toCharArray, fromCharArray) newtype Parser v = Parser (String -> Maybe (Tuple v String)) parse :: forall a. Parser a -> (String -> Maybe (Tuple a String)) parse (Parser p) = p -itemP :: Parser Char -itemP = Parser p +item :: Parser Char +item = Parser p where p str = case uncons str of Nothing -> Nothing Just { head: x, tail: xs } -> Just (Tuple x xs) @@ -41,35 +41,47 @@ instance bindParser :: Bind Parser where let (Parser p2) = f x in p2 xs -charP :: Char -> Parser Boolean -charP c = (_ == c) <$> itemP - -- Next steps. +empty :: forall a. Parser a +empty = Parser \_ -> Nothing + sat :: (Char -> Boolean) -> Parser Char -sat f = Parser p - where - p stream = case uncons stream of - Nothing -> Nothing - Just { head: x, tail: xs } -> if f x then Just (Tuple x xs) - else Nothing +sat p = do x <- item + if p x then pure x else empty -emptyP :: forall a. Parser a -emptyP = Parser \_ -> Nothing +isDigit :: Char -> Boolean +isDigit = between '0' '9' -sat2 :: (Char -> Boolean) -> Parser Char -sat2 p = do x <- itemP - if p x then pure x else emptyP +digit :: Parser Char +digit = sat isDigit ---try :: Parser a -> Parser a ---try p = Parser p' --- where --- p' = case parse p of --- Nothing -> p --- Just --- orElse, (<|>) :: Parser a -> Parser a -> Parser a +isLower :: Char -> Boolean +isLower = between 'a' 'z' -stringP :: String -> Parser Boolean -stringP str = case A.uncons (toCharArray str) of - Nothing -> Parser \stream -> Just (Tuple true stream) - Just { head: x, tail: xs } -> do _ <- charP x - stringP (fromCharArray xs) +lower :: Parser Char +lower = sat isLower + +isUpper :: Char -> Boolean +isUpper = between 'A' 'Z' + +upper :: Parser Char +upper = sat isUpper + +isAlpha :: Char -> Boolean +isAlpha c = A.any (\f -> f c) [isLower, isUpper] + +letter :: Parser Char +letter = sat isAlpha + +char :: Char -> Parser Char +char x = sat (_ == x) + +concat :: Char -> String -> String +concat c rest = singleton c <> rest + +string :: String -> Parser String +string str = case A.uncons (toCharArray str) of + Nothing -> Parser \stream -> Just (Tuple "" stream) + Just { head: x, tail: xs } -> do c <- char x + rest <- string (fromCharArray xs) + pure (concat c rest)