Problem writing a parser

Hello,
I’m trying to parse basic algebraic expressions. I’m using elm-tools/parser version 2.0.1.
Right now I’m stuck at “addition”: the problem is that the addition parser fails but the node parser doesn’t fallback on the number parser.

Here’s my code:

type Node
    = Number Float
    | Add Node Node


spaces : Parser ()
spaces =
    ignore zeroOrMore (\c -> c == ' ')


number : Parser Node
number =
    inContext "number" <|
        oneOf
            [ succeed (\i -> Number (-i))
                |. symbol "-"
                |= float
            , succeed Number
                |= float
            ]


node : Parser Node
node =
    inContext "expression" <|
        oneOf [ add, number ]


add : Parser Node
add =
    inContext "addition" <|
        succeed Add
            |= number
            |. spaces
            |. symbol "+"
            |. spaces
            |= number

I get an error when trying to parse string “1”.

Here is a running version on Ellie:
https://ellie-app.com/bv4X2yBqSa1/2

The problem is that the add parser consumes some input. oneOf will only try other parsers if parsers fail without consuming any input.

Ok that makes sense, thanks. Do you know how I could fail without consuming any input?

The key is delayedCommit – this will delay consuming input until another parser succeeds. So for example, here you would like to commit to the branch once you see a + operator.

OK so for anyone interested, I finaly worked it out, thanks to @gampleman’s hint:

The solution is indeed to use delayedCommitMap:

add : Parser Node
add =
    inContext "addition" <|
        delayedCommitMap Add
            number
            (succeed identity
                |. spaces
                |. symbol "+"
                |. spaces
                |= number
            )

The updated code is on Ellie:
https://ellie-app.com/bv4X2yBqSa1/3

1 Like