| 1 | unit USourceGenerator;
 | 
|---|
| 2 | 
 | 
|---|
| 3 | {$mode delphi}
 | 
|---|
| 4 | 
 | 
|---|
| 5 | interface
 | 
|---|
| 6 | 
 | 
|---|
| 7 | uses
 | 
|---|
| 8 |   Classes, SysUtils, USourceCode;
 | 
|---|
| 9 | 
 | 
|---|
| 10 | type
 | 
|---|
| 11 |   { TSourceGenerator }
 | 
|---|
| 12 | 
 | 
|---|
| 13 |   TSourceGenerator = class
 | 
|---|
| 14 |   private
 | 
|---|
| 15 |     Indent: Integer;
 | 
|---|
| 16 |     function GenerateBeginEnd(BeginEnd: TCommandBeginEnd): string;
 | 
|---|
| 17 |     function GenerateCommand(Command: TSourceCommand): string;
 | 
|---|
| 18 |     function GenerateRef(Reference: TSourceReference): string;
 | 
|---|
| 19 |     function IndentStr: string;
 | 
|---|
| 20 |   public
 | 
|---|
| 21 |     function Generate(SourceCode: TSourceCode): string;
 | 
|---|
| 22 |   end;
 | 
|---|
| 23 | 
 | 
|---|
| 24 | 
 | 
|---|
| 25 | implementation
 | 
|---|
| 26 | 
 | 
|---|
| 27 | { TSourceGenerator }
 | 
|---|
| 28 | 
 | 
|---|
| 29 | function TSourceGenerator.Generate(SourceCode: TSourceCode): string;
 | 
|---|
| 30 | var
 | 
|---|
| 31 |   I: Integer;
 | 
|---|
| 32 | begin
 | 
|---|
| 33 |   Indent := 0;
 | 
|---|
| 34 |   Result := '';
 | 
|---|
| 35 |   if SourceCode.Variables.Count > 0 then
 | 
|---|
| 36 |     Result := Result + IndentStr + 'var' + LineEnding;
 | 
|---|
| 37 |   Inc(Indent);
 | 
|---|
| 38 |   with SourceCode do
 | 
|---|
| 39 |   for I := 0 to Variables.Count - 1 do
 | 
|---|
| 40 |   with TSourceVariable(Variables[I]) do begin
 | 
|---|
| 41 |     Result := Result + IndentStr + Name + ': ';
 | 
|---|
| 42 |     if ValueType.Name = 'String' then
 | 
|---|
| 43 |       Result := Result + 'string'
 | 
|---|
| 44 |     else if ValueType.Name = 'Integer' then
 | 
|---|
| 45 |       Result := Result + 'Integer'
 | 
|---|
| 46 |     else if ValueType.Name = 'StringArray' then
 | 
|---|
| 47 |       Result := Result + 'array of string'
 | 
|---|
| 48 |     else if ValueType.Name = 'IntegerArray' then
 | 
|---|
| 49 |       Result := Result + 'array of Integer'
 | 
|---|
| 50 |     else raise Exception.Create('Unsupported type');
 | 
|---|
| 51 |     Result := Result + ';' + LineEnding;
 | 
|---|
| 52 |   end;
 | 
|---|
| 53 |   Dec(Indent);
 | 
|---|
| 54 |   Result := Result + GenerateBeginEnd(SourceCode.Main) + '.' + LineEnding;
 | 
|---|
| 55 | end;
 | 
|---|
| 56 | 
 | 
|---|
| 57 | function TSourceGenerator.GenerateRef(Reference: TSourceReference): string;
 | 
|---|
| 58 | var
 | 
|---|
| 59 |   Value: TSourceValue;
 | 
|---|
| 60 | begin
 | 
|---|
| 61 |   Result := '';
 | 
|---|
| 62 |   if Reference is TSourceReferenceConstant then begin
 | 
|---|
| 63 |     Value := TSourceReferenceConstant(Reference).Constant.Value;
 | 
|---|
| 64 |     if Value is TSourceValueString then
 | 
|---|
| 65 |       Result := Result + '''' + TSourceValueString(Value).Value + ''''
 | 
|---|
| 66 |     else
 | 
|---|
| 67 |     if Value is TSourceValueInteger then
 | 
|---|
| 68 |       Result := Result + IntToStr(TSourceValueInteger(Value).Value);
 | 
|---|
| 69 |   end else
 | 
|---|
| 70 |   if Reference is TSourceReferenceVariable then begin
 | 
|---|
| 71 |     Result := Result + TSourceReferenceVariable(Reference).Variable.Name;
 | 
|---|
| 72 |   end else
 | 
|---|
| 73 |   if Reference is TSourceReferenceArray then begin
 | 
|---|
| 74 |     Result := Result + TSourceReferenceArray(Reference).ArrayRef.Name +
 | 
|---|
| 75 |       '[' + GenerateRef(TSourceReferenceArray(Reference).Index) + ']';
 | 
|---|
| 76 |   end else raise Exception.Create('Unsupported parameter type');
 | 
|---|
| 77 | end;
 | 
|---|
| 78 | 
 | 
|---|
| 79 | function TSourceGenerator.GenerateCommand(Command: TSourceCommand): string;
 | 
|---|
| 80 | begin
 | 
|---|
| 81 |   Result := '';
 | 
|---|
| 82 |   if Command is TCommandFunctionCall then
 | 
|---|
| 83 |   with TCommandFunctionCall(Command) do begin
 | 
|---|
| 84 |     if Name = 'print' then begin
 | 
|---|
| 85 |       Result := Result + IndentStr + 'Write(' + GenerateRef(TSourceReference(Parameters[0])) + ');' +
 | 
|---|
| 86 |         LineEnding;
 | 
|---|
| 87 |     end else
 | 
|---|
| 88 |     if Name = 'println' then begin
 | 
|---|
| 89 |       Result := Result + IndentStr + 'WriteLn(' + GenerateRef(TSourceReference(Parameters[0])) + ');' +
 | 
|---|
| 90 |         LineEnding;
 | 
|---|
| 91 |     end else
 | 
|---|
| 92 |     if Name = 'assign' then begin
 | 
|---|
| 93 |       if TSourceReference(Parameters[0]) is TSourceReferenceArray then
 | 
|---|
| 94 |         Result := Result + IndentStr + 'SetLength(' + TSourceReferenceArray(Parameters[0]).ArrayRef.Name +
 | 
|---|
| 95 |           ', ' + GenerateRef(TSourceReferenceArray(Parameters[0]).Index) + ' + 1);' + LineEnding;
 | 
|---|
| 96 |       Result := Result + IndentStr + GenerateRef(TSourceReference(Parameters[0])) + ' := ' +
 | 
|---|
| 97 |         GenerateRef(TSourceReference(Parameters[1])) + ';' + LineEnding;
 | 
|---|
| 98 |     end else
 | 
|---|
| 99 |     if Name = 'inputln' then begin
 | 
|---|
| 100 |       Result := Result + IndentStr + 'ReadLn(' + GenerateRef(TSourceReference(Parameters[0])) + ');' + LineEnding;
 | 
|---|
| 101 |     end else
 | 
|---|
| 102 |     if Name = 'increment' then begin
 | 
|---|
| 103 |       Result := Result + IndentStr + 'Inc(' + GenerateRef(TSourceReference(Parameters[0])) + ', ' +
 | 
|---|
| 104 |         GenerateRef(TSourceReference(Parameters[1])) + ');' + LineEnding;
 | 
|---|
| 105 |     end else
 | 
|---|
| 106 |     if Name = 'decrement' then begin
 | 
|---|
| 107 |       Result := Result + IndentStr + 'Dec(' + GenerateRef(TSourceReference(Parameters[0])) + ', ' +
 | 
|---|
| 108 |         GenerateRef(TSourceReference(Parameters[1])) + ');' + LineEnding;
 | 
|---|
| 109 |     end else
 | 
|---|
| 110 |     raise Exception.Create('Unsupported instruction name.');
 | 
|---|
| 111 |   end else
 | 
|---|
| 112 |   if Command is TCommandBeginEnd then begin
 | 
|---|
| 113 |     Result := Result + GenerateBeginEnd(TCommandBeginEnd(Command)) +
 | 
|---|
| 114 |       ';' + LineEnding;
 | 
|---|
| 115 |   end else
 | 
|---|
| 116 |   if Command is TCommandBreak then begin
 | 
|---|
| 117 |     Result := Result + IndentStr + 'Break;' + LineEnding;
 | 
|---|
| 118 |   end else
 | 
|---|
| 119 |   if Command is TCommandContinue then begin
 | 
|---|
| 120 |     Result := Result + IndentStr + 'Continue;' + LineEnding;
 | 
|---|
| 121 |   end else
 | 
|---|
| 122 |   if Command is TCommandRepeat then begin
 | 
|---|
| 123 |     Result := Result + IndentStr + 'repeat' + LineEnding;
 | 
|---|
| 124 |     Inc(Indent);
 | 
|---|
| 125 |     Result := Result + GenerateCommand(TCommandRepeat(Command).Command);
 | 
|---|
| 126 |     Dec(Indent);
 | 
|---|
| 127 |     Result := Result + IndentStr + 'until False;' + LineEnding;
 | 
|---|
| 128 |   end else
 | 
|---|
| 129 |   if Command is TCommandIfEqual then begin
 | 
|---|
| 130 |     Result := Result + IndentStr + 'if ' +
 | 
|---|
| 131 |       GenerateRef(TCommandIfEqual(Command).Reference1) + ' = ' +
 | 
|---|
| 132 |       GenerateRef(TCommandIfEqual(Command).Reference2) + ' then ' + LineEnding;
 | 
|---|
| 133 |   end else
 | 
|---|
| 134 |   if Command is TCommandIfNotEqual then begin
 | 
|---|
| 135 |     Result := Result + IndentStr + 'if ' +
 | 
|---|
| 136 |       GenerateRef(TCommandIfNotEqual(Command).Reference1) + ' <> ' +
 | 
|---|
| 137 |       GenerateRef(TCommandIfNotEqual(Command).Reference2) + ' then ' + LineEnding;
 | 
|---|
| 138 |   end else
 | 
|---|
| 139 |   raise Exception.Create('Unsupported instruction');
 | 
|---|
| 140 | end;
 | 
|---|
| 141 | 
 | 
|---|
| 142 | function TSourceGenerator.GenerateBeginEnd(BeginEnd: TCommandBeginEnd): string;
 | 
|---|
| 143 | var
 | 
|---|
| 144 |   I: Integer;
 | 
|---|
| 145 | begin
 | 
|---|
| 146 |   Result := '';
 | 
|---|
| 147 |   Result := Result + IndentStr + 'begin' + LineEnding;
 | 
|---|
| 148 |   Inc(Indent);
 | 
|---|
| 149 |   with BeginEnd do
 | 
|---|
| 150 |   for I := 0 to Commands.Count - 1 do begin
 | 
|---|
| 151 |     Result := Result + GenerateCommand(TSourceCommand(Commands[I]));
 | 
|---|
| 152 |   end;
 | 
|---|
| 153 |   Dec(Indent);
 | 
|---|
| 154 |   Result := Result + IndentStr + 'end';
 | 
|---|
| 155 | end;
 | 
|---|
| 156 | 
 | 
|---|
| 157 | function TSourceGenerator.IndentStr: string;
 | 
|---|
| 158 | begin
 | 
|---|
| 159 |   SetLength(Result, Indent * 2);
 | 
|---|
| 160 |   if Indent > 0 then
 | 
|---|
| 161 |     FillChar(Result[1], Indent * 2, ' ');
 | 
|---|
| 162 | end;
 | 
|---|
| 163 | 
 | 
|---|
| 164 | 
 | 
|---|
| 165 | end.
 | 
|---|
| 166 | 
 | 
|---|