From 7e612ebf7a66614f0dea8114f907cc5a85a235f0 Mon Sep 17 00:00:00 2001 From: BENJAMIN PEINHARDT Date: Fri, 5 Jan 2024 19:41:56 -0600 Subject: [PATCH] fix comma bug --- CHANGELOG.md | 3 +++ gleam.toml | 2 +- src/gsv.gleam | 25 +++++++++++++++++-------- src/gsv/internal/ast.gleam | 22 +++++++++++++++------- test/gsv_test.gleam | 12 +++++------- 5 files changed, 41 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3fbdd1..97dfe27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +## v1.2.1 - 5 January 2024 +- Fix bug with double commas producing error, now produce empty string + ## v1.2.0 - 29 December 2023 - Add `to_lists_or_error` function diff --git a/gleam.toml b/gleam.toml index b12ae8f..267793a 100644 --- a/gleam.toml +++ b/gleam.toml @@ -1,5 +1,5 @@ name = "gsv" -version = "1.2.0" +version = "1.2.1" gleam = ">= 0.32.0" description = "A simple csv parser and generator written in gleam " diff --git a/src/gsv.gleam b/src/gsv.gleam index 1e1ce51..297a819 100644 --- a/src/gsv.gleam +++ b/src/gsv.gleam @@ -29,9 +29,13 @@ pub fn to_lists_or_panic(input: String) -> List(List(String)) { Ok(lol) -> lol Error(ParseError(Location(line, column), msg)) -> { panic as { - "[" <> "line " <> int.to_string(line) <> " column " <> int.to_string( - column, - ) <> "] of csv: " <> msg + "[" + <> "line " + <> int.to_string(line) + <> " column " + <> int.to_string(column) + <> "] of csv: " + <> msg } [[]] } @@ -48,7 +52,13 @@ pub fn to_lists_or_error(input: String) -> Result(List(List(String)), String) { |> ast.parse |> result.map_error(fn(e) { let ParseError(Location(line, column), msg) = e - "[" <> "line " <> int.to_string(line) <> " column " <> int.to_string(column) <> "] of csv: " <> msg + "[" + <> "line " + <> int.to_string(line) + <> " column " + <> int.to_string(column) + <> "] of csv: " + <> msg }) } @@ -85,10 +95,9 @@ pub fn from_lists( // If the string contains a , \n \r\n or " it needs to be escaped by wrapping in double quotes case - string.contains(entry, separator) || string.contains(entry, "\n") || string.contains( - entry, - "\"", - ) + string.contains(entry, separator) + || string.contains(entry, "\n") + || string.contains(entry, "\"") { True -> "\"" <> entry <> "\"" False -> entry diff --git a/src/gsv/internal/ast.gleam b/src/gsv/internal/ast.gleam index 2c99ff3..7a526a6 100644 --- a/src/gsv/internal/ast.gleam +++ b/src/gsv/internal/ast.gleam @@ -90,7 +90,8 @@ fn parse_p( "Expected \"\\n\" after \"\\r\", found: " <> token.to_lexeme(tok), )) - // If we just parsed a comma, we're expecting an Escaped or Non-Escaped string + // If we just parsed a comma, we're expecting an Escaped or Non-Escaped string, or another comma + // (indicating an empty string) [#(Textdata(str), _), ..remaining_tokens], JustParsedComma, [ curr_line, ..previously_parsed_lines @@ -109,12 +110,20 @@ fn parse_p( ..previously_parsed_lines ]) + [#(Comma, _), ..remaining_tokens], JustParsedComma, [ + curr_line, + ..previously_parsed_lines + ] -> + parse_p(remaining_tokens, JustParsedComma, [ + ["", ..curr_line], + ..previously_parsed_lines + ]) + [#(tok, loc), ..], JustParsedComma, _ -> Error(ParseError( loc, - "Expected escaped or non-escaped string after comma, found: " <> token.to_lexeme( - tok, - ), + "Expected escaped or non-escaped string after comma, found: " + <> token.to_lexeme(tok), )) // If we just parsed a new line, we're expecting an escaped or non-escaped string @@ -133,9 +142,8 @@ fn parse_p( [#(tok, loc), ..], JustParsedNewline, _ -> Error(ParseError( loc, - "Expected escaped or non-escaped string after newline, found: " <> token.to_lexeme( - tok, - ), + "Expected escaped or non-escaped string after newline, found: " + <> token.to_lexeme(tok), )) // If we're inside an escaped string, we can take anything until we get a double quote, diff --git a/test/gsv_test.gleam b/test/gsv_test.gleam index 0b04f7f..ea1042c 100644 --- a/test/gsv_test.gleam +++ b/test/gsv_test.gleam @@ -159,15 +159,15 @@ pub fn error_cases_test() { } } - produce_error("Ben, 25,, TRUE") + produce_error("Ben, 25,\n, TRUE") |> should.equal(#( Location(1, 9), - "Expected escaped or non-escaped string after comma, found: ,", + "Expected escaped or non-escaped string after comma, found: \n", )) - produce_error("Austin, 25, FALSE\n\"Ben Peinhardt\", 25,, TRUE") + produce_error("Austin, 25, FALSE\n\"Ben Peinhardt\", 25,\n, TRUE") |> should.equal(#( Location(2, 21), - "Expected escaped or non-escaped string after comma, found: ,", + "Expected escaped or non-escaped string after comma, found: \n", )) } @@ -178,7 +178,5 @@ pub fn error_cases_test() { pub fn totally_errors_test() { "Ben, 25,, TRUE" |> gsv.to_lists_or_error - |> should.equal(Error( - "[line 1 column 9] of csv: Expected escaped or non-escaped string after comma, found: ,", - )) + |> should.equal(Ok([["Ben", " 25", "", " TRUE"]])) }