mirror of
https://github.com/janishutz/eth-summaries.git
synced 2026-04-28 10:09:23 +02:00
76 lines
1.8 KiB
Haskell
76 lines
1.8 KiB
Haskell
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
|
|
|
|
{-# HLINT ignore "Use lambda-case" #-}
|
|
{-# HLINT ignore "Use newtype instead of data" #-}
|
|
|
|
import Prelude hiding (return, (>>), (>>=))
|
|
|
|
data Parser a = Prs (String -> [(a, String)])
|
|
|
|
-- Main parser function
|
|
parse :: Parser a -> String -> [(a, String)]
|
|
parse (Prs p) = p
|
|
|
|
-------------------
|
|
-- Basic parsers --
|
|
-------------------
|
|
-- Trivial failure ([] signifies parse failed)
|
|
failure :: Parser a
|
|
failure = Prs (const [])
|
|
|
|
-- Trivial success without progress
|
|
return :: a -> Parser a
|
|
return x = Prs (\inp -> [(x, inp)])
|
|
|
|
-- Trivial success with progress
|
|
item :: Parser Char
|
|
item =
|
|
Prs
|
|
( \inp -> case inp of
|
|
"" -> []
|
|
(x : xs) -> [(x, xs)]
|
|
)
|
|
|
|
----------
|
|
-- Glue --
|
|
----------
|
|
-- Apply both parsers
|
|
(|||) :: Parser a -> Parser a -> Parser a
|
|
p ||| q = Prs (\s -> parse p s ++ parse q s)
|
|
|
|
-- If first parser fails, apply second parser
|
|
(+++) :: Parser a -> Parser a -> Parser a
|
|
p +++ q =
|
|
Prs
|
|
( \s -> case parse p s of
|
|
[] -> parse q s
|
|
res -> res
|
|
)
|
|
|
|
-- Sequencing (first parser p, then parser q)
|
|
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
|
|
p >>= g = Prs (\s -> [(u, s'') | (t, s') <- parse p s, (u, s'') <- parse (g t) s'])
|
|
|
|
-- Simple version of the above
|
|
(>>) :: Parser a -> Parser b -> Parser b
|
|
p >> q = p >>= const q
|
|
|
|
-- Parse single character with property p
|
|
sat :: (Char -> Bool) -> Parser Char
|
|
sat p = item >>= \x -> if p x then return x else failure
|
|
|
|
char :: Char -> Parser Char
|
|
char x = sat (== x)
|
|
|
|
string :: String -> Parser String
|
|
string "" = return ""
|
|
string (x : xs) = char x >> string xs >> return (x : xs)
|
|
|
|
-- 0 or more repetitions of p
|
|
many :: Parser a -> Parser [a]
|
|
many p = many1 p ||| return []
|
|
|
|
-- 1 or more repetitions of p
|
|
many1 :: Parser a -> Parser [a]
|
|
many1 p = p >>= \t -> many p >>= \ts -> return (t : ts)
|