babylon.andOrNotEvaluator.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. module BABYLON.Internals {
  2. export class AndOrNotEvaluator {
  3. public static Eval(query: string, evaluateCallback: (val: any) => boolean): boolean {
  4. if (!query.match(/\([^\(\)]*\)/g)) {
  5. query = AndOrNotEvaluator._HandleParenthesisContent(query, evaluateCallback);
  6. }
  7. else {
  8. query = query.replace(/\([^\(\)]*\)/g, r => {
  9. // remove parenthesis
  10. r = r.slice(1, r.length - 1);
  11. return AndOrNotEvaluator._HandleParenthesisContent(r, evaluateCallback);
  12. });
  13. }
  14. if (query === "true") {
  15. return true;
  16. }
  17. if (query === "false") {
  18. return false;
  19. }
  20. return AndOrNotEvaluator.Eval(query, evaluateCallback);
  21. }
  22. private static _HandleParenthesisContent(parenthesisContent: string, evaluateCallback: (val) => boolean): string {
  23. evaluateCallback = evaluateCallback || ((r) => {
  24. return r === "true" ? true : false;
  25. });
  26. var result;
  27. var or = parenthesisContent.split("||");
  28. for (var i in or) {
  29. if (or.hasOwnProperty(i)) {
  30. var ori = AndOrNotEvaluator._SimplifyNegation(or[i].trim());
  31. var and = ori.split("&&");
  32. if (and.length > 1) {
  33. for (var j = 0; j < and.length; ++j) {
  34. var andj = AndOrNotEvaluator._SimplifyNegation(and[j].trim());
  35. if (andj !== "true" && andj !== "false") {
  36. if (andj[0] === "!") {
  37. result = !evaluateCallback(andj.substring(1));
  38. }
  39. else {
  40. result = evaluateCallback(andj);
  41. }
  42. }
  43. else {
  44. result = andj === "true" ? true : false;
  45. }
  46. if (!result) { // no need to continue since 'false && ... && ...' will always return false
  47. ori = "false";
  48. break;
  49. }
  50. }
  51. }
  52. if (result || ori === "true") { // no need to continue since 'true || ... || ...' will always return true
  53. result = true;
  54. break;
  55. }
  56. // result equals false (or undefined)
  57. if (ori !== "true" && ori !== "false") {
  58. if (ori[0] === "!") {
  59. result = !evaluateCallback(ori.substring(1));
  60. }
  61. else {
  62. result = evaluateCallback(ori);
  63. }
  64. }
  65. else {
  66. result = ori === "true" ? true : false;
  67. }
  68. }
  69. }
  70. // the whole parenthesis scope is replaced by 'true' or 'false'
  71. return result ? "true" : "false";
  72. }
  73. private static _SimplifyNegation(booleanString: string): string {
  74. booleanString = booleanString.replace(/^[\s!]+/, r => {
  75. // remove whitespaces
  76. r = r.replace(/[\s]/g, () => "");
  77. return r.length % 2 ? "!" : "";
  78. });
  79. booleanString = booleanString.trim();
  80. if (booleanString === "!true") {
  81. booleanString = "false";
  82. }
  83. else if (booleanString === "!false") {
  84. booleanString = "true";
  85. }
  86. return booleanString;
  87. }
  88. }
  89. }