Skip to content
Open
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: 1 addition & 1 deletion src/nibble.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ pub fn return(value: a) -> Parser(a, tok, ctx) {
///
/// 💡 [`succeed`](#succeed) and [`return`](#return) are names for the same thing.
/// We suggest using `succeed` in a pipeline with `nibble.then`, and `return`
/// unqalified when using `do` with Gleam's `use` syntax.
/// unqualified when using `do` with Gleam's `use` syntax.
///
pub fn succeed(value: a) -> Parser(a, tok, ctx) {
return(value)
Expand Down
7 changes: 4 additions & 3 deletions src/nibble/lexer.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
//// ```
////
//// Here we have some whitespace that would be matched by `lexer.whitespace`, by
//// we passed that matcher to the [`lexer.ignore`](#ignore) comabinator. The matcher
//// we passed that matcher to the [`lexer.ignore`](#ignore) combinator. The matcher
//// will still consume the input, but this time it will not produce a new token
//// value:
////
Expand Down Expand Up @@ -249,7 +249,7 @@ pub fn map(matcher: Matcher(a, mode), f: fn(a) -> b) -> Matcher(b, mode) {
}

/// Take an existing matcher and transform it by applying a function to the value
/// it producs. The function you provide can return a different [`Match`](#Match)
/// it produces. The function you provide can return a different [`Match`](#Match)
/// so you can, for example, take a matcher that `Keep`s a value and turn it into
/// a matcher that `Drop`s the value instead. This is out [`ignore`](#ignore) works!
///
Expand Down Expand Up @@ -564,13 +564,14 @@ pub fn whitespace(token: a) -> Matcher(a, mode) {
}
}

/// Match a line comment starting with the a given string. Keeps the leading whitespace.
///
pub fn comment(start: String, to_value: fn(String) -> a) -> Matcher(a, mode) {
let drop_length = string.length(start)
use mode, lexeme, lookahead <- Matcher

case string.starts_with(lexeme, start), lookahead {
True, "\n" ->
True, "\n" | True, "" ->
lexeme
|> string.drop_start(drop_length)
|> to_value
Expand Down
36 changes: 36 additions & 0 deletions test/unit/lexer_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type TokenT {
Num(Float)
Kwd(String)
Var(String)
Comment(String)
}

// INTEGER TESTS ---------------------------------------------------------------
Expand Down Expand Up @@ -210,6 +211,41 @@ pub fn variable_containing_keyword_test() {
])
}

// COMMENT TESTS --------------------------------------------------------------

pub fn linebreak_terminated_comment_test() {
use run <- should("lex a linebreak-terminated comment")

let input = "# this is a comment\n"
let expected = [
Token(
Span(1, 1, 1, 20),
"# this is a comment",
Comment(" this is a comment"),
),
]

run(input, expected, [
lexer.comment("#", Comment),
lexer.whitespace(Nil) |> lexer.ignore,
])
}

pub fn bare_comment_test() {
use run <- should("lex a bare comment")

let input = "// this is a comment"
let expected = [
Token(
Span(1, 1, 1, 21),
"// this is a comment",
Comment(" this is a comment"),
),
]

run(input, expected, [lexer.comment("//", Comment)])
}

// UTILS -----------------------------------------------------------------------

fn should(
Expand Down