I learned I struggle a lot with figuring out where have my various elm/parser
parsers gone wrong.
So far I probably only have two techniques:
Print the dead ends as nicely as possible
expectEqualParseResult :
String
-> Result (List (P.DeadEnd ParseContext ParseProblem)) a
-> Result (List (P.DeadEnd ParseContext ParseProblem)) a
-> Expectation
expectEqualParseResult input expected actual =
if actual == expected then
Expect.pass
else
case actual of
Err deadEnds ->
Expect.fail
(String.join "\n"
(input
:: "===>"
:: "Err"
:: List.map deadEndToString deadEnds
)
)
_ ->
actual |> Expect.equal expected
deadEndToString : P.DeadEnd ParseContext ParseProblem -> String
deadEndToString deadEnd =
let
metadata =
"("
++ String.fromInt (deadEnd.row - 1)
++ ","
++ String.fromInt (deadEnd.col - 1)
++ ") "
++ Debug.toString deadEnd.problem
in
String.join "\n "
("\n"
:: metadata
:: "---- with context stack ----"
:: List.map contextToString deadEnd.contextStack
)
contextToString : { row : Int, col : Int, context : ParseContext } -> String
contextToString context =
"("
++ String.fromInt (context.row - 1)
++ ","
++ String.fromInt (context.col - 1)
++ ") "
++ Debug.toString context.context
Example result
↓ ParserTest
↓ Stage.Parse.Parser.expr
↓ literal string
✗ empty
""
===>
Err
(0,2) ExpectingDoubleQuote
---- with context stack ----
(0,0) InString
(0,0) InLiteral
(0,0) InExpr
↓ ParserTest
↓ Stage.Parse.Parser.expr
↓ literal string
✗ one space
" "
===>
Err
(0,3) ExpectingDoubleQuote
---- with context stack ----
(0,0) InString
(0,0) InLiteral
(0,0) InExpr
↓ ParserTest
↓ Stage.Parse.Parser.expr
↓ literal string
✗ two numbers
"42"
===>
Err
(0,4) ExpectingDoubleQuote
---- with context stack ----
(0,0) InString
(0,0) InLiteral
(0,0) InExpr
`log` parser combinator
log : String -> Parser_ a -> Parser_ a
log message parser =
P.succeed ()
|> P.andThen
(\() ->
let
_ =
Debug.log "starting" message
in
P.succeed
(\source offsetBefore parseResult offsetAfter ->
let
_ =
Debug.log "-----------------------------------------------" message
_ =
Debug.log "source " source
_ =
Debug.log "chomped string " (String.slice offsetBefore offsetAfter source)
_ =
Debug.log "parsed result " parseResult
in
parseResult
)
|= P.getSource
|= P.getOffset
|= parser
|= P.getOffset
)
Example result
starting: "many"
-----------------------------------------------: "many"
source : "\"42\""
chomped string : "42\""
parsed result : ['4','2','"']
starting: "many"
starting: "many"
-----------------------------------------------: "many"
source : "\"\\\"\""
chomped string : "\\\"\""
parsed result : ['"','"']
starting: "many"
starting: "many"
What are yours? What do you usually do when you need to debug a Parser?