unit uengShaderPart; {$mode objfpc}{$H+} {$I uengShaderFile.inc} interface uses Classes, SysUtils, uengShaderFileParser, uengShaderFileTypes {$IFDEF USE_BITSPACE_UTILS} , uutlGenerics; {$ELSE} , fgl; {$ENDIF} type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderFileSearchFlag = ( sfFirstOnly, // search first match only sfEvaluateIf, // evaluate if statements before search and process with suitable subtree sfSearchChildren, // search in children sfSearchParents, // search in parents sfCurrentFileOnly // do not search in other files ); TengShaderFileSearchFlags = set of TengShaderFileSearchFlag; TengShaderPart = class; CengShaderPart = class of TengShaderPart; TengShaderPartList = specialize TutlSimpleList; TengShaderPart = class(TIntfObjNoRefCount) { Nested Types } public type TEnumerator = class(TObject) private fOwner: TengShaderPart; fPosition: Integer; function GetCurrent: TengShaderPart; public property Current: TengShaderPart read GetCurrent; function MoveNext: Boolean; constructor Create(const aOwner: TengShaderPart); end; TSearchList = class(TengShaderPartList) public constructor Create; end; { Code Loading & Storage } private { members } fRoot: TengShaderPart; fParent: TengShaderPart; fLine: Integer; fCol: Integer; protected { virtual getter } function GetCount: Integer; virtual; function GetChild(const aIndex: Integer): TengShaderPart; virtual; function GetText: String; virtual; function GetFilename: String; virtual; function GetFileReader: IengShaderFileReader; virtual; function GetFileWriter: IengShaderFileWriter; virtual; protected { parse methodes } function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; virtual; public function ParseText(const aArgs: TengParseArgs): String; { General } protected procedure FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList); virtual; public { general methods } property Root: TengShaderPart read fRoot; property Parent: TengShaderPart read fParent; property Line: Integer read fLine; property Col: Integer read fCol; property Filename: String read GetFilename; property Text: String read GetText; property Count: Integer read GetCount; property FileReader: IengShaderFileReader read GetFileReader; property FileWriter: IengShaderFileWriter read GetFileWriter; property Children[const aIndex: Integer]: TengShaderPart read GetChild; default; function HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean = false): Boolean; function GetParent(const aType: CengShaderPart; out aPart): Boolean; function FindFirst(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart): TengShaderPart; procedure FindAll(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart; const aList: TSearchList); function GetEnumerator: TEnumerator; constructor Create(const aParent: TengShaderPart); virtual; { Class Methods } public class function GetTokenName: String; virtual; class function CheckToken(const aToken: String): Boolean; virtual; class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); virtual; end; implementation uses uengShaderFileConstants; function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean; var c: CengShaderPart; begin result := true; if (Length(aTypes) = 0) then exit; for c in aTypes do if (aShaderPart is c) then exit; result := false; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPart.TEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.TEnumerator.GetCurrent: TengShaderPart; begin result := fOwner[fPosition]; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.TEnumerator.MoveNext: Boolean; begin inc(fPosition); result := (fPosition < fOwner.Count); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderPart.TEnumerator.Create(const aOwner: TengShaderPart); begin inherited Create; fOwner := aOwner; fPosition := -1; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPart.TSearchList//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderPart.TSearchList.Create; begin inherited Create(false); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPart//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.GetCount: Integer; begin result := 0; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.{%H-}GetChild(const aIndex: Integer): TengShaderPart; begin EengShaderPartInternal.Create('this part does not have any children'); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.GetText: String; begin result := ''; //DUMMY end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.GetFilename: String; begin if Assigned(fParent) then result := fParent.Filename else result := UNKNOWN_FILENAME; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.GetFileReader: IengShaderFileReader; begin if Assigned(fParent) then result := fParent.GetFileReader else result := nil; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.GetFileWriter: IengShaderFileWriter; begin if Assigned(fParent) then result := fParent.GetFileWriter else result := nil; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.ParseText(const aArgs: TengParseArgs): String; var params: TengTokenParameterList; begin params := TengTokenParameterList.Create(Filename); try fCol := aArgs.Col; fLine := aArgs.Line; if (GetTokenName <> '') then aArgs.ExtractToken(params); result := ParseIntern(aArgs, params); finally FreeAndNil(params); end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderPart.FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList); var c: TengShaderPart; begin if (sfFirstOnly in aFlags) and (aList.Count > 0) then exit; if CheckType(self, aTypes) then aList.Add(self); if (sfSearchChildren in aFlags) then begin for c in self do c.FindIntern(aFlags, aDepth+1, aTypes, aList); end; if (sfSearchParents in aFlags) and Assigned(Parent) then Parent.FindIntern(aFlags, aDepth-1, aTypes, aList); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; begin result := ''; // DUMMY end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean): Boolean; var p: TengShaderPart; begin result := (aIncludeSelf and (self is aType)) or GetParent(aType, p); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.GetParent(const aType: CengShaderPart; out aPart): Boolean; begin result := true; if (fParent is aType) then TengShaderPart(aPart) := fParent else if Assigned(fParent) then result := fParent.GetParent(aType, aPart) else result := false; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.FindFirst(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart): TengShaderPart; var l: TSearchList; begin l := TSearchList.Create; try FindIntern(aFlags + [sfFirstOnly], 0, aTypes, l); if (l.Count > 0) then result := l[0] else result := nil; finally FreeAndNil(l); end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderPart.FindAll(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart; const aList: TSearchList); begin FindIntern(aFlags, 0, aTypes, aList); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.GetEnumerator: TEnumerator; begin result := TEnumerator.Create(self); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderPart.Create(const aParent: TengShaderPart); begin inherited Create; fParent := aParent; if Assigned(fParent) then fRoot := fParent.Root else fRoot := nil; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPart.GetTokenName: String; begin result := ''; // DUMMY end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPart.CheckToken(const aToken: String): Boolean; begin result := (aToken = GetTokenName); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class procedure TengShaderPart.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); begin // DUMMY end; end.