Changeset 205 for branches/interpreter2/UGenerator.pas
- Timestamp:
- Apr 20, 2020, 1:10:44 AM (5 years ago)
- Location:
- branches/interpreter2
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/interpreter2
- Property svn:ignore
-
old new 4 4 interpreter.res 5 5 heaptrclog.trc 6 Generated
-
- Property svn:ignore
-
branches/interpreter2/UGenerator.pas
r204 r205 6 6 7 7 uses 8 Classes, SysUtils, strutils , USource;8 Classes, SysUtils, strutils; 9 9 10 10 type 11 12 { TGenerator }13 14 11 TGenerator = class 15 12 private 16 Indent: Integer; 13 FIndent: Integer; 14 procedure SetIndent(AValue: Integer); 15 public 16 Output: string; 17 17 procedure AddText(Text: string); 18 18 procedure AddTextLine(Text: string = ''); 19 procedure GenerateProgram(Block: TBlock; Prog:TProgram); 20 procedure GenerateBlock(ParentBlock: TBlock; Block: TBlock); 21 procedure GenerateBlockVar(ParentBlock: TBlock; Block: TBlock); 22 procedure GenerateBlockConst(ParentBlock: TBlock; Block: TBlock); 23 procedure GenerateBeginEnd(Block: TBlock; BeginEnd: TBeginEnd); 24 procedure GenerateCommand(Block: TBlock; Command: TCommand); 25 procedure GenerateIfThenElse(Block: TBlock; IfThenElse: TIfThenElse); 26 procedure GenerateWhileDo(Block: TBlock; WhileDo: TWhileDo); 27 procedure GenerateForToDo(Block: TBlock; ForToDo: TForToDo); 28 procedure GenerateFunctionCall(Block: TBlock; FunctionCall: TFunctionCall); 29 procedure GenerateAssignment(Block: TBlock; Assignment: TAssignment); 30 procedure GenerateExpression(Block: TBlock; Expression: TExpression); 31 procedure GenerateExpressionOperation(Block: TBlock; Expression: TExpressionOperation); 32 procedure GenerateExpressionOperand(Block: TBlock; Expression: TExpressionOperand); 33 procedure GenerateValue(Value: TValue); 34 public 35 Prog: TProgram; 36 Output: string; 37 procedure Generate; 19 property Indent: Integer read FIndent write SetIndent; 38 20 end; 21 39 22 40 23 implementation 41 24 42 { TGenerator } 43 44 procedure TGenerator.GenerateCommand(Block: TBlock; Command: TCommand); 25 procedure TGenerator.SetIndent(AValue: Integer); 45 26 begin 46 if Command is TBeginEnd then GenerateBeginEnd(Block, TBeginEnd(Command)) 47 else if Command is TFunctionCall then GenerateFunctionCall(Block, TFunctionCall(Command)) 48 else if Command is TAssignment then GenerateAssignment(Block, TAssignment(Command)) 49 else if Command is TIfThenElse then GenerateIfThenElse(Block, TIfThenElse(Command)) 50 else if Command is TWhileDo then GenerateWhileDo(Block, TWhileDo(Command)) 51 else if Command is TForToDo then GenerateForToDo(Block, TForToDo(Command)) 52 else raise Exception.Create('Unsupported command type'); 53 end; 54 55 procedure TGenerator.GenerateIfThenElse(Block: TBlock; IfThenElse: TIfThenElse); 56 begin 57 AddText('if '); 58 GenerateExpression(Block, IfThenElse.Expression); 59 AddText(' then '); 60 GenerateCommand(Block, IfThenElse.CommandThen); 61 if Assigned(IfThenElse.CommandElse) then begin 62 AddText(' else '); 63 GenerateCommand(Block, IfThenElse.CommandElse); 27 if FIndent = AValue then Exit; 28 if AValue > FIndent then begin 29 Output := Output + DupeString(' ', AValue - FIndent); 30 end else 31 if AValue < FIndent then begin 32 Output := Copy(Output, 1, Length(Output) - (FIndent - AValue) * 2); 64 33 end; 65 end; 66 67 procedure TGenerator.GenerateWhileDo(Block: TBlock; WhileDo: TWhileDo); 68 begin 69 AddText('while '); 70 GenerateExpression(Block, WhileDo.Expression); 71 AddText(' do '); 72 GenerateCommand(Block, WhileDo.Command); 73 end; 74 75 procedure TGenerator.GenerateForToDo(Block: TBlock; ForToDo: TForToDo); 76 begin 77 AddText('for '); 78 AddText(ForToDo.VariableRef.Name); 79 AddText(' := '); 80 GenerateExpression(Block, ForToDo.ExpressionFrom); 81 AddText(' to '); 82 GenerateExpression(Block, ForToDo.ExpressionTo); 83 AddText(' do '); 84 GenerateCommand(Block, ForToDo.Command); 85 end; 86 87 procedure TGenerator.GenerateFunctionCall(Block: TBlock; 88 FunctionCall: TFunctionCall); 89 var 90 I: Integer; 91 begin 92 AddText(FunctionCall.FunctionDef.Name); 93 if FunctionCall.Params.Count > 0 then begin 94 AddText('('); 95 for I := 0 to FunctionCall.Params.Count - 1 do 96 GenerateExpression(Block, TExpression(FunctionCall.Params[I])); 97 AddText(')'); 98 end; 99 end; 100 101 procedure TGenerator.GenerateAssignment(Block: TBlock; Assignment: TAssignment); 102 begin 103 AddText(Assignment.Variable.Name); 104 AddText(' := '); 105 GenerateExpression(Block, Assignment.Expression); 106 end; 107 108 procedure TGenerator.GenerateExpression(Block: TBlock; Expression: TExpression); 109 begin 110 if Expression is TExpressionOperation then 111 GenerateExpressionOperation(Block, TExpressionOperation(Expression)) 112 else 113 if Expression is TExpressionOperand then 114 GenerateExpressionOperand(Block, TExpressionOperand(Expression)) 115 else raise Exception.Create('Unknown expression class.'); 116 end; 117 118 procedure TGenerator.GenerateExpressionOperation(Block: TBlock; 119 Expression: TExpressionOperation); 120 var 121 I: Integer; 122 begin 123 for I := 0 to Expression.Items.Count - 1 do begin 124 if I > 0 then begin 125 AddText(' '); 126 if Expression.Operation = eoAdd then AddText('+') 127 else if Expression.Operation = eoSub then AddText('-') 128 else if Expression.Operation = eoEqual then AddText('=') 129 else if Expression.Operation = eoNotEqual then AddText('<>'); 130 AddText(' '); 131 end; 132 GenerateExpression(Block, TExpression(Expression.Items[I])); 133 end; 134 end; 135 136 procedure TGenerator.GenerateExpressionOperand(Block: TBlock; 137 Expression: TExpressionOperand); 138 begin 139 case Expression.OperandType of 140 otFunctionCall: GenerateFunctionCall(Block, Expression.FunctionCall); 141 otConstantDirect: GenerateValue(Expression.ConstantDirect.Value); 142 otConstantRef: AddText(Expression.ConstantRef.Name); 143 otVariableRef: AddText(Expression.VariableRef.Name); 144 else raise Exception.Create('Unsupported exception operand type.'); 145 end; 146 end; 147 148 procedure TGenerator.GenerateValue(Value: TValue); 149 begin 150 if Value is TValueBoolean then begin 151 if TValueBoolean(Value).Value then AddText('True') else AddText('False'); 152 end else if Value is TValueString then AddText('''' + StringReplace(TValueString(Value).Value, '''', '''''', [rfReplaceAll]) + '''') 153 else if Value is TValueInteger then AddText(IntToStr(TValueInteger(Value).Value)) 154 else raise Exception.Create('Unsupported value type.'); 34 FIndent := AValue; 155 35 end; 156 36 … … 165 45 end; 166 46 167 procedure TGenerator.GenerateProgram(Block: TBlock; Prog: TProgram);168 begin169 if Prog.Name <> '' then AddTextLine('program ' + Prog.Name + ';');170 GenerateBlock(Block, Prog.Block);171 AddTextLine('.');172 end;173 174 procedure TGenerator.GenerateBlock(ParentBlock: TBlock; Block: TBlock);175 begin176 GenerateBlockConst(ParentBlock, Block);177 GenerateBlockVar(ParentBlock, Block);178 GenerateBeginEnd(ParentBlock, Block.BeginEnd);179 end;180 181 procedure TGenerator.GenerateBlockVar(ParentBlock: TBlock; Block: TBlock);182 var183 I: Integer;184 Variable: TVariable;185 begin186 if Block.Variables.Count > 0 then begin187 AddText('var');188 Inc(Indent);189 AddTextLine;190 for I := 0 to Block.Variables.Count - 1 do begin191 Variable := TVariable(Block.Variables[I]);192 AddTextLine(Variable.Name + ': ' + Variable.TypeRef.Name + ';');193 end;194 Dec(Indent);195 AddTextLine;196 end;197 end;198 199 procedure TGenerator.GenerateBlockConst(ParentBlock: TBlock; Block: TBlock);200 var201 I: Integer;202 Constant: TConstant;203 begin204 if Block.Constants.Count > 0 then begin205 AddText('const');206 Inc(Indent);207 AddTextLine;208 for I := 0 to Block.Constants.Count - 1 do begin209 Constant := TConstant(Block.Constants[I]);210 AddText(Constant.Name + ': ' + Constant.TypeRef.Name + ' = ');211 GenerateValue(Constant.Value);212 AddTextLine(';');213 end;214 Dec(Indent);215 AddTextLine;216 end;217 end;218 219 procedure TGenerator.GenerateBeginEnd(Block: TBlock; BeginEnd: TBeginEnd);220 var221 I: Integer;222 begin223 AddText('begin');224 Inc(Indent);225 AddTextLine('');226 for I := 0 to BeginEnd.Commands.Count - 1 do begin227 GenerateCommand(Block, TCommand(BeginEnd.Commands[I]));228 AddText(';');229 if I < BeginEnd.Commands.Count - 1 then AddTextLine('');230 end;231 Dec(Indent);232 AddTextLine('');233 AddText('end');234 end;235 236 procedure TGenerator.Generate;237 begin238 Output := '';239 GenerateProgram(Prog.SystemBlock, Prog);240 end;241 242 47 end. 243 48
Note:
See TracChangeset
for help on using the changeset viewer.