No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

784 líneas
33 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;
  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; // TODO
  202. end;
  203. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. constructor TengExpressionVariable.Create(const aName: String; const aPart: TengShaderPartKeyValuePair; const aLine, aCol: Integer);
  205. begin
  206. inherited Create(aLine, aCol);
  207. fName := aName;
  208. fPart := aPart;
  209. end;
  210. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  211. //TengExpressionGroup///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  212. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  213. function TengExpressionGroup.GetCount: Integer;
  214. begin
  215. result := 1;
  216. end;
  217. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  218. function TengExpressionGroup.GetChild(const aIndex: Integer): TengShaderPart;
  219. begin
  220. if (aIndex >= 0) and (aIndex < 1)
  221. then result := fChild
  222. else raise EengOutOfRange.Create(0, 0, aIndex, self);
  223. end;
  224. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  225. function TengExpressionGroup.GetText: String;
  226. begin
  227. if Assigned(fChild)
  228. then result := TOKEN_OP_GROUP_BEGIN + fChild.GetText + TOKEN_OP_GROUP_END
  229. else result := '';
  230. end;
  231. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  232. function TengExpressionGroup.GetValue: Variant;
  233. begin
  234. if Assigned(fChild)
  235. then result := fChild.GetValue
  236. else result := Unassigned;
  237. end;
  238. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  239. constructor TengExpressionGroup.Create(const aChild: TengExpressionItem; const aLine, aCol: Integer);
  240. begin
  241. inherited Create(aLine, aCol);
  242. fChild := aChild;
  243. end;
  244. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  245. destructor TengExpressionGroup.Destroy;
  246. begin
  247. FreeAndNil(fChild);
  248. inherited Destroy;
  249. end;
  250. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  251. //TengExpressionOperation///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  252. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  253. function TengExpressionOperation.GetWeight: Integer;
  254. begin
  255. result := -1;
  256. end;
  257. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  258. function TengExpressionOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
  259. begin
  260. result := nil;
  261. end;
  262. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  263. function TengExpressionOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
  264. begin
  265. result := nil;
  266. end;
  267. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  268. //TengExpressionUnaryOperation//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  269. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  270. function TengExpressionUnaryOperation.GetWeight: Integer;
  271. begin
  272. result := UNARY_OPERATION_WEIGHTS[fUnaryOp];
  273. end;
  274. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  275. function TengExpressionUnaryOperation.GetCount: Integer;
  276. begin
  277. result := 1;
  278. end;
  279. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  280. function TengExpressionUnaryOperation.GetChild(const aIndex: Integer): TengShaderPart;
  281. begin
  282. if (aIndex >= 0) and (aIndex < 1)
  283. then result := fChild
  284. else raise EengOutOfRange.Create(0, 0, aIndex, self);
  285. end;
  286. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  287. function TengExpressionUnaryOperation.GetText: String;
  288. begin
  289. if not Assigned(fChild) then
  290. EengExpression.Create('no child assigned', self);
  291. result :=
  292. {$IFDEF EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN+{$ENDIF}
  293. EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + fChild.GetText
  294. {$IFDEF EXPRESSION_ADD_BRACKET}+TOKEN_OP_GROUP_END{$ENDIF};
  295. end;
  296. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  297. function TengExpressionUnaryOperation.GetValue: Variant;
  298. var
  299. v: Variant;
  300. begin
  301. if not Assigned(fChild) then
  302. raise EengExpression.Create('no child assigned', self);
  303. try
  304. case fUnaryOp of
  305. opBinaryNot: begin
  306. v := fChild.GetValue;
  307. result := not Integer(v);
  308. end;
  309. opLogicalNot: begin
  310. v := fChild.GetValue;
  311. result := not Boolean(v);
  312. end;
  313. else
  314. result := inherited GetValue;
  315. end;
  316. except
  317. on ex: Exception do
  318. raise EengInvalidParamter.Create(
  319. ex.Message + '("' + GetText + '" ==> ' +
  320. EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + v + '")',
  321. Line, Col, Filename, self);
  322. end;
  323. end;
  324. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  325. function TengExpressionUnaryOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
  326. begin
  327. result := fChild;
  328. fChild := aItem;
  329. end;
  330. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  331. function TengExpressionUnaryOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
  332. begin
  333. result := fChild;
  334. fChild := aItem;
  335. end;
  336. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  337. constructor TengExpressionUnaryOperation.Create(const aUnaryOp: TengExpressionUnaryOperator; const aChild: TengExpressionItem; const aLine, aCol: Integer);
  338. begin
  339. inherited Create(aLine, aCol);
  340. fChild := aChild;
  341. fUnaryOp := aUnaryOp;
  342. end;
  343. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  344. destructor TengExpressionUnaryOperation.Destroy;
  345. begin
  346. FreeAndNil(fChild);
  347. inherited Destroy;
  348. end;
  349. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  350. //TengExpressionBinaryOperation/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  351. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  352. function TengExpressionBinaryOperation.GetWeight: Integer;
  353. begin
  354. result := BINARY_OPERATION_WEIGHTS[fBinaryOp];
  355. end;
  356. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  357. function TengExpressionBinaryOperation.GetCount: Integer;
  358. begin
  359. result := 2;
  360. end;
  361. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  362. function TengExpressionBinaryOperation.GetChild(const aIndex: Integer): TengShaderPart;
  363. begin
  364. if (aIndex < 0) and (aIndex >= 2) then
  365. raise EengOutOfRange.Create(0, 1, aIndex, self);
  366. case aIndex of
  367. 0: result := fFirst;
  368. 1: result := fSecond;
  369. end;
  370. end;
  371. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  372. function TengExpressionBinaryOperation.GetText: String;
  373. begin
  374. if not Assigned(fFirst) or not Assigned(fSecond) then
  375. raise EengExpression.Create('first or second item not assigned');
  376. result :=
  377. {$IFDEF EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN +{$ENDIF}
  378. fFirst.GetText + ' ' + EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + fSecond.GetText
  379. {$IFDEF EXPRESSION_ADD_BRACKET} + TOKEN_OP_GROUP_END{$ENDIF};
  380. end;
  381. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  382. function TengExpressionBinaryOperation.GetValue: Variant;
  383. var
  384. v1: Variant;
  385. v2: Variant;
  386. begin
  387. if not Assigned(fFirst) or not Assigned(fSecond) then
  388. raise EengExpression.Create('first or second item not assigned');
  389. v1 := fFirst.GetValue;
  390. v2 := fSecond.GetValue;
  391. try
  392. case fBinaryOp of
  393. opBinaryOr: result := (Integer(v1) or Integer(v2));
  394. opBinaryAnd: result := (Integer(v1) and Integer(v2));
  395. opBinaryXor: result := (Integer(v1) xor Integer(v2));
  396. opMultiply: result := (v1 * v2);
  397. opDivide: result := (v1 / v2);
  398. opAdd: result := (v1 + v2);
  399. opSubtract: result := (v1 - v2);
  400. opLogicalOr: result := (Boolean(v1) or Boolean(v2));
  401. opLogicalAnd: result := (Boolean(v1) and Boolean(v2));
  402. opLogicalXor: result := (Boolean(v1) xor Boolean(v2));
  403. opEquals: result := (v1 = v2);
  404. opLesser: result := (v1 < v2);
  405. opGreater: result := (v1 > v2);
  406. opLEquals: result := (v1 <= v2);
  407. opGEquals: result := (v1 >= v2);
  408. opUnequals: result := (v1 <> v2);
  409. else
  410. result := inherited GetValue;
  411. end;
  412. except
  413. on ex: Exception do
  414. raise EengInvalidParamter.Create(
  415. ex.Message + ' ("' + GetText + '" ==> "' + v1 + ' ' +
  416. EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + v2 + '")',
  417. self);
  418. end;
  419. end;
  420. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  421. function TengExpressionBinaryOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
  422. begin
  423. result := fFirst;
  424. fFirst := aItem;
  425. end;
  426. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  427. function TengExpressionBinaryOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
  428. begin
  429. result := fSecond;
  430. fSecond := aItem;
  431. end;
  432. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  433. constructor TengExpressionBinaryOperation.Create(const aOperator: TengExpressionBinaryOperator;
  434. const aFirst, aSecond: TengExpressionItem; const aLine, aCol: Integer);
  435. begin
  436. inherited Create(aLine, aCol);
  437. fBinaryOp := aOperator;
  438. fFirst := aFirst;
  439. fSecond := aSecond;
  440. end;
  441. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  442. destructor TengExpressionBinaryOperation.Destroy;
  443. begin
  444. FreeAndNil(fFirst);
  445. FreeAndNil(fSecond);
  446. inherited Destroy;
  447. end;
  448. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  449. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  450. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  451. type
  452. TkvpSearchResults = class(TengSearchResults)
  453. private
  454. fName: String;
  455. protected
  456. function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; override;
  457. public
  458. constructor Create(const aName: String);
  459. end;
  460. TExpectedParam = (exVariable, exValue, exGroupBegin, exGroupEnd, exUnaryOperation, exBinaryOperation);
  461. TExpectedParams = set of TExpectedParam;
  462. TExpressionParser = class(TObject)
  463. private
  464. fParent: TengShaderPart;
  465. fParamPos: Integer;
  466. fParams: TengTokenParameterList;
  467. private
  468. function NextParam(out aParam: TengTokenParameter): Boolean;
  469. function IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
  470. function IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
  471. procedure RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
  472. function Move(var aItem: TengExpressionItem): TengExpressionItem;
  473. function Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
  474. function GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
  475. public
  476. function GetGroup: TengExpressionItem;
  477. constructor Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
  478. end;
  479. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  480. //TkvpSearchResults/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  481. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  482. function TkvpSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean;
  483. begin
  484. result := inherited CheckObj(aPart, aContinue);
  485. if result then
  486. result := ((aPart as TengShaderPartKeyValuePair).Name = fName);
  487. end;
  488. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  489. constructor TkvpSearchResults.Create(const aName: String);
  490. begin
  491. inherited Create([TengShaderPartKeyValuePair]);
  492. fName := aName;
  493. end;
  494. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  495. //TExpressionParser/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  496. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  497. function TExpressionParser.NextParam(out aParam: TengTokenParameter): Boolean;
  498. begin
  499. inc(fParamPos);
  500. result := (fParamPos < fParams.Count);
  501. if result
  502. then aParam := fParams[fParamPos]
  503. else FillByte(aParam, SizeOf(aParam), 0);
  504. end;
  505. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  506. function TExpressionParser.IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
  507. begin
  508. result := true;
  509. for aOperator in TengExpressionUnaryOperator do
  510. if (aParam = EXPRESSION_UNARY_OPERATIONS[aOperator]) then
  511. exit;
  512. result := false;
  513. end;
  514. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  515. function TExpressionParser.IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
  516. begin
  517. result := true;
  518. for aOperator in TengExpressionBinaryOperator do
  519. if (aParam = EXPRESSION_BINARY_OPERATIONS[aOperator]) then
  520. exit;
  521. result := false;
  522. end;
  523. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  524. procedure TExpressionParser.RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
  525. begin
  526. if (aName = '') then
  527. aName := aParam.Name;
  528. raise EengExpression.Create(aMsg + ' ' + aParam.Name, aParam.Line, aParam.Col, fParent.Filename, fParent);
  529. end;
  530. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  531. function TExpressionParser.Move(var aItem: TengExpressionItem): TengExpressionItem;
  532. begin
  533. result := aItem;
  534. aItem := nil;
  535. end;
  536. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  537. function TExpressionParser.Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
  538. var
  539. o, n: TengExpressionOperation;
  540. tmp: TengExpressionItem;
  541. begin
  542. result := nil;
  543. try
  544. if not Assigned(aOld) then begin
  545. result := aNew;
  546. exit;
  547. end else if not Assigned(aNew) then begin
  548. result := aOld;
  549. exit;
  550. end else if (aOld is TengExpressionOperation) and (aNew is TengExpressionOperation) then begin
  551. o := (aOld as TengExpressionOperation);
  552. n := (aNew as TengExpressionOperation);
  553. if (n.Weight < o.Weight) then begin
  554. tmp := n.ExchangeFirst(o.ExchangeLast(n));
  555. aNew := nil;
  556. result := aOld;
  557. end else begin
  558. tmp := n.ExchangeFirst(o);
  559. aOld := nil;
  560. result := aNew;
  561. end;
  562. if Assigned(tmp) then
  563. raise EengExpressionInternal.Create(1, fParent);
  564. end else if (aOld is TengExpressionOperation) then begin
  565. o := (aOld as TengExpressionOperation);
  566. o.ExchangeLast(aNew);
  567. aNew := nil;
  568. result := aOld;
  569. end else if (aNew is TengExpressionOperation) then begin
  570. n := (aNew as TengExpressionOperation);
  571. n.ExchangeFirst(aOld);
  572. aOld := nil;
  573. result := aNew;
  574. end;;
  575. except
  576. FreeAndNil(aOld);
  577. FreeAndNil(aNew);
  578. result := nil;
  579. raise;
  580. end;
  581. end;
  582. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  583. function TExpressionParser.GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
  584. var
  585. uOp: TengExpressionUnaryOperator;
  586. bOp: TengExpressionBinaryOperator;
  587. item: TengExpressionItem;
  588. param: TengTokenParameter;
  589. sr: TkvpSearchResults;
  590. tmp: TengShaderPart;
  591. begin
  592. item := nil;
  593. result := nil;
  594. try
  595. if NextParam(param) then begin
  596. // GroupBegin
  597. if (param.Name = TOKEN_OP_GROUP_BEGIN) then begin
  598. if not (exGroupBegin in aExpected) then
  599. RaiseEx('unexpected', param);
  600. item := GetGroup;
  601. result := TengExpressionGroup.Create(Move(item), param.Col, param.Line);
  602. // GroupEnd
  603. end else if (param.Name = TOKEN_OP_GROUP_END) then begin
  604. if not (exGroupEnd in aExpected) then
  605. RaiseEx('unexpected', param);
  606. // UnaryOperation
  607. end else if IsUnaryOperation(param.Name, uOp) then begin
  608. if not (exUnaryOperation in aExpected) then
  609. RaiseEx('unexpected operation:', param);
  610. item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
  611. result := TengExpressionUnaryOperation.Create(uOp, Move(item), param.Line, param.Col);
  612. // BinaryOperation
  613. end else if IsBinaryOperation(param.Name, bOp) then begin
  614. if not (exBinaryOperation in aExpected) then
  615. RaiseEx('unexpected operation:', param);
  616. item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
  617. item := TengExpressionBinaryOperation.Create(bOp, nil, Move(item), param.Line, param.Col);
  618. result := Merge(result, item);
  619. // Value
  620. end else if param.Quoted and IsValidIdentifier(param.Name) then begin
  621. if not (exValue in aExpected) then
  622. RaiseEx('unexpected value:', param);
  623. result := TengExpressionValue.Create(param.Name, param.Line, param.Col);
  624. // Variable
  625. end else if IsValidIdentifier(param.Name) then begin
  626. if not (exVariable in aExpected) then
  627. RaiseEx('unexpected variable:', param);
  628. sr := TkvpSearchResults.Create(param.Name);
  629. try
  630. fParent.Find([], sr);
  631. tmp := ExtractSearchResult(fParent, param.Name, sr, param.Line, param.Col);
  632. result := TengExpressionVariable.Create(param.Name, (tmp as TengShaderPartKeyValuePair), param.Line, param.Col);
  633. finally
  634. FreeAndNil(sr);
  635. end;
  636. // Unknown
  637. end else
  638. raise EengExpression.Create('invalid parameter: ' + param.Name, param.Line, param.Col, fParent.Filename, fParent);
  639. end;
  640. if not Assigned(result) and not (exGroupEnd in aExpected) then
  641. RaiseEx('unexpected', param, 'end');
  642. except
  643. FreeAndNil(item);
  644. FreeAndNil(result);
  645. raise;
  646. end;
  647. end;
  648. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  649. function TExpressionParser.GetGroup: TengExpressionItem;
  650. var
  651. ex: TExpectedParams;
  652. item: TengExpressionItem;
  653. b: Boolean;
  654. begin
  655. item := nil;
  656. result := nil;
  657. try
  658. ex := [exVariable, exValue, exGroupBegin, exUnaryOperation];
  659. repeat
  660. item := GetExpr(ex);
  661. b := Assigned(item);
  662. result := Merge(result, Move(item));
  663. ex := ex + [exBinaryOperation, exGroupEnd];
  664. until not b;
  665. except
  666. FreeAndNil(result);
  667. FreeAndNil(item);
  668. raise;
  669. end;
  670. end;
  671. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  672. constructor TExpressionParser.Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
  673. begin
  674. fParamPos := aIndex - 1;
  675. fParams := aParams;
  676. fParent := aParent;
  677. end;
  678. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  679. function ParseExpression(const aParent: TengShaderPart; const aParams: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
  680. var
  681. parser: TExpressionParser;
  682. begin
  683. parser := TExpressionParser.Create(aParent, aParams, aIndex);
  684. try
  685. result := parser.GetGroup;
  686. finally
  687. FreeAndNil(parser);
  688. end;
  689. end;
  690. end.