Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

217 рядки
8.8 KiB

  1. unit uengShaderPartIf;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils,
  7. uengShaderPart, uengShaderCodePart, uengShaderPartScope, uengShaderFileExpression,
  8. uengShaderFileParser, uengShaderGeneratorArgs;
  9. type
  10. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  11. TengShaderPartIfCntr = class(TengShaderPartScope)
  12. { Class Methods }
  13. public
  14. class function GetTokenName: String; override;
  15. end;
  16. TengShaderPartIf = class(TengShaderPartIfCntr)
  17. { Code Loading & Storage }
  18. private
  19. fExpression: TengExpressionItem;
  20. fIfPart: TengShaderPartScope;
  21. fElsePart: TengShaderPartScope;
  22. function HandleToken(const aToken: String; const aArgs: TengParseArgs): String;
  23. protected
  24. function HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; virtual;
  25. function GetCount: Integer; override;
  26. function GetChild(const aIndex: Integer): TengShaderPart; override;
  27. function GetText: String; override;
  28. function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;
  29. { Code Generation }
  30. public
  31. procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override;
  32. { General }
  33. public
  34. property Expression: TengExpressionItem read fExpression;
  35. property IfPart: TengShaderPartScope read fIfPart;
  36. property ElsePart: TengShaderPartScope read fElsePart;
  37. destructor Destroy; override;
  38. end;
  39. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  40. TengShaderPartElIf = class(TengShaderPartIf)
  41. { Code Loading & Storage }
  42. protected
  43. function HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; override;
  44. { Class Methods }
  45. public
  46. class function GetTokenName: String; override;
  47. end;
  48. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  49. TengShaderPartElse = class(TengShaderPartScope)
  50. { Code Loading & Storage }
  51. protected
  52. function GetText: String; override;
  53. { Class Methods }
  54. public
  55. class function GetTokenName: String; override;
  56. end;
  57. implementation
  58. uses
  59. uengShaderFileTypes, uengShaderFileConstants, uengShaderFileHelper;
  60. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  61. //TengShaderPartIfCntr//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  62. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  63. class function TengShaderPartIfCntr.GetTokenName: String;
  64. begin
  65. result := TOKEN_IF;
  66. end;
  67. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  68. //TengShaderPartIf//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  69. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  70. function TengShaderPartIf.HandleToken(const aToken: String; const aArgs: TengParseArgs): String;
  71. type
  72. CengShaderPartScope = class of TengShaderPartScope;
  73. const
  74. TOKEN_CLASSES: array[0..1] of CengShaderPartScope = (
  75. TengShaderPartElse,
  76. TengShaderPartElIf
  77. );
  78. var
  79. c: CengShaderPartScope;
  80. begin
  81. for c in TOKEN_CLASSES do begin
  82. if c.CheckToken(aToken) then begin
  83. c.Validate(aArgs, self);
  84. fElsePart := c.Create(self);
  85. break;
  86. end;
  87. end;
  88. result := aToken;
  89. if Assigned(fElsePart) then
  90. result := fElsePart.ParseText(aArgs);
  91. result := HandeEndToken(result, aArgs);
  92. end;
  93. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  94. function TengShaderPartIf.HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String;
  95. begin
  96. result := CheckEndToken(aToken, aArgs, self);
  97. end;
  98. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  99. function TengShaderPartIf.GetCount: Integer;
  100. begin
  101. result := 1;
  102. if Assigned(fElsePart) then
  103. inc(result, 1);
  104. end;
  105. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  106. function TengShaderPartIf.GetChild(const aIndex: Integer): TengShaderPart;
  107. begin
  108. if (aIndex < 0) or (aIndex >= Count) then
  109. raise EengOutOfRange.Create(0, Count-1, aIndex, self);
  110. case aIndex of
  111. 0: result := fIfPart;
  112. 1: result := fElsePart;
  113. end;
  114. end;
  115. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  116. function TengShaderPartIf.GetText: String;
  117. begin
  118. result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fExpression.Text + TOKEN_CHAR_END + fIfPart.Text;
  119. if Assigned(fElsePart) then
  120. result := result + fElsePart.Text;
  121. result := result + TOKEN_CHAR_BEGIN + TOKEN_END + TOKEN_CHAR_END;
  122. end;
  123. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  124. function TengShaderPartIf.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
  125. begin
  126. if (aParams[0].Name <> GetTokenName) then with aParams[0] do
  127. raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
  128. if (aParams.Count < 2) then
  129. raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self);
  130. fExpression := ParseExpression(self, aParams, 1);
  131. fIfPart := TengShaderPartIfCntr.Create(self);
  132. result := fIfPart.ParseText(aArgs);
  133. result := HandleToken(result, aArgs);
  134. end;
  135. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  136. procedure TengShaderPartIf.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
  137. var
  138. b: Boolean;
  139. p: TengShaderCodePart;
  140. begin
  141. b := fExpression.GetValue;
  142. if b
  143. then p := fIfPart
  144. else p := fElsePart;
  145. if Assigned(p) then begin
  146. p.GenerateCodeIntern(aArgs);
  147. aArgs.AppendToPrevLine;
  148. end else
  149. aArgs.AddToken(GetTokenName);
  150. end;
  151. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  152. destructor TengShaderPartIf.Destroy;
  153. begin
  154. FreeAndNil(fExpression);
  155. FreeAndNil(fIfPart);
  156. FreeAndNil(fElsePart);
  157. inherited Destroy;
  158. end;
  159. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  160. //TengShaderPartElIf////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  161. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  162. function TengShaderPartElIf.HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String;
  163. begin
  164. result := aToken;
  165. if (result <> TOKEN_END) then
  166. raise EengUnexpectedToken.Create(aToken, TOKEN_END, aArgs.Col, aArgs.Line, Filename, self);
  167. end;
  168. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169. class function TengShaderPartElIf.GetTokenName: String;
  170. begin
  171. result := TOKEN_ELIF;
  172. end;
  173. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  174. //TengShaderPartElse////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  175. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  176. function TengShaderPartElse.GetText: String;
  177. begin
  178. result := TOKEN_CHAR_BEGIN + GetTokenName + TOKEN_CHAR_END + inherited GetText;
  179. end;
  180. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. class function TengShaderPartElse.GetTokenName: String;
  182. begin
  183. result := TOKEN_ELSE;
  184. end;
  185. end.