Advertisement
AbbatFaria

Logical expression parser

Aug 31st, 2023
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 6.89 KB | Source Code | 0 0
  1. unit uExpressionParser;
  2. {$mode Delphi}
  3.  
  4. interface
  5.  
  6. uses
  7.   Classes, SysUtils, Generics.Collections,
  8.   uDCLData, uDCLConst;
  9.  
  10.  function ParseLogicalExpression(S: String): Boolean;
  11.  function LogicalParser(S: String): TList<TCondition>;
  12.  function CalcLogicalExpression(var Conditions: TList<TCondition>): Boolean;
  13.  
  14. implementation
  15.  
  16. uses
  17.    uStringParams;
  18.  
  19. function LogicalParser(S: String): TList<TCondition>;
  20. var
  21.   LeftMode, RightMode, NotExists, InString: Boolean;
  22.   LeftSide, RightSide: String;
  23.   p, l, i: Integer;
  24.   ConditionType: TConditionTypes;
  25.   ConditionItem: TCondition;
  26.   LastConditionPair: TPairCondition;
  27. begin
  28.   Result:=TList<TCondition>.Create;
  29.   LastConditionPair:=pcNone;
  30.  
  31.   S:=S+'&';
  32.   LeftMode:=True;
  33.   RightMode:=False;
  34.   InString:=False;
  35.   NotExists:=False;
  36.   LeftSide:='';
  37.   l:=Length(S);
  38.   p:=1;
  39.   ConditionType:=ctND;
  40.   RightSide:='';
  41.   while p<=l do
  42.   begin
  43.     if S[p]='(' then
  44.     begin
  45.       LeftMode:=False;
  46.       RightMode:=True;
  47.     end
  48.     else
  49.     if S[p]=')' then
  50.     begin
  51.       if NotExists then
  52.         ConditionType:=ctNotIn
  53.       else
  54.         ConditionType:=ctIn;
  55.       LeftMode:=False;
  56.       RightMode:=False;
  57.     end
  58.     else
  59.     if S[p]='[' then
  60.     begin
  61.       LeftMode:=False;
  62.       RightMode:=True;
  63.     end
  64.     else
  65.     if S[p]=']' then
  66.     begin
  67.       if NotExists then
  68.         ConditionType:=ctNotBt
  69.       else
  70.         ConditionType:=ctBt;
  71.       LeftMode:=False;
  72.       RightMode:=False;
  73.     end
  74.     else
  75.     if S[p]='=' then
  76.     begin
  77.       if NotExists then
  78.         ConditionType:=ctNotEq
  79.       else
  80.         ConditionType:=ctEq;
  81.       LeftMode:=False;
  82.       RightMode:=True;
  83.     end
  84.     else
  85.     if S[p]='<' then
  86.     begin
  87.       ConditionType:=ctLe;
  88.       LeftMode:=False;
  89.       RightMode:=True;
  90.  
  91.       if S[p+1]='=' then
  92.       begin
  93.         ConditionType:=ctLeEq;
  94.         Inc(p);
  95.       end;
  96.       if S[p+1]='>' then
  97.       begin
  98.         ConditionType:=ctNotEq;
  99.         Inc(p);
  100.       end;
  101.     end
  102.     else
  103.     if S[p]='>' then
  104.     begin
  105.       ConditionType:=ctGt;
  106.       LeftMode:=False;
  107.       RightMode:=True;
  108.  
  109.       if S[p+1]='=' then
  110.       begin
  111.         ConditionType:=ctGtEq;
  112.         Inc(p);
  113.       end;
  114.     end
  115.     else
  116.     if S[p] in ['&', '|'] then
  117.     begin
  118.       ConditionItem:=TCondition.Create;
  119.       ConditionItem.FieldNameLeft:=LeftSide;
  120.       ConditionItem.ConditionType:=ConditionType;
  121.  
  122.       case ConditionType of
  123.       ctEq, ctNotEq, ctGt, ctGtEq, ctLe, ctLeEq: begin
  124.         ConditionItem.Values.Add(GetClearParam(RightSide, ''''));
  125.       end;
  126.       ctBt, ctNotBt, ctNotIn, ctIn: begin
  127.         for i:=1 to ParamsCount(RightSide) do
  128.         begin
  129.           ConditionItem.Values.Add(GetClearParam(GetParam(RightSide, i), ''''));
  130.         end;
  131.       end;
  132.       end;
  133.  
  134.       ConditionItem.ItemCondition:=LastConditionPair;
  135.  
  136.       Result.Add(ConditionItem);
  137.  
  138.       LeftMode:=True;
  139.       RightMode:=False;
  140.       LeftSide:='';
  141.       RightSide:='';
  142.       ConditionType:=ctND;
  143.       NotExists:=False;
  144.  
  145.       if S[p]='&' then
  146.         LastConditionPair:=pcAnd;
  147.       if S[p]='|' then
  148.         LastConditionPair:=pcOr;
  149.     end
  150.     else
  151.     begin
  152.       if S[p]='!' then
  153.       begin
  154.         if LeftMode then
  155.         begin
  156.           if not InString then
  157.           begin
  158.             LeftMode:=False;
  159.             NotExists:=True;
  160.           end;
  161.         end;
  162.       end;
  163.  
  164.       if (S[p]<>' ') or InString then
  165.       begin
  166.         if LeftMode then
  167.         begin
  168.           LeftSide:=LeftSide+S[p];
  169.         end
  170.         else
  171.         if RightMode then
  172.         begin
  173.           RightSide:=RightSide+S[p];
  174.         end;
  175.       end;
  176.  
  177.       if S[p]='''' then
  178.       begin
  179.         InString:=not InString;
  180.       end;
  181.     end;
  182.  
  183.     inc(p);
  184.   end;
  185. end;
  186.  
  187. function GetPairCondition(ItemCondition: TPairCondition; CurrResult, LastResult: Boolean): Boolean;
  188. begin
  189.   case ItemCondition of
  190.   pcNone: begin
  191.     Result:=CurrResult;
  192.   end;
  193.   pcAnd: begin
  194.     Result:=LastResult and CurrResult;
  195.   end;
  196.   pcOr: begin
  197.     Result:=LastResult or CurrResult;
  198.   end;
  199.   end;
  200. end;
  201.  
  202. function CalcLogicalExpression(var Conditions: TList<TCondition>): Boolean;
  203. var
  204.   CondItem: TCondition;
  205.   S: String;
  206.   LastResult, LocalResult: Boolean;
  207. begin
  208.   LastResult:=True;
  209.   for CondItem in Conditions do
  210.   begin
  211.     if CondItem.Values.Count>0 then
  212.     begin
  213.       case CondItem.ConditionType of
  214.       ctEq: begin
  215.         LastResult:=GetPairCondition(CondItem.ItemCondition, CondItem.FieldNameLeft=CondItem.Values[0], LastResult);
  216.       end;
  217.       ctNotEq: begin
  218.         LastResult:=GetPairCondition(CondItem.ItemCondition, CondItem.FieldNameLeft<>CondItem.Values[0], LastResult);
  219.       end;
  220.       ctGt: begin
  221.         LastResult:=GetPairCondition(CondItem.ItemCondition, CondItem.FieldNameLeft>CondItem.Values[0], LastResult);
  222.       end;
  223.       ctGtEq: begin
  224.         LastResult:=GetPairCondition(CondItem.ItemCondition, CondItem.FieldNameLeft>=CondItem.Values[0], LastResult);
  225.       end;
  226.       ctLe: begin
  227.         LastResult:=GetPairCondition(CondItem.ItemCondition, CondItem.FieldNameLeft<CondItem.Values[0], LastResult);
  228.       end;
  229.       ctLeEq: begin
  230.         LastResult:=GetPairCondition(CondItem.ItemCondition, CondItem.FieldNameLeft<=CondItem.Values[0], LastResult);
  231.       end;
  232.       ctBt, ctNotBt: begin
  233.         case CondItem.ConditionType of
  234.         ctBt: begin
  235.           if (CondItem.Values.Count>=2) and (CondItem.FieldNameLeft<=CondItem.Values[0]) and (CondItem.FieldNameLeft<=CondItem.Values[1]) then
  236.           begin
  237.             LastResult:=GetPairCondition(CondItem.ItemCondition, True, LastResult);
  238.           end
  239.           else
  240.             LastResult:=GetPairCondition(CondItem.ItemCondition, False, LastResult);
  241.         end;
  242.         ctNotBt: begin
  243.           if (CondItem.Values.Count>=2) and (not ((CondItem.FieldNameLeft<=CondItem.Values[0]) and (CondItem.FieldNameLeft<=CondItem.Values[1]))) then
  244.           begin
  245.             LastResult:=GetPairCondition(CondItem.ItemCondition, True, LastResult);
  246.           end
  247.           else
  248.             LastResult:=GetPairCondition(CondItem.ItemCondition, False, LastResult);
  249.         end;
  250.         end;
  251.       end;
  252.       ctNotIn, ctIn: begin
  253.         LocalResult:=CondItem.ConditionType=ctNotIn;
  254.         for S in CondItem.Values do
  255.         begin
  256.           if S=CondItem.FieldNameLeft then
  257.           begin
  258.             LocalResult:=CondItem.ConditionType=ctIn;
  259.             break;
  260.           end;
  261.         end;
  262.         LastResult:=GetPairCondition(CondItem.ItemCondition, LocalResult, LastResult);
  263.       end;
  264.       end;
  265.     end
  266.     else
  267.     begin
  268.       LastResult:=GetPairCondition(CondItem.ItemCondition, False, LastResult);
  269.     end;
  270.   end;
  271.  
  272.   Result:=LastResult;
  273. end;
  274.  
  275. function ParseLogicalExpression(S: String): Boolean;
  276. var
  277.   Conds: TList<TCondition>;
  278. begin
  279.   Conds:=LogicalParser(S);
  280.   Result:=CalcLogicalExpression(Conds);
  281. end;
  282.  
  283. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement