aboutsummarylogtreecommitdiffstats
path: root/uRepeatExpression.pas
blob: 8731283ef4d5391f1abaad9a5a908e183b6a9ae8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
unit uRepeatExpression;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

function ProcessRepeatExpression(const input: string): string;

implementation

function ProcessRepeatExpression(const input: string): string;
var
  startPos, endPos: Integer;
  repeatContent, varPart, casesPart, template: string;
  cases: TStringList;
  i: Integer;
  varName: string;
  outputBuilder: TStringList;
begin
  Result := input;
  outputBuilder := TStringList.Create;
  try
    outputBuilder.Text := input;

    // Find @repeat pattern
    startPos := Pos('@repeat', outputBuilder.Text);
    while startPos > 0 do
    begin
      endPos := Pos(']]', outputBuilder.Text, startPos);
      if endPos = 0 then Break;

      // Extract the entire repeat block
      repeatContent := Copy(outputBuilder.Text, startPos, endPos - startPos + 2);

      // Extract variable definition part { var = case1|case2|caseN }
      varPart := Copy(repeatContent,
                     Pos('{', repeatContent) + 1,
                     Pos('}', repeatContent) - Pos('{', repeatContent) - 1);
      varPart := Trim(varPart);

      // Get variable name and cases
      varName := Trim(Copy(varPart, 1, Pos('=', varPart) - 1));
      casesPart := Trim(Copy(varPart, Pos('=', varPart) + 1, Length(varPart)));

      // Split cases
      cases := TStringList.Create;
      try
        cases.Delimiter := '|';
        cases.StrictDelimiter := True;
        cases.DelimitedText := casesPart;

        // Extract template [[ string &var; other ]]
        template := Copy(repeatContent,
                        Pos('[[', repeatContent) + 2,
                        Pos(']]', repeatContent) - Pos('[[', repeatContent) - 2);
        template := Trim(template);

        // Process each case
        Result := '';
        for i := 0 to cases.Count - 1 do
        begin
          if i > 0 then Result := Result + ' ';
          Result := Result + StringReplace(template, '&' + varName + ';', cases[i], [rfReplaceAll]);
        end;

        // Replace the original @repeat block with processed content
        outputBuilder.Text := StringReplace(outputBuilder.Text, repeatContent, Result, []);
      finally
        cases.Free;
      end;

      // Look for next @repeat pattern
      startPos := Pos('@repeat', outputBuilder.Text);
    end;

    Result := Trim(outputBuilder.Text);
  finally
    outputBuilder.Free;
  end;
end;

end.