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.

771 lines
32 KiB

  1. unit uengShaderFileExpression;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils, variants,
  7. uengShaderPart, uengShaderFileParser, uengShaderPartKeyValuePair;
  8. type
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. TengExpressionItem = class(TengShaderPart)
  11. public
  12. function GetValue: Variant; virtual;
  13. constructor Create(const aLine, aCol: Integer); reintroduce;
  14. end;
  15. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. TengExpressionValue = class(TengExpressionItem)
  17. private
  18. fValue: Variant;
  19. public
  20. property Value: Variant read fValue;
  21. function GetText: String; override;
  22. function GetValue: Variant; override;
  23. constructor Create(const aValue: Variant; const aLine, aCol: Integer);
  24. end;
  25. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  26. TengExpressionVariable = class(TengExpressionItem)
  27. private
  28. fName: String;
  29. fPart: TengShaderPartKeyValuePair;
  30. public
  31. property Name: String read fName;
  32. property Part: TengShaderPartKeyValuePair read fPart;
  33. function GetText: String; override;
  34. function GetValue: Variant; override;
  35. constructor Create(const aName: String; const aPart: TengShaderPartKeyValuePair; const aLine, aCol: Integer);
  36. end;
  37. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  38. TengExpressionGroup = class(TengExpressionItem)
  39. private
  40. fChild: TengExpressionItem;
  41. protected
  42. function GetCount: Integer; override;
  43. function GetChild(const aIndex: Integer): TengShaderPart; override;
  44. public
  45. property Child: TengExpressionItem read fChild;
  46. function GetText: String; override;
  47. function GetValue: Variant; override;
  48. constructor Create(const aChild: TengExpressionItem; const aLine, aCol: Integer);
  49. destructor Destroy; override;
  50. end;
  51. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  52. TengExpressionOperation = class(TengExpressionItem)
  53. protected
  54. function GetWeight: Integer; virtual;
  55. public
  56. property Weight: Integer read GetWeight;
  57. function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; virtual;
  58. function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; virtual;
  59. end;
  60. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  61. TengExpressionUnaryOperator = (
  62. opBinaryNot,
  63. opLogicalNot
  64. );
  65. TengExpressionUnaryOperation = class(TengExpressionOperation)
  66. private
  67. fChild: TengExpressionItem;
  68. fUnaryOp: TengExpressionUnaryOperator;
  69. protected
  70. function GetWeight: Integer; override;
  71. function GetCount: Integer; override;
  72. function GetChild(const aIndex: Integer): TengShaderPart; override;
  73. public
  74. property Child: TengExpressionItem read fChild;
  75. property UnaryOp: TengExpressionUnaryOperator read fUnaryOp;
  76. function GetText: String; override;
  77. function GetValue: Variant; override;
  78. function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; override;
  79. function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; override;
  80. constructor Create(const aUnaryOp: TengExpressionUnaryOperator; const aChild: TengExpressionItem; const aLine, aCol: Integer);
  81. destructor Destroy; override;
  82. end;
  83. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  84. TengExpressionBinaryOperator = ( //order of elements in this enum is also the weight of the operators
  85. opBinaryOr, opBinaryAnd, opBinaryXor, // binary
  86. opMultiply, opDivide, opAdd, opSubtract, // arithmetic
  87. opLogicalOr, opLogicalAnd, opLogicalXor, // logical
  88. opEquals, opLesser, opGreater, opLEquals, opGEquals, opUnequals // comparison
  89. );
  90. TengExpressionBinaryOperation = class(TengExpressionOperation)
  91. private
  92. fFirst: TengExpressionItem;
  93. fSecond: TengExpressionItem;
  94. fBinaryOp: TengExpressionBinaryOperator;
  95. protected
  96. function GetWeight: Integer; override;
  97. function GetCount: Integer; override;
  98. function GetChild(const aIndex: Integer): TengShaderPart; override;
  99. public
  100. property First: TengExpressionItem read fFirst write fFirst;
  101. property Second: TengExpressionItem read fSecond write fSecond;
  102. property BinaryOp: TengExpressionBinaryOperator read fBinaryOp;
  103. function GetText: String; override;
  104. function GetValue: Variant; override;
  105. function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; override;
  106. function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; override;
  107. constructor Create(const aOperator: TengExpressionBinaryOperator; const aFirst, aSecond: TengExpressionItem; const aLine, aCol: Integer);
  108. destructor Destroy; override;
  109. end;
  110. function ParseExpression(const aParent: TengShaderPart; const aParams: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
  111. implementation
  112. uses
  113. uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartScope, uengShaderFile;
  114. const
  115. EXPRESSION_UNARY_OPERATIONS: array[TengExpressionUnaryOperator] of String = (
  116. TOKEN_OP_BINARY_NOT, //opBinaryNot
  117. TOKEN_OP_LOGICAL_NOT //opLogicalNot
  118. );
  119. EXPRESSION_BINARY_OPERATIONS: array[TengExpressionBinaryOperator] of String = (
  120. TOKEN_OP_BINARY_OR, //opBinaryOr
  121. TOKEN_OP_BINARY_AND, //opBinaryAnd
  122. TOKEN_OP_BINARY_XOR, //opBinaryXor
  123. TOKEN_OP_MULTIPLY, //opMultiply
  124. TOKEN_OP_DIVIDE, //opDivide
  125. TOKEN_OP_ADD, //opAdd
  126. TOKEN_OP_SUBTRACT, //opSubtract
  127. TOKEN_OP_LOGICAL_OR, //opLogicalOr
  128. TOKEN_OP_LOGICAL_AND, //opLogicalAnd
  129. TOKEN_OP_LOGICAL_XOR, //opLogicalXor
  130. TOKEN_OP_EQUALS, //opEquals
  131. TOKEN_OP_LESSER, //opLesser
  132. TOKEN_OP_GREATER, //opGreater
  133. TOKEN_OP_LEQUALS, //opLEquals
  134. TOKEN_OP_GEQUALS, //opGEquals
  135. TOKEN_OP_UNEQUALS //opUnequals
  136. );
  137. UNARY_OPERATION_WEIGHTS: array[TengExpressionUnaryOperator] of Integer = (
  138. 00, //opBinaryNot
  139. 00 //opLogicalNot
  140. );
  141. BINARY_OPERATION_WEIGHTS: array[TengExpressionBinaryOperator] of Integer = (
  142. 01, //opBinaryOr
  143. 02, //opBinaryAnd
  144. 03, //opBinaryXor
  145. 04, //opMultiply
  146. 05, //opDivide
  147. 06, //opAdd
  148. 07, //opSubtract
  149. 14, //opLogicalOr
  150. 15, //opLogicalAnd
  151. 16, //opLogicalXor
  152. 08, //opEquals
  153. 09, //opLesser
  154. 10, //opGreater
  155. 11, //opLEquals
  156. 12, //opGEquals
  157. 13 //opUnequals
  158. );
  159. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  160. //TengExpressionItem////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  161. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  162. function TengExpressionItem.GetValue: Variant;
  163. begin
  164. result := Unassigned; // DUMMY
  165. end;
  166. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  167. constructor TengExpressionItem.Create(const aLine, aCol: Integer);
  168. begin
  169. inherited Create(nil);
  170. fLine := aLine;
  171. fCol := aCol;
  172. end;
  173. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  174. //TengExpressionValue///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  175. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  176. function TengExpressionValue.GetText: String;
  177. begin
  178. result := TOKEN_CHAR_QUOTE + fValue + TOKEN_CHAR_QUOTE;
  179. end;
  180. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. function TengExpressionValue.GetValue: Variant;
  182. begin
  183. result := fValue;
  184. end;
  185. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  186. constructor TengExpressionValue.Create(const aValue: Variant; const aLine, aCol: Integer);
  187. begin
  188. inherited Create(aLine, aCol);
  189. fValue := aValue;
  190. end;
  191. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  192. //TengExpressionVariable////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  193. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  194. function TengExpressionVariable.GetText: String;
  195. begin
  196. result := fName;
  197. end;
  198. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  199. function TengExpressionVariable.GetValue: Variant;
  200. begin
  201. result := Unassigned;
  202. if Assigned(fPart) then
  203. result := fPart.Value;
  204. end;
  205. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  206. constructor TengExpressionVariable.Create(const aName: String; const aPart: TengShaderPartKeyValuePair; const aLine, aCol: Integer);
  207. begin
  208. inherited Create(aLine, aCol);
  209. fName := aName;
  210. fPart := aPart;
  211. end;
  212. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  213. //TengExpressionGroup///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  214. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  215. function TengExpressionGroup.GetCount: Integer;
  216. begin
  217. result := 1;
  218. end;
  219. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  220. function TengExpressionGroup.GetChild(const aIndex: Integer): TengShaderPart;
  221. begin
  222. if (aIndex >= 0) and (aIndex < 1)
  223. then result := fChild
  224. else raise EengOutOfRange.Create(0, 0, aIndex, self);
  225. end;
  226. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  227. function TengExpressionGroup.GetText: String;
  228. begin
  229. if Assigned(fChild)
  230. then result := TOKEN_OP_GROUP_BEGIN + fChild.GetText + TOKEN_OP_GROUP_END
  231. else result := '';
  232. end;
  233. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  234. function TengExpressionGroup.GetValue: Variant;
  235. begin
  236. if Assigned(fChild)
  237. then result := fChild.GetValue
  238. else result := Unassigned;
  239. end;
  240. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  241. constructor TengExpressionGroup.Create(const aChild: TengExpressionItem; const aLine, aCol: Integer);
  242. begin
  243. inherited Create(aLine, aCol);
  244. fChild := aChild;
  245. end;
  246. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  247. destructor TengExpressionGroup.Destroy;
  248. begin
  249. FreeAndNil(fChild);
  250. inherited Destroy;
  251. end;
  252. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  253. //TengExpressionOperation///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  254. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  255. function TengExpressionOperation.GetWeight: Integer;
  256. begin
  257. result := -1;
  258. end;
  259. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  260. function TengExpressionOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
  261. begin
  262. result := nil;
  263. end;
  264. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  265. function TengExpressionOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
  266. begin
  267. result := nil;
  268. end;
  269. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  270. //TengExpressionUnaryOperation//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  271. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  272. function TengExpressionUnaryOperation.GetWeight: Integer;
  273. begin
  274. result := UNARY_OPERATION_WEIGHTS[fUnaryOp];
  275. end;
  276. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  277. function TengExpressionUnaryOperation.GetCount: Integer;
  278. begin
  279. result := 1;
  280. end;
  281. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  282. function TengExpressionUnaryOperation.GetChild(const aIndex: Integer): TengShaderPart;
  283. begin
  284. if (aIndex >= 0) and (aIndex < 1)
  285. then result := fChild
  286. else raise EengOutOfRange.Create(0, 0, aIndex, self);
  287. end;
  288. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  289. function TengExpressionUnaryOperation.GetText: String;
  290. begin
  291. if not Assigned(fChild) then
  292. EengExpression.Create('no child assigned', self);
  293. result :=
  294. {$IFDEF SHADER_FILE_EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN+{$ENDIF}
  295. EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + fChild.GetText
  296. {$IFDEF SHADER_FILE_EXPRESSION_ADD_BRACKET}+TOKEN_OP_GROUP_END{$ENDIF};
  297. end;
  298. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  299. function TengExpressionUnaryOperation.GetValue: Variant;
  300. var
  301. v: Variant;
  302. begin
  303. if not Assigned(fChild) then
  304. raise EengExpression.Create('no child assigned', self);
  305. try
  306. case fUnaryOp of
  307. opBinaryNot: begin
  308. v := fChild.GetValue;
  309. result := not Integer(v);
  310. end;
  311. opLogicalNot: begin
  312. v := fChild.GetValue;
  313. result := not Boolean(v);
  314. end;
  315. else
  316. result := inherited GetValue;
  317. end;
  318. except
  319. on ex: Exception do
  320. raise EengInvalidParamter.Create(
  321. ex.Message + '("' + GetText + '" ==> ' +
  322. EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + v + '")',
  323. Line, Col, Filename, self);
  324. end;
  325. end;
  326. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  327. function TengExpressionUnaryOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
  328. begin
  329. result := fChild;
  330. fChild := aItem;
  331. end;
  332. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  333. function TengExpressionUnaryOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
  334. begin
  335. result := fChild;
  336. fChild := aItem;
  337. end;
  338. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  339. constructor TengExpressionUnaryOperation.Create(const aUnaryOp: TengExpressionUnaryOperator; const aChild: TengExpressionItem; const aLine, aCol: Integer);
  340. begin
  341. inherited Create(aLine, aCol);
  342. fChild := aChild;
  343. fUnaryOp := aUnaryOp;
  344. end;
  345. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  346. destructor TengExpressionUnaryOperation.Destroy;
  347. begin
  348. FreeAndNil(fChild);
  349. inherited Destroy;
  350. end;
  351. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  352. //TengExpressionBinaryOperation/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  353. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  354. function TengExpressionBinaryOperation.GetWeight: Integer;
  355. begin
  356. result := BINARY_OPERATION_WEIGHTS[fBinaryOp];
  357. end;
  358. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  359. function TengExpressionBinaryOperation.GetCount: Integer;
  360. begin
  361. result := 2;
  362. end;
  363. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  364. function TengExpressionBinaryOperation.GetChild(const aIndex: Integer): TengShaderPart;
  365. begin
  366. if (aIndex < 0) and (aIndex >= 2) then
  367. raise EengOutOfRange.Create(0, 1, aIndex, self);
  368. case aIndex of
  369. 0: result := fFirst;
  370. 1: result := fSecond;
  371. else
  372. result := nil;
  373. end;
  374. end;
  375. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  376. function TengExpressionBinaryOperation.GetText: String;
  377. begin
  378. if not Assigned(fFirst) or not Assigned(fSecond) then
  379. raise EengExpression.Create('first or second item not assigned');
  380. result :=
  381. {$IFDEF SHADER_FILE_EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN +{$ENDIF}
  382. fFirst.GetText + ' ' + EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + fSecond.GetText
  383. {$IFDEF SHADER_FILE_EXPRESSION_ADD_BRACKET} + TOKEN_OP_GROUP_END{$ENDIF};
  384. end;
  385. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  386. function TengExpressionBinaryOperation.GetValue: Variant;
  387. var
  388. v1: Variant;
  389. v2: Variant;
  390. begin
  391. if not Assigned(fFirst) or not Assigned(fSecond) then
  392. raise EengExpression.Create('first or second item not assigned');
  393. v1 := fFirst.GetValue;
  394. v2 := fSecond.GetValue;
  395. try
  396. case fBinaryOp of
  397. opBinaryOr: result := (Integer(v1) or Integer(v2));
  398. opBinaryAnd: result := (Integer(v1) and Integer(v2));
  399. opBinaryXor: result := (Integer(v1) xor Integer(v2));
  400. opMultiply: result := (v1 * v2);
  401. opDivide: result := (v1 / v2);
  402. opAdd: result := (v1 + v2);
  403. opSubtract: result := (v1 - v2);
  404. opLogicalOr: result := (Boolean(v1) or Boolean(v2));
  405. opLogicalAnd: result := (Boolean(v1) and Boolean(v2));
  406. opLogicalXor: result := (Boolean(v1) xor Boolean(v2));
  407. opEquals: result := (v1 = v2);
  408. opLesser: result := (v1 < v2);
  409. opGreater: result := (v1 > v2);
  410. opLEquals: result := (v1 <= v2);
  411. opGEquals: result := (v1 >= v2);
  412. opUnequals: result := (v1 <> v2);
  413. else
  414. result := inherited GetValue;
  415. end;
  416. except
  417. on ex: Exception do
  418. raise EengInvalidParamter.Create(
  419. ex.Message + ' ("' + GetText + '" ==> "' + v1 + ' ' +
  420. EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + v2 + '")',
  421. self);
  422. end;
  423. end;
  424. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  425. function TengExpressionBinaryOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
  426. begin
  427. result := fFirst;
  428. fFirst := aItem;
  429. end;
  430. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  431. function TengExpressionBinaryOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
  432. begin
  433. result := fSecond;
  434. fSecond := aItem;
  435. end;
  436. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  437. constructor TengExpressionBinaryOperation.Create(const aOperator: TengExpressionBinaryOperator;
  438. const aFirst, aSecond: TengExpressionItem; const aLine, aCol: Integer);
  439. begin
  440. inherited Create(aLine, aCol);
  441. fBinaryOp := aOperator;
  442. fFirst := aFirst;
  443. fSecond := aSecond;
  444. end;
  445. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  446. destructor TengExpressionBinaryOperation.Destroy;
  447. begin
  448. FreeAndNil(fFirst);
  449. FreeAndNil(fSecond);
  450. inherited Destroy;
  451. end;
  452. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  453. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  454. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  455. type
  456. TExpectedParam = (exVariable, exValue, exGroupBegin, exGroupEnd, exUnaryOperation, exBinaryOperation);
  457. TExpectedParams = set of TExpectedParam;
  458. TExpressionParser = class(TObject)
  459. private
  460. fParent: TengShaderPart;
  461. fParamPos: Integer;
  462. fParams: TengTokenParameterList;
  463. private
  464. function NextParam(out aParam: TengTokenParameter): Boolean;
  465. function IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
  466. function IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
  467. procedure RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
  468. function Move(var aItem: TengExpressionItem): TengExpressionItem;
  469. function Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
  470. function GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
  471. public
  472. function GetGroup: TengExpressionItem;
  473. constructor Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
  474. end;
  475. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  476. //TExpressionParser/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  477. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  478. function TExpressionParser.NextParam(out aParam: TengTokenParameter): Boolean;
  479. begin
  480. inc(fParamPos);
  481. result := (fParamPos < fParams.Count);
  482. if result
  483. then aParam := fParams[fParamPos]
  484. else FillByte(aParam{%H-}, SizeOf(aParam), 0);
  485. end;
  486. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  487. function TExpressionParser.IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
  488. begin
  489. result := true;
  490. for aOperator in TengExpressionUnaryOperator do
  491. if (aParam = EXPRESSION_UNARY_OPERATIONS[aOperator]) then
  492. exit;
  493. result := false;
  494. end;
  495. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  496. function TExpressionParser.IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
  497. begin
  498. result := true;
  499. for aOperator in TengExpressionBinaryOperator do
  500. if (aParam = EXPRESSION_BINARY_OPERATIONS[aOperator]) then
  501. exit;
  502. result := false;
  503. end;
  504. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  505. procedure TExpressionParser.RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
  506. begin
  507. if (aName = '') then
  508. aName := aParam.Name;
  509. raise EengExpression.Create(aMsg + ' ' + aParam.Name, aParam.Line, aParam.Col, fParent.Filename, fParent);
  510. end;
  511. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  512. function TExpressionParser.Move(var aItem: TengExpressionItem): TengExpressionItem;
  513. begin
  514. result := aItem;
  515. aItem := nil;
  516. end;
  517. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  518. function TExpressionParser.Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
  519. var
  520. o, n: TengExpressionOperation;
  521. tmp: TengExpressionItem;
  522. begin
  523. result := nil;
  524. try
  525. if not Assigned(aOld) then begin
  526. result := aNew;
  527. exit;
  528. end else if not Assigned(aNew) then begin
  529. result := aOld;
  530. exit;
  531. end else if (aOld is TengExpressionOperation) and (aNew is TengExpressionOperation) then begin
  532. o := (aOld as TengExpressionOperation);
  533. n := (aNew as TengExpressionOperation);
  534. if (n.Weight < o.Weight) then begin
  535. tmp := n.ExchangeFirst(o.ExchangeLast(n));
  536. aNew := nil;
  537. result := aOld;
  538. end else begin
  539. tmp := n.ExchangeFirst(o);
  540. aOld := nil;
  541. result := aNew;
  542. end;
  543. if Assigned(tmp) then
  544. raise EengExpressionInternal.Create(1, fParent);
  545. end else if (aOld is TengExpressionOperation) then begin
  546. o := (aOld as TengExpressionOperation);
  547. o.ExchangeLast(aNew);
  548. aNew := nil;
  549. result := aOld;
  550. end else if (aNew is TengExpressionOperation) then begin
  551. n := (aNew as TengExpressionOperation);
  552. n.ExchangeFirst(aOld);
  553. aOld := nil;
  554. result := aNew;
  555. end;;
  556. except
  557. FreeAndNil(aOld);
  558. FreeAndNil(aNew);
  559. result := nil;
  560. raise;
  561. end;
  562. end;
  563. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  564. function TExpressionParser.GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
  565. var
  566. uOp: TengExpressionUnaryOperator;
  567. bOp: TengExpressionBinaryOperator;
  568. item: TengExpressionItem;
  569. param: TengTokenParameter;
  570. sr: TengSearchResults;
  571. walker: TengKeyValuePairSearchWalker;
  572. tmp: TengShaderPart;
  573. begin
  574. item := nil;
  575. result := nil;
  576. try
  577. if NextParam(param) then begin
  578. // GroupBegin
  579. if (param.Name = TOKEN_OP_GROUP_BEGIN) then begin
  580. if not (exGroupBegin in aExpected) then
  581. RaiseEx('unexpected', param);
  582. item := GetGroup;
  583. result := TengExpressionGroup.Create(Move(item), param.Col, param.Line);
  584. // GroupEnd
  585. end else if (param.Name = TOKEN_OP_GROUP_END) then begin
  586. if not (exGroupEnd in aExpected) then
  587. RaiseEx('unexpected', param);
  588. // UnaryOperation
  589. end else if IsUnaryOperation(param.Name, uOp) then begin
  590. if not (exUnaryOperation in aExpected) then
  591. RaiseEx('unexpected operation:', param);
  592. item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
  593. result := TengExpressionUnaryOperation.Create(uOp, Move(item), param.Line, param.Col);
  594. // BinaryOperation
  595. end else if IsBinaryOperation(param.Name, bOp) then begin
  596. if not (exBinaryOperation in aExpected) then
  597. RaiseEx('unexpected operation:', param);
  598. item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
  599. item := TengExpressionBinaryOperation.Create(bOp, nil, Move(item), param.Line, param.Col);
  600. result := Merge(result, item);
  601. // Value
  602. end else if param.Quoted and IsValidIdentifier(param.Name) then begin
  603. if not (exValue in aExpected) then
  604. RaiseEx('unexpected value:', param);
  605. result := TengExpressionValue.Create(param.Name, param.Line, param.Col);
  606. // Variable
  607. end else if IsValidIdentifier(param.Name) then begin
  608. if not (exVariable in aExpected) then
  609. RaiseEx('unexpected variable:', param);
  610. sr := TengSearchResults.Create;
  611. walker := TengKeyValuePairSearchWalker.Create(sr);
  612. try
  613. walker.Name := param.Name;
  614. walker.SearchFlags := [sfSearchChildren, sfSearchParents, sfSearchInherited];
  615. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic);
  616. walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope);
  617. walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
  618. walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile);
  619. walker.Run(fParent);
  620. tmp := ExtractSearchResult(fParent, param.Name, sr, [ifWarning, ifRaiseEx], param.Line, param.Col);
  621. result := TengExpressionVariable.Create(param.Name, (tmp as TengShaderPartKeyValuePair), param.Line, param.Col);
  622. finally
  623. FreeAndNil(walker);
  624. FreeAndNil(sr);
  625. end;
  626. // Unknown
  627. end else
  628. raise EengExpression.Create('invalid parameter: ' + param.Name, param.Line, param.Col, fParent.Filename, fParent);
  629. end;
  630. if not Assigned(result) and not (exGroupEnd in aExpected) then
  631. RaiseEx('unexpected', param, 'end');
  632. except
  633. FreeAndNil(item);
  634. FreeAndNil(result);
  635. raise;
  636. end;
  637. end;
  638. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  639. function TExpressionParser.GetGroup: TengExpressionItem;
  640. var
  641. ex: TExpectedParams;
  642. item: TengExpressionItem;
  643. b: Boolean;
  644. begin
  645. item := nil;
  646. result := nil;
  647. try
  648. ex := [exVariable, exValue, exGroupBegin, exUnaryOperation];
  649. repeat
  650. item := GetExpr(ex);
  651. b := Assigned(item);
  652. result := Merge(result, Move(item));
  653. ex := ex + [exBinaryOperation, exGroupEnd];
  654. until not b;
  655. except
  656. FreeAndNil(result);
  657. FreeAndNil(item);
  658. raise;
  659. end;
  660. end;
  661. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  662. constructor TExpressionParser.Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
  663. begin
  664. fParamPos := aIndex - 1;
  665. fParams := aParams;
  666. fParent := aParent;
  667. end;
  668. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  669. function ParseExpression(const aParent: TengShaderPart; const aParams: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
  670. var
  671. parser: TExpressionParser;
  672. begin
  673. parser := TExpressionParser.Create(aParent, aParams, aIndex);
  674. try
  675. result := parser.GetGroup;
  676. finally
  677. FreeAndNil(parser);
  678. end;
  679. end;
  680. end.