Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

758 wiersze
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;
  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. TExpectedParam = (exVariable, exValue, exGroupBegin, exGroupEnd, exUnaryOperation, exBinaryOperation);
  453. TExpectedParams = set of TExpectedParam;
  454. TExpressionParser = class(TObject)
  455. private
  456. fParent: TengShaderPart;
  457. fParamPos: Integer;
  458. fParams: TengTokenParameterList;
  459. private
  460. function NextParam(out aParam: TengTokenParameter): Boolean;
  461. function IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
  462. function IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
  463. procedure RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
  464. function Move(var aItem: TengExpressionItem): TengExpressionItem;
  465. function Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
  466. function GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
  467. public
  468. function GetGroup: TengExpressionItem;
  469. constructor Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
  470. end;
  471. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  472. //TExpressionParser/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  473. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  474. function TExpressionParser.NextParam(out aParam: TengTokenParameter): Boolean;
  475. begin
  476. inc(fParamPos);
  477. result := (fParamPos < fParams.Count);
  478. if result
  479. then aParam := fParams[fParamPos]
  480. else FillByte(aParam, SizeOf(aParam), 0);
  481. end;
  482. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  483. function TExpressionParser.IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
  484. begin
  485. result := true;
  486. for aOperator in TengExpressionUnaryOperator do
  487. if (aParam = EXPRESSION_UNARY_OPERATIONS[aOperator]) then
  488. exit;
  489. result := false;
  490. end;
  491. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  492. function TExpressionParser.IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
  493. begin
  494. result := true;
  495. for aOperator in TengExpressionBinaryOperator do
  496. if (aParam = EXPRESSION_BINARY_OPERATIONS[aOperator]) then
  497. exit;
  498. result := false;
  499. end;
  500. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  501. procedure TExpressionParser.RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
  502. begin
  503. if (aName = '') then
  504. aName := aParam.Name;
  505. raise EengExpression.Create(aMsg + ' ' + aParam.Name, aParam.Line, aParam.Col, fParent.Filename, fParent);
  506. end;
  507. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  508. function TExpressionParser.Move(var aItem: TengExpressionItem): TengExpressionItem;
  509. begin
  510. result := aItem;
  511. aItem := nil;
  512. end;
  513. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  514. function TExpressionParser.Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
  515. var
  516. o, n: TengExpressionOperation;
  517. tmp: TengExpressionItem;
  518. begin
  519. result := nil;
  520. try
  521. if not Assigned(aOld) then begin
  522. result := aNew;
  523. exit;
  524. end else if not Assigned(aNew) then begin
  525. result := aOld;
  526. exit;
  527. end else if (aOld is TengExpressionOperation) and (aNew is TengExpressionOperation) then begin
  528. o := (aOld as TengExpressionOperation);
  529. n := (aNew as TengExpressionOperation);
  530. if (n.Weight < o.Weight) then begin
  531. tmp := n.ExchangeFirst(o.ExchangeLast(n));
  532. aNew := nil;
  533. result := aOld;
  534. end else begin
  535. tmp := n.ExchangeFirst(o);
  536. aOld := nil;
  537. result := aNew;
  538. end;
  539. if Assigned(tmp) then
  540. raise EengExpressionInternal.Create(1, fParent);
  541. end else if (aOld is TengExpressionOperation) then begin
  542. o := (aOld as TengExpressionOperation);
  543. o.ExchangeLast(aNew);
  544. aNew := nil;
  545. result := aOld;
  546. end else if (aNew is TengExpressionOperation) then begin
  547. n := (aNew as TengExpressionOperation);
  548. n.ExchangeFirst(aOld);
  549. aOld := nil;
  550. result := aNew;
  551. end;;
  552. except
  553. FreeAndNil(aOld);
  554. FreeAndNil(aNew);
  555. result := nil;
  556. raise;
  557. end;
  558. end;
  559. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  560. function TExpressionParser.GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
  561. var
  562. uOp: TengExpressionUnaryOperator;
  563. bOp: TengExpressionBinaryOperator;
  564. item: TengExpressionItem;
  565. param: TengTokenParameter;
  566. sr: TkvpSearchResults;
  567. tmp: TengShaderPart;
  568. begin
  569. item := nil;
  570. result := nil;
  571. try
  572. if NextParam(param) then begin
  573. // GroupBegin
  574. if (param.Name = TOKEN_OP_GROUP_BEGIN) then begin
  575. if not (exGroupBegin in aExpected) then
  576. RaiseEx('unexpected', param);
  577. item := GetGroup;
  578. result := TengExpressionGroup.Create(Move(item), param.Col, param.Line);
  579. // GroupEnd
  580. end else if (param.Name = TOKEN_OP_GROUP_END) then begin
  581. if not (exGroupEnd in aExpected) then
  582. RaiseEx('unexpected', param);
  583. // UnaryOperation
  584. end else if IsUnaryOperation(param.Name, uOp) then begin
  585. if not (exUnaryOperation in aExpected) then
  586. RaiseEx('unexpected operation:', param);
  587. item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
  588. result := TengExpressionUnaryOperation.Create(uOp, Move(item), param.Line, param.Col);
  589. // BinaryOperation
  590. end else if IsBinaryOperation(param.Name, bOp) then begin
  591. if not (exBinaryOperation in aExpected) then
  592. RaiseEx('unexpected operation:', param);
  593. item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
  594. item := TengExpressionBinaryOperation.Create(bOp, nil, Move(item), param.Line, param.Col);
  595. result := Merge(result, item);
  596. // Value
  597. end else if param.Quoted and IsValidIdentifier(param.Name) then begin
  598. if not (exValue in aExpected) then
  599. RaiseEx('unexpected value:', param);
  600. result := TengExpressionValue.Create(param.Name, param.Line, param.Col);
  601. // Variable
  602. end else if IsValidIdentifier(param.Name) then begin
  603. if not (exVariable in aExpected) then
  604. RaiseEx('unexpected variable:', param);
  605. sr := TkvpSearchResults.Create(param.Name, true, true);
  606. try
  607. fParent.Find(SEARCH_FLAG_CURRENT_SCOPE, sr);
  608. tmp := ExtractSearchResult(fParent, param.Name, sr, param.Line, param.Col);
  609. result := TengExpressionVariable.Create(param.Name, (tmp as TengShaderPartKeyValuePair), param.Line, param.Col);
  610. finally
  611. FreeAndNil(sr);
  612. end;
  613. // Unknown
  614. end else
  615. raise EengExpression.Create('invalid parameter: ' + param.Name, param.Line, param.Col, fParent.Filename, fParent);
  616. end;
  617. if not Assigned(result) and not (exGroupEnd in aExpected) then
  618. RaiseEx('unexpected', param, 'end');
  619. except
  620. FreeAndNil(item);
  621. FreeAndNil(result);
  622. raise;
  623. end;
  624. end;
  625. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  626. function TExpressionParser.GetGroup: TengExpressionItem;
  627. var
  628. ex: TExpectedParams;
  629. item: TengExpressionItem;
  630. b: Boolean;
  631. begin
  632. item := nil;
  633. result := nil;
  634. try
  635. ex := [exVariable, exValue, exGroupBegin, exUnaryOperation];
  636. repeat
  637. item := GetExpr(ex);
  638. b := Assigned(item);
  639. result := Merge(result, Move(item));
  640. ex := ex + [exBinaryOperation, exGroupEnd];
  641. until not b;
  642. except
  643. FreeAndNil(result);
  644. FreeAndNil(item);
  645. raise;
  646. end;
  647. end;
  648. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  649. constructor TExpressionParser.Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
  650. begin
  651. fParamPos := aIndex - 1;
  652. fParams := aParams;
  653. fParent := aParent;
  654. end;
  655. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  656. function ParseExpression(const aParent: TengShaderPart; const aParams: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
  657. var
  658. parser: TExpressionParser;
  659. begin
  660. parser := TExpressionParser.Create(aParent, aParams, aIndex);
  661. try
  662. result := parser.GetGroup;
  663. finally
  664. FreeAndNil(parser);
  665. end;
  666. end;
  667. end.