From d7ea5f69a75e071c8d851bd9cb9e7ece4b61f831 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Mon, 27 May 2024 11:52:07 +0200 Subject: [PATCH] Fix float formatting with tight-binding +/- A leading `+`/`-` is part of the float literal if there is no space in between (in which case it becomes a call). This patch fixes the regexes to handle this for float parsing. --- src/runestone.jl | 7 ++++++- test/runtests.jl | 18 +++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/runestone.jl b/src/runestone.jl index 592f407..3aee271 100644 --- a/src/runestone.jl +++ b/src/runestone.jl @@ -96,6 +96,7 @@ function format_float_literals(ctx::Context, node::JuliaSyntax.GreenNode) # Check and shortcut the happy path first r = r""" ^ + (?:[+-])? # Optional sign (?:(?:[1-9]\d*)|0) # Non-zero followed by any digit, or just a single zero \. # Decimal point (?:(?:\d*[1-9])|0) # Any digit with a final nonzero, or just a single zero @@ -110,9 +111,13 @@ function format_float_literals(ctx::Context, node::JuliaSyntax.GreenNode) return nothing end # Split up the pieces - r = r"^(?\d*)(?:\.?(?\d*))?(?:(?[eEf][+-]?)(?\d+))?$" + r = r"^(?[+-])?(?\d*)(?:\.?(?\d*))?(?:(?[eEf][+-]?)(?\d+))?$" m = match(r, str) io = IOBuffer() # TODO: Could be reused? + # Write the sign part + if (sgn = m[:sgn]; sgn !== nothing) + write(io, sgn) + end # Strip leading zeros from integral part int_part = isempty(m[:int]) ? "0" : m[:int] int_part = replace(int_part, r"^0*((?:[1-9]\d*)|0)$" => s"\1") diff --git a/test/runtests.jl b/test/runtests.jl index 714017f..b840c2c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -79,13 +79,17 @@ end ["1f-3", "01f-3", "01.f-3", "1.f-3", "1.000f-3", "01.00f-3"] => "1.0f-3", ] mod = Module() - for (as, b) in test_cases - for a in as - c = Core.eval(mod, Meta.parse(a)) - d = Core.eval(mod, Meta.parse(b)) - @test c == d - @test typeof(c) == typeof(d) - @test format_string(a) == b + for prefix in ("", "-", "+") + for (as, b) in test_cases + b = prefix * b + for a in as + a = prefix * a + c = Core.eval(mod, Meta.parse(a)) + d = Core.eval(mod, Meta.parse(b)) + @test c == d + @test typeof(c) == typeof(d) + @test format_string(a) == b + end end end end