diff --git a/editor/src/Elmz/Parser.elm b/editor/src/Elmz/Parser.elm index 6e8082e20..c8eff0839 100644 --- a/editor/src/Elmz/Parser.elm +++ b/editor/src/Elmz/Parser.elm @@ -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 *> diff --git a/editor/src/Unison/SearchboxParser.elm b/editor/src/Unison/SearchboxParser.elm index dba18c372..2aae3201d 100644 --- a/editor/src/Unison/SearchboxParser.elm +++ b/editor/src/Unison/SearchboxParser.elm @@ -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)))