Low-level functions for creating parser combinator libraries.
Again, when parsing, you want to allocate as little as possible. So this function lets you say:
isSubChar isSpace offset "this is the source string"
--==> newOffsetThe (Char -> Bool) argument is called a predicate.
The newOffset value can be a few different things:
-1 means that the predicate failed-2 means the predicate succeeded with a \noffset + 1 or offset + 2
depending on whether the UTF16 character is one or two
words wide.It is better to use union types in general, but it is worth the danger within parsing libraries to get the benefit outside.
So you can write a chomp function like this:
chomp : (Char -> Bool) -> Int -> Int -> Int -> String -> (Int, Int, Int)
chomp isGood offset row col source =
let
newOffset =
Prim.isSubChar isGood offset source
in
-- no match
if newOffset == -1 then
(offset, row, col)
-- newline match
else if newOffset == -2 then
chomp isGood (offset + 1) (row + 1) 1 source
-- normal match
else
chomp isGood newOffset row (col + 1) sourceNotice that chomp can be tail-call optimized, so this turns into a
while loop under the hood.
Find a substring after a given offset.
findSubString before "42" offset row col "Is 42 the answer?"
--==> (newOffset, newRow, newCol)If offset = 0 and before = True we would get (3, 1, 4)
If offset = 0 and before = False we would get (5, 1, 6)
If offset = 7 we would get (-1, 1, 18)
When making a fast parser, you want to avoid allocation as much as possible. That means you never want to mess with the source string, only keep track of an offset into that string.
You use
isSubStringlike this:You are looking for
"let"at a givenoffset. On failure, thenewOffsetis-1. On success, thenewOffsetis the new offset. With our"let"example, it would beoffset + 3.You also provide the current
rowandcolwhich do not align withoffsetin a clean way. For example, when you see a\nyou are atrow = row + 1andcol = 1. Furthermore, some UTF16 characters are two words wide, so even if there are no newlines,offsetandcolmay not be equal.