diff --git a/src/parser.gleam b/src/parser.gleam index a48721be9a98e457ed3da9981b31c5623b545714..fa08485aef226824f8c1179a50a17bf456c85fe3 100644 --- a/src/parser.gleam +++ b/src/parser.gleam @@ -86,7 +86,7 @@ pub fn tab() -> Parser(Node, String, ctx) { return(Tab) } -pub fn line_comment_prefix() -> Parser(Node, String, ctx) { +pub fn line_comment_prefix() -> Parser(Node, String, String) { use _ <- nibble.do(consume_exact_string("--")) return(LineCommentPrefix) diff --git a/test/ghall_test.gleam b/test/ghall_test.gleam index ea6359a9aeb3bd25c4b1bbcdd5ed5ed798caf5f9..ea61dbbf18276d04446db79c9be8fbef034fc92f 100644 --- a/test/ghall_test.gleam +++ b/test/ghall_test.gleam @@ -1,7 +1,7 @@ import birdie import gleam/int import gleam/list -import gleam/string +import gleam/result import gleeunit import nibble.{Expected} import nibble/lexer.{Span, Token} @@ -86,11 +86,11 @@ pub fn parse_line_ending_fails_on_lone_carriage_return_test() { let input = "\r" let tokens = quasi_lexer.chars() |> quasi_lexer.run(on: input) let parser = parser.end_of_line() - let assert Error(error) = nibble.run(tokens, parser) + let result = nibble.run(tokens, parser) - snapshot_helpers.snap_parse_error( + snapshot_helpers.snap_parse_result_nodes( input, - error, + result |> result.map(list.wrap), "Line ending should reject lone carriage return", ) } @@ -121,35 +121,15 @@ pub fn parse_multiple_line_endings_test() { use eol3 <- nibble.do(parser.end_of_line()) nibble.return([eol1, eol2, eol3]) } - let assert Ok(nodes) = nibble.run(tokens, parser) + let result = nibble.run(tokens, parser) - snapshot_helpers.snap_parse_success( + snapshot_helpers.snap_parse_result_nodes( input, - nodes, + result, "Multiple line endings should all parse as EndOfLine", ) } -pub fn demo_visual_error_rendering_test() { - let input = "let x = 42\r" - let tokens = quasi_lexer.chars() |> quasi_lexer.run(on: input) - - // Try to parse "let" followed by a line ending - let parser = { - use _ <- nibble.do(parser.let_keyword()) - use _ <- nibble.do(parser.exact_string(" x = 42", node.Let)) - parser.end_of_line() - } - - let assert Error(errors) = nibble.run(tokens, parser) - - snapshot_helpers.snap_parse_error( - input, - errors, - "Visual error demo: shows escaped chars, spans, and parser context", - ) -} - // Tests for printable parser (%x20-7F) pub fn parse_printable_space_test() { diff --git a/test/snapshot_helpers.gleam b/test/snapshot_helpers.gleam index ba4bf2e720995d175f8849ec03398a2e4a606b94..7788049a30046f02674196637b53708b5bd166cd 100644 --- a/test/snapshot_helpers.gleam +++ b/test/snapshot_helpers.gleam @@ -153,16 +153,33 @@ pub fn snap_lexer_output( birdie.snap(snap, title: title) } +/// Create a snapshot of a parse result (success or error) +pub fn snap_parse_result_nodes( + input: String, + result: Result(List(Node), List(nibble.DeadEnd(tok, ctx))), + title: String, +) -> Nil { + let snap = case result { + Ok(nodes) -> + "Input: " + <> escape_string(input) + <> "\n" + <> format_nodes(nodes) + Error(errors) -> + // Input is shown with each error, so no need to show it at the top level + format_dead_ends(input, errors) + } + + birdie.snap(snap, title: title) +} + /// Create a snapshot of a parse error showing input and errors pub fn snap_parse_error( input: String, errors: List(nibble.DeadEnd(tok, ctx)), title: String, ) -> Nil { - // Input is shown with each error, so no need to show it at the top level - let snap = format_dead_ends(input, errors) - - birdie.snap(snap, title: title) + snap_parse_result_nodes(input, Error(errors), title) } /// Create a snapshot of successful parse showing input and result @@ -171,13 +188,7 @@ pub fn snap_parse_success( nodes: List(Node), title: String, ) -> Nil { - let snap = - "Input: " - <> escape_string(input) - <> "\n" - <> format_nodes(nodes) - - birdie.snap(snap, title: title) + snap_parse_result_nodes(input, Ok(nodes), title) } /// Create a snapshot for a Result type (success or error) @@ -302,11 +313,6 @@ fn visual_span_label(gutter_width: Int, col: Int, label: String) -> String { gutter <> before <> "└─ " <> label } -/// Get the center column of a span for label positioning -fn span_center_col(span: Span) -> Int { - let Span(_, cs, _, ce) = span - cs + { ce - cs } / 2 -} /// Render a single span visually with context lines pub fn visual_single_span(