| 1 | unit Source;
|
|---|
| 2 |
|
|---|
| 3 | {$mode delphi}
|
|---|
| 4 |
|
|---|
| 5 | interface
|
|---|
| 6 |
|
|---|
| 7 | type
|
|---|
| 8 | PBeginEnd = ^TBeginEnd;
|
|---|
| 9 | PAssignment = ^TAssignment;
|
|---|
| 10 | PVariable = ^TVariable;
|
|---|
| 11 | PVariableRef = ^TVariableRef;
|
|---|
| 12 | PConstant = ^TConstant;
|
|---|
| 13 | PIfThenElse = ^TIfThenElse;
|
|---|
| 14 | PWhileDo = ^TWhileDo;
|
|---|
| 15 | PExpression = ^TExpression;
|
|---|
| 16 | PExecution = ^TExecution;
|
|---|
| 17 | PType = ^TType;
|
|---|
| 18 | PTypes = ^TTypes;
|
|---|
| 19 | PEnumerationStates = ^TEnumerationStates;
|
|---|
| 20 | PFunction = ^TFunction;
|
|---|
| 21 | PVariables = ^TVariables;
|
|---|
| 22 | PGetValue = ^TGetValue;
|
|---|
| 23 |
|
|---|
| 24 | TOperator = (opNone, opAdd, opSubtract, opAnd, opOr, opNot, opEqual, opNotEqual,
|
|---|
| 25 | opLess, opGreater, opLessOrEqual, opGreaterOrEqual);
|
|---|
| 26 |
|
|---|
| 27 | TBaseType = (btNone, btBoolean, btInteger, btChar, btShortString, btArray,
|
|---|
| 28 | btSimple, btPointer, btRecord, btSimpleForward, btEnumeration, btFunction,
|
|---|
| 29 | btRecordCase);
|
|---|
| 30 |
|
|---|
| 31 | TType = record
|
|---|
| 32 | TypeList: PTypes;
|
|---|
| 33 | Name: string;
|
|---|
| 34 | BaseType: TBaseType;
|
|---|
| 35 | case TBaseType of
|
|---|
| 36 | btPointer: (PointedType: PType);
|
|---|
| 37 | btRecord: (Fields: PTypes);
|
|---|
| 38 | btSimple: (Simple: PType);
|
|---|
| 39 | btSimpleForward: (ForwardType: shortstring);
|
|---|
| 40 | btEnumeration: (States: PEnumerationStates);
|
|---|
| 41 | btArray: (ArrayItemType: PType);
|
|---|
| 42 | btFunction: (Func: PFunction);
|
|---|
| 43 | btRecordCase: (CaseItems: PTypes);
|
|---|
| 44 | end;
|
|---|
| 45 |
|
|---|
| 46 | TEnumerationStates = record
|
|---|
| 47 | Items: array of string;
|
|---|
| 48 | end;
|
|---|
| 49 |
|
|---|
| 50 | { TTypes }
|
|---|
| 51 |
|
|---|
| 52 | TTypes = record
|
|---|
| 53 | ParentList: PTypes;
|
|---|
| 54 | Items: array of TType;
|
|---|
| 55 | procedure Add(DataType: TType);
|
|---|
| 56 | function GetByName(Name: string): PType;
|
|---|
| 57 | function GetLast: PType;
|
|---|
| 58 | end;
|
|---|
| 59 |
|
|---|
| 60 | TConstant = record
|
|---|
| 61 | Name: shortstring;
|
|---|
| 62 | DataType: PType;
|
|---|
| 63 | Index: Integer;
|
|---|
| 64 | case TBaseType of
|
|---|
| 65 | btChar: (ValueChar: Char);
|
|---|
| 66 | btInteger: (ValueInteger: Integer);
|
|---|
| 67 | btShortString: (ValueString: ShortString);
|
|---|
| 68 | btBoolean: (ValueBoolean: Boolean);
|
|---|
| 69 | btRecord: (ValueRecord: PVariables);
|
|---|
| 70 | btArray: (ValueArray: PVariables);
|
|---|
| 71 | end;
|
|---|
| 72 |
|
|---|
| 73 | { TConstants }
|
|---|
| 74 |
|
|---|
| 75 | TConstants = record
|
|---|
| 76 | Items: array of TConstant;
|
|---|
| 77 | procedure Add(Constant: TConstant);
|
|---|
| 78 | function GetByName(Name: string): PConstant;
|
|---|
| 79 | end;
|
|---|
| 80 | PConstants = ^TConstants;
|
|---|
| 81 |
|
|---|
| 82 | TVariable = record
|
|---|
| 83 | Name: string;
|
|---|
| 84 | DataType: PType;
|
|---|
| 85 | Index: Integer;
|
|---|
| 86 | Value: TConstant;
|
|---|
| 87 | end;
|
|---|
| 88 |
|
|---|
| 89 | { TVariables }
|
|---|
| 90 |
|
|---|
| 91 | TVariables = record
|
|---|
| 92 | ParentList: PVariables;
|
|---|
| 93 | Items: array of TVariable;
|
|---|
| 94 | procedure Add(Variable: TVariable);
|
|---|
| 95 | function GetByName(Name: string): PVariable;
|
|---|
| 96 | function GetLast: PVariable;
|
|---|
| 97 | end;
|
|---|
| 98 |
|
|---|
| 99 | TVariableRef = record
|
|---|
| 100 | Variable: PVariable;
|
|---|
| 101 | case TBaseType of
|
|---|
| 102 | btRecord: (Field: PType);
|
|---|
| 103 | btArray: (Index: PGetValue);
|
|---|
| 104 | end;
|
|---|
| 105 |
|
|---|
| 106 | TFunctionParameter = record
|
|---|
| 107 | Name: string;
|
|---|
| 108 | DataType: PType;
|
|---|
| 109 | Output: Boolean;
|
|---|
| 110 | end;
|
|---|
| 111 |
|
|---|
| 112 | { TFunctionParameters }
|
|---|
| 113 |
|
|---|
| 114 | TFunctionParameters = record
|
|---|
| 115 | TypeList: PTypes;
|
|---|
| 116 | Items: array of TFunctionParameter;
|
|---|
| 117 | procedure Add(Param: TFunctionParameter);
|
|---|
| 118 | end;
|
|---|
| 119 | PFunctionParameters = ^TFunctionParameters;
|
|---|
| 120 |
|
|---|
| 121 | TFunctionCall = procedure ;
|
|---|
| 122 |
|
|---|
| 123 | TCmdType = (ctNone, ctWhileDo, ctIfThenElse, ctBeginEnd, ctAssignment, ctExecution);
|
|---|
| 124 | TCommand = record
|
|---|
| 125 | CmdType: TCmdType;
|
|---|
| 126 | case Integer of
|
|---|
| 127 | 0: (WhileDo: PWhileDo);
|
|---|
| 128 | 1: (IfThenElse: PIfThenElse);
|
|---|
| 129 | 2: (BeginEnd: PBeginEnd);
|
|---|
| 130 | 3: (Assignment: PAssignment);
|
|---|
| 131 | 4: (Execution: PExecution);
|
|---|
| 132 | end;
|
|---|
| 133 | PCommand = ^TCommand;
|
|---|
| 134 |
|
|---|
| 135 | { TBeginEnd }
|
|---|
| 136 |
|
|---|
| 137 | TBeginEnd = record
|
|---|
| 138 | Commands: array of TCommand;
|
|---|
| 139 | procedure Add;
|
|---|
| 140 | function GetLast: PCommand;
|
|---|
| 141 | end;
|
|---|
| 142 |
|
|---|
| 143 | TReadType = (rtVariable, rtConstant, rtExpression, rtFunctionCall, rtValue);
|
|---|
| 144 | TGetValue = record
|
|---|
| 145 | ReadType: TReadType;
|
|---|
| 146 | case TReadType of
|
|---|
| 147 | rtVariable: (VariableRef: PVariableRef);
|
|---|
| 148 | rtConstant: (Constant: PConstant);
|
|---|
| 149 | rtExpression: (Expression: PExpression);
|
|---|
| 150 | rtFunctionCall: (FunctionCall: PExecution);
|
|---|
| 151 | rtValue: (Value: TConstant);
|
|---|
| 152 | end;
|
|---|
| 153 |
|
|---|
| 154 | TExpNodeType = (ntNone, ntValue, ntOperator);
|
|---|
| 155 |
|
|---|
| 156 | TExpression = record
|
|---|
| 157 | NodeType: TExpNodeType;
|
|---|
| 158 | OperatorType: TOperator;
|
|---|
| 159 | Items: array of TExpression;
|
|---|
| 160 | Value: TGetValue;
|
|---|
| 161 | Parentheses: Boolean;
|
|---|
| 162 | Associated: Boolean;
|
|---|
| 163 | end;
|
|---|
| 164 |
|
|---|
| 165 | TAssignment = record
|
|---|
| 166 | Destination: PVariableRef;
|
|---|
| 167 | Source: TGetValue;
|
|---|
| 168 | end;
|
|---|
| 169 |
|
|---|
| 170 | TIfThenElse = record
|
|---|
| 171 | Condition: TGetValue;
|
|---|
| 172 | DoThen: TCommand;
|
|---|
| 173 | DoElse: TCommand;
|
|---|
| 174 | end;
|
|---|
| 175 |
|
|---|
| 176 | TWhileDo = record
|
|---|
| 177 | Condition: TGetValue;
|
|---|
| 178 | Command: TCommand;
|
|---|
| 179 | end;
|
|---|
| 180 |
|
|---|
| 181 | { TFunction }
|
|---|
| 182 |
|
|---|
| 183 | TFunction = record // TCommand
|
|---|
| 184 | Name: string;
|
|---|
| 185 | Parameters: TFunctionParameters;
|
|---|
| 186 | ReturnType: PType;
|
|---|
| 187 | BeginEnd: TBeginEnd;
|
|---|
| 188 | Variables: TVariables;
|
|---|
| 189 | Types: TTypes;
|
|---|
| 190 | ParentRecord: PType;
|
|---|
| 191 | end;
|
|---|
| 192 |
|
|---|
| 193 | { TFunctions }
|
|---|
| 194 |
|
|---|
| 195 | TFunctions = record
|
|---|
| 196 | Items: array of TFunction;
|
|---|
| 197 | procedure Add(Func: TFunction);
|
|---|
| 198 | function GetByName(Name: string): PFunction;
|
|---|
| 199 | function GetLast: PFunction;
|
|---|
| 200 | end;
|
|---|
| 201 |
|
|---|
| 202 | TExecutionParams = record
|
|---|
| 203 | Items: array of TGetValue;
|
|---|
| 204 | end;
|
|---|
| 205 |
|
|---|
| 206 | TExecution = record
|
|---|
| 207 | Func: PFunction;
|
|---|
| 208 | Parameters: TExecutionParams;
|
|---|
| 209 | end;
|
|---|
| 210 |
|
|---|
| 211 | TDirective = record
|
|---|
| 212 | Name: string;
|
|---|
| 213 | Value: string;
|
|---|
| 214 | end;
|
|---|
| 215 | PDirective = ^TDirective;
|
|---|
| 216 |
|
|---|
| 217 | TUses = record
|
|---|
| 218 | Items: array of string;
|
|---|
| 219 | end;
|
|---|
| 220 | PUses = ^TUses;
|
|---|
| 221 |
|
|---|
| 222 | TUnit = record
|
|---|
| 223 | Name: string;
|
|---|
| 224 | Types: TTypes;
|
|---|
| 225 | Variables: TVariables;
|
|---|
| 226 | Constants: TConstants;
|
|---|
| 227 | UsesSection: TUses;
|
|---|
| 228 | Functions: TFunctions;
|
|---|
| 229 | end;
|
|---|
| 230 | PUnit = ^TUnit;
|
|---|
| 231 |
|
|---|
| 232 | { TUnits }
|
|---|
| 233 |
|
|---|
| 234 | TUnits = record
|
|---|
| 235 | Items: array of TUnit;
|
|---|
| 236 | function GetByName(Name: string): PUnit;
|
|---|
| 237 | end;
|
|---|
| 238 |
|
|---|
| 239 | TProgramCode = record
|
|---|
| 240 | Name: string;
|
|---|
| 241 | BaseDir: string;
|
|---|
| 242 | Variables: TVariables;
|
|---|
| 243 | Constants: TConstants;
|
|---|
| 244 | Types: TTypes;
|
|---|
| 245 | Functions: TFunctions;
|
|---|
| 246 | BeginEnd: TBeginEnd;
|
|---|
| 247 | UsesSection: TUses;
|
|---|
| 248 | Units: TUnits;
|
|---|
| 249 | end;
|
|---|
| 250 | PProgramCode = ^TProgramCode;
|
|---|
| 251 |
|
|---|
| 252 | function ConstantCreate(Name: string; DataType: PType): TConstant;
|
|---|
| 253 | function VariableCreate(Name: string; DataType: PType): TVariable;
|
|---|
| 254 | function FunctionCreate(Name: string; DataType: PType): TFunction;
|
|---|
| 255 | function TypeCreate(Name: string; BaseType: TBaseType): TType;
|
|---|
| 256 | function FunctionParameterCreate(Name: string; DataType: PType; Output: Boolean = False): TFunctionParameter;
|
|---|
| 257 |
|
|---|
| 258 | var
|
|---|
| 259 | OperatorString: array[TOperator] of string = ('', '+', '-', 'and', 'or', 'not',
|
|---|
| 260 | '=', '<>', '<', '>', '<=', '>=');
|
|---|
| 261 |
|
|---|
| 262 | const
|
|---|
| 263 | OperatorPrecedence: array[0..10] of TOperator = (opNot, opAnd, opOr, opAdd,
|
|---|
| 264 | opSubtract, opEqual, opNotEqual, opLess, opGreater, opLessOrEqual, opGreaterOrEqual);
|
|---|
| 265 | Keywords: array[0..18] of string = ('begin', 'end', 'if', 'then', 'else', 'while',
|
|---|
| 266 | 'do', 'type', 'var', 'const', 'uses', 'unit', 'program', 'array', 'procedure',
|
|---|
| 267 | 'function', 'interface', 'implementation', 'record');
|
|---|
| 268 |
|
|---|
| 269 |
|
|---|
| 270 | implementation
|
|---|
| 271 |
|
|---|
| 272 | function ConstantCreate(Name: string; DataType: PType): TConstant;
|
|---|
| 273 | begin
|
|---|
| 274 | Result.Name := Name;
|
|---|
| 275 | Result.DataType := DataType;
|
|---|
| 276 | end;
|
|---|
| 277 |
|
|---|
| 278 | function VariableCreate(Name: string; DataType: PType): TVariable;
|
|---|
| 279 | begin
|
|---|
| 280 | Result.Name := Name;
|
|---|
| 281 | Result.DataType := DataType;
|
|---|
| 282 | end;
|
|---|
| 283 |
|
|---|
| 284 | function FunctionCreate(Name: string; DataType: PType): TFunction;
|
|---|
| 285 | begin
|
|---|
| 286 | Result.Name := Name;
|
|---|
| 287 | Result.ReturnType := DataType;
|
|---|
| 288 | end;
|
|---|
| 289 |
|
|---|
| 290 | function TypeCreate(Name: string; BaseType:TBaseType): TType;
|
|---|
| 291 | begin
|
|---|
| 292 | Result.Name := Name;
|
|---|
| 293 | Result.BaseType := BaseType;
|
|---|
| 294 | end;
|
|---|
| 295 |
|
|---|
| 296 | function FunctionParameterCreate(Name: string; DataType: PType; Output: Boolean = False): TFunctionParameter;
|
|---|
| 297 | begin
|
|---|
| 298 | Result.Name := Name;
|
|---|
| 299 | Result.DataType := DataType;
|
|---|
| 300 | Result.Output := Output;
|
|---|
| 301 | end;
|
|---|
| 302 |
|
|---|
| 303 | { TUnits }
|
|---|
| 304 |
|
|---|
| 305 | function TUnits.GetByName(Name: string): PUnit;
|
|---|
| 306 | var
|
|---|
| 307 | I: Integer;
|
|---|
| 308 | begin
|
|---|
| 309 | I := 0;
|
|---|
| 310 | while (I < Length(Items)) and (Items[I].Name <> Name) do I := I + 1;
|
|---|
| 311 | if I < Length(Items) then Result := @Items[I]
|
|---|
| 312 | else Result := nil;
|
|---|
| 313 | end;
|
|---|
| 314 |
|
|---|
| 315 | { TBeginEnd }
|
|---|
| 316 |
|
|---|
| 317 | procedure TBeginEnd.Add;
|
|---|
| 318 | begin
|
|---|
| 319 | SetLength(Commands, Length(Commands) + 1);
|
|---|
| 320 | end;
|
|---|
| 321 |
|
|---|
| 322 | function TBeginEnd.GetLast: PCommand;
|
|---|
| 323 | begin
|
|---|
| 324 | Result := @Commands[Length(Commands) - 1];
|
|---|
| 325 | end;
|
|---|
| 326 |
|
|---|
| 327 | { TConstants }
|
|---|
| 328 |
|
|---|
| 329 | procedure TConstants.Add(Constant: TConstant);
|
|---|
| 330 | begin
|
|---|
| 331 | SetLength(Items, Length(Items) + 1);
|
|---|
| 332 | Items[Length(Items) - 1] := Constant;
|
|---|
| 333 | Items[Length(Items) - 1].Index := Length(Items) - 1;
|
|---|
| 334 | end;
|
|---|
| 335 |
|
|---|
| 336 | function TConstants.GetByName(Name: string): PConstant;
|
|---|
| 337 | var
|
|---|
| 338 | I: Integer;
|
|---|
| 339 | begin
|
|---|
| 340 | I := 0;
|
|---|
| 341 | while (I < Length(Items)) and (Items[I].Name <> Name) do I := I + 1;
|
|---|
| 342 | if I < Length(Items) then Result := @Items[I]
|
|---|
| 343 | else Result := nil;
|
|---|
| 344 | end;
|
|---|
| 345 |
|
|---|
| 346 | { TVariables }
|
|---|
| 347 |
|
|---|
| 348 | procedure TVariables.Add(Variable: TVariable);
|
|---|
| 349 | begin
|
|---|
| 350 | SetLength(Items, Length(Items) + 1);
|
|---|
| 351 | Items[Length(Items) - 1] := Variable;
|
|---|
| 352 | Items[Length(Items) - 1].Index := Length(Items) - 1;
|
|---|
| 353 | end;
|
|---|
| 354 |
|
|---|
| 355 | function TVariables.GetByName(Name: string): PVariable;
|
|---|
| 356 | var
|
|---|
| 357 | I: Integer;
|
|---|
| 358 | begin
|
|---|
| 359 | I := 0;
|
|---|
| 360 | while (I < Length(Items)) and (Items[I].Name <> Name) do I := I + 1;
|
|---|
| 361 | if I < Length(Items) then Result := @Items[I]
|
|---|
| 362 | else begin
|
|---|
| 363 | if ParentList <> nil then Result := ParentList^.GetByName(Name)
|
|---|
| 364 | else Result := nil;
|
|---|
| 365 | end;
|
|---|
| 366 | end;
|
|---|
| 367 |
|
|---|
| 368 | function TVariables.GetLast: PVariable;
|
|---|
| 369 | begin
|
|---|
| 370 | Result := @Items[Length(Items) - 1];
|
|---|
| 371 | end;
|
|---|
| 372 |
|
|---|
| 373 | { TFunctionParameters }
|
|---|
| 374 |
|
|---|
| 375 | procedure TFunctionParameters.Add(Param: TFunctionParameter);
|
|---|
| 376 | begin
|
|---|
| 377 | SetLength(Items, Length(Items) + 1);
|
|---|
| 378 | Items[Length(Items) - 1] := Param;
|
|---|
| 379 | end;
|
|---|
| 380 |
|
|---|
| 381 | { TTypes }
|
|---|
| 382 |
|
|---|
| 383 | procedure TTypes.Add(DataType: TType);
|
|---|
| 384 | begin
|
|---|
| 385 | SetLength(Items, Length(Items) + 1);
|
|---|
| 386 | Items[Length(Items) - 1] := DataType;
|
|---|
| 387 | end;
|
|---|
| 388 |
|
|---|
| 389 | function TTypes.GetByName(Name: string): PType;
|
|---|
| 390 | var
|
|---|
| 391 | I: Integer;
|
|---|
| 392 | begin
|
|---|
| 393 | I := 0;
|
|---|
| 394 | while (I < Length(Items)) and (Items[I].Name <> Name) do I := I + 1;
|
|---|
| 395 | if I < Length(Items) then Result := @Items[I]
|
|---|
| 396 | else begin
|
|---|
| 397 | if ParentList <> nil then Result := ParentList^.GetByName(Name)
|
|---|
| 398 | else Result := nil;
|
|---|
| 399 | end;
|
|---|
| 400 | end;
|
|---|
| 401 |
|
|---|
| 402 | function TTypes.GetLast: PType;
|
|---|
| 403 | begin
|
|---|
| 404 | Result := @Items[Length(Items) - 1];
|
|---|
| 405 | end;
|
|---|
| 406 |
|
|---|
| 407 | { TFunctions }
|
|---|
| 408 |
|
|---|
| 409 | procedure TFunctions.Add(Func: TFunction);
|
|---|
| 410 | begin
|
|---|
| 411 | SetLength(Items, Length(Items) + 1);
|
|---|
| 412 | Items[Length(Items) - 1] := Func;
|
|---|
| 413 | end;
|
|---|
| 414 |
|
|---|
| 415 | function TFunctions.GetByName(Name: string): PFunction;
|
|---|
| 416 | var
|
|---|
| 417 | I: Integer;
|
|---|
| 418 | begin
|
|---|
| 419 | I := 0;
|
|---|
| 420 | while (I < Length(Items)) and (Items[I].Name <> Name) do I := I + 1;
|
|---|
| 421 | if I < Length(Items) then Result := @Items[I]
|
|---|
| 422 | else Result := nil;
|
|---|
| 423 | end;
|
|---|
| 424 |
|
|---|
| 425 | function TFunctions.GetLast: PFunction;
|
|---|
| 426 | begin
|
|---|
| 427 | Result := @Items[Length(Items) - 1];
|
|---|
| 428 | end;
|
|---|
| 429 |
|
|---|
| 430 | end.
|
|---|
| 431 |
|
|---|