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.

244 lines
8.4 KiB

  1. unit uengShaderPartClass;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils,
  7. uengShaderPart, uengShaderGenerator, uengShaderGeneratorArgs, uengShaderFileParser
  8. {$IFDEF SHADER_FILE_USE_BITSPACE_UTILS}
  9. , uutlGenerics
  10. {$ENDIF}
  11. ;
  12. type
  13. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14. TengShaderPartClass = class;
  15. TengShaderPartClassList = specialize TutlSimpleList<TengShaderPartClass>;
  16. TengShaderPartClass = class(TengShaderGenerator)
  17. { Code Loading & Storage }
  18. private { member }
  19. fName: String;
  20. fExtends: TStringList;
  21. fInherited: TengShaderPartClassList;
  22. private { getter }
  23. function GetExtends: TStrings;
  24. procedure UpdateInherited;
  25. protected { virtual getter }
  26. function GetText: String; override;
  27. function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;
  28. procedure UpdateProperties; override;
  29. { Code Generation }
  30. public
  31. procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override;
  32. { General }
  33. public
  34. property Name: String read fName;
  35. property Extends: TStrings read GetExtends;
  36. property InheritedClasses: TengShaderPartClassList read fInherited;
  37. constructor Create(const aParent: TengShaderPart); override;
  38. destructor Destroy; override;
  39. { Class Methods }
  40. public
  41. class function GetTokenName: String; override;
  42. class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); override;
  43. end;
  44. TengShaderPartClassMap = specialize TutlMap<string, TengShaderPartClass>;
  45. implementation
  46. uses
  47. uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartKeyValuePair,
  48. uengShaderPartScope, uengShaderFile;
  49. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  50. //TengShaderPartClass///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  51. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  52. function TengShaderPartClass.GetExtends: TStrings;
  53. begin
  54. result := fExtends;
  55. end;
  56. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  57. procedure TengShaderPartClass.UpdateInherited;
  58. procedure FilterResults(const aName: String; const aResults, aNewResults: TengShaderPartList);
  59. var
  60. p: TengShaderPart;
  61. begin
  62. aNewResults.Clear;
  63. for p in aResults do
  64. if ((p as TengShaderPartClass).Name = aName) then
  65. aNewResults.Add(p);
  66. end;
  67. var
  68. sr, res: TengSearchResults;
  69. walker: TengSearchWalker;
  70. s: String;
  71. begin
  72. if (fExtends.Count <= 0) then
  73. exit;
  74. sr := TengSearchResults.Create;
  75. res := TengSearchResults.Create;
  76. walker := TengSearchWalker.Create(sr);
  77. try
  78. walker.Owner := self;
  79. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartClass);
  80. walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope);
  81. walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
  82. walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile);
  83. walker.SearchFlags := [
  84. sfIgnoreOwner,
  85. sfSearchChildrenLazy,
  86. sfSearchChildren,
  87. sfSearchParents
  88. ];
  89. fInherited.Clear;
  90. walker.Run(self);
  91. for s in fExtends do begin
  92. FilterResults(s, sr, res);
  93. fInherited.Add(ExtractSearchResult(self, s, res) as TengShaderPartClass);
  94. end;
  95. finally
  96. FreeAndNil(walker);
  97. FreeAndNil(res);
  98. FreeAndNil(sr);
  99. end;
  100. end;
  101. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  102. function TengShaderPartClass.GetText: String;
  103. var
  104. s: String;
  105. begin
  106. result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fName;
  107. if (fExtends.Count > 0) then begin
  108. result := result + ' ' + TOKEN_EXTENDS;
  109. for s in fExtends do
  110. result := result + ' ' + s;
  111. end;
  112. result := result + TOKEN_CHAR_END +
  113. inherited GetText +
  114. TOKEN_CHAR_BEGIN + TOKEN_END + TOKEN_CHAR_END;
  115. end;
  116. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  117. function TengShaderPartClass.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
  118. var
  119. i: Integer;
  120. begin
  121. if (aParams[0].Name <> GetTokenName) then with aParams[0] do
  122. raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
  123. if (aParams.Count < 2) then
  124. raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self);
  125. with aParams[1] do begin
  126. if not IsValidIdentifier(Name) then
  127. raise EengInvalidIdentifier.Create(Name, self);
  128. fName := Name;
  129. end;
  130. if (aParams.Count > 2) then begin
  131. if (aParams.Count < 4) then
  132. raise EengInvalidParamterCount.Create(GetTokenName, 4, -1, self);
  133. if (aParams[2].Name <> TOKEN_EXTENDS) then with aParams[2] do
  134. raise EengInvalidParamter.Create(aParams[2].Name, TOKEN_EXTENDS, Line, Col, Filename, self);
  135. fExtends.Clear;
  136. for i := 3 to aParams.Count-1 do
  137. fExtends.Add(aParams[i].Name);
  138. end;
  139. UpdateInherited;
  140. result := inherited ParseIntern(aArgs, aParams);
  141. result := CheckEndToken(result, aArgs, self);
  142. end;
  143. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  144. procedure TengShaderPartClass.UpdateProperties;
  145. var
  146. sr: TengSearchResults;
  147. walker: TengSearchWalker;
  148. p: TengShaderPart;
  149. c: TengShaderPartClass;
  150. begin
  151. inherited UpdateProperties;
  152. for c in fInherited do
  153. c.CopyProperties(self);
  154. sr := TengSearchResults.Create;
  155. walker := TengSearchWalker.Create(sr);
  156. try
  157. walker.SearchFlags := [sfSearchChildren];
  158. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty);
  159. walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass);
  160. walker.Run(self);
  161. for p in sr.GetReverseEnumerator do
  162. AddProperty(p as TengShaderPartProperty);
  163. finally
  164. FreeAndNil(walker);
  165. FreeAndNil(sr);
  166. end;
  167. end;
  168. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169. procedure TengShaderPartClass.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
  170. var
  171. c: TengShaderPartClass;
  172. begin
  173. for c in fInherited do
  174. c.GenerateCodeIntern(aArgs);
  175. aArgs.BeginBlock;
  176. try
  177. inherited GenerateCodeIntern(aArgs);
  178. finally
  179. aArgs.EndBlock;
  180. end;
  181. end;
  182. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. constructor TengShaderPartClass.Create(const aParent: TengShaderPart);
  184. begin
  185. inherited Create(aParent);
  186. fExtends := TStringList.Create;
  187. fInherited := TengShaderPartClassList.Create(false);
  188. end;
  189. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  190. destructor TengShaderPartClass.Destroy;
  191. begin
  192. FreeAndNil(fInherited);
  193. FreeAndNil(fExtends);
  194. inherited Destroy;
  195. end;
  196. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. class function TengShaderPartClass.GetTokenName: String;
  198. begin
  199. result := TOKEN_CLASS;
  200. end;
  201. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  202. class procedure TengShaderPartClass.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);
  203. procedure RaiseEx(const aToken: String);
  204. begin
  205. with aArgs do
  206. raise EengShaderPart.Create('token ' + GetTokenName + ' is not allowed in ' + aToken, Line, Col, Filename, aParent);
  207. end;
  208. begin
  209. inherited Validate(aArgs, aParent);
  210. if aParent.HasParent(TengShaderPartClass, true) then
  211. RaiseEx(TengShaderPartClass.GetTokenName);
  212. end;
  213. end.