Fix bug in parser satisfy function

This commit is contained in:
Paul Chiusano 2015-05-05 11:30:03 -04:00
parent d013e98362
commit 1a1063c0a7
2 changed files with 23 additions and 20 deletions

View File

@ -27,13 +27,12 @@ map f p s = case p s of
(<$>) : (a -> b) -> Parser a -> Parser b
(<$>) = map
-- note: implementation not stack safe
many : Parser a -> Parser (List a)
many a s = case a s of
Err e -> if e.committed then Err e else Ok ([],0)
Ok (hd,consumed) -> case many a { s | offset <- s.offset + consumed } of
Err e -> Err e
Ok (tl,consumedTl) -> Ok (hd :: tl, consumed + consumedTl)
many a =
-- note: implementation not stack safe
(a `andThen` \hd -> map ((::) hd) (many a))
`or`
unit []
some : Parser a -> Parser (List a)
some a = (::) <$> a <*> many a
@ -41,8 +40,9 @@ some a = (::) <$> a <*> many a
andThen : Parser a -> (a -> Parser b) -> Parser b
andThen p f s = case p s of
Err e -> Err e
Ok (a, consumed) ->
(if consumed > 0 then commit else identity) (f a) { s | offset <- s.offset + consumed }
Ok (a, consumed) -> case f a { s | offset <- s.offset + consumed } of
Err e -> Err e
Ok (b, consumedb) -> Ok (b, consumed + consumedb)
commit : Parser a -> Parser a
commit p s = case p s of
@ -77,8 +77,10 @@ ap f a = f `andThen` \f -> map f a
satisfy : (Char -> Bool) -> Parser String
satisfy f s =
let sub = String.slice s.offset ((String.length s.string) `max` (s.offset + 1)) s.string
in if String.all f sub then Ok (sub, 1) else Err { message = [], committed = False }
let sub = String.slice s.offset ((String.length s.string) `min` (s.offset + 1)) s.string
in if String.all f sub && s.offset < String.length s.string
then Ok (sub, 1)
else Err { message = [], committed = False }
symbol : Char -> Parser String
symbol c = satisfy ((==) c)
@ -119,6 +121,14 @@ regex r s = let compiled = Regex.regex r in case reset s of
[] -> Err { message = [], committed = False }
hd :: _ -> Ok (hd, String.length hd)
until : Char -> Parser String
until c =
map String.concat (many (satisfy ((/=) c)))
until1 : Char -> Parser String
until1 c =
map String.concat (some (satisfy ((/=) c)))
infixl 4 <*>
infixl 4 <*
infixl 4 *>

View File

@ -17,7 +17,7 @@ parser : { literal : Term -> a
-> Parser a
parser env =
let lit = Parser.map env.literal literal
q = Parser.map env.query (until ' ')
q = Parser.map env.query (Parser.until ' ')
any = Parser.satisfy (always True)
in Parser.choice
[ env.combine <$> (lit <* space) <*> any
@ -59,12 +59,12 @@ float : Parser Term
float = Parser.map (Term.Lit << Term.Number) (Parser.attempt Parser.float)
string : Parser Term
string = (Parser.symbol quote *> (until quote) <* Parser.symbol quote)
string = (Parser.symbol quote *> (Parser.until quote) <* Parser.symbol quote)
|> Parser.map (Term.Lit << Term.Text)
openString : Parser Term
openString =
Parser.symbol quote `Parser.andThen` \_ -> until quote
Parser.symbol quote `Parser.andThen` \_ -> Parser.until quote
|> Parser.map (Term.Lit << Term.Text)
distance : Parser Term
@ -85,10 +85,3 @@ fraction = Parser.symbol '1'
quote = '"' -- "
until : Char -> Parser String
until c =
Parser.map String.concat (Parser.many (Parser.satisfy ((/=) c)))
until1 : Char -> Parser String
until1 c =
Parser.map String.concat (Parser.some (Parser.satisfy ((/=) c)))