Skip to content

A decimal exponent is not required for a number #204

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Bugfixes:
* whiteSpace
* skipSpaces

- `number` should parse scientific notation when exponent does not contain a decimal (#204 by @MaybeJustJames)


## [v9.1.0](https://github.com/purescript-contrib/purescript-parsing/releases/tag/v9.1.0) - 2022-06-12

Expand Down
2 changes: 1 addition & 1 deletion src/Parsing/String/Basic.purs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ number =
numberRegex :: forall m. ParserT String m String
numberRegex = either unsafeCrashWith identity $ regex pattern mempty
where
pattern = "[+-]?[0-9]*(\\.[0-9]*)?([eE][+-]?[0-9]*(\\.[0-9]*))?"
pattern = "[+-]?[0-9]*(\\.[0-9]*)?([eE][+-]?[0-9]*(\\.[0-9]*)?)?"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this makes everything optional, won't this also successfully parse things that aren't numbers (e.g. "foo)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes the group (\\.[0-9]*) optional. So only a decimal point followed by 0 or more decimal digits becomes optional.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[+-]? -- these chars are optional
[0-9]* -- there can be 0 or more of these chars
(\\.[0-9]*)? -- these chars can be optional
(
  [eE] -- not optional
  [+-]? -- optional
  [0-9]* -- 0 or more chars
  (\\.[0-9]*)? -- now optional (previously wasn't)
)? -- Wait! This entire block is already optional!?

Nevermind, I think my issue is with the regex as a whole since all parts are optional.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, that is a good point. There should probably be an "or" somewhere early on so that it matches either a digit or a . followed by a digit at a minimum.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's really hard to write a regex that admits all legal number strings but no other strings, but luckily that's not what we're doing here. We only need to find the number substring boundary so that we can pass the substring to the Data.Number.fromString function. So

  1. We need to admit all number strings. That's the first importance, and this PR fixes that.
  2. It's okay if we admit some string that are not number strings. They'll be rejected by Data.Number.fromString.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay, that totally makes sense! I probably should have looked outside the context of this regex.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, thanks for clarifying that!


-- | Parser based on the __Data.Int.fromString__ function.
-- |
Expand Down
5 changes: 5 additions & 0 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,11 @@ main = do
, expected: Right (-0.3)
}

assertEqual' "number xEy"
{ actual: runParser "2e1" number
, expected: Right 20.0
}

-- test from issue #73
assertEqual' "number 2"
{ actual: runParser "0.7531531167929774" number
Expand Down