From a82cfdf0349554df162817a6525cfe9211007870 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Fri, 16 Jan 2026 19:31:16 +0100 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20Allow=20'=C2=AC'=20for=20negation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- grammar.txt | 2 +- src/semantic_versioning-extended.adb | 5 ++++- tests/src/semver_tests-negation.adb | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/grammar.txt b/grammar.txt index 1e5fbc0..178fcfd 100644 --- a/grammar.txt +++ b/grammar.txt @@ -18,4 +18,4 @@ list_or ::= ('|' | 'or') EVS_or EVS_and ::= (EVS_Nested | VS) [and_list] EVS_or ::= (EVS_Nested | VS) [or_list] OP ::= '<' | '>' etc -NEG ::= '!' | 'not' +NEG ::= '!' | '¬' | 'not' diff --git a/src/semantic_versioning-extended.adb b/src/semantic_versioning-extended.adb index 10224f1..c85d3d3 100644 --- a/src/semantic_versioning-extended.adb +++ b/src/semantic_versioning-extended.adb @@ -525,12 +525,13 @@ package body Semantic_Versioning.Extended is when ')' => return Rparen; when '0' .. '9' => return Number; when '|' => return Pipe; - when '!' => return Negation; + when '!' | '¬' => return Negation; when '<' | '>' | '=' | '/' | '~' | '^' => return VS; -- already checked above, but... when others => return Unknown; end case; end Internal; + begin return T : constant Tokens := Internal do Trace ("Next token: " & T'Img); @@ -561,6 +562,8 @@ package body Semantic_Versioning.Extended is when Negation => if Is_Keyword ("not") then Match ("not"); + elsif Str (I) = '¬' then + Match ('¬'); else Match ('!'); end if; diff --git a/tests/src/semver_tests-negation.adb b/tests/src/semver_tests-negation.adb index cba0d4e..56c3cf3 100644 --- a/tests/src/semver_tests-negation.adb +++ b/tests/src/semver_tests-negation.adb @@ -15,4 +15,7 @@ begin Assert (X.Value ("!^1").Synthetic_Image = X.Value ("!(^1)").Synthetic_Image); -- Equivalent + + -- Alternate symbol + Assert (X.Is_In (V ("1.1"), X.Value ("¬1"))); end Semver_Tests.Negation; From 4833b7dd963c5372b9803d0add855b9d83175414 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Sun, 18 Jan 2026 09:21:07 +0100 Subject: [PATCH 2/6] =?UTF-8?q?Only=20allow=20'=C2=AC'=20in=20unicode=20mo?= =?UTF-8?q?de?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/semantic_versioning-extended.adb | 11 +++++++++-- tests/src/semver_tests-options.adb | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/semantic_versioning-extended.adb b/src/semantic_versioning-extended.adb index c85d3d3..02cc972 100644 --- a/src/semantic_versioning-extended.adb +++ b/src/semantic_versioning-extended.adb @@ -333,7 +333,8 @@ package body Semantic_Versioning.Extended is return List_Img; when Negated => - return "!(" & Img (Trees.First_Child (Pos)) & ")"; + return (if Opts.Unicode then U ("¬") else "!") + & "(" & Img (Trees.First_Child (Pos)) & ")"; end case; end Img; @@ -525,7 +526,13 @@ package body Semantic_Versioning.Extended is when ')' => return Rparen; when '0' .. '9' => return Number; when '|' => return Pipe; - when '!' | '¬' => return Negation; + when '!' => return Negation; + when '¬' => + if not Opts.Unicode then + Error ("Unicode operator '¬' not allowed " & + "(Unicode option is disabled)"); + end if; + return Negation; when '<' | '>' | '=' | '/' | '~' | '^' => return VS; -- already checked above, but... when others => return Unknown; diff --git a/tests/src/semver_tests-options.adb b/tests/src/semver_tests-options.adb index 7de54fa..9a8c861 100644 --- a/tests/src/semver_tests-options.adb +++ b/tests/src/semver_tests-options.adb @@ -92,6 +92,12 @@ begin XVS1 := X.Value (U ("≥1.2.0"), Opts => Unicode_Opts); Assert (X.Is_In (V1_2, XVS1), "Extended Unicode parsing failed"); + XVS1 := X.Value (U ("¬1.2.0"), Opts => Unicode_Opts); + Assert (not X.Is_In (V1_2, XVS1), "Extended Unicode negation parsing failed"); + + Assert (not X.Parse (U ("¬1.2.0"), Opts => No_Unicode_Opts).Valid, + "Parse should fail for Unicode negation when disabled"); + -- Test Synthetic_Image with different options XVS1 := X.Value (">=1.2.0 & /=1.2.5"); Assert (X.Synthetic_Image (XVS1, Opts => Unicode_Opts) = @@ -104,6 +110,16 @@ begin "Extended ASCII output failed: " & X.Synthetic_Image (XVS1, Opts => No_Unicode_Opts)); + XVS1 := X.Value ("!1.2.0"); + Assert (X.Synthetic_Image (XVS1, Opts => Unicode_Opts) = + U ("¬(=1.2.0)"), + "Extended Unicode negation output failed: " & + X.Synthetic_Image (XVS1, Opts => Unicode_Opts)); + Assert (X.Synthetic_Image (XVS1, Opts => No_Unicode_Opts) = + "!(=1.2.0)", + "Extended ASCII negation output failed: " & + X.Synthetic_Image (XVS1, Opts => No_Unicode_Opts)); + -- Test Implicit_Equal with Extended XVS1 := X.Value ("=1.2.0"); Assert (X.Synthetic_Image (XVS1, Opts => With_Implicit) = "1.2.0", From 540b7a82834e268aee85319f0e0020a70918913e Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Sun, 18 Jan 2026 09:31:48 +0100 Subject: [PATCH 3/6] wip: encoding problem --- tests/alire.toml | 1 + tests/src/semver_tests-with_unicode.adb | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/tests/alire.toml b/tests/alire.toml index 94b8bbb..e0b0771 100644 --- a/tests/alire.toml +++ b/tests/alire.toml @@ -10,3 +10,4 @@ semantic_versioning = { path = '..' } [build-profiles] semantic_versioning = 'validation' +semver_tests = 'validation' diff --git a/tests/src/semver_tests-with_unicode.adb b/tests/src/semver_tests-with_unicode.adb index 9cbe73a..e62796c 100644 --- a/tests/src/semver_tests-with_unicode.adb +++ b/tests/src/semver_tests-with_unicode.adb @@ -1,6 +1,19 @@ procedure Semver_Tests.With_Unicode is + Unicode_Opts : constant Basic.Options := + (Unicode => True, + Word_Operators => False, + Implicit_Equal => False); + + begin Assert (X.Is_In (V ("1.1"), X.Value_U ("≠1"))); Assert (X.Is_In (V ("1.1"), X.Value_U ("≥1"))); Assert (X.Is_In (V ("1.1"), X.Value_U ("≤1.1"))); + + declare + XVS : constant X.Version_Set := X.Value_U ("¬1"); + begin + Assert (not X.Is_In (V ("1.0.0"), XVS)); + Assert (X.Synthetic_Image (XVS, Opts => Unicode_Opts) = U ("¬(=1.0.0)")); + end; end Semver_Tests.With_Unicode; From 83a8912f63f53f83997a9befc213260409e95b33 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Mon, 19 Jan 2026 00:48:40 +0100 Subject: [PATCH 4/6] =?UTF-8?q?Fix=20usage=20of=20'=C2=AC'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/semantic_versioning-extended.adb | 26 +++++++++++++++---------- src/semantic_versioning-extended.ads | 4 +++- tests/src/semver_tests-negation.adb | 2 +- tests/src/semver_tests-options.adb | 2 +- tests/src/semver_tests-with_unicode.adb | 2 +- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/semantic_versioning-extended.adb b/src/semantic_versioning-extended.adb index 02cc972..1bd9ecd 100644 --- a/src/semantic_versioning-extended.adb +++ b/src/semantic_versioning-extended.adb @@ -379,6 +379,8 @@ package body Semantic_Versioning.Extended is VS, End_Of_Input); + Not_UChar : constant String := U ("¬"); + I : Integer := Str'First; -- Next char to process Err : Unbounded_String; @@ -520,6 +522,14 @@ package body Semantic_Versioning.Extended is return VS; end if; + if Begins_With (Str (I .. Str'Last), Not_UChar) then + if not Opts.Unicode then + Error (U ("Unicode operator '¬' not allowed " & + "(Unicode option is disabled)")); + end if; + return Negation; + end if; + case Str (I) is when '&' => return Ampersand; when '(' => return Lparen; @@ -527,12 +537,6 @@ package body Semantic_Versioning.Extended is when '0' .. '9' => return Number; when '|' => return Pipe; when '!' => return Negation; - when '¬' => - if not Opts.Unicode then - Error ("Unicode operator '¬' not allowed " & - "(Unicode option is disabled)"); - end if; - return Negation; when '<' | '>' | '=' | '/' | '~' | '^' => return VS; -- already checked above, but... when others => return Unknown; @@ -569,8 +573,8 @@ package body Semantic_Versioning.Extended is when Negation => if Is_Keyword ("not") then Match ("not"); - elsif Str (I) = '¬' then - Match ('¬'); + elsif Begins_With (Str (I .. Str'Last), Not_UChar) then + Match (Not_UChar); else Match ('!'); end if; @@ -770,7 +774,9 @@ package body Semantic_Versioning.Extended is ------------- function Value_U (Str : Wide_Wide_String; - Relaxed : Boolean := False) return Version_Set - is (Value (U (Str), Relaxed)); + Relaxed : Boolean := False; + Opts : Basic.Options := Basic.Default_Options) + return Version_Set + is (Value (U (Str), Relaxed, Opts)); end Semantic_Versioning.Extended; diff --git a/src/semantic_versioning-extended.ads b/src/semantic_versioning-extended.ads index e124806..d8df0ce 100644 --- a/src/semantic_versioning-extended.ads +++ b/src/semantic_versioning-extended.ads @@ -67,7 +67,9 @@ package Semantic_Versioning.Extended with Preelaborate is -- Options control parsing (Unicode for accepting Unicode operators) function Value_U (Str : Wide_Wide_String; - Relaxed : Boolean := False) return Version_Set; + Relaxed : Boolean := False; + Opts : Basic.Options := Basic.Default_Options) + return Version_Set; function Image (VS : Version_Set) return String; -- Original image, as given to Value diff --git a/tests/src/semver_tests-negation.adb b/tests/src/semver_tests-negation.adb index 56c3cf3..3b6a357 100644 --- a/tests/src/semver_tests-negation.adb +++ b/tests/src/semver_tests-negation.adb @@ -17,5 +17,5 @@ begin -- Equivalent -- Alternate symbol - Assert (X.Is_In (V ("1.1"), X.Value ("¬1"))); + Assert (X.Is_In (V ("1.1"), X.Value_U ("¬1"))); end Semver_Tests.Negation; diff --git a/tests/src/semver_tests-options.adb b/tests/src/semver_tests-options.adb index 9a8c861..d39e61e 100644 --- a/tests/src/semver_tests-options.adb +++ b/tests/src/semver_tests-options.adb @@ -92,7 +92,7 @@ begin XVS1 := X.Value (U ("≥1.2.0"), Opts => Unicode_Opts); Assert (X.Is_In (V1_2, XVS1), "Extended Unicode parsing failed"); - XVS1 := X.Value (U ("¬1.2.0"), Opts => Unicode_Opts); + XVS1 := X.Value_U ("¬1.2.0", Opts => Unicode_Opts); Assert (not X.Is_In (V1_2, XVS1), "Extended Unicode negation parsing failed"); Assert (not X.Parse (U ("¬1.2.0"), Opts => No_Unicode_Opts).Valid, diff --git a/tests/src/semver_tests-with_unicode.adb b/tests/src/semver_tests-with_unicode.adb index e62796c..345899c 100644 --- a/tests/src/semver_tests-with_unicode.adb +++ b/tests/src/semver_tests-with_unicode.adb @@ -11,7 +11,7 @@ begin Assert (X.Is_In (V ("1.1"), X.Value_U ("≤1.1"))); declare - XVS : constant X.Version_Set := X.Value_U ("¬1"); + XVS : constant X.Version_Set := X.Value_U ("¬1", Opts => Unicode_Opts); begin Assert (not X.Is_In (V ("1.0.0"), XVS)); Assert (X.Synthetic_Image (XVS, Opts => Unicode_Opts) = U ("¬(=1.0.0)")); From 602eb5db08f2f77c05b7aae181946abc2487f858 Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Mon, 19 Jan 2026 00:57:20 +0100 Subject: [PATCH 5/6] Fix indentation Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/semantic_versioning-extended.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/semantic_versioning-extended.adb b/src/semantic_versioning-extended.adb index 1bd9ecd..6902ff4 100644 --- a/src/semantic_versioning-extended.adb +++ b/src/semantic_versioning-extended.adb @@ -524,7 +524,7 @@ package body Semantic_Versioning.Extended is if Begins_With (Str (I .. Str'Last), Not_UChar) then if not Opts.Unicode then - Error (U ("Unicode operator '¬' not allowed " & + Error (U ("Unicode operator '¬' not allowed " & "(Unicode option is disabled)")); end if; return Negation; From b3aaa05498a2cfebffa1a71d70c566907bb5ba39 Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Mon, 19 Jan 2026 00:58:50 +0100 Subject: [PATCH 6/6] Fix whitespace --- tests/src/semver_tests-with_unicode.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/semver_tests-with_unicode.adb b/tests/src/semver_tests-with_unicode.adb index 345899c..9a6a32a 100644 --- a/tests/src/semver_tests-with_unicode.adb +++ b/tests/src/semver_tests-with_unicode.adb @@ -1,10 +1,10 @@ procedure Semver_Tests.With_Unicode is + Unicode_Opts : constant Basic.Options := (Unicode => True, Word_Operators => False, Implicit_Equal => False); - begin Assert (X.Is_In (V ("1.1"), X.Value_U ("≠1"))); Assert (X.Is_In (V ("1.1"), X.Value_U ("≥1")));