Workarounds for a bug in
Parser.
The Elm Parser internally keeps track of the current position in two ways:
See the Positions chapter in the Parser documentation for more details.
Normally both kinds of position infos (row and column vs. offset) are in sync with each other. (For a given source string, you can calculate both row and column from the offset and vice versa.)
There's a bug in the Parser code though.
The following parsers break this synchronicity:
lineComment,
multiComment,
chompUntil, and
chompUntilEndOr.
They set...
Here's an example with chompUntil:
import Parser exposing ((|.), (|=), Parser)
testParser : Parser { row : Int, col : Int, offset : Int }
testParser =
Parser.succeed (\row col offset -> { row = row, col = col, offset = offset })
|. Parser.chompUntil "token"
|= Parser.getRow
|= Parser.getCol
|= Parser.getOffset
Parser.run testParser "< token >"
--> Ok { row = 1, col = 8, offset = 2 }The state after the test parser is run:
As a workaround, this package offers xxxBefore and xxxAfter parsers which consistently position
both row/column and offset either before or after the (closing) token.
lineCommentBefore and lineCommentAftermultiCommentBefore and multiCommentAfterchompUntilBefore and chompUntilAfterchompUntilEndOrBefore and chompUntilEndOrAfterWhy are there two different workarounds for each buggy parser?
On the one hand, if you already have working parsers and don't use the row or column information,
then you can replace them with the xxxBefore variants and they will continue to work.
(There's one exception for the multiComment parser though, see below.)
On the other hand, most often the xxxAfter variants are easier to use,
because you don't need to chomp the (closing) token yourself.
So if you write new parsers, you'll likely want to use the xxxAfter variants.
Plus, if the bug will be fixed, it can be assumed that the
fixed parsers will work like the xxxAfter variants.
(If you want to know why, you can look at the description of
this pull request.)
If you are unsure whether to use the xxxBefore or the xxxAfter parsers
or whether to use the workarounds at all, you could follow these guidelines:
xxxBefore workarounds.
Then you don't have to change your existing parsers,
but the workarounds maintain an internally consistent state.
This makes it easier to combine them with other parsers later.
(There's one exception for the multiComment parser though, see below.)xxxAfter workarounds, because often they are easier to use
and because they implement the intended behavior.
You'll have to modify the surrounding parsers, but they don't work anyhow.xxxAfter workarounds, because often they are easier to use
and because they implement the intended behavior.There's one exception to the rules above: if the
multiComment
parser is used with
Nestable
comments, then it isn't affected from the bug.
(For this mode it's implemented differently.)
Therefore this parser should be replaced with the multiCommentAfter
workaround to keep the current behavior.
Just like Parser.lineComment
except it consistently stops after the linefeed character.
Just like Parser.multiComment
except it consistently stops before the last closing string.
Just like Parser.multiComment
except it consistently stops after the last closing string.
Just like Parser.chompUntil
except it consistently stops before the string.
Just like Parser.chompUntil
except it consistently stops after the string.
Just like Parser.chompUntilEndOr
except it consistently stops before the string (if it is found).
Just like Parser.chompUntilEndOr
except it consistently stops after the string (if it is found).
Just like
Parser.lineCommentexcept it consistently stops before the linefeed character.