Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
JosephTLyons committed Oct 10, 2024
0 parents commit 98a9798
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 0 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: test

on:
push:
branches:
- master
- main
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: "26.0.2"
gleam-version: "1.5.0"
rebar3-version: "3"
# elixir-version: "1.15.4"
- run: gleam deps download
- run: gleam test
- run: gleam format --check src test
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.beam
*.ez
/build
erl_crash.dump
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# lenient_parse

[![Package Version](https://img.shields.io/hexpm/v/lenient_parse)](https://hex.pm/packages/lenient_parse)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/lenient_parse/)

```sh
gleam add lenient_parse@1
```
```gleam
import lenient_parse
pub fn main() {
// TODO: An example of the project in use
}
```

Further documentation can be found at <https://hexdocs.pm/lenient_parse>.

## Development

```sh
gleam run # Run the project
gleam test # Run the tests
```
19 changes: 19 additions & 0 deletions gleam.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name = "lenient_parse"
version = "1.0.0"

# Fill out these fields if you intend to generate HTML documentation or publish
# your project to the Hex package manager.
#
# description = ""
# licences = ["Apache-2.0"]
# repository = { type = "github", user = "", repo = "" }
# links = [{ title = "Website", href = "" }]
#
# For a full reference of all the available options, you can have a look at
# https://gleam.run/writing-gleam/gleam-toml/.

[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"

[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"
11 changes: 11 additions & 0 deletions manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This file was generated by Gleam
# You typically do not need to edit this file

packages = [
{ name = "gleam_stdlib", version = "0.40.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "86606B75A600BBD05E539EB59FABC6E307EEEA7B1E5865AFB6D980A93BCB2181" },
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
]

[requirements]
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
36 changes: 36 additions & 0 deletions src/lenient_parse.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import gleam/bool
import gleam/float
import gleam/int
import gleam/result
import gleam/string

/// Converts a string to a float using a more lenient parsing method than gleam's `float.parse()`. It behaves similarly to Python's `float()` built-in function.
///
/// It attempts to parse the input string in the following order:
/// 1. As a standard float
/// 2. As an integer (which is then converted to a float)
/// 3. As a float with leading or trailing decimal point
///
/// ## Examples
///
/// ```gleam
/// lenient_parse.to_float("3.14") // -> Ok(3.14)
/// lenient_parse.to_float("42") // -> Ok(42.0)
/// lenient_parse.to_float(".5") // -> Ok(0.5)
/// lenient_parse.to_float("2.") // -> Ok(2.0)
/// lenient_parse.to_float("dog") // -> Error(Nil)
/// ```
pub fn to_float(text: String) -> Result(Float, Nil) {
let text = text |> string.trim

use <- bool.guard(text |> string.is_empty, Error(Nil))
use _ <- result.try_recover(text |> float.parse)
use _ <- result.try_recover(text |> int.parse |> result.map(int.to_float))

case string.first(text), string.last(text) {
Ok("."), _ -> float.parse("0" <> text)
_, Ok(".") -> float.parse(text <> "0")
_, _ -> Error(Nil)
}
}
// TODO: Update doc comment with rules and examples
100 changes: 100 additions & 0 deletions test/lenient_parse_test.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import gleeunit
import gleeunit/should
import lenient_parse

pub fn main() {
gleeunit.main()
}

pub fn to_float_standard_format_test() {
"1.001"
|> lenient_parse.to_float
|> should.equal(Ok(1.001))

"1.00"
|> lenient_parse.to_float
|> should.equal(Ok(1.0))

"1.0"
|> lenient_parse.to_float
|> should.equal(Ok(1.0))

"0.1"
|> lenient_parse.to_float
|> should.equal(Ok(0.1))

"+123.321"
|> lenient_parse.to_float
|> should.equal(Ok(123.321))

"-123.321"
|> lenient_parse.to_float
|> should.equal(Ok(-123.321))
}

pub fn to_float_int_test() {
"1"
|> lenient_parse.to_float
|> should.equal(Ok(1.0))
}

pub fn to_float_leading_trailing_dot_test() {
"1."
|> lenient_parse.to_float
|> should.equal(Ok(1.0))

".1"
|> lenient_parse.to_float
|> should.equal(Ok(0.1))
}

pub fn to_float_whitespace_test() {
" 1 "
|> lenient_parse.to_float
|> should.equal(Ok(1.0))

" 1.0 "
|> lenient_parse.to_float
|> should.equal(Ok(1.0))
}

// TODO: scientific notation
// pub fn to_float_scientific_notation_test() {
// // "420e3"
// // |> lenient_parse.to_float
// // |> should.equal(Ok(1e10))

// // "420e-3"
// // |> lenient_parse.to_float
// // |> should.equal(Ok(-2.5e-3))
// }

pub fn to_float_shouldnt_parse_test() {
"..1"
|> lenient_parse.to_float
|> should.equal(Error(Nil))

"1.."
|> lenient_parse.to_float
|> should.equal(Error(Nil))

".1."
|> lenient_parse.to_float
|> should.equal(Error(Nil))

"."
|> lenient_parse.to_float
|> should.equal(Error(Nil))

" "
|> lenient_parse.to_float
|> should.equal(Error(Nil))

""
|> lenient_parse.to_float
|> should.equal(Error(Nil))

"abc"
|> lenient_parse.to_float
|> should.equal(Error(Nil))
}

0 comments on commit 98a9798

Please sign in to comment.