elm / parser

A parsing library, focused on simplicity and great error messages
https://package.elm-lang.org/packages/elm/parser/latest
BSD 3-Clause "New" or "Revised" License
230 stars 46 forks source link

int parser fails on trailing "e" #28

Open malaire opened 5 years ago

malaire commented 5 years ago

int parser fails to parse 42efg while parsing 42abc works. ellie: https://ellie-app.com/4jqm8pFGXyLa1

Related issues: https://github.com/elm/parser/issues/14 and https://github.com/elm/parser/issues/25

wolfpakz commented 5 years ago

I've run into this issue as well while parsing Bencoded content.

In this example, parsing "2" from "i2e" is the goal.

Input Result Expected
i2 Success Success
i2h Success Success
i2e Problem Success
i2.5 Problem Success

Code: https://ellie-app.com/5cLQ4CgfWvGa1

The "i2.5h" and "i2e" examples fail in the same way, making it seem like Parser.int is interested in floats as well as integers. I also tried using Parser.number and only allowed int, hoping the specificity would improve the situation, but alas, the same results.

j-maas commented 4 years ago

e also causes problems with floats, because it commits when it sees a leading e.

floatOrText =
    oneOf
        [ float |> map (\n -> "Number: " ++ String.fromFloat n)
        , chompUntilEndOr "\n" |> getChompedString
    ]

run floatOrText "not starting with e" --> Ok "not starting with e"
run floatOrText "1e10" --> Ok "Number: 10000000000"
run floatOrText "e should be text" --> Err: ExpectingFloat

Example on Ellie: https://ellie-app.com/8yp6MxtzSsna1

After reading https://github.com/elm/expectations, I've opened a separate issue (#44).

matsumonkie commented 4 years ago

I'm facing a similar issue with character e messing with my parser :-( Have anyone found a temporary fix ?

rlefevre commented 4 years ago

@matsumonkie See here for example: https://github.com/elm/parser/issues/14#issuecomment-450547742

You may need to adapt if you want to handle negative numbers.

matsumonkie commented 4 years ago

Thank you for your answer @rlefevre I think my issue is not related to your comment though.

When I use the [https://package.elm-lang.org/packages/elm/parser/latest/Parser#variable](variable parser) almost exactly like this:

typeVar : Parser String
typeVar =
  variable
    { start = Char.isLower
    , inner = \c -> Char.isAlphaNum c || c == '_'
    , reserved = Set.fromList [ "let", "in", "case", "of" ]
    }

I noticed that it worked fine as long as the variable name doesn't start with the letter e. So "foo" works fine but "efoo" doesn't.

j-maas commented 4 years ago

@matsumonkie I've used this workaround for now:

{-| The built-in float parser has a bug with leading 'e'.
See <https://github.com/elm/parser/issues/28>
-}
parseFloat : Parser Float
parseFloat =
    {- By making it backtrackable, even if the input starts with an 'e',
       we will be able to try out other alternatives instead of getting
       stuck on it as an invalid number.
    -}
    Parser.backtrackable <| Parser.float ExpectingFloat InvalidNumber
rlefevre commented 4 years ago

@matsumonkie If the problem comes from Parser.variable, you should open a new issue about it, this issue is about Parser.int.

But I don't think that there is a problem with variable, for example: https://ellie-app.com/8Mq3xfyKVn5a1

Instead you most likely have a Parser.int or Parser.float in a oneOf before the typeVar parser, leading to the issue: https://ellie-app.com/8MqcZtr6mmka1

This is the Parser.int that chomps the e from the string and makes the whole oneOf fail (because of the issue we are commenting in).

So you can either use the numeral parser I linked to above from the other issue: https://ellie-app.com/8MqdgSc3bJKa1 It checks that only digits are used to parse a positive integer (you can adapt it for floats or negative numbers).

Or you can just put the typeVar parser before the int one: https://ellie-app.com/8MqdBfTyKqBa1 If this is possible, this is likely the most efficient work-around.

backtrackable is an option too, but it might be less efficient.

matsumonkie commented 4 years ago

Instead you most likely have a Parser.int or Parser.float in a oneOf before the typeVar parser, leading to the issue: https://ellie-app.com/8MqcZtr6mmka1

This is the Parser.int that chomps the e from the string and makes the whole oneOf fail (because of the issue we are commenting in).

Well... that was exactly it! Sorry for the inconvenience :-S And many thanks for your answer, it helped a lot!