You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

302 lines
12 KiB

  1. unit uengShaderPart;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils,
  7. uengShaderFileParser, uengShaderFileTypes
  8. {$IFDEF SHADER_FILE_USE_BITSPACE_UTILS}
  9. , uutlGenerics
  10. {$ELSE}
  11. , uengShaderFileGenerics
  12. {$ENDIF}
  13. ;
  14. type
  15. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. TengShaderPart = class;
  17. CengShaderPart = class of TengShaderPart;
  18. CengShaderPartArr = array of CengShaderPart;
  19. TengShaderPartList = specialize TutlSimpleList<TengShaderPart>;
  20. TengShaderPartWalker = class(TObject)
  21. protected
  22. procedure Visit(const aPart, aCaller: TengShaderPart; const aArgs: Pointer); virtual;
  23. public
  24. procedure Run(const aPart: TengShaderPart);
  25. end;
  26. TengShaderPart = class(TIntfObjNoRefCount)
  27. { Nested Types }
  28. public type
  29. TEnumerator = class(TObject)
  30. private
  31. fOwner: TengShaderPart;
  32. fPosition: Integer;
  33. fReverse: Boolean;
  34. function GetCurrent: TengShaderPart;
  35. public
  36. property Current: TengShaderPart read GetCurrent;
  37. function GetEnumerator: TEnumerator;
  38. function MoveNext: Boolean;
  39. constructor Create(const aOwner: TengShaderPart; const aReverse: Boolean = false);
  40. end;
  41. { Code Loading & Storage }
  42. protected { members }
  43. fRoot: TengShaderPart;
  44. fParent: TengShaderPart;
  45. fLine: Integer;
  46. fCol: Integer;
  47. protected { virtual getter }
  48. function GetCount: Integer; virtual;
  49. function GetChild(const aIndex: Integer): TengShaderPart; virtual;
  50. function GetText: String; virtual;
  51. function GetFilename: String; virtual;
  52. function GetFileReader: IengShaderFileReader; virtual;
  53. function GetFileWriter: IengShaderFileWriter; virtual;
  54. { General }
  55. protected
  56. procedure LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); virtual;
  57. public { general methods }
  58. property Root: TengShaderPart read fRoot;
  59. property Parent: TengShaderPart read fParent;
  60. property Line: Integer read fLine;
  61. property Col: Integer read fCol;
  62. property Filename: String read GetFilename;
  63. property Text: String read GetText;
  64. property Count: Integer read GetCount;
  65. property FileReader: IengShaderFileReader read GetFileReader;
  66. property FileWriter: IengShaderFileWriter read GetFileWriter;
  67. property Children[const aIndex: Integer]: TengShaderPart read GetChild; default;
  68. function HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean = false): Boolean;
  69. function GetParent(const aType: CengShaderPart; out aPart): Boolean;
  70. function GetParent(const aType: CengShaderPart): TengShaderPart;
  71. procedure PrintTrace(const aPrefix: String; const aLines: TStrings);
  72. procedure LogMsg(const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  73. function GetEnumerator: TEnumerator;
  74. function GetReverseEnumerator: TEnumerator;
  75. constructor Create(const aParent: TengShaderPart); virtual;
  76. { Class Methods }
  77. public
  78. class function GetTokenName: String; virtual;
  79. class function CheckToken(const aToken: String): Boolean; virtual;
  80. class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); virtual;
  81. end;
  82. implementation
  83. uses
  84. uengShaderFileConstants;
  85. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  86. //TengShaderPart.TEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  87. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  88. function TengShaderPart.TEnumerator.GetCurrent: TengShaderPart;
  89. begin
  90. result := fOwner[fPosition];
  91. end;
  92. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  93. function TengShaderPart.TEnumerator.GetEnumerator: TEnumerator;
  94. begin
  95. result := self;
  96. end;
  97. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  98. function TengShaderPart.TEnumerator.MoveNext: Boolean;
  99. begin
  100. if not fReverse
  101. then inc(fPosition)
  102. else dec(fPosition);
  103. result := (0 <= fPosition) and (fPosition < fOwner.Count);
  104. end;
  105. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  106. constructor TengShaderPart.TEnumerator.Create(const aOwner: TengShaderPart; const aReverse: Boolean);
  107. begin
  108. inherited Create;
  109. fOwner := aOwner;
  110. fReverse := aReverse;
  111. if not fReverse
  112. then fPosition := -1
  113. else fPosition := aOwner.Count;
  114. end;
  115. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  116. //TengShaderPartWalker//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  117. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  118. procedure TengShaderPartWalker.Visit(const aPart, aCaller: TengShaderPart; const aArgs: Pointer);
  119. begin
  120. // DUMMY
  121. end;
  122. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  123. procedure TengShaderPartWalker.Run(const aPart: TengShaderPart);
  124. begin
  125. Visit(aPart, nil, nil);
  126. end;
  127. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  128. //TengShaderPart////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  129. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  130. function TengShaderPart.GetCount: Integer;
  131. begin
  132. result := 0;
  133. end;
  134. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  135. function TengShaderPart.{%H-}GetChild(const aIndex: Integer): TengShaderPart;
  136. begin
  137. result := nil;
  138. EengShaderPartInternal.Create('this part does not have any children');
  139. end;
  140. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  141. function TengShaderPart.GetText: String;
  142. begin
  143. result := ''; //DUMMY
  144. end;
  145. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  146. function TengShaderPart.GetFilename: String;
  147. begin
  148. if Assigned(fParent)
  149. then result := fParent.Filename
  150. else result := UNKNOWN_FILENAME;
  151. end;
  152. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  153. function TengShaderPart.GetFileReader: IengShaderFileReader;
  154. begin
  155. if Assigned(fParent)
  156. then result := fParent.GetFileReader
  157. else result := nil;
  158. end;
  159. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  160. function TengShaderPart.GetFileWriter: IengShaderFileWriter;
  161. begin
  162. if Assigned(fParent)
  163. then result := fParent.GetFileWriter
  164. else result := nil;
  165. end;
  166. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  167. procedure TengShaderPart.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  168. begin
  169. if Assigned(Parent) then
  170. Parent.LogMsgIntern(aSender, aLogLevel, aMsg);
  171. end;
  172. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  173. function TengShaderPart.HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean): Boolean;
  174. var
  175. p: TengShaderPart;
  176. begin
  177. result := (aIncludeSelf and (self is aType)) or GetParent(aType, p);
  178. end;
  179. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  180. function TengShaderPart.GetParent(const aType: CengShaderPart; out aPart): Boolean;
  181. begin
  182. result := true;
  183. TengShaderPart(aPart) := nil;
  184. if (fParent is aType) then
  185. TengShaderPart(aPart) := fParent
  186. else if Assigned(fParent) then
  187. result := fParent.GetParent(aType, aPart)
  188. else
  189. result := false;
  190. end;
  191. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  192. function TengShaderPart.GetParent(const aType: CengShaderPart): TengShaderPart;
  193. begin
  194. if not GetParent(aType, result) then
  195. raise EengShaderPartInternal.Create(GetTokenName + ' has no parent of type ' + aType.GetTokenName, self);
  196. end;
  197. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  198. procedure TengShaderPart.PrintTrace(const aPrefix: String; const aLines: TStrings);
  199. function GetName(const aPart: TengShaderPart): String;
  200. begin
  201. result := aPart.GetTokenName;
  202. if (result = '')
  203. then result := aPart.ClassName
  204. else result := result + ' (' + aPart.ClassName + ')';
  205. end;
  206. var
  207. p: TengShaderPart;
  208. begin
  209. p := self;
  210. while Assigned(p) do begin
  211. aLines.Add(Format('%s%s (%d:%d): %s', [aPrefix, p.Filename, p.Line+1, p.Col, GetName(p)]));
  212. p := p.Parent;
  213. end;
  214. end;
  215. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  216. procedure TengShaderPart.LogMsg(const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  217. begin
  218. LogMsgIntern(self, aLogLevel, aMsg);
  219. end;
  220. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  221. function TengShaderPart.GetEnumerator: TEnumerator;
  222. begin
  223. result := TEnumerator.Create(self);
  224. end;
  225. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  226. function TengShaderPart.GetReverseEnumerator: TEnumerator;
  227. begin
  228. result := TEnumerator.Create(self, true);
  229. end;
  230. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  231. constructor TengShaderPart.Create(const aParent: TengShaderPart);
  232. begin
  233. inherited Create;
  234. fParent := aParent;
  235. if Assigned(fParent)
  236. then fRoot := fParent.Root
  237. else fRoot := nil;
  238. end;
  239. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  240. class function TengShaderPart.GetTokenName: String;
  241. begin
  242. result := ''; // DUMMY
  243. end;
  244. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  245. class function TengShaderPart.CheckToken(const aToken: String): Boolean;
  246. begin
  247. result := (aToken = GetTokenName);
  248. end;
  249. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  250. class procedure TengShaderPart.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);
  251. begin
  252. // DUMMY
  253. end;
  254. end.