Skip to content

Commit

Permalink
v1
Browse files Browse the repository at this point in the history
  • Loading branch information
bcpeinhardt committed Dec 27, 2023
1 parent 19bc1dc commit 3ca2c68
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 70 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Changelog

## Unreleased

## v1.0.0 - 27 December 2023
- Init changelog w/v1 so people's stuff doesn't break.
2 changes: 1 addition & 1 deletion gleam.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name = "gsv"
version = "0.1.0"
version = "1.0.0"
gleam = ">= 0.32.0"
description = "A simple csv parser and generator written in gleam "

Expand Down
31 changes: 14 additions & 17 deletions src/gsv.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,21 @@ pub fn from_lists(
) -> String {
input
|> list.map(fn(row) {
list.map(
row,
fn(entry) {
// Double quotes need to be escaped with an extra doublequote
let entry = string.replace(entry, "\"", "\"\"")
list.map(row, fn(entry) {
// Double quotes need to be escaped with an extra doublequote
let entry = string.replace(entry, "\"", "\"\"")

// 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,
"\"",
)
{
True -> "\"" <> entry <> "\""
False -> entry
}
},
)
// 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,
"\"",
)
{
True -> "\"" <> entry <> "\""
False -> entry
}
})
})
|> list.map(fn(row) { string.join(row, separator) })
|> string.join(le_to_string(line_ending))
Expand Down
51 changes: 23 additions & 28 deletions src/gsv/internal/ast.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,19 @@ fn parse_p(
curr_line,
..previously_parsed_lines
] ->
parse_p(
remaining_tokens,
JustParsedField,
[[str, ..curr_line], ..previously_parsed_lines],
)
parse_p(remaining_tokens, JustParsedField, [
[str, ..curr_line],
..previously_parsed_lines
])

[Doublequote, ..remaining_tokens], JustParsedComma, [
curr_line,
..previously_parsed_lines
] ->
parse_p(
remaining_tokens,
InsideEscapedString,
[["", ..curr_line], ..previously_parsed_lines],
)
parse_p(remaining_tokens, InsideEscapedString, [
["", ..curr_line],
..previously_parsed_lines
])

_, JustParsedComma, _ -> Error(Nil)

Expand All @@ -101,11 +99,10 @@ fn parse_p(
curr_line,
..previously_parsed_lines
] ->
parse_p(
remaining_tokens,
InsideEscapedString,
[["", ..curr_line], ..previously_parsed_lines],
)
parse_p(remaining_tokens, InsideEscapedString, [
["", ..curr_line],
..previously_parsed_lines
])

_, JustParsedNewline, _ -> Error(Nil)

Expand All @@ -115,11 +112,10 @@ fn parse_p(
[str, ..rest_curr_line],
..previously_parsed_lines
] ->
parse_p(
remaining_tokens,
InsideEscapedString,
[[str <> "\"", ..rest_curr_line], ..previously_parsed_lines],
)
parse_p(remaining_tokens, InsideEscapedString, [
[str <> "\"", ..rest_curr_line],
..previously_parsed_lines
])

[Doublequote, ..remaining_tokens], InsideEscapedString, llf ->
parse_p(remaining_tokens, JustParsedField, llf)
Expand All @@ -128,13 +124,12 @@ fn parse_p(
[str, ..rest_curr_line],
..previously_parsed_lines
] ->
parse_p(
remaining_tokens,
InsideEscapedString,
[
[str <> token.to_lexeme(other_token), ..rest_curr_line],
..previously_parsed_lines
],
)
parse_p(remaining_tokens, InsideEscapedString, [
[str <> token.to_lexeme(other_token), ..rest_curr_line],
..previously_parsed_lines
])

// Anything else is an error
_, _, _ -> Error(Nil)
}
}
29 changes: 13 additions & 16 deletions src/gsv/internal/token.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,20 @@ pub fn to_lexeme(token: CsvToken) -> String {
pub fn scan(input: String) -> List(CsvToken) {
input
|> string.to_utf_codepoints
|> list.fold(
[],
fn(acc, x) {
case string.utf_codepoint_to_int(x) {
0x2c -> [Comma, ..acc]
0x22 -> [Doublequote, ..acc]
0x0a -> [LF, ..acc]
0x0D -> [CR, ..acc]
_ -> {
let cp = string.from_utf_codepoints([x])
case acc {
[Textdata(str), ..rest] -> [Textdata(str <> cp), ..rest]
_ -> [Textdata(cp), ..acc]
}
|> list.fold([], fn(acc, x) {
case string.utf_codepoint_to_int(x) {
0x2c -> [Comma, ..acc]
0x22 -> [Doublequote, ..acc]
0x0a -> [LF, ..acc]
0x0D -> [CR, ..acc]
_ -> {
let cp = string.from_utf_codepoints([x])
case acc {
[Textdata(str), ..rest] -> [Textdata(str <> cp), ..rest]
_ -> [Textdata(cp), ..acc]
}
}
},
)
}
})
|> list.reverse
}
14 changes: 6 additions & 8 deletions test/gsv_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@ pub fn parse_test() {
"Ben, 25,\" TRUE\n\r\"\"\"\nAustin, 25, FALSE"
|> scan
|> parse
|> should.equal(Ok([
["Ben", " 25", " TRUE\n\r\""],
["Austin", " 25", " FALSE"],
]))
|> should.equal(
Ok([["Ben", " 25", " TRUE\n\r\""], ["Austin", " 25", " FALSE"]]),
)
}

pub fn parse_empty_string_fail_test() {
Expand All @@ -48,10 +47,9 @@ pub fn parse_empty_string_fail_test() {
pub fn csv_parse_test() {
"Ben, 25,\" TRUE\n\r\"\"\"\nAustin, 25, FALSE"
|> gsv.to_lists
|> should.equal(Ok([
["Ben", " 25", " TRUE\n\r\""],
["Austin", " 25", " FALSE"],
]))
|> should.equal(
Ok([["Ben", " 25", " TRUE\n\r\""], ["Austin", " 25", " FALSE"]]),
)
}

pub fn scan_crlf_test() {
Expand Down

0 comments on commit 3ca2c68

Please sign in to comment.