@docs Parser, run
symbolWithEndLocation functionality
symbolWithRange functionality
Make sure the given String isn't empty and does not contain \n or 2-part UTF-16 characters. symbolFollowedBy functionality
Make sure the given String isn't empty and does not contain \n or 2-part UTF-16 characters. symbolBacktrackableFollowedBy functionality
followedBySymbol functionality
Parse words without other word characters after like let, case, type or import.
Make sure the given String isn't empty and does not contain \n
or 2-part UTF-16 characters.
run (keyword "let" ()) "let" == Ok ()
run (keyword "let" ()) "var" == Err ... (ExpectingKeyword "let") ...
run (keyword "let" ()) "letters" == Err ... (ExpectingKeyword "let") ...Note: Notice the third case there! keyword actually looks ahead one
character to make sure it is not a letter, digit, or underscore.
This will help with the weird cases like
case(x, y) being totally fine but casex not being fine.
keyword functionality
Make sure the given String isn't empty and does not contain \n or 2-part UTF-16 characters. keywordFollowedBy functionality
whileWithoutLinebreak functionality
whileMapWithRange functionality
ifFollowedByWhileWithoutLinebreak functionality
ifFollowedByWhileMapWithoutLinebreak functionality
ifFollowedByWhileMapWithRangeWithoutLinebreak functionality
Create a parser for variables. If we wanted to parse type variables in Elm, we could try something like this:
import Char
import ParserFast exposing (..)
import Set
typeVar : Parser String
typeVar =
ParserFast.ifFollowedByWhileValidateWithoutLinebreak
Char.isLower
(\c -> Char.isAlphaNum c || c == '_')
(\final -> final == "let" || final == "in" || final == "case" || final == "of")This is saying it must start with a lower-case character. After that, characters can be letters, digits, or underscores. It is also saying that if you run into any of these reserved names after parsing as much as possible, it is definitely not a variable. ifFollowedByWhileValidateWithoutLinebreak functionality
ifFollowedByWhileValidateMapWithRangeWithoutLinebreak functionality
whileWithoutLinebreakAnd2PartUtf16ToResultAndThen functionality
whileWithoutLinebreakAnd2PartUtf16ValidateMapWithRangeBacktrackableFollowedBySymbol functionality
Parse an integer base 10.
run int "1" == Ok 1
run int "1234" == Ok 1234
run int "-789" == Err ...
run int "0123" == Err ...
run int "1.34" == Err ...
run int "1e31" == Err ...
run int "123a" == Err ...
run int "0x1A" == Err ...
int : Parser Int
int =
ParserFast.integerDecimalMapWithRange (\_ n -> n)integerDecimalMapWithRange functionality
Parse an integer base 10 or base 16.
run int "1" == Ok 1
run int "1234" == Ok 1234
run int "0x1A" == Ok 26
run int "-789" == Err ...
run int "0123" == Err ...
run int "1.34" == Err ...
run int "1e31" == Err ...
run int "123a" == Err ...
int : Parser Int
int =
ParserFast.integerDecimalOrHexadecimalMapWithRange (\_ n -> n) (\_ n -> n)integerDecimalOrHexadecimalMapWithRange functionality
Parse an integer base 10 or base 16 or a float.
run number "1" == Ok 1
run number "1234" == Ok 1234
run number "0x1A" == Ok 26
run number "1.34" == Ok 1.34
run number "2e3" == Ok 2000
run number "-789" == Err ...
run number "0123" == Err ...
run number "123a" == Err ...
number : Parser Int
number =
ParserFast.integerDecimalOrHexadecimalMapWithRange (\_ n -> n) (\_ n -> n) (\_ n -> n)floatOrIntegerDecimalOrHexadecimalMapWithRange functionality
Match zero or more \n, \r and space characters, then proceed with the given parser skipWhileWhitespaceFollowedBy functionality
followedBySkipWhileWhitespace functionality
Parse multi-line comments that can itself contain other arbitrary multi-comments inside. nestableMultiCommentMapWithRange functionality
Transform the successful result of a parser.
Maybe you have a value that is an integer or null:
nullOrInt : Parser (Maybe Int)
nullOrInt =
ParserFast.oneOf2
(ParserFast.map Just int)
(ParserFast.keyword "null" Nothing)
-- run nullOrInt "0" == Ok (Just 0)
-- run nullOrInt "13" == Ok (Just 13)
-- run nullOrInt "null" == Ok Nothing
-- run nullOrInt "zero" == Err ...map functionality
Helper to delay computation, mostly to refer to a recursive parser.
Say we want a parser for simple boolean expressions:
true
false
true || false
true || (true || false)Notice that a boolean expression might contain other boolean expressions. That means we will want to define our parser in terms of itself:
type Boolean
= MyTrue
| MyFalse
| MyOr Boolean Boolean
boolean : Parser Boolean
boolean =
ParserFast.oneOf3
(ParserFast.keyword "true" MyTrue)
(ParserFast.keyword "false" MyFalse)
(ParserFast.symbolFollowedBy "("
(ParserFast.map2 MyOr
(ParserFast.skipWhileWhitespaceFollowedBy
(ParserFast.lazy (\_ -> boolean))
|> ParserFast.followedBySkipWhileWhitespace
|> ParserFast.followedBySymbol "||"
|> ParserFast.followedBySkipWhileWhitespace
)
(ParserFast.lazy (\_ -> boolean)
|> ParserFast.followedBySkipWhileWhitespace
)
)
|> ParserFast.followedBySymbol ")"
)Notice that boolean uses boolean in its definition! In Elm, you can
only define a value in terms of itself it is behind a function call. So
lazy helps us define these self-referential parsers.
If the recursion is linear, first consider the loop- helpers to avoid stack overflows
Parse 2 parser in sequence and combine their results
map2WithStartLocation functionality
map2WithRange functionality
map3WithStartLocation functionality
map3WithRange functionality
map4 functionality
map4WithRange functionality
map5 functionality
map5WithStartLocation functionality
map5WithRange functionality
map6 functionality
map6WithStartLocation functionality
map6WithRange functionality
map7WithRange functionality
map8WithStartLocation functionality
map9WithRange functionality
loopWhileSucceeds functionality
loopWhileSucceedsOntoResultFromParser functionality
loopUntil functionality
map2OrSucceed functionality
map2WithRangeOrSucceed functionality
map3OrSucceed functionality
map4OrSucceed functionality
oneOf2Map functionality
oneOf2MapWithStartRowColumnAndEndRowColumn functionality
oneOf2OrSucceed functionality
oneOf7 functionality
oneOf9 functionality
For a given parser, take the current start column as indentation for the whole block parsed by the given parser withIndentSetToColumn functionality
withIndentSetToColumnMinus functionality
Can be used to verify the current indentation like this:
checkIndent : Parser ()
checkIndent =
columnIndentAndThen (\indent column -> column > indent)
"expecting more spaces"So the checkIndent parser only succeeds when you are "deeper" than the
current indent level. You could use this to parse elm-style let expressions.
validateEndColumnIndentation functionality
mapWithRange functionality
columnAndThen functionality
Editors think of code as a grid, but behind the scenes it is just a flat
array of UTF-16 characters. getOffset tells you your index in that flat
array. So if you consume "\n\n\n\n" you are on row 5, column 1, and offset 4.
Note: JavaScript uses a somewhat odd version of UTF-16 strings, so a single
character may take two slots. So in JavaScript, 'abc'.length === 3 but
'🙈🙉🙊'.length === 6. Try it out! And since Elm runs in JavaScript, the offset
moves by those rules.
offsetSourceAndThenOrSucceed functionality
Parse exact text like
(and,. Make sure the given String isn't empty and does not contain \n or 2-part UTF-16 characters.Note: This is good for stuff like brackets and semicolons, but it might need extra validations for binary operators like
-because you can find yourself in weird situations. For example, is3--4a typo? Or is it3 - -4? symbol functionality