Parser: read_input so we can provide unaltered input read by a parser.

master
Philippe Pittoli 2024-01-31 19:28:00 +01:00
parent 57fdd3f9d9
commit ea72414e6a
2 changed files with 34 additions and 2 deletions

View File

@ -1,5 +1,5 @@
module GenericParser.Parser where
import Prelude (between, (<<<), bind, (==), ($), pure, class Bind, unit, (+), (<>), class Applicative, class Functor, Unit, class Apply)
import Prelude (between, (<<<), bind, (==), ($), pure, class Bind, unit, (+), (-), (<>), class Applicative, class Functor, Unit, class Apply)
import Control.Alt (class Alt)
import Control.Alternative (class Alternative)
@ -202,3 +202,24 @@ parse_last_char s p = case last_char s of
-- Get the last character of a String.
last_char :: String -> Maybe Char
last_char = A.last <<< CU.toCharArray
-- | `read_input`: take a parser and provide the whole read input segment, unaltered.
-- | This function allows to create complex parsers only reading input, not re-assembling it once read.
-- | This prevents errors while concatenating strings while the unaltered input already is there to be used.
-- |
-- | This function can be used to verify a parser doesn't alter its input.
-- |
-- | Example, the following function `func` uses a combination of several
-- | parsers without having to handle the input in any way (no manipulation whatsoever).
-- | Yet, thanks to `read_input` the returned value of `func` is the whole, unaltered read input.
-- | ```
-- | func :: forall e. Parser e String
-- | func = read_input do _ <- something
-- | _ <- tryMaybe something_else
-- | void very_complex_stuff
-- | ```
read_input :: forall e s. Parser e s -> Parser e String
read_input p = do input <- current_input
_ <- p
endpos <- current_position
pure $ CU.take (endpos - input.position) input.string

View File

@ -8,6 +8,7 @@ import Effect.Console (log)
import Effect (Effect, foreachE)
import GenericParser.Parser (Parser(..))
import GenericParser.Parser as P
import GenericParser.DomainParser.Common (ldh_str, DomainError(..))
import GenericParser.DomainParserRFC1035 as RFC1035
import GenericParser.DomainParser as ModernDomains
@ -85,6 +86,16 @@ main = do
test_series "E.address (short)" E.address id showerror_email T.valid_email_addresses_short
log ""
let spaces = [ """" """", """ " """" ]
let spaces = [ """" """", """ " """" ]
lreturns = [ """" \r\nx"""", """ "\r\n"""", """ "\r\n """" ]
characters = [ "\r", "\n", "\"" ]
test_series "E.quoted_string (short)" E.quoted_string id showerror_email spaces
test_series "E.qcontent (short)" E.qcontent id showerror_email spaces
test_series "E.quoted_string (lreturns)" E.quoted_string id showerror_email lreturns
test_series "E.qcontent (characters)" E.qcontent id showerror_email characters
log ""
let quotedstrings = [ """" "spaces?""", """ " " """ ]
test_series "E.quoted_string---------------" E.quoted_string id showerror_email quotedstrings
test_series "P.read_input (E.quoted_string)" (P.read_input E.quoted_string) id showerror_email quotedstrings