From d68de7f2fbecbfb3ff3c9a224b3fb13e43f5526e Mon Sep 17 00:00:00 2001 From: Bram Date: Fri, 29 Mar 2024 07:13:06 +0100 Subject: [PATCH] Add parser helper functions --- elm.json | 1 + src/Internal/Tools/ParserExtra.elm | 77 ++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/Internal/Tools/ParserExtra.elm diff --git a/elm.json b/elm.json index 66e87bf..1c32573 100644 --- a/elm.json +++ b/elm.json @@ -13,6 +13,7 @@ "dependencies": { "elm/core": "1.0.0 <= v < 2.0.0", "elm/json": "1.0.0 <= v < 2.0.0", + "elm/parser": "1.0.0 <= v < 2.0.0", "elm/time": "1.0.0 <= v < 2.0.0", "miniBill/elm-fast-dict": "1.0.0 <= v < 2.0.0" }, diff --git a/src/Internal/Tools/ParserExtra.elm b/src/Internal/Tools/ParserExtra.elm new file mode 100644 index 0000000..0148b3b --- /dev/null +++ b/src/Internal/Tools/ParserExtra.elm @@ -0,0 +1,77 @@ +module Internal.Tools.ParserExtra exposing (..) + +import Parser as P exposing (Parser, (|.), (|=)) + +zeroOrMore : Parser a -> Parser (List a) +zeroOrMore parser = + P.loop [] + (\tail -> + P.oneOf + [ P.succeed (\head -> P.Loop (head :: tail)) + |= parser + , P.succeed (P.Done (List.reverse tail)) + ] + ) + +oneOrMore : Parser a -> Parser (List a) +oneOrMore parser = + P.succeed (::) + |= parser + |= zeroOrMore parser + +atLeast : Int -> Parser a -> Parser (List a) +atLeast n parser = + P.loop [] + (\tail -> + if List.length tail < n then + P.succeed (\head -> P.Loop (head :: tail)) + |= parser + else + P.oneOf + [ P.succeed (\head -> P.Loop (head :: tail)) + |= parser + , P.succeed (P.Done (List.reverse tail)) + ] + ) + +atMost : Int -> Parser a -> Parser (List a) +atMost n parser = + P.loop [] + (\tail -> + if List.length tail < n then + P.oneOf + [ P.succeed (\head -> P.Loop (head :: tail)) + |= parser + , P.succeed (P.Done (List.reverse tail)) + ] + else + P.succeed (P.Done (List.reverse tail)) + ) + +times : Int -> Int -> Parser a -> Parser (List a) +times inf sup parser = + let + low : Int + low = max 0 (min inf sup) + + high : Int + high = max 0 sup + in + P.loop [] + (\tail -> + if List.length tail < low then + P.succeed (\head -> P.Loop (head :: tail)) + |= parser + else if List.length tail < high then + P.oneOf + [ P.succeed (\head -> P.Loop (head :: tail)) + |= parser + , P.succeed (P.Done (List.reverse tail)) + ] + else + P.succeed (P.Done (List.reverse tail)) + ) + +exactly : Int -> Parser a -> Parser (List a) +exactly n = + times n n