Regular Expressions in Ada

Ada provides support for regular expressions through the GNAT.Regpat package. Here are some examples of common regexp-related tasks in Ada.

with Ada.Text_IO;
with GNAT.Regpat;

procedure Regular_Expressions is
   use Ada.Text_IO;
   use GNAT.Regpat;

   Pattern : constant String := "p([a-z]+)ch";
   Matcher : Pattern_Matcher := Compile(Pattern);
   Matches : Match_Array(0..1);
begin
   -- This tests whether a pattern matches a string.
   if Match(Pattern, "peach") then
      Put_Line("true");
   else
      Put_Line("false");
   end if;

   -- Many operations are available using the Pattern_Matcher.
   -- Here's a match test like we saw earlier.
   if Match(Matcher, "peach") then
      Put_Line("true");
   else
      Put_Line("false");
   end if;

   -- This finds the match for the regexp.
   Match(Matcher, "peach punch", Matches);
   if Matches(0) /= No_Match then
      Put_Line(Slice("peach punch", Matches(0)));
   end if;

   -- This also finds the first match but returns the
   -- start and end indexes for the match instead of the
   -- matching text.
   Match(Matcher, "peach punch", Matches);
   if Matches(0) /= No_Match then
      Put_Line("idx: " & Matches(0).First'Image & " " & Matches(0).Last'Image);
   end if;

   -- The submatch variant includes information about
   -- both the whole-pattern matches and the submatches
   -- within those matches.
   Match(Matcher, "peach punch", Matches);
   if Matches(0) /= No_Match then
      Put_Line(Slice("peach punch", Matches(0)) & " " & Slice("peach punch", Matches(1)));
   end if;

   -- Ada doesn't have a direct equivalent to Go's FindAllString,
   -- but we can implement similar functionality using a loop.
   declare
      Input : constant String := "peach punch pinch";
      Start : Positive := Input'First;
   begin
      Put("All matches: ");
      loop
         Match(Matcher, Input(Start..Input'Last), Matches);
         exit when Matches(0) = No_Match;
         Put(Slice(Input, Matches(0)) & " ");
         Start := Matches(0).Last + 1;
      end loop;
      New_Line;
   end;

   -- The GNAT.Regpat package doesn't provide a direct equivalent to
   -- Go's ReplaceAllString, but we can implement similar functionality.
   declare
      function Replace_Match (S : String) return String is
      begin
         return "<fruit>";
      end Replace_Match;

      Input : constant String := "a peach";
      Output : String := Input;
      Last : Natural := Input'Last;
   begin
      Loop_Replace :
      loop
         Match(Matcher, Output(Output'First..Last), Matches);
         exit Loop_Replace when Matches(0) = No_Match;
         Output(Matches(0).First..Last) := Replace_Match(Slice(Output, Matches(0))) & Output(Matches(0).Last+1..Last);
         Last := Last + Replace_Match(Slice(Output, Matches(0)))'Length - (Matches(0).Last - Matches(0).First + 1);
      end loop Loop_Replace;
      Put_Line(Output);
   end;
end Regular_Expressions;

To run the program, save it as regular_expressions.adb and use the GNAT compiler:

$ gnatmake regular_expressions.adb
$ ./regular_expressions
true
true
peach
idx:  1  5
peach ea
All matches: peach punch pinch 
a <fruit>

This Ada code demonstrates various regular expression operations similar to those in the original example. Note that Ada’s regular expression support is not as extensive as Go’s, so some operations are implemented manually or slightly differently. The GNAT.Regpat package provides the core functionality for pattern matching and searching.

For a complete reference on Ada regular expressions, check the GNAT.Regpat package documentation in your Ada compiler’s documentation.