fpexprpars.pp 125 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2008 Michael Van Canneyt.
  4. Expression parser, supports variables, functions and
  5. float/integer//boolean/datetime operations.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$mode objfpc}
  13. {$h+}
  14. {$IFNDEF FPC_DOTTEDUNITS}
  15. unit fpexprpars;
  16. {$ENDIF FPC_DOTTEDUNITS}
  17. interface
  18. {$IFDEF FPC_DOTTEDUNITS}
  19. uses
  20. System.Classes, System.SysUtils, System.Contnrs;
  21. {$ELSE FPC_DOTTEDUNITS}
  22. uses
  23. Classes, SysUtils, contnrs;
  24. {$ENDIF FPC_DOTTEDUNITS}
  25. Type
  26. // tokens
  27. TTokenType = (ttPlus, ttMinus, ttLessThan, ttLargerThan, ttEqual, ttDiv,
  28. ttMod, ttMul, ttLeft, ttRight, ttLessThanEqual,
  29. ttLargerThanEqual, ttunequal, ttNumber, ttString, ttIdentifier,
  30. ttComma, ttAnd, ttOr, ttXor, ttTrue, ttFalse, ttNot, ttif,
  31. ttCase, ttPower, ttEOF); // keep ttEOF last
  32. TExprFloat = Double;
  33. Const
  34. ttDelimiters = [ttPlus, ttMinus, ttLessThan, ttLargerThan, ttEqual, ttDiv,
  35. ttMul, ttLeft, ttRight, ttLessThanEqual, ttLargerThanEqual,
  36. ttunequal, ttPower];
  37. ttComparisons = [ttLargerThan,ttLessthan,
  38. ttLargerThanEqual,ttLessthanEqual,
  39. ttEqual,ttUnequal];
  40. Type
  41. TFPExpressionParser = Class;
  42. TExprBuiltInManager = Class;
  43. TFPExprFunction = Class;
  44. TFPExprFunctionClass = Class of TFPExprFunction;
  45. TNumberKind = (nkDecimal, nkHex, nkOctal, nkBinary);
  46. { TFPExpressionScanner }
  47. TFPExpressionScanner = Class(TObject)
  48. FSource : AnsiString;
  49. LSource,
  50. FPos : Integer;
  51. FChar : PAnsiChar;
  52. FToken : AnsiString;
  53. FTokenType : TTokenType;
  54. private
  55. function GetCurrentChar: AnsiChar;
  56. procedure ScanError(const Msg: AnsiString);
  57. protected
  58. procedure SetSource(const AValue: AnsiString ); virtual;
  59. function DoIdentifier: TTokenType;
  60. function DoNumber(AKind: TNumberKind): TTokenType;
  61. function DoDelimiter: TTokenType;
  62. function DoString: TTokenType;
  63. Function NextPos : AnsiChar; // inline;
  64. procedure SkipWhiteSpace; // inline;
  65. function IsWordDelim(C : AnsiChar) : Boolean; // inline;
  66. function IsDelim(C : AnsiChar) : Boolean; // inline;
  67. function IsDigit(C : AnsiChar; AKind: TNumberKind) : Boolean; // inline;
  68. function IsAlpha(C : AnsiChar) : Boolean; // inline;
  69. public
  70. Constructor Create;
  71. Function GetToken : TTokenType;
  72. Property Token : AnsiString Read FToken;
  73. Property TokenType : TTokenType Read FTokenType;
  74. Property Source : AnsiString Read FSource Write SetSource;
  75. Property Pos : Integer Read FPos;
  76. Property CurrentChar : AnsiChar Read GetCurrentChar;
  77. end;
  78. EExprScanner = Class(Exception);
  79. TResultType = (rtBoolean,rtInteger,rtFloat,rtDateTime,rtString,rtCurrency);
  80. TResultTypes = set of TResultType;
  81. TFPExpressionResult = record
  82. ResString : AnsiString;
  83. Case ResultType : TResultType of
  84. rtBoolean : (ResBoolean : Boolean);
  85. rtInteger : (ResInteger : Int64);
  86. rtFloat : (ResFloat : TExprFloat);
  87. rtCurrency : (ResCurrency : Currency);
  88. rtDateTime : (ResDateTime : TDatetime);
  89. rtString : ();
  90. end;
  91. PFPExpressionResult = ^TFPExpressionResult;
  92. TExprParameterArray = Array of TFPExpressionResult;
  93. { TFPExprNode }
  94. TFPExprNode = Class(TObject)
  95. Protected
  96. Procedure CheckNodeType(Anode : TFPExprNode; Allowed : TResultTypes);
  97. // A procedure with var saves an implicit try/finally in each node
  98. // A marked difference in execution speed.
  99. Procedure GetNodeValue(var Result : TFPExpressionResult); virtual; abstract;
  100. Public
  101. Procedure Check; virtual; abstract;
  102. Procedure InitAggregate; virtual;
  103. Procedure UpdateAggregate; virtual;
  104. Class Function IsAggregate : Boolean; virtual;
  105. Function HasAggregate : Boolean; virtual;
  106. Function NodeType : TResultType; virtual; abstract;
  107. Function NodeValue : TFPExpressionResult;
  108. Function AsString : AnsiString; virtual; abstract;
  109. end;
  110. TExprArgumentArray = Array of TFPExprNode;
  111. { TFPBinaryOperation }
  112. TFPBinaryOperation = Class(TFPExprNode)
  113. private
  114. FLeft: TFPExprNode;
  115. FRight: TFPExprNode;
  116. Protected
  117. Procedure CheckSameNodeTypes;
  118. Public
  119. Constructor Create(ALeft,ARight : TFPExprNode);
  120. Destructor Destroy; override;
  121. Procedure InitAggregate; override;
  122. Procedure UpdateAggregate; override;
  123. Function HasAggregate : Boolean; override;
  124. Procedure Check; override;
  125. Property left : TFPExprNode Read FLeft;
  126. Property Right : TFPExprNode Read FRight;
  127. end;
  128. TFPBinaryOperationClass = Class of TFPBinaryOperation;
  129. { TFPBooleanOperation }
  130. TFPBooleanOperation = Class(TFPBinaryOperation)
  131. Public
  132. Procedure Check; override;
  133. Function NodeType : TResultType; override;
  134. end;
  135. { TFPBinaryAndOperation }
  136. TFPBinaryAndOperation = Class(TFPBooleanOperation)
  137. Protected
  138. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  139. Public
  140. Function AsString : AnsiString; override;
  141. end;
  142. { TFPBinaryOrOperation }
  143. TFPBinaryOrOperation = Class(TFPBooleanOperation)
  144. Protected
  145. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  146. Public
  147. Function AsString : AnsiString; override;
  148. end;
  149. { TFPBinaryXOrOperation }
  150. TFPBinaryXOrOperation = Class(TFPBooleanOperation)
  151. Protected
  152. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  153. Public
  154. Function AsString : AnsiString; override;
  155. end;
  156. { TFPBooleanResultOperation }
  157. TFPBooleanResultOperation = Class(TFPBinaryOperation)
  158. Public
  159. Procedure Check; override;
  160. Function NodeType : TResultType; override;
  161. end;
  162. TFPBooleanResultOperationClass = Class of TFPBooleanResultOperation;
  163. { TFPEqualOperation }
  164. TFPEqualOperation = Class(TFPBooleanResultOperation)
  165. Protected
  166. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  167. Public
  168. Function AsString : AnsiString; override;
  169. end;
  170. { TFPUnequalOperation }
  171. TFPUnequalOperation = Class(TFPEqualOperation)
  172. Protected
  173. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  174. Public
  175. Function AsString : AnsiString; override;
  176. end;
  177. { TFPOrderingOperation }
  178. TFPOrderingOperation = Class(TFPBooleanResultOperation)
  179. Public
  180. Procedure Check; override;
  181. end;
  182. { TFPLessThanOperation }
  183. TFPLessThanOperation = Class(TFPOrderingOperation)
  184. Protected
  185. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  186. Public
  187. Function AsString : AnsiString; override;
  188. end;
  189. { TFPGreaterThanOperation }
  190. TFPGreaterThanOperation = Class(TFPOrderingOperation)
  191. Protected
  192. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  193. Public
  194. Function AsString : AnsiString; override;
  195. end;
  196. { TFPLessThanEqualOperation }
  197. TFPLessThanEqualOperation = Class(TFPGreaterThanOperation)
  198. Protected
  199. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  200. Public
  201. Function AsString : AnsiString; override;
  202. end;
  203. { TFPGreaterThanEqualOperation }
  204. TFPGreaterThanEqualOperation = Class(TFPLessThanOperation)
  205. Protected
  206. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  207. Public
  208. Function AsString : AnsiString; override;
  209. end;
  210. { TIfOperation }
  211. TIfOperation = Class(TFPBinaryOperation)
  212. private
  213. FCondition: TFPExprNode;
  214. protected
  215. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  216. Public
  217. Procedure Check; override;
  218. Procedure InitAggregate; override;
  219. Procedure UpdateAggregate; override;
  220. Function HasAggregate : Boolean; override;
  221. Function NodeType : TResultType; override;
  222. Constructor Create(ACondition,ALeft,ARight : TFPExprNode);
  223. Destructor destroy; override;
  224. Function AsString : AnsiString; override;
  225. Property Condition : TFPExprNode Read FCondition;
  226. end;
  227. { TCaseOperation }
  228. TCaseOperation = Class(TFPExprNode)
  229. private
  230. FArgs : TExprArgumentArray;
  231. FCondition: TFPExprNode;
  232. protected
  233. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  234. Public
  235. Procedure Check; override;
  236. Procedure InitAggregate; override;
  237. Procedure UpdateAggregate; override;
  238. function HasAggregate: Boolean; override;
  239. Function NodeType : TResultType; override;
  240. Constructor Create(Args : TExprArgumentArray);
  241. Destructor destroy; override;
  242. Function AsString : AnsiString; override;
  243. Property Condition : TFPExprNode Read FCondition;
  244. end;
  245. { TMathOperation }
  246. TMathOperation = Class(TFPBinaryOperation)
  247. Public
  248. Procedure Check; override;
  249. Function NodeType : TResultType; override;
  250. end;
  251. { TFPAddOperation }
  252. TFPAddOperation = Class(TMathOperation)
  253. Protected
  254. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  255. Public
  256. Function AsString : AnsiString; override;
  257. end;
  258. { TFPSubtractOperation }
  259. TFPSubtractOperation = Class(TMathOperation)
  260. Public
  261. Procedure Check; override;
  262. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  263. Function AsString : AnsiString; override;
  264. end;
  265. { TFPMultiplyOperation }
  266. TFPMultiplyOperation = Class(TMathOperation)
  267. Public
  268. Procedure check; override;
  269. Function AsString : AnsiString; override;
  270. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  271. end;
  272. { TFPDivideOperation }
  273. TFPDivideOperation = Class(TMathOperation)
  274. Public
  275. Procedure Check; override;
  276. Function AsString : AnsiString; override;
  277. Function NodeType : TResultType; override;
  278. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  279. end;
  280. { TFPModuloOperation }
  281. TFPModuloOperation = Class(TMathOperation)
  282. Public
  283. Procedure Check; override;
  284. Function AsString : AnsiString; override;
  285. Function NodeType : TResultType; override;
  286. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  287. end;
  288. { TFPPowerOperation }
  289. TFPPowerOperation = class(TMathOperation)
  290. public
  291. Procedure Check; override;
  292. Function AsString : AnsiString; override;
  293. Function NodeType : TResultType; override;
  294. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  295. end;
  296. { TFPUnaryOperator }
  297. TFPUnaryOperator = Class(TFPExprNode)
  298. private
  299. FOperand: TFPExprNode;
  300. Public
  301. Constructor Create(AOperand : TFPExprNode);
  302. Destructor Destroy; override;
  303. Procedure InitAggregate; override;
  304. Procedure UpdateAggregate; override;
  305. Function HasAggregate : Boolean; override;
  306. Procedure Check; override;
  307. Property Operand : TFPExprNode Read FOperand;
  308. end;
  309. { TFPConvertNode }
  310. TFPConvertNode = Class(TFPUnaryOperator)
  311. Function AsString : AnsiString; override;
  312. end;
  313. { TFPNotNode }
  314. TFPNotNode = Class(TFPUnaryOperator)
  315. Public
  316. Procedure Check; override;
  317. Function NodeType : TResultType; override;
  318. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  319. Function AsString : AnsiString; override;
  320. end;
  321. TIntConvertNode = Class(TFPConvertNode)
  322. Public
  323. Procedure Check; override;
  324. end;
  325. { TIntToFloatNode }
  326. TIntToFloatNode = Class(TIntConvertNode)
  327. Public
  328. Function NodeType : TResultType; override;
  329. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  330. end;
  331. { TIntToCurrencyNode }
  332. TIntToCurrencyNode = Class(TIntConvertNode)
  333. Public
  334. Function NodeType : TResultType; override;
  335. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  336. end;
  337. { TIntToDateTimeNode }
  338. TIntToDateTimeNode = Class(TIntConvertNode)
  339. Public
  340. Function NodeType : TResultType; override;
  341. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  342. end;
  343. { TFloatToDateTimeNode }
  344. TFloatToDateTimeNode = Class(TFPConvertNode)
  345. Public
  346. Procedure Check; override;
  347. Function NodeType : TResultType; override;
  348. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  349. end;
  350. { TFloatToCurrencyNode }
  351. TFloatToCurrencyNode = Class(TFPConvertNode)
  352. Public
  353. Procedure Check; override;
  354. Function NodeType : TResultType; override;
  355. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  356. end;
  357. { TCurrencyToDateTimeNode }
  358. TCurrencyToDateTimeNode = Class(TFPConvertNode)
  359. Public
  360. Procedure Check; override;
  361. Function NodeType : TResultType; override;
  362. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  363. end;
  364. { TCurrencyToFloatNode }
  365. TCurrencyToFloatNode = Class(TFPConvertNode)
  366. Public
  367. Procedure Check; override;
  368. Function NodeType : TResultType; override;
  369. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  370. end;
  371. { TFPNegateOperation }
  372. TFPNegateOperation = Class(TFPUnaryOperator)
  373. Public
  374. Procedure Check; override;
  375. Function NodeType : TResultType; override;
  376. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  377. Function AsString : AnsiString; override;
  378. end;
  379. { TFPConstExpression }
  380. TFPConstExpression = Class(TFPExprnode)
  381. private
  382. FValue : TFPExpressionResult;
  383. public
  384. Constructor CreateString(const AValue : AnsiString);
  385. Constructor CreateInteger(AValue : Int64);
  386. Constructor CreateDateTime(AValue : TDateTime);
  387. Constructor CreateFloat(AValue : TExprFloat);
  388. Constructor CreateBoolean(AValue : Boolean);
  389. constructor CreateCurrency(AValue: Currency);
  390. Procedure Check; override;
  391. Function NodeType : TResultType; override;
  392. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  393. Function AsString : AnsiString; override;
  394. // For inspection
  395. Property ConstValue : TFPExpressionResult read FValue;
  396. end;
  397. TIdentifierType = (itVariable,itFunctionCallBack,itFunctionHandler,itFunctionNode);
  398. TFPExprFunctionCallBack = Procedure (Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  399. TFPExprFunctionEvent = Procedure (Var Result : TFPExpressionResult; Const Args : TExprParameterArray) of object;
  400. TFPExprVariableCallBack = Procedure (Var Result : TFPExpressionResult; ConstRef AName : ShortString);
  401. TFPExprVariableEvent = Procedure (Var Result : TFPExpressionResult; ConstRef AName : ShortString) of Object;
  402. { TFPExprIdentifierDef }
  403. TFPExprIdentifierDef = Class(TCollectionItem)
  404. private
  405. FNodeType: TFPExprFunctionClass;
  406. FOnGetVarValue: TFPExprVariableEvent;
  407. FOnGetVarValueCB: TFPExprVariableCallBack;
  408. FStringValue : AnsiString;
  409. FValue : TFPExpressionResult;
  410. FArgumentTypes: AnsiString;
  411. FIDType: TIdentifierType;
  412. FName: ShortString;
  413. FVariableArgumentCount: Boolean;
  414. FOnGetValue: TFPExprFunctionEvent;
  415. FOnGetValueCB: TFPExprFunctionCallBack;
  416. function GetAsBoolean: Boolean;
  417. function GetAsDateTime: TDateTime;
  418. function GetAsFloat: TExprFloat;
  419. function GetAsCurrency : Currency;
  420. function GetAsInteger: Int64;
  421. function GetAsString: AnsiString;
  422. function GetResultType: TResultType;
  423. function GetValue: AnsiString;
  424. procedure SetArgumentTypes(const AValue: AnsiString);
  425. procedure SetAsBoolean(const AValue: Boolean);
  426. procedure SetAsDateTime(const AValue: TDateTime);
  427. procedure SetAsFloat(const AValue: TExprFloat);
  428. procedure SetAsCurrency(const AValue: Currency);
  429. procedure SetAsInteger(const AValue: Int64);
  430. procedure SetAsString(const AValue: AnsiString);
  431. procedure SetName(const AValue: ShortString);
  432. procedure SetResultType(const AValue: TResultType);
  433. procedure SetValue(const AValue: AnsiString);
  434. Protected
  435. Procedure CheckResultType(Const AType : TResultType);
  436. Procedure CheckVariable;
  437. Procedure FetchValue;
  438. Public
  439. Function ArgumentCount : Integer;
  440. Procedure Assign(Source : TPersistent); override;
  441. Function EventBasedVariable : Boolean; Inline;
  442. Property AsFloat : TExprFloat Read GetAsFloat Write SetAsFloat;
  443. Property AsCurrency : Currency Read GetAsCurrency Write SetAsCurrency;
  444. Property AsInteger : Int64 Read GetAsInteger Write SetAsInteger;
  445. Property AsString : AnsiString Read GetAsString Write SetAsString;
  446. Property AsBoolean : Boolean Read GetAsBoolean Write SetAsBoolean;
  447. Property AsDateTime : TDateTime Read GetAsDateTime Write SetAsDateTime;
  448. Property OnGetFunctionValueCallBack : TFPExprFunctionCallBack Read FOnGetValueCB Write FOnGetValueCB;
  449. Property OnGetVariableValueCallBack : TFPExprVariableCallBack Read FOnGetVarValueCB Write FOnGetVarValueCB;
  450. Published
  451. Property IdentifierType : TIdentifierType Read FIDType Write FIDType;
  452. Property Name : ShortString Read FName Write SetName;
  453. Property Value : AnsiString Read GetValue Write SetValue;
  454. Property ParameterTypes : AnsiString Read FArgumentTypes Write SetArgumentTypes;
  455. Property ResultType : TResultType Read GetResultType Write SetResultType;
  456. Property OnGetFunctionValue : TFPExprFunctionEvent Read FOnGetValue Write FOnGetValue;
  457. Property OnGetVariableValue : TFPExprVariableEvent Read FOnGetVarValue Write FOnGetVarValue;
  458. Property NodeType : TFPExprFunctionClass Read FNodeType Write FNodeType;
  459. property VariableArgumentCount: Boolean read FVariableArgumentCount write FVariableArgumentCount;
  460. end;
  461. TBuiltInCategory = (bcStrings,bcDateTime,bcMath,bcBoolean,bcConversion,bcData,bcVaria,bcUser,bcAggregate);
  462. TBuiltInCategories = Set of TBuiltInCategory;
  463. { TFPBuiltInExprIdentifierDef }
  464. TFPBuiltInExprIdentifierDef = Class(TFPExprIdentifierDef)
  465. private
  466. FCategory: TBuiltInCategory;
  467. Public
  468. Procedure Assign(Source : TPersistent); override;
  469. Published
  470. Property Category : TBuiltInCategory Read FCategory Write FCategory;
  471. end;
  472. { TFPExprIdentifierDefs }
  473. TFPExprIdentifierDefs = Class(TCollection)
  474. private
  475. FParser: TFPExpressionParser;
  476. function GetI(AIndex : Integer): TFPExprIdentifierDef;
  477. procedure SetI(AIndex : Integer; const AValue: TFPExprIdentifierDef);
  478. Protected
  479. procedure Update(Item: TCollectionItem); override;
  480. Property Parser: TFPExpressionParser Read FParser;
  481. Public
  482. Function IndexOfIdentifier(Const AName : ShortString) : Integer;
  483. Function FindIdentifier(Const AName : ShortString) : TFPExprIdentifierDef;
  484. Function IdentifierByName(Const AName : ShortString) : TFPExprIdentifierDef;
  485. Function AddVariable(Const AName : ShortString; AResultType : TResultType; ACallback : TFPExprVariableCallBack) : TFPExprIdentifierDef;
  486. Function AddVariable(Const AName : ShortString; AResultType : TResultType; ACallback : TFPExprVariableEvent) : TFPExprIdentifierDef;
  487. Function AddVariable(Const AName : ShortString; AResultType : TResultType; const AValue : AnsiString) : TFPExprIdentifierDef;
  488. Function AddBooleanVariable(Const AName : ShortString; AValue : Boolean) : TFPExprIdentifierDef;
  489. Function AddIntegerVariable(Const AName : ShortString; AValue : Integer) : TFPExprIdentifierDef;
  490. Function AddFloatVariable(Const AName : ShortString; AValue : TExprFloat) : TFPExprIdentifierDef;
  491. Function AddCurrencyVariable(Const AName : ShortString; AValue : Currency) : TFPExprIdentifierDef;
  492. Function AddStringVariable(Const AName : ShortString; const AValue : AnsiString) : TFPExprIdentifierDef;
  493. Function AddDateTimeVariable(Const AName : ShortString; AValue : TDateTime) : TFPExprIdentifierDef;
  494. Function AddFunction(Const AName : ShortString; Const AResultType : AnsiChar; Const AParamTypes : AnsiString; ACallBack : TFPExprFunctionCallBack) : TFPExprIdentifierDef;
  495. Function AddFunction(Const AName : ShortString; Const AResultType : AnsiChar; Const AParamTypes : AnsiString; ACallBack : TFPExprFunctionEvent) : TFPExprIdentifierDef;
  496. Function AddFunction(Const AName : ShortString; Const AResultType : AnsiChar; Const AParamTypes : AnsiString; ANodeClass : TFPExprFunctionClass) : TFPExprIdentifierDef;
  497. property Identifiers[AIndex : Integer] : TFPExprIdentifierDef Read GetI Write SetI; Default;
  498. end;
  499. { TFPExprIdentifierNode }
  500. TFPExprIdentifierNode = Class(TFPExprNode)
  501. Private
  502. FID : TFPExprIdentifierDef;
  503. PResult : PFPExpressionResult;
  504. FResultType : TResultType;
  505. public
  506. Constructor CreateIdentifier(AID : TFPExprIdentifierDef);
  507. Function NodeType : TResultType; override;
  508. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  509. Property Identifier : TFPExprIdentifierDef Read FID;
  510. end;
  511. { TFPExprVariable }
  512. TFPExprVariable = Class(TFPExprIdentifierNode)
  513. Procedure Check; override;
  514. function AsString: AnsiString; override;
  515. end;
  516. { TFPExprFunction }
  517. TFPExprFunction = Class(TFPExprIdentifierNode)
  518. private
  519. FArgumentNodes : TExprArgumentArray;
  520. FargumentParams : TExprParameterArray;
  521. Protected
  522. Procedure CalcParams;
  523. function ConvertArgument(aIndex: Integer; aNode: TFPExprNode; aType: TResultType): TFPExprNode; virtual;
  524. Public
  525. Procedure Check; override;
  526. Constructor CreateFunction(AID : TFPExprIdentifierDef; Const Args : TExprArgumentArray); virtual;
  527. Destructor Destroy; override;
  528. Procedure InitAggregate; override;
  529. Procedure UpdateAggregate; override;
  530. Function HasAggregate : Boolean; override;
  531. Property ArgumentNodes : TExprArgumentArray Read FArgumentNodes;
  532. Property ArgumentParams : TExprParameterArray Read FArgumentParams;
  533. Function AsString : AnsiString; override;
  534. end;
  535. { TAggregateExpr }
  536. TAggregateExpr = Class(TFPExprFunction)
  537. Protected
  538. FResult : TFPExpressionResult;
  539. public
  540. Class Function IsAggregate : Boolean; override;
  541. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  542. end;
  543. { TAggregateMin }
  544. TAggregateMin = Class(TAggregateExpr)
  545. Protected
  546. FFirst: Boolean;
  547. Public
  548. Procedure InitAggregate; override;
  549. Procedure UpdateAggregate; override;
  550. end;
  551. { TAggregateMax }
  552. TAggregateMax = Class(TAggregateExpr)
  553. Protected
  554. FFirst: Boolean;
  555. Public
  556. Procedure InitAggregate; override;
  557. Procedure UpdateAggregate; override;
  558. end;
  559. { TAggregateSum }
  560. TAggregateSum = Class(TAggregateExpr)
  561. Public
  562. function ConvertArgument(aIndex: Integer; aNode: TFPExprNode; aType: TResultType): TFPExprNode; override;
  563. Procedure InitAggregate; override;
  564. Procedure UpdateAggregate; override;
  565. end;
  566. { TAggregateAvg }
  567. TAggregateAvg = Class(TAggregateSum)
  568. Protected
  569. FCount : Integer;
  570. Public
  571. Procedure InitAggregate; override;
  572. Procedure UpdateAggregate; override;
  573. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  574. end;
  575. { TAggregateCount }
  576. TAggregateCount = Class(TAggregateExpr)
  577. Public
  578. Procedure InitAggregate; override;
  579. Procedure UpdateAggregate; override;
  580. end;
  581. { TFPFunctionCallBack }
  582. TFPFunctionCallBack = Class(TFPExprFunction)
  583. Private
  584. FCallBack : TFPExprFunctionCallBack;
  585. Public
  586. Constructor CreateFunction(AID : TFPExprIdentifierDef; Const Args : TExprArgumentArray); override;
  587. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  588. Property CallBack : TFPExprFunctionCallBack Read FCallBack;
  589. end;
  590. { TFPFunctionEventHandler }
  591. TFPFunctionEventHandler = Class(TFPExprFunction)
  592. Private
  593. FCallBack : TFPExprFunctionEvent;
  594. Public
  595. Constructor CreateFunction(AID : TFPExprIdentifierDef; Const Args : TExprArgumentArray); override;
  596. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  597. Property CallBack : TFPExprFunctionEvent Read FCallBack;
  598. end;
  599. { TFPExpressionParser }
  600. TIdentifierEvent = Procedure (Sender : TObject; Const aIdentifier : AnsiString; var aIdent : TFPExprIdentifierDef) of object;
  601. TFPExpressionParser = class(TComponent)
  602. private
  603. FBuiltIns: TBuiltInCategories;
  604. FExpression: AnsiString;
  605. FScanner : TFPExpressionScanner;
  606. FExprNode : TFPExprNode;
  607. FIdentifiers : TFPExprIdentifierDefs;
  608. FHashList : TFPHashObjectlist;
  609. FDirty : Boolean;
  610. FOnExtractIdentifier : TIdentifierEvent;
  611. FExtractIdentifiers : TStrings;
  612. FUnknownIdentifier : TFPExprIdentifierDef;
  613. procedure CheckEOF;
  614. function GetAsBoolean: Boolean;
  615. function GetAsDateTime: TDateTime;
  616. function GetAsFloat: TExprFloat;
  617. function GetAsCurrency: Currency;
  618. function GetAsInteger: Int64;
  619. function GetAsString: AnsiString;
  620. function GetExtractingIdentifiers: Boolean;
  621. function MatchNodes(Todo, Match: TFPExprNode): TFPExprNode;
  622. procedure CheckNodes(var Left, Right: TFPExprNode);
  623. procedure SetBuiltIns(const AValue: TBuiltInCategories);
  624. procedure SetIdentifiers(const AValue: TFPExprIdentifierDefs);
  625. procedure AddIdentifierToStrings(Sender : TObject; Const aIdentifier : AnsiString; var ID : TFPExprIdentifierDef);
  626. Protected
  627. procedure ParserError(const Msg: AnsiString);
  628. procedure SetExpression(const AValue: AnsiString); virtual;
  629. Procedure CheckResultType(Const Res :TFPExpressionResult; AType : TResultType); inline;
  630. Procedure CheckResultTypes(Const Res :TFPExpressionResult; ATypes : TResultTypes); inline;
  631. Class function ConvertNode(Todo: TFPExprNode; ToType: TResultType): TFPExprNode;
  632. class Function BuiltinsManager : TExprBuiltInManager;
  633. Function Level1 : TFPExprNode;
  634. Function Level2 : TFPExprNode;
  635. Function Level3 : TFPExprNode;
  636. Function Level4 : TFPExprNode;
  637. Function Level5 : TFPExprNode;
  638. Function Level6 : TFPExprNode;
  639. Function Level7 : TFPExprNode;
  640. Function Primitive : TFPExprNode;
  641. function GetToken: TTokenType;
  642. Function TokenType : TTokenType;
  643. Function CurrentToken : AnsiString;
  644. Procedure CreateHashList;
  645. Property Scanner : TFPExpressionScanner Read FScanner;
  646. Property ExprNode : TFPExprNode Read FExprNode;
  647. Property Dirty : Boolean Read FDirty;
  648. Property ExtractingIdentifiers : Boolean Read GetExtractingIdentifiers;
  649. public
  650. Constructor Create(AOwner :TComponent); override;
  651. Destructor Destroy; override;
  652. Function IdentifierByName(const AName : ShortString) : TFPExprIdentifierDef; virtual;
  653. Procedure Clear;
  654. Procedure EvaluateExpression(Out Result : TFPExpressionResult);
  655. Procedure ExtractIdentifierNames(Const aExpression : AnsiString; aList : TStringList); overload;
  656. Procedure ExtractIdentifierNames(Const aExpression : AnsiString; aCallback : TIdentifierEvent); overload;
  657. function ExtractNode(var N: TFPExprNode): Boolean;
  658. Function Evaluate : TFPExpressionResult;
  659. Function ResultType : TResultType;
  660. Function HasAggregate : Boolean;
  661. Procedure InitAggregate;
  662. Procedure UpdateAggregate;
  663. Property AsFloat : TExprFloat Read GetAsFloat;
  664. Property AsCurrency : Currency Read GetAsCurrency;
  665. Property AsInteger : Int64 Read GetAsInteger;
  666. Property AsString : AnsiString Read GetAsString;
  667. Property AsBoolean : Boolean Read GetAsBoolean;
  668. Property AsDateTime : TDateTime Read GetAsDateTime;
  669. Published
  670. // The Expression to parse
  671. property Expression : Ansistring read FExpression write SetExpression;
  672. Property Identifiers : TFPExprIdentifierDefs Read FIdentifiers Write SetIdentifiers;
  673. Property BuiltIns : TBuiltInCategories Read FBuiltIns Write SetBuiltIns;
  674. end;
  675. TFPExpressionParserClass = Class of TFPExpressionParser;
  676. { TExprBuiltInManager }
  677. TExprBuiltInManager = Class(TComponent)
  678. Private
  679. FDefs : TFPExprIdentifierDefs;
  680. function GetCount: Integer;
  681. function GetI(AIndex : Integer): TFPBuiltInExprIdentifierDef;
  682. protected
  683. Property Defs : TFPExprIdentifierDefs Read FDefs;
  684. Public
  685. Constructor Create(AOwner : TComponent); override;
  686. Destructor Destroy; override;
  687. Function IndexOfIdentifier(Const AName : ShortString) : Integer;
  688. Function FindIdentifier(Const AName : ShortString) : TFPBuiltinExprIdentifierDef;
  689. Function IdentifierByName(Const AName : ShortString) : TFPBuiltinExprIdentifierDef;
  690. Function AddVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AResultType : TResultType; const AValue : AnsiString) : TFPBuiltInExprIdentifierDef;
  691. Function AddBooleanVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : Boolean) : TFPBuiltInExprIdentifierDef;
  692. Function AddIntegerVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : Integer) : TFPBuiltInExprIdentifierDef;
  693. Function AddFloatVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : TExprFloat) : TFPBuiltInExprIdentifierDef;
  694. Function AddCurrencyVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : Currency) : TFPBuiltInExprIdentifierDef;
  695. Function AddStringVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; const AValue : AnsiString) : TFPBuiltInExprIdentifierDef;
  696. Function AddDateTimeVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : TDateTime) : TFPBuiltInExprIdentifierDef;
  697. Function AddFunction(Const ACategory : TBuiltInCategory; Const AName : ShortString; Const AResultType : AnsiChar; Const AParamTypes : AnsiString; ACallBack : TFPExprFunctionCallBack) : TFPBuiltInExprIdentifierDef;
  698. Function AddFunction(Const ACategory : TBuiltInCategory; Const AName : ShortString; Const AResultType : AnsiChar; Const AParamTypes : AnsiString; ACallBack : TFPExprFunctionEvent) : TFPBuiltInExprIdentifierDef;
  699. Function AddFunction(Const ACategory : TBuiltInCategory; Const AName : ShortString; Const AResultType : AnsiChar; Const AParamTypes : AnsiString; ANodeClass : TFPExprFunctionClass) : TFPBuiltInExprIdentifierDef;
  700. Procedure Delete(AIndex: Integer);
  701. Function Remove(const aIdentifier : AnsiString) : Integer;
  702. Property IdentifierCount : Integer Read GetCount;
  703. Property Identifiers[AIndex : Integer] :TFPBuiltInExprIdentifierDef Read GetI;
  704. end;
  705. EExprParser = Class(Exception);
  706. Const
  707. AllBuiltIns = [bcStrings,bcDateTime,bcMath,bcBoolean,bcConversion,bcData,bcVaria,bcUser,bcAggregate];
  708. Function TokenName (AToken : TTokenType) : AnsiString;
  709. Function ResultTypeName (AResult : TResultType) : AnsiString;
  710. Function CharToResultType(C : AnsiChar) : TResultType;
  711. Function BuiltinIdentifiers : TExprBuiltInManager;
  712. Procedure RegisterStdBuiltins(AManager : TExprBuiltInManager; Categories : TBuiltInCategories = AllBuiltIns);
  713. function ArgToFloat(Arg: TFPExpressionResult): TExprFloat;
  714. implementation
  715. {$IFDEF FPC_DOTTEDUNITS}
  716. uses System.TypInfo;
  717. {$ELSE FPC_DOTTEDUNITS}
  718. uses typinfo;
  719. {$ENDIF FPC_DOTTEDUNITS}
  720. { TFPExpressionParser }
  721. const
  722. cNull=#0;
  723. cSingleQuote = '''';
  724. cHexIdentifier = '$';
  725. cOctalIdentifier = '&';
  726. cBinaryIdentifier = '%';
  727. Digits = ['0'..'9','.'];
  728. HexDigits = ['0'..'9', 'A'..'F', 'a'..'f'];
  729. OctalDigits = ['0'..'7'];
  730. BinaryDigits = ['0', '1'];
  731. WhiteSpace = [' ',#13,#10,#9];
  732. Operators = ['+','-','<','>','=','/','*','^'];
  733. Delimiters = Operators+[',','(',')'];
  734. Symbols = ['%']+Delimiters;
  735. WordDelimiters = WhiteSpace + Symbols;
  736. var
  737. FileFormatSettings: TFormatSettings;
  738. Resourcestring
  739. SErrCannotRecursivelyExtractIdentifiers = 'Cannot recursively extract identifiers';
  740. SBadQuotes = 'Unterminated ';
  741. SUnknownDelimiter = 'Unknown delimiter character: "%s"';
  742. SErrUnknownCharacter = 'Unknown character at pos %d: "%s"';
  743. SErrUnexpectedEndOfExpression = 'Unexpected end of expression';
  744. SErrUnknownComparison = 'Internal error: Unknown comparison';
  745. SErrUnknownBooleanOp = 'Internal error: Unknown boolean operation';
  746. SErrBracketExpected = 'Expected ) bracket at position %d, but got %s';
  747. SerrUnknownTokenAtPos = 'Unknown token at pos %d : %s';
  748. SErrLeftBracketExpected = 'Expected ( bracket at position %d, but got %s';
  749. SErrInvalidFloat = '%s is not a valid floating-point value';
  750. SErrUnknownIdentifier = 'Unknown identifier: %s';
  751. SErrInExpression = 'Cannot evaluate: error in expression';
  752. SErrInExpressionEmpty = 'Cannot evaluate: empty expression';
  753. SErrCommaExpected = 'Expected comma (,) at position %d, but got %s';
  754. SErrInvalidNumberChar = 'Unexpected character in number : %s';
  755. SErrInvalidNumber = 'Invalid numerical value : %s';
  756. SErrUnterminatedIdentifier = 'Unterminated quoted identifier: %s';
  757. SErrNoOperand = 'No operand for unary operation %s';
  758. SErrNoleftOperand = 'No left operand for binary operation %s';
  759. SErrNoRightOperand = 'No right operand for binary operation %s';
  760. SErrNoNegation = 'Cannot negate expression of type %s : %s';
  761. SErrNoNOTOperation = 'Cannot perform "not" on expression of type %s: %s';
  762. SErrTypesDoNotMatch = 'Type mismatch: %s<>%s for expressions "%s" and "%s".';
  763. SErrNoNodeToCheck = 'Internal error: No node to check !';
  764. SInvalidNodeType = 'Node type (%s) not in allowed types (%s) for expression: %s';
  765. SErrUnterminatedExpression = 'Badly terminated expression. Found token at position %d : %s';
  766. SErrDuplicateIdentifier = 'An identifier with name "%s" already exists.';
  767. SErrInvalidResultCharacter = '"%s" is not a valid return type indicator';
  768. ErrInvalidArgumentCount = 'Invalid argument count for function %s';
  769. SErrInvalidArgumentType = 'Invalid type for argument %d: Expected %s, got %s';
  770. SErrInvalidResultType = 'Invalid result type: %s';
  771. SErrNotVariable = 'Identifier %s is not a variable';
  772. SErrIFNeedsBoolean = 'First argument to IF must be of type boolean: %s';
  773. SErrCaseNeeds3 = 'Case statement needs to have at least 4 arguments';
  774. SErrCaseEvenCount = 'Case statement needs to have an even number of arguments';
  775. SErrCaseLabelNotAConst = 'Case label %d "%s" is not a constant expression';
  776. SErrCaseLabelType = 'Case label %d "%s" needs type %s, but has type %s';
  777. SErrCaseValueType = 'Case value %d "%s" needs type %s, but has type %s';
  778. SErrDivisionByZero = '%s division by zero';
  779. { ---------------------------------------------------------------------
  780. Auxiliary functions
  781. ---------------------------------------------------------------------}
  782. Procedure RaiseParserError(const Msg : AnsiString);
  783. begin
  784. Raise EExprParser.Create(Msg);
  785. end;
  786. Procedure RaiseParserError(const Fmt : AnsiString; Args : Array of const);
  787. begin
  788. Raise EExprParser.CreateFmt(Fmt,Args);
  789. end;
  790. function TokenName(AToken: TTokenType): AnsiString;
  791. begin
  792. Result:=GetEnumName(TypeInfo(TTokenType),Ord(AToken));
  793. end;
  794. function ResultTypeName(AResult: TResultType): AnsiString;
  795. begin
  796. Result:=GetEnumName(TypeInfo(TResultType),Ord(AResult));
  797. end;
  798. function CharToResultType(C: AnsiChar): TResultType;
  799. begin
  800. Case Upcase(C) of
  801. 'S' : Result:=rtString;
  802. 'D' : Result:=rtDateTime;
  803. 'B' : Result:=rtBoolean;
  804. 'I' : Result:=rtInteger;
  805. 'F' : Result:=rtFloat;
  806. 'C' : Result:=rtCurrency;
  807. else
  808. RaiseParserError(SErrInvalidResultCharacter,[C]);
  809. end;
  810. end;
  811. Var
  812. BuiltIns : TExprBuiltInManager;
  813. function BuiltinIdentifiers: TExprBuiltInManager;
  814. begin
  815. If (BuiltIns=Nil) then
  816. BuiltIns:=TExprBuiltInManager.Create(Nil);
  817. Result:=BuiltIns;
  818. end;
  819. Procedure FreeBuiltIns;
  820. begin
  821. FreeAndNil(Builtins);
  822. end;
  823. { TFloatToCurrencyNode }
  824. procedure TFloatToCurrencyNode.Check;
  825. begin
  826. CheckNodeType(Operand,[rtFloat]);
  827. end;
  828. function TFloatToCurrencyNode.NodeType: TResultType;
  829. begin
  830. Result:=rtCurrency;
  831. end;
  832. procedure TFloatToCurrencyNode.GetNodeValue(var Result: TFPExpressionResult);
  833. begin
  834. Operand.GetNodeValue(Result);
  835. Result.ResultType:=rtCurrency;
  836. Result.ResCurrency:=Result.ResFloat;
  837. end;
  838. { TIntToCurrencyNode }
  839. function TIntToCurrencyNode.NodeType: TResultType;
  840. begin
  841. Result:=rtCurrency;
  842. end;
  843. procedure TIntToCurrencyNode.GetNodeValue(var Result: TFPExpressionResult);
  844. begin
  845. Operand.GetNodeValue(Result);
  846. Result.ResCurrency:=Result.ResInteger;
  847. Result.ResultType:=rtCurrency;
  848. end;
  849. { TFPModuloOperation }
  850. procedure TFPModuloOperation.Check;
  851. begin
  852. CheckNodeType(Left,[rtInteger]);
  853. CheckNodeType(Right,[rtInteger]);
  854. inherited Check;
  855. end;
  856. function TFPModuloOperation.AsString: AnsiString;
  857. begin
  858. Result:=Left.AsString+' mod '+Right.asString;
  859. end;
  860. function TFPModuloOperation.NodeType: TResultType;
  861. begin
  862. Result:=rtInteger;
  863. end;
  864. procedure TFPModuloOperation.GetNodeValue(var Result: TFPExpressionResult);
  865. Var
  866. RRes : TFPExpressionResult;
  867. begin
  868. Left.GetNodeValue(Result);
  869. Right.GetNodeValue(RRes);
  870. Result.ResInteger:=Result.ResInteger mod RRes.ResInteger;
  871. Result.ResultType:=rtInteger;
  872. end;
  873. { TAggregateMax }
  874. procedure TAggregateMax.InitAggregate;
  875. begin
  876. inherited InitAggregate;
  877. FFirst:=True;
  878. FResult.ResultType:=FArgumentNodes[0].NodeType;
  879. Case FResult.ResultType of
  880. rtFloat : FResult.resFloat:=0.0;
  881. rtCurrency : FResult.resCurrency:=0.0;
  882. rtInteger : FResult.resInteger:=0;
  883. end;
  884. end;
  885. procedure TAggregateMax.UpdateAggregate;
  886. Var
  887. OK : Boolean;
  888. N : TFPExpressionResult;
  889. begin
  890. FArgumentNodes[0].GetNodeValue(N);
  891. if FFirst then
  892. begin
  893. FResult.ResultType:=N.ResultType;
  894. FFirst:=False;
  895. OK:=True;
  896. end
  897. else
  898. Case N.ResultType of
  899. rtFloat: OK:=N.ResFloat>FResult.ResFloat;
  900. rtCurrency: OK:=N.ResCurrency>FResult.ResCurrency;
  901. rtinteger: OK:=N.ResInteger>FResult.ResFloat;
  902. end;
  903. if OK then
  904. Case N.ResultType of
  905. rtFloat: FResult.ResFloat:=N.ResFloat;
  906. rtinteger: FResult.ResFloat:=N.ResInteger;
  907. rtCurrency: FResult.ResCurrency:=N.ResCurrency;
  908. end;
  909. end;
  910. { TAggregateMin }
  911. procedure TAggregateMin.InitAggregate;
  912. begin
  913. inherited InitAggregate;
  914. FFirst:=True;
  915. FResult.ResultType:=FArgumentNodes[0].NodeType;
  916. Case FResult.ResultType of
  917. rtFloat : FResult.resFloat:=0.0;
  918. rtCurrency : FResult.resCurrency:=0.0;
  919. rtInteger : FResult.resInteger:=0;
  920. end;
  921. end;
  922. procedure TAggregateMin.UpdateAggregate;
  923. Var
  924. OK : Boolean;
  925. N : TFPExpressionResult;
  926. begin
  927. FArgumentNodes[0].GetNodeValue(N);
  928. if FFirst then
  929. begin
  930. FFirst:=False;
  931. OK:=True;
  932. end
  933. else
  934. Case N.ResultType of
  935. rtFloat: OK:=N.ResFloat<FResult.ResFloat;
  936. rtCurrency: OK:=N.ResCurrency<FResult.ResCurrency;
  937. rtinteger: OK:=N.ResInteger<FResult.ResFloat;
  938. end;
  939. if OK then
  940. Case FResult.ResultType of
  941. rtFloat: FResult.ResFloat:=N.ResFloat;
  942. rtCurrency: FResult.ResCurrency:=N.ResCurrency;
  943. rtinteger: FResult.ResFloat:=N.ResInteger;
  944. end;
  945. inherited UpdateAggregate;
  946. end;
  947. { TAggregateAvg }
  948. procedure TAggregateAvg.InitAggregate;
  949. begin
  950. inherited InitAggregate;
  951. end;
  952. procedure TAggregateAvg.UpdateAggregate;
  953. begin
  954. inherited UpdateAggregate;
  955. Inc(FCount);
  956. end;
  957. procedure TAggregateAvg.GetNodeValue(var Result: TFPExpressionResult);
  958. begin
  959. inherited GetNodeValue(Result);
  960. Result.ResultType:=FResult.ResultType;
  961. if FCount=0 then
  962. Case FResult.ResultType of
  963. rtInteger:
  964. begin
  965. Result.ResultType:=rtFloat;
  966. Result.ResFloat:=0.0;
  967. end;
  968. rtFloat:
  969. Result.ResFloat:=0.0;
  970. rtCurrency:
  971. Result.ResCurrency:=0.0;
  972. end
  973. else
  974. Case FResult.ResultType of
  975. rtInteger:
  976. begin
  977. Result.ResultType:=rtFloat;
  978. Result.ResFloat:=FResult.ResInteger/FCount;
  979. end;
  980. rtFloat:
  981. Result.ResFloat:=FResult.ResFloat/FCount;
  982. rtCurrency:
  983. Result.ResCurrency:=FResult.ResCurrency/FCount;
  984. end;
  985. end;
  986. { TAggregateCount }
  987. procedure TAggregateCount.InitAggregate;
  988. begin
  989. FResult.ResultType:=rtInteger;
  990. FResult.ResInteger:=0;
  991. end;
  992. procedure TAggregateCount.UpdateAggregate;
  993. begin
  994. Inc(FResult.ResInteger);
  995. end;
  996. { TAggregateExpr }
  997. class function TAggregateExpr.IsAggregate: Boolean;
  998. begin
  999. Result:=True;
  1000. end;
  1001. procedure TAggregateExpr.GetNodeValue(var Result: TFPExpressionResult);
  1002. begin
  1003. Result:=FResult;
  1004. end;
  1005. { TAggregateSum }
  1006. function TAggregateSum.ConvertArgument(aIndex: Integer; aNode: TFPExprNode; aType: TResultType): TFPExprNode;
  1007. begin
  1008. if not (aNode.NodeType in [rtFloat,rtInteger,rtCurrency]) then
  1009. RaiseParserError(SErrInvalidArgumentType,[aIndex,ResultTypeName(aType),ResultTypeName(aNode.NodeType)]);
  1010. Result:=aNode;
  1011. end;
  1012. procedure TAggregateSum.InitAggregate;
  1013. begin
  1014. FResult.ResultType:=FArgumentNodes[0].NodeType;
  1015. Case FResult.ResultType of
  1016. rtFloat: FResult.ResFloat:=0.0;
  1017. rtCurrency : FResult.ResCurrency:=0.0;
  1018. rtinteger: FResult.ResInteger:=0;
  1019. end;
  1020. end;
  1021. procedure TAggregateSum.UpdateAggregate;
  1022. Var
  1023. R : TFPExpressionResult;
  1024. begin
  1025. FArgumentNodes[0].GetNodeValue(R);
  1026. Case FResult.ResultType of
  1027. rtFloat: FResult.ResFloat:=FResult.ResFloat+R.ResFloat;
  1028. rtCurrency: FResult.ResCurrency:=FResult.ResCurrency+R.ResCurrency;
  1029. rtinteger: FResult.ResInteger:=FResult.ResInteger+R.ResInteger;
  1030. end;
  1031. end;
  1032. { ---------------------------------------------------------------------
  1033. TFPExpressionScanner
  1034. ---------------------------------------------------------------------}
  1035. function TFPExpressionScanner.IsAlpha(C: AnsiChar): Boolean;
  1036. begin
  1037. Result := C in ['A'..'Z', 'a'..'z'];
  1038. end;
  1039. constructor TFPExpressionScanner.Create;
  1040. begin
  1041. Source:='';
  1042. end;
  1043. procedure TFPExpressionScanner.SetSource(const AValue: AnsiString);
  1044. begin
  1045. FSource:=AValue;
  1046. LSource:=Length(FSource);
  1047. FTokenType:=ttEOF;
  1048. If LSource=0 then
  1049. FPos:=0
  1050. else
  1051. FPos:=1;
  1052. FChar:=PAnsiChar(FSource);
  1053. FToken:='';
  1054. end;
  1055. function TFPExpressionScanner.NextPos: AnsiChar;
  1056. begin
  1057. Inc(FPos);
  1058. Inc(FChar);
  1059. Result:=FChar^;
  1060. end;
  1061. function TFPExpressionScanner.IsWordDelim(C: AnsiChar): Boolean;
  1062. begin
  1063. Result:=C in WordDelimiters;
  1064. end;
  1065. function TFPExpressionScanner.IsDelim(C: AnsiChar): Boolean;
  1066. begin
  1067. Result:=C in Delimiters;
  1068. end;
  1069. function TFPExpressionScanner.IsDigit(C: AnsiChar; AKind: TNumberKind): Boolean;
  1070. begin
  1071. case AKind of
  1072. nkDecimal: Result := C in Digits;
  1073. nkHex : Result := C in HexDigits;
  1074. nkOctal : Result := C in OctalDigits;
  1075. nkBinary : Result := C in BinaryDigits;
  1076. end;
  1077. end;
  1078. Procedure TFPExpressionScanner.SkipWhiteSpace;
  1079. begin
  1080. While (FChar^ in WhiteSpace) and (FPos<=LSource) do
  1081. NextPos;
  1082. end;
  1083. Function TFPExpressionScanner.DoDelimiter : TTokenType;
  1084. Var
  1085. B : Boolean;
  1086. C,D : AnsiChar;
  1087. begin
  1088. C:=FChar^;
  1089. FToken:=C;
  1090. B:=C in ['<','>'];
  1091. D:=C;
  1092. C:=NextPos;
  1093. if B and (C in ['=','>']) then
  1094. begin
  1095. FToken:=FToken+C;
  1096. NextPos;
  1097. If (D='>') then
  1098. Result:=ttLargerThanEqual
  1099. else if (C='>') then
  1100. Result:=ttUnequal
  1101. else
  1102. Result:=ttLessThanEqual;
  1103. end
  1104. else
  1105. Case D of
  1106. '+' : Result := ttPlus;
  1107. '-' : Result := ttMinus;
  1108. '<' : Result := ttLessThan;
  1109. '>' : Result := ttLargerThan;
  1110. '=' : Result := ttEqual;
  1111. '/' : Result := ttDiv;
  1112. '*' : Result := ttMul;
  1113. '(' : Result := ttLeft;
  1114. ')' : Result := ttRight;
  1115. ',' : Result := ttComma;
  1116. '^' : Result := ttPower;
  1117. else
  1118. ScanError(Format(SUnknownDelimiter,[D]));
  1119. end;
  1120. end;
  1121. Procedure TFPExpressionScanner.ScanError(const Msg : AnsiString);
  1122. begin
  1123. Raise EExprScanner.Create(Msg)
  1124. end;
  1125. Function TFPExpressionScanner.DoString : TTokenType;
  1126. Function TerminatingChar(C : AnsiChar) : boolean;
  1127. begin
  1128. Result:=(C=cNull) or
  1129. ((C=cSingleQuote) and
  1130. Not ((FPos<LSource) and (FSource[FPos+1]=cSingleQuote)));
  1131. end;
  1132. Var
  1133. C : AnsiChar;
  1134. begin
  1135. FToken := '';
  1136. C:=NextPos;
  1137. while not TerminatingChar(C) do
  1138. begin
  1139. FToken:=FToken+C;
  1140. If C=cSingleQuote then
  1141. NextPos;
  1142. C:=NextPos;
  1143. end;
  1144. if (C=cNull) then
  1145. ScanError(SBadQuotes);
  1146. Result := ttString;
  1147. FTokenType:=Result;
  1148. NextPos;
  1149. end;
  1150. function TFPExpressionScanner.GetCurrentChar: AnsiChar;
  1151. begin
  1152. If FChar<>Nil then
  1153. Result:=FChar^
  1154. else
  1155. Result:=#0;
  1156. end;
  1157. procedure Val(const S: AnsiString; out V: TExprFloat; out Code: Integer);
  1158. var
  1159. L64: Int64;
  1160. begin
  1161. if (S <> '') and (S[1] in ['&', '$', '%']) then
  1162. begin
  1163. System.Val(S, L64, Code);
  1164. if Code = 0 then
  1165. V := L64
  1166. end
  1167. else
  1168. System.Val(S, V, Code);
  1169. end;
  1170. Function TFPExpressionScanner.DoNumber(AKind: TNumberKind) : TTokenType;
  1171. Var
  1172. C : AnsiChar;
  1173. X : TExprFloat;
  1174. I : Integer;
  1175. prevC: AnsiChar;
  1176. function ValidDigit(C: AnsiChar; AKind: TNumberKind): Boolean;
  1177. begin
  1178. Result := IsDigit(C, AKind);
  1179. if (not Result) then
  1180. case AKind of
  1181. nkDecimal:
  1182. Result := ((FToken <> '') and (UpCase(C)='E')) or
  1183. ((FToken <> '') and (C in ['+','-']) and (prevC='E'));
  1184. nkHex:
  1185. Result := (C = cHexIdentifier) and (prevC = #0);
  1186. nkOctal:
  1187. Result := (C = cOctalIdentifier) and (prevC = #0);
  1188. nkBinary:
  1189. Result := (C = cBinaryIdentifier) and (prevC = #0);
  1190. end;
  1191. end;
  1192. begin
  1193. C:=CurrentChar;
  1194. prevC := #0;
  1195. while (C <> cNull) do
  1196. begin
  1197. if IsWordDelim(C) then
  1198. case AKind of
  1199. nkDecimal:
  1200. if not (prevC in ['E','-','+']) then break;
  1201. nkHex, nkOctal:
  1202. break;
  1203. nkBinary:
  1204. if (prevC <> #0) then break; // allow '%' as first AnsiChar
  1205. end;
  1206. if not ValidDigit(C, AKind) then
  1207. ScanError(Format(SErrInvalidNumberChar,[C]));
  1208. FToken := FToken+C;
  1209. prevC := Upcase(C);
  1210. C:=NextPos;
  1211. end;
  1212. Val(FToken,X,I);
  1213. If (I<>0) then
  1214. ScanError(Format(SErrInvalidNumber,[FToken]));
  1215. Result:=ttNumber;
  1216. end;
  1217. Function TFPExpressionScanner.DoIdentifier : TTokenType;
  1218. Var
  1219. C : AnsiChar;
  1220. S : AnsiString;
  1221. begin
  1222. C:=CurrentChar;
  1223. while (not IsWordDelim(C)) and (C<>cNull) do
  1224. begin
  1225. if (C<>'"') then
  1226. FToken:=FToken+C
  1227. else
  1228. begin
  1229. C:=NextPos;
  1230. While Not (C in [cNull,'"']) do
  1231. begin
  1232. FToken:=FToken+C;
  1233. C:=NextPos;
  1234. end;
  1235. if (C<>'"') then
  1236. ScanError(Format(SErrUnterminatedIdentifier,[FToken]));
  1237. end;
  1238. C:=NextPos;
  1239. end;
  1240. S:=LowerCase(Token);
  1241. If (S='or') then
  1242. Result:=ttOr
  1243. else if (S='xor') then
  1244. Result:=ttXOr
  1245. else if (S='and') then
  1246. Result:=ttAnd
  1247. else if (S='true') then
  1248. Result:=ttTrue
  1249. else if (S='false') then
  1250. Result:=ttFalse
  1251. else if (S='not') then
  1252. Result:=ttnot
  1253. else if (S='if') then
  1254. Result:=ttif
  1255. else if (S='case') then
  1256. Result:=ttcase
  1257. else if (S='mod') then
  1258. Result:=ttMod
  1259. else
  1260. Result:=ttIdentifier;
  1261. end;
  1262. Function TFPExpressionScanner.GetToken : TTokenType;
  1263. Var
  1264. C : AnsiChar;
  1265. begin
  1266. FToken := '';
  1267. SkipWhiteSpace;
  1268. C:=FChar^;
  1269. if c=cNull then
  1270. Result:=ttEOF
  1271. else if IsDelim(C) then
  1272. Result:=DoDelimiter
  1273. else if (C=cSingleQuote) then
  1274. Result:=DoString
  1275. else if (C=cHexIdentifier) then
  1276. Result := DoNumber(nkHex)
  1277. else if (C=cOctalIdentifier) then
  1278. Result := DoNumber(nkOctal)
  1279. else if (C=cBinaryIdentifier) then
  1280. Result := DoNumber(nkBinary)
  1281. else if IsDigit(C, nkDecimal) then
  1282. Result:=DoNumber(nkDecimal)
  1283. else if IsAlpha(C) or (C='"') then
  1284. Result:=DoIdentifier
  1285. else
  1286. ScanError(Format(SErrUnknownCharacter,[FPos,C])) ;
  1287. FTokenType:=Result;
  1288. end;
  1289. { ---------------------------------------------------------------------
  1290. TFPExpressionParser
  1291. ---------------------------------------------------------------------}
  1292. function TFPExpressionParser.TokenType: TTokenType;
  1293. begin
  1294. Result:=FScanner.TokenType;
  1295. end;
  1296. function TFPExpressionParser.CurrentToken: AnsiString;
  1297. begin
  1298. Result:=FScanner.Token;
  1299. end;
  1300. procedure TFPExpressionParser.CreateHashList;
  1301. Var
  1302. ID : TFPExpridentifierDef;
  1303. BID : TFPBuiltinExpridentifierDef;
  1304. I : Integer;
  1305. M : TExprBuiltinManager;
  1306. begin
  1307. FHashList.Clear;
  1308. // Builtins
  1309. M:=BuiltinsManager;
  1310. If (FBuiltins<>[]) and Assigned(M) then
  1311. For I:=0 to M.IdentifierCount-1 do
  1312. begin
  1313. BID:=M.Identifiers[I];
  1314. If BID.Category in FBuiltins then
  1315. FHashList.Add(LowerCase(BID.Name),BID);
  1316. end;
  1317. // User
  1318. For I:=0 to FIdentifiers.Count-1 do
  1319. begin
  1320. ID:=FIdentifiers[i];
  1321. FHashList.Add(LowerCase(ID.Name),ID);
  1322. end;
  1323. FDirty:=False;
  1324. end;
  1325. function TFPExpressionParser.IdentifierByName(const AName: ShortString): TFPExprIdentifierDef;
  1326. begin
  1327. If FDirty then
  1328. CreateHashList;
  1329. Result:=TFPExprIdentifierDef(FHashList.Find(LowerCase(AName)));
  1330. end;
  1331. procedure TFPExpressionParser.Clear;
  1332. begin
  1333. FExpression:='';
  1334. FHashList.Clear;
  1335. FreeAndNil(FExprNode);
  1336. end;
  1337. constructor TFPExpressionParser.Create(AOwner: TComponent);
  1338. begin
  1339. inherited Create(AOwner);
  1340. FIdentifiers:=TFPExprIdentifierDefs.Create(TFPExprIdentifierDef);
  1341. FIdentifiers.FParser:=Self;
  1342. FScanner:=TFPExpressionScanner.Create;
  1343. FHashList:=TFPHashObjectList.Create(False);
  1344. end;
  1345. destructor TFPExpressionParser.Destroy;
  1346. begin
  1347. FreeAndNil(FHashList);
  1348. FreeAndNil(FExprNode);
  1349. FreeAndNil(FIdentifiers);
  1350. FreeAndNil(FScanner);
  1351. inherited Destroy;
  1352. end;
  1353. function TFPExpressionParser.GetToken: TTokenType;
  1354. begin
  1355. Result:=FScanner.GetToken;
  1356. end;
  1357. procedure TFPExpressionParser.CheckEOF;
  1358. begin
  1359. If (TokenType=ttEOF) then
  1360. ParserError(SErrUnexpectedEndOfExpression);
  1361. end;
  1362. procedure TFPExpressionParser.SetIdentifiers(const AValue: TFPExprIdentifierDefs
  1363. );
  1364. begin
  1365. FIdentifiers.Assign(AValue)
  1366. end;
  1367. procedure TFPExpressionParser.AddIdentifierToStrings(Sender: TObject; const aIdentifier: AnsiString; var ID : TFPExprIdentifierDef);
  1368. begin
  1369. ID:=Nil;
  1370. If Assigned(FExtractIdentifiers) then
  1371. FExtractIdentifiers.Add(aIdentifier);
  1372. end;
  1373. procedure TFPExpressionParser.EvaluateExpression(Out Result: TFPExpressionResult);
  1374. begin
  1375. If (FExpression='') then
  1376. ParserError(SErrInExpressionEmpty);
  1377. if not Assigned(FExprNode) then
  1378. ParserError(SErrInExpression);
  1379. FExprNode.GetNodeValue(Result);
  1380. end;
  1381. Procedure TFPExpressionParser.ExtractIdentifierNames(Const aExpression : AnsiString; aCallback : TIdentifierEvent); overload;
  1382. Var
  1383. N : TFPExprNode;
  1384. OldExpr : AnsiString;
  1385. begin
  1386. if Assigned(Self.FOnExtractIdentifier) then
  1387. ParserError(SErrCannotRecursivelyExtractIdentifiers);
  1388. N:=Nil;
  1389. FOnExtractIdentifier:=aCallBack;
  1390. try
  1391. // for safety
  1392. FreeAndNil(FUnknownIdentifier);
  1393. // Save old data
  1394. OldExpr:=Expression;
  1395. ExtractNode(N);
  1396. // Parse
  1397. Expression:=aExpression;
  1398. finally
  1399. FOnExtractIdentifier:=Nil;
  1400. FreeAndNil(FUnknownIdentifier);
  1401. FExpression:=OldExpr;
  1402. FExprNode:=N;
  1403. end;
  1404. end;
  1405. procedure TFPExpressionParser.ExtractIdentifierNames(const aExpression: AnsiString; aList: TStringList);
  1406. begin
  1407. if Assigned(FExtractIdentifiers) then
  1408. ParserError(SErrCannotRecursivelyExtractIdentifiers);
  1409. FExtractIdentifiers:=aList;
  1410. try
  1411. ExtractIdentifierNames(aExpression,@AddIdentifierToStrings);
  1412. finally
  1413. FExtractIdentifiers:=Nil;
  1414. end;
  1415. end;
  1416. function TFPExpressionParser.ExtractNode(Var N : TFPExprNode) : Boolean;
  1417. begin
  1418. Result:=Assigned(FExprNode);
  1419. if Result then
  1420. begin
  1421. N:=FExprNode;
  1422. FExprNode:=Nil;
  1423. FExpression:='';
  1424. end;
  1425. end;
  1426. procedure TFPExpressionParser.ParserError(const Msg: AnsiString);
  1427. begin
  1428. Raise EExprParser.Create(Msg);
  1429. end;
  1430. Class function TFPExpressionParser.ConvertNode(Todo : TFPExprNode; ToType : TResultType): TFPExprNode;
  1431. begin
  1432. Result:=ToDo;
  1433. Case ToDo.NodeType of
  1434. rtInteger :
  1435. Case ToType of
  1436. rtFloat : Result:=TIntToFloatNode.Create(Result);
  1437. rtCurrency : Result:=TIntToCurrencyNode.Create(Result);
  1438. rtDateTime : Result:=TIntToDateTimeNode.Create(Result);
  1439. end;
  1440. rtFloat :
  1441. Case ToType of
  1442. rtCurrency : Result:=TFloatToCurrencyNode.Create(Result);
  1443. rtDateTime : Result:=TFloatToDateTimeNode.Create(Result);
  1444. end;
  1445. rtCurrency :
  1446. Case ToType of
  1447. rtFloat : Result:=TCurrencyToFloatNode.Create(Result);
  1448. rtDateTime : Result:=TCurrencyToDateTimeNode.Create(Result);
  1449. end;
  1450. end;
  1451. end;
  1452. function TFPExpressionParser.GetAsBoolean: Boolean;
  1453. var
  1454. Res: TFPExpressionResult;
  1455. begin
  1456. EvaluateExpression(Res);
  1457. CheckResultType(Res,rtBoolean);
  1458. Result:=Res.ResBoolean;
  1459. end;
  1460. function TFPExpressionParser.GetAsDateTime: TDateTime;
  1461. var
  1462. Res: TFPExpressionResult;
  1463. begin
  1464. EvaluateExpression(Res);
  1465. CheckResultType(Res,rtDateTime);
  1466. Result:=Res.ResDatetime;
  1467. end;
  1468. function TFPExpressionParser.GetAsFloat: TExprFloat;
  1469. var
  1470. Res: TFPExpressionResult;
  1471. begin
  1472. EvaluateExpression(Res);
  1473. CheckResultTypes(Res,[rtFloat,rtCurrency,rtInteger]);
  1474. case Res.ResultType of
  1475. rtInteger : Result:=Res.ResInteger;
  1476. rtFloat : Result:=Res.ResFloat;
  1477. rtCurrency : Result:=res.ResCurrency;
  1478. end;
  1479. end;
  1480. function TFPExpressionParser.GetAsCurrency: Currency;
  1481. var
  1482. Res: TFPExpressionResult;
  1483. begin
  1484. EvaluateExpression(Res);
  1485. CheckResultTypes(Res,[rtFloat,rtCurrency,rtInteger]);
  1486. case Res.ResultType of
  1487. rtInteger : Result:=Res.ResInteger;
  1488. rtFloat : Result:=Res.ResFloat;
  1489. rtCurrency : Result:=res.ResCurrency;
  1490. end;
  1491. end;
  1492. function TFPExpressionParser.GetAsInteger: Int64;
  1493. var
  1494. Res: TFPExpressionResult;
  1495. begin
  1496. EvaluateExpression(Res);
  1497. CheckResultType(Res,rtInteger);
  1498. Result:=Res.ResInteger;
  1499. end;
  1500. function TFPExpressionParser.GetAsString: AnsiString;
  1501. var
  1502. Res: TFPExpressionResult;
  1503. begin
  1504. EvaluateExpression(Res);
  1505. CheckResultType(Res,rtString);
  1506. Result:=Res.ResString;
  1507. end;
  1508. function TFPExpressionParser.GetExtractingIdentifiers: Boolean;
  1509. begin
  1510. Result:=Assigned(FOnExtractIdentifier);
  1511. end;
  1512. {
  1513. Checks types of todo and match. If ToDO can be converted to it matches
  1514. the type of match, then a node is inserted.
  1515. For binary operations, this function is called for both operands.
  1516. }
  1517. function TFPExpressionParser.MatchNodes(Todo,Match : TFPExprNode): TFPExprNode;
  1518. Var
  1519. FromType,ToType : TResultType;
  1520. begin
  1521. Result:=Todo;
  1522. FromType:=Todo.NodeType;
  1523. ToType:=Match.NodeType;
  1524. If (FromType<>ToType) then
  1525. Case FromType of
  1526. rtInteger:
  1527. if (ToType in [rtFloat,rtCurrency,rtDateTime]) then
  1528. Result:=ConvertNode(Todo,toType);
  1529. rtFloat:
  1530. if (ToType in [rtCurrency,rtDateTime]) then
  1531. Result:=ConvertNode(Todo,toType);
  1532. rtCurrency:
  1533. if (ToType in [rtFloat,rtDateTime]) then
  1534. Result:=ConvertNode(Todo,toType);
  1535. end;
  1536. end;
  1537. {
  1538. if the result types differ, they are converted to a common type if possible.
  1539. }
  1540. procedure TFPExpressionParser.CheckNodes(var Left, Right: TFPExprNode);
  1541. begin
  1542. Left:=MatchNodes(Left,Right);
  1543. Right:=MatchNodes(Right,Left);
  1544. end;
  1545. procedure TFPExpressionParser.SetBuiltIns(const AValue: TBuiltInCategories);
  1546. begin
  1547. if FBuiltIns=AValue then exit;
  1548. FBuiltIns:=AValue;
  1549. FDirty:=True;
  1550. end;
  1551. function TFPExpressionParser.Level1: TFPExprNode;
  1552. var
  1553. tt: TTokenType;
  1554. Right : TFPExprNode;
  1555. begin
  1556. {$ifdef debugexpr}Writeln('Level 1 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1557. if TokenType = ttNot then
  1558. begin
  1559. GetToken;
  1560. CheckEOF;
  1561. Right:=Level2;
  1562. Result:=TFPNotNode.Create(Right);
  1563. end
  1564. else
  1565. Result:=Level2;
  1566. Try
  1567. while (TokenType in [ttAnd,ttOr,ttXor]) do
  1568. begin
  1569. tt:=TokenType;
  1570. GetToken;
  1571. CheckEOF;
  1572. Right:=Level2;
  1573. Case tt of
  1574. ttOr : Result:=TFPBinaryOrOperation.Create(Result,Right);
  1575. ttAnd : Result:=TFPBinaryAndOperation.Create(Result,Right);
  1576. ttXor : Result:=TFPBinaryXorOperation.Create(Result,Right);
  1577. Else
  1578. ParserError(SErrUnknownBooleanOp)
  1579. end;
  1580. end;
  1581. Except
  1582. Result.Free;
  1583. Raise;
  1584. end;
  1585. end;
  1586. function TFPExpressionParser.Level2: TFPExprNode;
  1587. var
  1588. Right : TFPExprNode;
  1589. tt : TTokenType;
  1590. C : TFPBinaryOperationClass;
  1591. begin
  1592. {$ifdef debugexpr} Writeln('Level 2 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1593. Result:=Level3;
  1594. try
  1595. if (TokenType in ttComparisons) then
  1596. begin
  1597. tt:=TokenType;
  1598. GetToken;
  1599. CheckEOF;
  1600. Right:=Level3;
  1601. CheckNodes(Result,Right);
  1602. Case tt of
  1603. ttLessthan : C:=TFPLessThanOperation;
  1604. ttLessthanEqual : C:=TFPLessThanEqualOperation;
  1605. ttLargerThan : C:=TFPGreaterThanOperation;
  1606. ttLargerThanEqual : C:=TFPGreaterThanEqualOperation;
  1607. ttEqual : C:=TFPEqualOperation;
  1608. ttUnequal : C:=TFPUnequalOperation;
  1609. Else
  1610. ParserError(SErrUnknownComparison)
  1611. end;
  1612. Result:=C.Create(Result,Right);
  1613. end;
  1614. Except
  1615. Result.Free;
  1616. Raise;
  1617. end;
  1618. end;
  1619. function TFPExpressionParser.Level3: TFPExprNode;
  1620. var
  1621. tt : TTokenType;
  1622. right : TFPExprNode;
  1623. begin
  1624. {$ifdef debugexpr} Writeln('Level 3 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1625. Result:=Level4;
  1626. try
  1627. while TokenType in [ttPlus,ttMinus] do
  1628. begin
  1629. tt:=TokenType;
  1630. GetToken;
  1631. CheckEOF;
  1632. Right:=Level4;
  1633. if Not ExtractingIdentifiers then
  1634. CheckNodes(Result,Right);
  1635. Case tt of
  1636. ttPlus : Result:=TFPAddOperation.Create(Result,Right);
  1637. ttMinus : Result:=TFPSubtractOperation.Create(Result,Right);
  1638. end;
  1639. end;
  1640. Except
  1641. Result.Free;
  1642. Raise;
  1643. end;
  1644. end;
  1645. function TFPExpressionParser.Level4: TFPExprNode;
  1646. var
  1647. tt : TTokenType;
  1648. right : TFPExprNode;
  1649. begin
  1650. {$ifdef debugexpr} Writeln('Level 4 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1651. Result:=Level5;
  1652. try
  1653. while (TokenType in [ttMul,ttDiv,ttMod]) do
  1654. begin
  1655. tt:=TokenType;
  1656. GetToken;
  1657. Right:=Level5;
  1658. if Not ExtractingIdentifiers then
  1659. CheckNodes(Result,Right);
  1660. Case tt of
  1661. ttMul : Result:=TFPMultiplyOperation.Create(Result,Right);
  1662. ttDiv : Result:=TFPDivideOperation.Create(Result,Right);
  1663. ttMod : Result:=TFPModuloOperation.Create(Result,Right);
  1664. end;
  1665. end;
  1666. Except
  1667. Result.Free;
  1668. Raise;
  1669. end;
  1670. end;
  1671. function TFPExpressionParser.Level5: TFPExprNode;
  1672. Var
  1673. B : Boolean;
  1674. begin
  1675. {$ifdef debugexpr} Writeln('Level 5 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1676. B:=False;
  1677. if (TokenType in [ttPlus,ttMinus]) then
  1678. begin
  1679. B:=TokenType=ttMinus;
  1680. GetToken;
  1681. end;
  1682. Result:=Level6;
  1683. If B then
  1684. Result:=TFPNegateOperation.Create(Result);
  1685. end;
  1686. function TFPExpressionParser.Level6: TFPExprNode;
  1687. var
  1688. right: TFPExprNode;
  1689. begin
  1690. {$ifdef debugexpr} Writeln('Level 6 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1691. Result := Level7;
  1692. try
  1693. while (TokenType = ttPower) do
  1694. begin
  1695. GetToken;
  1696. right := Level5; // Accept '(', unary '+', '-' as next tokens
  1697. CheckNodes(Result, right);
  1698. Result := TFPPowerOperation.Create(Result, right);
  1699. end;
  1700. except
  1701. Result.Free;
  1702. Raise;
  1703. end;
  1704. end;
  1705. function TFPExpressionParser.Level7: TFPExprNode;
  1706. begin
  1707. {$ifdef debugexpr} Writeln('Level 7 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1708. if (TokenType=ttLeft) then
  1709. begin
  1710. GetToken;
  1711. Result:=Level1;
  1712. try
  1713. if (TokenType<>ttRight) then
  1714. ParserError(Format(SErrBracketExpected,[SCanner.Pos,CurrentToken]));
  1715. GetToken;
  1716. Except
  1717. Result.Free;
  1718. Raise;
  1719. end;
  1720. end
  1721. else
  1722. Result:=Primitive;
  1723. end;
  1724. function TFPExpressionParser.Primitive: TFPExprNode;
  1725. Var
  1726. I : Int64;
  1727. C : Integer;
  1728. X : TExprFloat;
  1729. ACount : Integer;
  1730. IFF : Boolean;
  1731. IFC : Boolean;
  1732. ID : TFPExprIdentifierDef;
  1733. Args : TExprArgumentArray;
  1734. AI : Integer;
  1735. S : AnsiString;
  1736. begin
  1737. {$ifdef debugexpr} Writeln('Primitive : ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1738. SetLength(Args,0);
  1739. if (TokenType=ttNumber) then
  1740. begin
  1741. if TryStrToInt64(CurrentToken,I) then
  1742. Result:=TFPConstExpression.CreateInteger(I)
  1743. else
  1744. begin
  1745. Val(CurrentToken,X,C);
  1746. If (C=0) then
  1747. Result:=TFPConstExpression.CreateFloat(X)
  1748. else
  1749. ParserError(Format(SErrInvalidFloat,[CurrentToken]));
  1750. end;
  1751. end
  1752. else if (TokenType=ttString) then
  1753. Result:=TFPConstExpression.CreateString(CurrentToken)
  1754. else if (TokenType in [ttTrue,ttFalse]) then
  1755. Result:=TFPConstExpression.CreateBoolean(TokenType=ttTrue)
  1756. else if Not (TokenType in [ttIdentifier,ttIf,ttcase]) then
  1757. ParserError(Format(SerrUnknownTokenAtPos,[Scanner.Pos,CurrentToken]))
  1758. else
  1759. begin
  1760. IFF:=TokenType=ttIf;
  1761. IFC:=TokenType=ttCase;
  1762. if Not (IFF or IFC) then
  1763. begin
  1764. S:=CurrentToken;
  1765. ID:=self.IdentifierByName(S);
  1766. If (ID=Nil) then
  1767. begin
  1768. if Assigned(FOnExtractIdentifier) then
  1769. begin
  1770. // Call only once in case of stringlist.
  1771. If Not (Assigned(FExtractIdentifiers) and (FExtractIdentifiers.IndexOf(S)<>-1)) then
  1772. FOnExtractIdentifier(Self,S,ID);
  1773. if (ID=Nil) then
  1774. begin
  1775. if not Assigned(FUnknownIdentifier) then
  1776. FUnknownIdentifier:=TFPExprIdentifierDef.Create(Nil);
  1777. ID:=FUnknownIdentifier;
  1778. end;
  1779. end
  1780. else
  1781. ParserError(Format(SErrUnknownIdentifier,[S]))
  1782. end
  1783. end;
  1784. // Determine number of arguments
  1785. if Iff then
  1786. ACount:=3
  1787. else if IfC then
  1788. ACount:=-4
  1789. else if (ID.IdentifierType in [itFunctionCallBack,itFunctionHandler,itFunctionNode]) then
  1790. ACount:=ID.ArgumentCount
  1791. else
  1792. ACount:=0;
  1793. // Parse arguments.
  1794. // Negative is for variable number of arguments, where Abs(value) is the minimum number of arguments
  1795. If (ACount<>0) then
  1796. begin
  1797. GetToken;
  1798. If (TokenType<>ttLeft) then
  1799. ParserError(Format(SErrLeftBracketExpected,[Scanner.Pos,CurrentToken]));
  1800. SetLength(Args,Abs(ACount));
  1801. AI:=0;
  1802. Try
  1803. Repeat
  1804. GetToken;
  1805. // Check if we must enlarge the argument array
  1806. If (ACount<0) and (AI=Length(Args)) then
  1807. begin
  1808. SetLength(Args,AI+1);
  1809. Args[AI]:=Nil;
  1810. end;
  1811. Args[AI]:=Level1;
  1812. Inc(AI);
  1813. If (TokenType<>ttComma) then
  1814. If (AI<Abs(ACount)) then
  1815. ParserError(Format(SErrCommaExpected,[Scanner.Pos,CurrentToken]))
  1816. Until (AI=ACount) or ((ACount<0) and (TokenType=ttRight));
  1817. If TokenType<>ttRight then
  1818. ParserError(Format(SErrBracketExpected,[Scanner.Pos,CurrentToken]));
  1819. except
  1820. On E : Exception do
  1821. begin
  1822. Dec(AI);
  1823. While (AI>=0) do
  1824. begin
  1825. FreeAndNil(Args[Ai]);
  1826. Dec(AI);
  1827. end;
  1828. Raise;
  1829. end;
  1830. end;
  1831. end;
  1832. If Iff then
  1833. Result:=TIfOperation.Create(Args[0],Args[1],Args[2])
  1834. else If IfC then
  1835. Result:=TCaseOperation.Create(Args)
  1836. else
  1837. Case ID.IdentifierType of
  1838. itVariable : Result:= TFPExprVariable.CreateIdentifier(ID);
  1839. itFunctionCallBack : Result:= TFPFunctionCallback.CreateFunction(ID,Args);
  1840. itFunctionHandler : Result:= TFPFunctionEventHandler.CreateFunction(ID,Args);
  1841. itFunctionNode : Result:= ID.NodeType.CreateFunction(ID,Args);
  1842. end;
  1843. end;
  1844. GetToken;
  1845. end;
  1846. procedure TFPExpressionParser.SetExpression(const AValue: AnsiString);
  1847. begin
  1848. if FExpression=AValue then exit;
  1849. FExpression:=AValue;
  1850. FScanner.Source:=AValue;
  1851. If Assigned(FExprNode) then
  1852. FreeAndNil(FExprNode);
  1853. If (FExpression<>'') then
  1854. begin
  1855. GetToken;
  1856. FExprNode:=Level1;
  1857. If (TokenType<>ttEOF) then
  1858. ParserError(Format(SErrUnterminatedExpression,[Scanner.Pos,CurrentToken]));
  1859. if not ExtractingIdentifiers then
  1860. FExprNode.Check;
  1861. end;
  1862. end;
  1863. procedure TFPExpressionParser.CheckResultType(const Res: TFPExpressionResult;
  1864. AType: TResultType); inline;
  1865. begin
  1866. If (Res.ResultType<>AType) then
  1867. RaiseParserError(SErrInvalidResultType,[ResultTypeName(Res.ResultType)]);
  1868. end;
  1869. procedure TFPExpressionParser.CheckResultTypes(const Res: TFPExpressionResult; ATypes: TResultTypes);
  1870. begin
  1871. If Not (Res.ResultType in ATypes) then
  1872. RaiseParserError(SErrInvalidResultType,[ResultTypeName(Res.ResultType)]);
  1873. end;
  1874. class function TFPExpressionParser.BuiltinsManager: TExprBuiltInManager;
  1875. begin
  1876. Result:=BuiltinIdentifiers;
  1877. end;
  1878. function TFPExpressionParser.Evaluate: TFPExpressionResult;
  1879. begin
  1880. EvaluateExpression(Result);
  1881. end;
  1882. function TFPExpressionParser.ResultType: TResultType;
  1883. begin
  1884. if not Assigned(FExprNode) then
  1885. ParserError(SErrInExpression);
  1886. Result:=FExprNode.NodeType;
  1887. end;
  1888. function TFPExpressionParser.HasAggregate: Boolean;
  1889. begin
  1890. Result:=Assigned(FExprNode) and FExprNode.HasAggregate;
  1891. end;
  1892. procedure TFPExpressionParser.InitAggregate;
  1893. begin
  1894. If Assigned(FExprNode) then
  1895. FExprNode.InitAggregate;
  1896. end;
  1897. procedure TFPExpressionParser.UpdateAggregate;
  1898. begin
  1899. If Assigned(FExprNode) then
  1900. FExprNode.UpdateAggregate;
  1901. end;
  1902. { ---------------------------------------------------------------------
  1903. TFPExprIdentifierDefs
  1904. ---------------------------------------------------------------------}
  1905. function TFPExprIdentifierDefs.GetI(AIndex : Integer): TFPExprIdentifierDef;
  1906. begin
  1907. Result:=TFPExprIdentifierDef(Items[AIndex]);
  1908. end;
  1909. procedure TFPExprIdentifierDefs.SetI(AIndex : Integer;
  1910. const AValue: TFPExprIdentifierDef);
  1911. begin
  1912. Items[AIndex]:=AValue;
  1913. end;
  1914. procedure TFPExprIdentifierDefs.Update(Item: TCollectionItem);
  1915. begin
  1916. If Assigned(FParser) then
  1917. FParser.FDirty:=True;
  1918. end;
  1919. function TFPExprIdentifierDefs.IndexOfIdentifier(const AName: ShortString
  1920. ): Integer;
  1921. begin
  1922. Result:=Count-1;
  1923. While (Result>=0) And (CompareText(GetI(Result).Name,AName)<>0) do
  1924. Dec(Result);
  1925. end;
  1926. function TFPExprIdentifierDefs.FindIdentifier(const AName: ShortString
  1927. ): TFPExprIdentifierDef;
  1928. Var
  1929. I : Integer;
  1930. begin
  1931. I:=IndexOfIdentifier(AName);
  1932. If (I=-1) then
  1933. Result:=Nil
  1934. else
  1935. Result:=GetI(I);
  1936. end;
  1937. function TFPExprIdentifierDefs.IdentifierByName(const AName: ShortString
  1938. ): TFPExprIdentifierDef;
  1939. begin
  1940. Result:=FindIdentifier(AName);
  1941. if (Result=Nil) then
  1942. RaiseParserError(SErrUnknownIdentifier,[AName]);
  1943. end;
  1944. function TFPExprIdentifierDefs.AddVariable(const AName: ShortString;
  1945. AResultType: TResultType; ACallback: TFPExprVariableCallBack
  1946. ): TFPExprIdentifierDef;
  1947. begin
  1948. Result:=Add as TFPExprIdentifierDef;
  1949. Result.IdentifierType:=itVariable;
  1950. Result.Name:=AName;
  1951. Result.ResultType:=AResultType;
  1952. Result.OnGetVariableValueCallBack:=ACallBack
  1953. end;
  1954. function TFPExprIdentifierDefs.AddVariable(const AName: ShortString;
  1955. AResultType: TResultType; ACallback: TFPExprVariableEvent
  1956. ): TFPExprIdentifierDef;
  1957. begin
  1958. Result:=Add as TFPExprIdentifierDef;
  1959. Result.IdentifierType:=itVariable;
  1960. Result.Name:=AName;
  1961. Result.ResultType:=AResultType;
  1962. Result.OnGetVariableValue:=ACallBack
  1963. end;
  1964. function TFPExprIdentifierDefs.AddVariable(const AName: ShortString;
  1965. AResultType: TResultType; const AValue: AnsiString): TFPExprIdentifierDef;
  1966. begin
  1967. Result:=Add as TFPExprIdentifierDef;
  1968. Result.IdentifierType:=itVariable;
  1969. Result.Name:=AName;
  1970. Result.ResultType:=AResultType;
  1971. Result.Value:=AValue;
  1972. end;
  1973. function TFPExprIdentifierDefs.AddBooleanVariable(const AName: ShortString;
  1974. AValue: Boolean): TFPExprIdentifierDef;
  1975. begin
  1976. Result:=Add as TFPExprIdentifierDef;
  1977. Result.IdentifierType:=itVariable;
  1978. Result.Name:=AName;
  1979. Result.ResultType:=rtBoolean;
  1980. Result.FValue.ResBoolean:=AValue;
  1981. end;
  1982. function TFPExprIdentifierDefs.AddIntegerVariable(const AName: ShortString;
  1983. AValue: Integer): TFPExprIdentifierDef;
  1984. begin
  1985. Result:=Add as TFPExprIdentifierDef;
  1986. Result.IdentifierType:=itVariable;
  1987. Result.Name:=AName;
  1988. Result.ResultType:=rtInteger;
  1989. Result.FValue.ResInteger:=AValue;
  1990. end;
  1991. function TFPExprIdentifierDefs.AddFloatVariable(const AName: ShortString;
  1992. AValue: TExprFloat): TFPExprIdentifierDef;
  1993. begin
  1994. Result:=Add as TFPExprIdentifierDef;
  1995. Result.IdentifierType:=itVariable;
  1996. Result.Name:=AName;
  1997. Result.ResultType:=rtFloat;
  1998. Result.FValue.ResFloat:=AValue;
  1999. end;
  2000. function TFPExprIdentifierDefs.AddCurrencyVariable(const AName: ShortString; AValue: Currency): TFPExprIdentifierDef;
  2001. begin
  2002. Result:=Add as TFPExprIdentifierDef;
  2003. Result.IdentifierType:=itVariable;
  2004. Result.Name:=AName;
  2005. Result.ResultType:=rtCurrency;
  2006. Result.FValue.ResCurrency:=AValue;
  2007. end;
  2008. function TFPExprIdentifierDefs.AddStringVariable(const AName: ShortString;
  2009. const AValue: AnsiString): TFPExprIdentifierDef;
  2010. begin
  2011. Result:=Add as TFPExprIdentifierDef;
  2012. Result.IdentifierType:=itVariable;
  2013. Result.Name:=AName;
  2014. Result.ResultType:=rtString;
  2015. Result.FValue.ResString:=AValue;
  2016. end;
  2017. function TFPExprIdentifierDefs.AddDateTimeVariable(const AName: ShortString;
  2018. AValue: TDateTime): TFPExprIdentifierDef;
  2019. begin
  2020. Result:=Add as TFPExprIdentifierDef;
  2021. Result.IdentifierType:=itVariable;
  2022. Result.Name:=AName;
  2023. Result.ResultType:=rtDateTime;
  2024. Result.FValue.ResDateTime:=AValue;
  2025. end;
  2026. function TFPExprIdentifierDefs.AddFunction(const AName: ShortString;
  2027. const AResultType: AnsiChar; const AParamTypes: AnsiString;
  2028. ACallBack: TFPExprFunctionCallBack): TFPExprIdentifierDef;
  2029. begin
  2030. Result:=Add as TFPExprIdentifierDef;
  2031. Result.Name:=Aname;
  2032. Result.IdentifierType:=itFunctionCallBack;
  2033. if (AParamTypes <> '') and (AParamTypes[Length(AParamTypes)] = '+') then begin
  2034. Result.ParameterTypes := Copy(AParamTypes, 1, Length(AParamTypes)-1);
  2035. Result.FVariableArgumentCount := true;
  2036. end else
  2037. Result.ParameterTypes := AParamTypes;
  2038. Result.ResultType:=CharToResultType(AResultType);
  2039. Result.FOnGetValueCB:=ACallBack;
  2040. end;
  2041. function TFPExprIdentifierDefs.AddFunction(const AName: ShortString;
  2042. const AResultType: AnsiChar; const AParamTypes: AnsiString;
  2043. ACallBack: TFPExprFunctionEvent): TFPExprIdentifierDef;
  2044. begin
  2045. Result:=Add as TFPExprIdentifierDef;
  2046. Result.Name:=Aname;
  2047. Result.IdentifierType:=itFunctionHandler;
  2048. if (AParamTypes <> '') and (AParamTypes[Length(AParamTypes)] = '+') then begin
  2049. Result.ParameterTypes := Copy(AParamTypes, 1, Length(AParamTypes)-1);
  2050. Result.FVariableArgumentCount := true;
  2051. end else
  2052. Result.ParameterTypes := AParamTypes;
  2053. Result.ResultType:=CharToResultType(AResultType);
  2054. Result.FOnGetValue:=ACallBack;
  2055. end;
  2056. function TFPExprIdentifierDefs.AddFunction(const AName: ShortString;
  2057. const AResultType: AnsiChar; const AParamTypes: AnsiString;
  2058. ANodeClass: TFPExprFunctionClass): TFPExprIdentifierDef;
  2059. begin
  2060. Result:=Add as TFPExprIdentifierDef;
  2061. Result.Name:=Aname;
  2062. Result.IdentifierType:=itFunctionNode;
  2063. if (AParamTypes <> '') and (AParamTypes[Length(AParamTypes)] = '+') then begin
  2064. Result.ParameterTypes := Copy(AParamTypes, 1, Length(AParamTypes)-1);
  2065. Result.FVariableArgumentCount := true;
  2066. end else
  2067. Result.ParameterTypes := AParamTypes;
  2068. Result.ResultType:=CharToResultType(AResultType);
  2069. Result.FNodeType:=ANodeClass;
  2070. end;
  2071. { ---------------------------------------------------------------------
  2072. TFPExprIdentifierDef
  2073. ---------------------------------------------------------------------}
  2074. procedure TFPExprIdentifierDef.SetName(const AValue: ShortString);
  2075. begin
  2076. if FName=AValue then exit;
  2077. If (AValue<>'') then
  2078. If Assigned(Collection) and (TFPExprIdentifierDefs(Collection).IndexOfIdentifier(AValue)<>-1) then
  2079. RaiseParserError(SErrDuplicateIdentifier,[AValue]);
  2080. FName:=AValue;
  2081. end;
  2082. procedure TFPExprIdentifierDef.SetResultType(const AValue: TResultType);
  2083. begin
  2084. If AValue<>FValue.ResultType then
  2085. begin
  2086. FValue.ResultType:=AValue;
  2087. SetValue(FStringValue);
  2088. end;
  2089. end;
  2090. procedure TFPExprIdentifierDef.SetValue(const AValue: AnsiString);
  2091. begin
  2092. FStringValue:=AValue;
  2093. If (AValue<>'') then
  2094. Case FValue.ResultType of
  2095. rtBoolean : FValue.ResBoolean:=FStringValue='True';
  2096. rtInteger : FValue.ResInteger:=StrToInt(AValue);
  2097. rtFloat : FValue.ResFloat:=StrToFloat(AValue, FileFormatSettings);
  2098. rtCurrency : FValue.ResFloat:=StrToCurr(AValue, FileFormatSettings);
  2099. rtDateTime : FValue.ResDateTime:=StrToDateTime(AValue, FileFormatSettings);
  2100. rtString : FValue.ResString:=AValue;
  2101. end
  2102. else
  2103. Case FValue.ResultType of
  2104. rtBoolean : FValue.ResBoolean:=False;
  2105. rtInteger : FValue.ResInteger:=0;
  2106. rtFloat : FValue.ResFloat:=0.0;
  2107. rtCurrency : FValue.ResCurrency:=0.0;
  2108. rtDateTime : FValue.ResDateTime:=0;
  2109. rtString : FValue.ResString:='';
  2110. end
  2111. end;
  2112. procedure TFPExprIdentifierDef.CheckResultType(const AType: TResultType);
  2113. begin
  2114. If FValue.ResultType<>AType then
  2115. RaiseParserError(SErrInvalidResultType,[ResultTypeName(AType)])
  2116. end;
  2117. procedure TFPExprIdentifierDef.CheckVariable;
  2118. begin
  2119. If Identifiertype<>itvariable then
  2120. RaiseParserError(SErrNotVariable,[Name]);
  2121. if EventBasedVariable then
  2122. FetchValue;
  2123. end;
  2124. function TFPExprIdentifierDef.ArgumentCount: Integer;
  2125. begin
  2126. if FVariableArgumentCount then
  2127. Result := -Length(FArgumentTypes)
  2128. else
  2129. Result:=Length(FArgumentTypes);
  2130. end;
  2131. procedure TFPExprIdentifierDef.Assign(Source: TPersistent);
  2132. Var
  2133. EID : TFPExprIdentifierDef;
  2134. begin
  2135. if (Source is TFPExprIdentifierDef) then
  2136. begin
  2137. EID:=Source as TFPExprIdentifierDef;
  2138. FStringValue:=EID.FStringValue;
  2139. FValue:=EID.FValue;
  2140. FArgumentTypes:=EID.FArgumentTypes;
  2141. FVariableArgumentCount := EID.FVariableArgumentCount;
  2142. FIDType:=EID.FIDType;
  2143. FName:=EID.FName;
  2144. FOnGetValue:=EID.FOnGetValue;
  2145. FOnGetValueCB:=EID.FOnGetValueCB;
  2146. FOnGetVarValue:=EID.FOnGetVarValue;
  2147. FOnGetVarValueCB:=EID.FOnGetVarValueCB;
  2148. end
  2149. else
  2150. inherited Assign(Source);
  2151. end;
  2152. procedure TFPExprIdentifierDef.SetArgumentTypes(const AValue: AnsiString);
  2153. Var
  2154. I : integer;
  2155. begin
  2156. if FArgumentTypes=AValue then exit;
  2157. For I:=1 to Length(AValue) do
  2158. CharToResultType(AValue[i]);
  2159. FArgumentTypes:=AValue;
  2160. end;
  2161. procedure TFPExprIdentifierDef.SetAsBoolean(const AValue: Boolean);
  2162. begin
  2163. CheckVariable;
  2164. CheckResultType(rtBoolean);
  2165. FValue.ResBoolean:=AValue;
  2166. end;
  2167. procedure TFPExprIdentifierDef.SetAsDateTime(const AValue: TDateTime);
  2168. begin
  2169. CheckVariable;
  2170. CheckResultType(rtDateTime);
  2171. FValue.ResDateTime:=AValue;
  2172. end;
  2173. procedure TFPExprIdentifierDef.SetAsFloat(const AValue: TExprFloat);
  2174. begin
  2175. CheckVariable;
  2176. CheckResultType(rtFloat);
  2177. FValue.ResFloat:=AValue;
  2178. end;
  2179. procedure TFPExprIdentifierDef.SetAsCurrency(const AValue: Currency);
  2180. begin
  2181. CheckVariable;
  2182. CheckResultType(rtCurrency);
  2183. FValue.ResCurrency:=AValue;
  2184. end;
  2185. procedure TFPExprIdentifierDef.SetAsInteger(const AValue: Int64);
  2186. begin
  2187. CheckVariable;
  2188. CheckResultType(rtInteger);
  2189. FValue.ResInteger:=AValue;
  2190. end;
  2191. procedure TFPExprIdentifierDef.SetAsString(const AValue: AnsiString);
  2192. begin
  2193. CheckVariable;
  2194. CheckResultType(rtString);
  2195. FValue.resString:=AValue;
  2196. end;
  2197. function TFPExprIdentifierDef.GetValue: AnsiString;
  2198. begin
  2199. Case FValue.ResultType of
  2200. rtBoolean : If FValue.ResBoolean then
  2201. Result:='True'
  2202. else
  2203. Result:='False';
  2204. rtInteger : Result:=IntToStr(FValue.ResInteger);
  2205. rtFloat : Result:=FloatToStr(FValue.ResFloat, FileFormatSettings);
  2206. rtCurrency : Result:=CurrToStr(FValue.ResCurrency, FileFormatSettings);
  2207. rtDateTime : Result:=FormatDateTime('cccc',FValue.ResDateTime, FileFormatSettings);
  2208. rtString : Result:=FValue.ResString;
  2209. end;
  2210. end;
  2211. procedure TFPExprIdentifierDef.FetchValue;
  2212. Var
  2213. RT,RT2 : TResultType;
  2214. I : Integer;
  2215. begin
  2216. RT:=FValue.ResultType;
  2217. if Assigned(FOnGetVarValue) then
  2218. FOnGetVarValue(FValue,FName)
  2219. else
  2220. FOnGetVarValueCB(FValue,FName);
  2221. RT2:=FValue.ResultType;
  2222. if RT2<>RT then
  2223. begin
  2224. // Automatically convert integer to float.
  2225. if (rt2=rtInteger) and (rt=rtFloat) then
  2226. begin
  2227. FValue.ResultType:=RT;
  2228. I:=FValue.resInteger;
  2229. FValue.resFloat:=I;
  2230. end
  2231. else
  2232. begin
  2233. // Restore
  2234. FValue.ResultType:=RT;
  2235. Raise EExprParser.CreateFmt('Value handler for variable %s returned wrong type, expected "%s", got "%s"',[
  2236. FName,
  2237. GetEnumName(TypeInfo(TResultType),Ord(rt)),
  2238. GetEnumName(TypeInfo(TResultType),Ord(rt2))
  2239. ]);
  2240. end;
  2241. end;
  2242. end;
  2243. function TFPExprIdentifierDef.EventBasedVariable: Boolean;
  2244. begin
  2245. Result:=Assigned(FOnGetVarValue) or Assigned(FOnGetVarValueCB);
  2246. end;
  2247. function TFPExprIdentifierDef.GetResultType: TResultType;
  2248. begin
  2249. Result:=FValue.ResultType;
  2250. end;
  2251. function TFPExprIdentifierDef.GetAsFloat: TExprFloat;
  2252. begin
  2253. CheckResultType(rtFloat);
  2254. CheckVariable;
  2255. Result:=FValue.ResFloat;
  2256. end;
  2257. function TFPExprIdentifierDef.GetAsCurrency: Currency;
  2258. begin
  2259. CheckResultType(rtCurrency);
  2260. CheckVariable;
  2261. Result:=FValue.ResCurrency;
  2262. end;
  2263. function TFPExprIdentifierDef.GetAsBoolean: Boolean;
  2264. begin
  2265. CheckResultType(rtBoolean);
  2266. CheckVariable;
  2267. Result:=FValue.ResBoolean;
  2268. end;
  2269. function TFPExprIdentifierDef.GetAsDateTime: TDateTime;
  2270. begin
  2271. CheckResultType(rtDateTime);
  2272. CheckVariable;
  2273. Result:=FValue.ResDateTime;
  2274. end;
  2275. function TFPExprIdentifierDef.GetAsInteger: Int64;
  2276. begin
  2277. CheckResultType(rtInteger);
  2278. CheckVariable;
  2279. Result:=FValue.ResInteger;
  2280. end;
  2281. function TFPExprIdentifierDef.GetAsString: AnsiString;
  2282. begin
  2283. CheckResultType(rtString);
  2284. CheckVariable;
  2285. Result:=FValue.ResString;
  2286. end;
  2287. { ---------------------------------------------------------------------
  2288. TExprBuiltInManager
  2289. ---------------------------------------------------------------------}
  2290. function TExprBuiltInManager.GetCount: Integer;
  2291. begin
  2292. Result:=FDefs.Count;
  2293. end;
  2294. function TExprBuiltInManager.GetI(AIndex : Integer
  2295. ): TFPBuiltInExprIdentifierDef;
  2296. begin
  2297. Result:=TFPBuiltInExprIdentifierDef(FDefs[Aindex])
  2298. end;
  2299. constructor TExprBuiltInManager.Create(AOwner: TComponent);
  2300. begin
  2301. inherited Create(AOwner);
  2302. FDefs:=TFPExprIdentifierDefs.Create(TFPBuiltInExprIdentifierDef)
  2303. end;
  2304. destructor TExprBuiltInManager.Destroy;
  2305. begin
  2306. FreeAndNil(FDefs);
  2307. inherited Destroy;
  2308. end;
  2309. function TExprBuiltInManager.IndexOfIdentifier(const AName: ShortString
  2310. ): Integer;
  2311. begin
  2312. Result:=FDefs.IndexOfIdentifier(AName);
  2313. end;
  2314. function TExprBuiltInManager.FindIdentifier(const AName: ShortString
  2315. ): TFPBuiltinExprIdentifierDef;
  2316. begin
  2317. Result:=TFPBuiltinExprIdentifierDef(FDefs.FindIdentifier(AName));
  2318. end;
  2319. function TExprBuiltInManager.IdentifierByName(const AName: ShortString
  2320. ): TFPBuiltinExprIdentifierDef;
  2321. begin
  2322. Result:=TFPBuiltinExprIdentifierDef(FDefs.IdentifierByName(AName));
  2323. end;
  2324. function TExprBuiltInManager.AddVariable(const ACategory: TBuiltInCategory;
  2325. const AName: ShortString; AResultType: TResultType; const AValue: AnsiString
  2326. ): TFPBuiltInExprIdentifierDef;
  2327. begin
  2328. Result:=TFPBuiltInExprIdentifierDef(FDefs.Addvariable(AName,AResultType,AValue));
  2329. Result.Category:=ACategory;
  2330. end;
  2331. function TExprBuiltInManager.AddBooleanVariable(
  2332. const ACategory: TBuiltInCategory; const AName: ShortString; AValue: Boolean
  2333. ): TFPBuiltInExprIdentifierDef;
  2334. begin
  2335. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddBooleanvariable(AName,AValue));
  2336. Result.Category:=ACategory;
  2337. end;
  2338. function TExprBuiltInManager.AddIntegerVariable(
  2339. const ACategory: TBuiltInCategory; const AName: ShortString; AValue: Integer
  2340. ): TFPBuiltInExprIdentifierDef;
  2341. begin
  2342. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddIntegerVariable(AName,AValue));
  2343. Result.Category:=ACategory;
  2344. end;
  2345. function TExprBuiltInManager.AddFloatVariable(
  2346. const ACategory: TBuiltInCategory; const AName: ShortString;
  2347. AValue: TExprFloat): TFPBuiltInExprIdentifierDef;
  2348. begin
  2349. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddFloatVariable(AName,AValue));
  2350. Result.Category:=ACategory;
  2351. end;
  2352. function TExprBuiltInManager.AddCurrencyVariable(const ACategory: TBuiltInCategory; const AName: ShortString; AValue: Currency
  2353. ): TFPBuiltInExprIdentifierDef;
  2354. begin
  2355. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddCurrencyVariable(AName,AValue));
  2356. Result.Category:=ACategory;
  2357. end;
  2358. function TExprBuiltInManager.AddStringVariable(
  2359. const ACategory: TBuiltInCategory; const AName: ShortString; const AValue:AnsiString
  2360. ): TFPBuiltInExprIdentifierDef;
  2361. begin
  2362. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddStringVariable(AName,AValue));
  2363. Result.Category:=ACategory;
  2364. end;
  2365. function TExprBuiltInManager.AddDateTimeVariable(
  2366. const ACategory: TBuiltInCategory; const AName: ShortString; AValue: TDateTime
  2367. ): TFPBuiltInExprIdentifierDef;
  2368. begin
  2369. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddDateTimeVariable(AName,AValue));
  2370. Result.Category:=ACategory;
  2371. end;
  2372. function TExprBuiltInManager.AddFunction(const ACategory: TBuiltInCategory;
  2373. const AName: ShortString; const AResultType: AnsiChar; const AParamTypes: AnsiString;
  2374. ACallBack: TFPExprFunctionCallBack): TFPBuiltInExprIdentifierDef;
  2375. begin
  2376. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddFunction(AName,AResultType,AParamTypes,ACallBack));
  2377. Result.Category:=ACategory;
  2378. end;
  2379. function TExprBuiltInManager.AddFunction(const ACategory: TBuiltInCategory;
  2380. const AName: ShortString; const AResultType: AnsiChar; const AParamTypes: AnsiString;
  2381. ACallBack: TFPExprFunctionEvent): TFPBuiltInExprIdentifierDef;
  2382. begin
  2383. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddFunction(AName,AResultType,AParamTypes,ACallBack));
  2384. Result.Category:=ACategory;
  2385. end;
  2386. function TExprBuiltInManager.AddFunction(const ACategory: TBuiltInCategory;
  2387. const AName: ShortString; const AResultType: AnsiChar; const AParamTypes: AnsiString;
  2388. ANodeClass: TFPExprFunctionClass): TFPBuiltInExprIdentifierDef;
  2389. begin
  2390. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddFunction(AName,AResultType,AParamTypes,ANodeClass));
  2391. Result. Category:=ACategory;
  2392. end;
  2393. procedure TExprBuiltInManager.Delete(AIndex: Integer);
  2394. begin
  2395. FDefs.Delete(AIndex);
  2396. end;
  2397. function TExprBuiltInManager.Remove(const aIdentifier: AnsiString): Integer;
  2398. begin
  2399. Result:=IndexOfIdentifier(aIdentifier);
  2400. if Result<>-1 then
  2401. Delete(Result);
  2402. end;
  2403. { ---------------------------------------------------------------------
  2404. Various Nodes
  2405. ---------------------------------------------------------------------}
  2406. { TFPBinaryOperation }
  2407. procedure TFPBinaryOperation.CheckSameNodeTypes;
  2408. Var
  2409. LT,RT : TResultType;
  2410. begin
  2411. LT:=Left.NodeType;
  2412. RT:=Right.NodeType;
  2413. if (RT<>LT) then
  2414. RaiseParserError(SErrTypesDoNotMatch,[ResultTypeName(LT),ResultTypeName(RT),Left.AsString,Right.AsString])
  2415. end;
  2416. constructor TFPBinaryOperation.Create(ALeft, ARight: TFPExprNode);
  2417. begin
  2418. FLeft:=ALeft;
  2419. FRight:=ARight;
  2420. end;
  2421. destructor TFPBinaryOperation.Destroy;
  2422. begin
  2423. FreeAndNil(FLeft);
  2424. FreeAndNil(FRight);
  2425. inherited Destroy;
  2426. end;
  2427. procedure TFPBinaryOperation.InitAggregate;
  2428. begin
  2429. inherited InitAggregate;
  2430. if Assigned(Left) then
  2431. Left.InitAggregate;
  2432. if Assigned(Right) then
  2433. Right.InitAggregate;
  2434. end;
  2435. procedure TFPBinaryOperation.UpdateAggregate;
  2436. begin
  2437. inherited UpdateAggregate;
  2438. if Assigned(Left) then
  2439. Left.UpdateAggregate;
  2440. if Assigned(Right) then
  2441. Right.UpdateAggregate;
  2442. end;
  2443. function TFPBinaryOperation.HasAggregate: Boolean;
  2444. begin
  2445. Result:=inherited HasAggregate;
  2446. if Assigned(Left) then
  2447. Result:=Result or Left.HasAggregate;
  2448. if Assigned(Right) then
  2449. Result:=Result or Right.HasAggregate;
  2450. end;
  2451. procedure TFPBinaryOperation.Check;
  2452. begin
  2453. If Not Assigned(Left) then
  2454. RaiseParserError(SErrNoLeftOperand,[classname]);
  2455. If Not Assigned(Right) then
  2456. RaiseParserError(SErrNoRightOperand,[classname]);
  2457. end;
  2458. { TFPUnaryOperator }
  2459. constructor TFPUnaryOperator.Create(AOperand: TFPExprNode);
  2460. begin
  2461. FOperand:=AOperand;
  2462. end;
  2463. destructor TFPUnaryOperator.Destroy;
  2464. begin
  2465. FreeAndNil(FOperand);
  2466. inherited Destroy;
  2467. end;
  2468. procedure TFPUnaryOperator.InitAggregate;
  2469. begin
  2470. inherited InitAggregate;
  2471. if Assigned(FOperand) then
  2472. FOperand.InitAggregate;
  2473. end;
  2474. procedure TFPUnaryOperator.UpdateAggregate;
  2475. begin
  2476. inherited UpdateAggregate;
  2477. if Assigned(FOperand) then
  2478. FOperand.UpdateAggregate;
  2479. end;
  2480. function TFPUnaryOperator.HasAggregate: Boolean;
  2481. begin
  2482. Result:=inherited HasAggregate;
  2483. if Assigned(FOperand) then
  2484. Result:=Result or FOperand.HasAggregate;
  2485. end;
  2486. procedure TFPUnaryOperator.Check;
  2487. begin
  2488. If Not Assigned(Operand) then
  2489. RaiseParserError(SErrNoOperand,[Self.className]);
  2490. end;
  2491. { TFPConstExpression }
  2492. constructor TFPConstExpression.CreateString(const AValue: AnsiString);
  2493. begin
  2494. FValue.ResultType:=rtString;
  2495. FValue.ResString:=AValue;
  2496. end;
  2497. constructor TFPConstExpression.CreateInteger(AValue: Int64);
  2498. begin
  2499. FValue.ResultType:=rtInteger;
  2500. FValue.ResInteger:=AValue;
  2501. end;
  2502. constructor TFPConstExpression.CreateDateTime(AValue: TDateTime);
  2503. begin
  2504. FValue.ResultType:=rtDateTime;
  2505. FValue.ResDateTime:=AValue;
  2506. end;
  2507. constructor TFPConstExpression.CreateFloat(AValue: TExprFloat);
  2508. begin
  2509. Inherited create;
  2510. FValue.ResultType:=rtFloat;
  2511. FValue.ResFloat:=AValue;
  2512. end;
  2513. constructor TFPConstExpression.CreateCurrency(AValue: Currency);
  2514. begin
  2515. Inherited create;
  2516. FValue.ResultType:=rtCurrency;
  2517. FValue.ResCurrency:=AValue;
  2518. end;
  2519. constructor TFPConstExpression.CreateBoolean(AValue: Boolean);
  2520. begin
  2521. FValue.ResultType:=rtBoolean;
  2522. FValue.ResBoolean:=AValue;
  2523. end;
  2524. procedure TFPConstExpression.Check;
  2525. begin
  2526. // Nothing to check;
  2527. end;
  2528. function TFPConstExpression.NodeType: TResultType;
  2529. begin
  2530. Result:=FValue.ResultType;
  2531. end;
  2532. Procedure TFPConstExpression.GetNodeValue(var Result : TFPExpressionResult);
  2533. begin
  2534. Result:=FValue;
  2535. end;
  2536. function TFPConstExpression.AsString: AnsiString;
  2537. begin
  2538. Case NodeType of
  2539. rtString : Result:=''''+FValue.resString+'''';
  2540. rtInteger : Result:=IntToStr(FValue.resInteger);
  2541. rtDateTime : Result:=''''+FormatDateTime('cccc',FValue.resDateTime)+'''';
  2542. rtBoolean : If FValue.ResBoolean then Result:='True' else Result:='False';
  2543. rtFloat : Str(FValue.ResFloat,Result);
  2544. rtCurrency : Str(FValue.ResCurrency,Result);
  2545. end;
  2546. end;
  2547. { TFPNegateOperation }
  2548. procedure TFPNegateOperation.Check;
  2549. begin
  2550. Inherited;
  2551. If Not (Operand.NodeType in [rtInteger,rtFloat,rtCurrency]) then
  2552. RaiseParserError(SErrNoNegation,[ResultTypeName(Operand.NodeType),Operand.AsString])
  2553. end;
  2554. function TFPNegateOperation.NodeType: TResultType;
  2555. begin
  2556. Result:=Operand.NodeType;
  2557. end;
  2558. Procedure TFPNegateOperation.GetNodeValue(var Result : TFPExpressionResult);
  2559. begin
  2560. Operand.GetNodeValue(Result);
  2561. Case Result.ResultType of
  2562. rtInteger : Result.resInteger:=-Result.ResInteger;
  2563. rtFloat : Result.resFloat:=-Result.ResFloat;
  2564. rtCurrency : Result.resCurrency:=-Result.ResCurrency;
  2565. end;
  2566. end;
  2567. function TFPNegateOperation.AsString: AnsiString;
  2568. begin
  2569. Result:='-'+TrimLeft(Operand.AsString);
  2570. end;
  2571. { TFPBinaryAndOperation }
  2572. procedure TFPBooleanOperation.Check;
  2573. begin
  2574. inherited Check;
  2575. CheckNodeType(Left,[rtInteger,rtBoolean]);
  2576. CheckNodeType(Right,[rtInteger,rtBoolean]);
  2577. CheckSameNodeTypes;
  2578. end;
  2579. function TFPBooleanOperation.NodeType: TResultType;
  2580. begin
  2581. Result:=Left.NodeType;
  2582. end;
  2583. Procedure TFPBinaryAndOperation.GetNodeValue(var Result : TFPExpressionResult);
  2584. Var
  2585. RRes : TFPExpressionResult;
  2586. begin
  2587. Left.GetNodeValue(Result);
  2588. Right.GetNodeValue(RRes);
  2589. Case Result.ResultType of
  2590. rtBoolean : Result.resBoolean:=Result.ResBoolean and RRes.ResBoolean;
  2591. rtInteger : Result.resInteger:=Result.ResInteger and RRes.ResInteger;
  2592. end;
  2593. end;
  2594. function TFPBinaryAndOperation.AsString: AnsiString;
  2595. begin
  2596. Result:=Left.AsString+' and '+Right.AsString;
  2597. end;
  2598. { TFPExprNode }
  2599. procedure TFPExprNode.CheckNodeType(Anode: TFPExprNode; Allowed: TResultTypes);
  2600. Var
  2601. S : AnsiString;
  2602. A : TResultType;
  2603. begin
  2604. If (Anode=Nil) then
  2605. RaiseParserError(SErrNoNodeToCheck);
  2606. If Not (ANode.NodeType in Allowed) then
  2607. begin
  2608. S:='';
  2609. For A:=Low(TResultType) to High(TResultType) do
  2610. If A in Allowed then
  2611. begin
  2612. If S<>'' then
  2613. S:=S+',';
  2614. S:=S+ResultTypeName(A);
  2615. end;
  2616. RaiseParserError(SInvalidNodeType,[ResultTypeName(ANode.NodeType),S,ANode.AsString]);
  2617. end;
  2618. end;
  2619. procedure TFPExprNode.InitAggregate;
  2620. begin
  2621. // Do nothing
  2622. end;
  2623. procedure TFPExprNode.UpdateAggregate;
  2624. begin
  2625. // Do nothing
  2626. end;
  2627. function TFPExprNode.HasAggregate: Boolean;
  2628. begin
  2629. Result:=IsAggregate;
  2630. end;
  2631. class function TFPExprNode.IsAggregate: Boolean;
  2632. begin
  2633. Result:=False;
  2634. end;
  2635. function TFPExprNode.NodeValue: TFPExpressionResult;
  2636. begin
  2637. GetNodeValue(Result);
  2638. end;
  2639. { TFPBinaryOrOperation }
  2640. function TFPBinaryOrOperation.AsString: AnsiString;
  2641. begin
  2642. Result:=Left.AsString+' or '+Right.AsString;
  2643. end;
  2644. Procedure TFPBinaryOrOperation.GetNodeValue(var Result : TFPExpressionResult);
  2645. Var
  2646. RRes : TFPExpressionResult;
  2647. begin
  2648. Left.GetNodeValue(Result);
  2649. Right.GetNodeValue(RRes);
  2650. Case Result.ResultType of
  2651. rtBoolean : Result.resBoolean:=Result.ResBoolean or RRes.ResBoolean;
  2652. rtInteger : Result.resInteger:=Result.ResInteger or RRes.ResInteger;
  2653. end;
  2654. end;
  2655. { TFPBinaryXOrOperation }
  2656. function TFPBinaryXOrOperation.AsString: AnsiString;
  2657. begin
  2658. Result:=Left.AsString+' xor '+Right.AsString;
  2659. end;
  2660. Procedure TFPBinaryXOrOperation.GetNodeValue(var Result : TFPExpressionResult);
  2661. Var
  2662. RRes : TFPExpressionResult;
  2663. begin
  2664. Left.GetNodeValue(Result);
  2665. Right.GetNodeValue(RRes);
  2666. Case Result.ResultType of
  2667. rtBoolean : Result.resBoolean:=Result.ResBoolean xor RRes.ResBoolean;
  2668. rtInteger : Result.resInteger:=Result.ResInteger xor RRes.ResInteger;
  2669. end;
  2670. end;
  2671. { TFPNotNode }
  2672. procedure TFPNotNode.Check;
  2673. begin
  2674. If Not (Operand.NodeType in [rtInteger,rtBoolean]) then
  2675. RaiseParserError(SErrNoNotOperation,[ResultTypeName(Operand.NodeType),Operand.AsString])
  2676. end;
  2677. function TFPNotNode.NodeType: TResultType;
  2678. begin
  2679. Result:=Operand.NodeType;
  2680. end;
  2681. procedure TFPNotNode.GetNodeValue(var Result: TFPExpressionResult);
  2682. begin
  2683. Operand.GetNodeValue(Result);
  2684. Case result.ResultType of
  2685. rtInteger : Result.resInteger:=Not Result.resInteger;
  2686. rtBoolean : Result.resBoolean:=Not Result.resBoolean;
  2687. end
  2688. end;
  2689. function TFPNotNode.AsString: AnsiString;
  2690. begin
  2691. Result:='not '+Operand.AsString;
  2692. end;
  2693. { TIfOperation }
  2694. constructor TIfOperation.Create(ACondition, ALeft, ARight: TFPExprNode);
  2695. begin
  2696. Inherited Create(ALeft,ARight);
  2697. FCondition:=ACondition;
  2698. end;
  2699. destructor TIfOperation.destroy;
  2700. begin
  2701. FreeAndNil(FCondition);
  2702. inherited destroy;
  2703. end;
  2704. procedure TIfOperation.GetNodeValue(var Result: TFPExpressionResult);
  2705. begin
  2706. FCondition.GetNodeValue(Result);
  2707. If Result.ResBoolean then
  2708. Left.GetNodeValue(Result)
  2709. else
  2710. Right.GetNodeValue(Result)
  2711. end;
  2712. procedure TIfOperation.Check;
  2713. begin
  2714. inherited Check;
  2715. if (Condition.NodeType<>rtBoolean) then
  2716. RaiseParserError(SErrIFNeedsBoolean,[Condition.AsString]);
  2717. CheckSameNodeTypes;
  2718. end;
  2719. procedure TIfOperation.InitAggregate;
  2720. begin
  2721. inherited InitAggregate;
  2722. If Assigned(FCondition) then
  2723. fCondition.InitAggregate;
  2724. end;
  2725. procedure TIfOperation.UpdateAggregate;
  2726. begin
  2727. inherited UpdateAggregate;
  2728. If Assigned(FCondition) then
  2729. FCondition.UpdateAggregate;
  2730. end;
  2731. function TIfOperation.HasAggregate: Boolean;
  2732. begin
  2733. Result:=inherited HasAggregate;
  2734. if Assigned(Condition) then
  2735. Result:=Result or Condition.HasAggregate;
  2736. end;
  2737. function TIfOperation.NodeType: TResultType;
  2738. begin
  2739. Result:=Left.NodeType;
  2740. end;
  2741. function TIfOperation.AsString: AnsiString;
  2742. begin
  2743. Result:=Format('if(%s , %s , %s)',[Condition.AsString,Left.AsString,Right.AsString]);
  2744. end;
  2745. { TCaseOperation }
  2746. procedure TCaseOperation.GetNodeValue(var Result: TFPExpressionResult);
  2747. Var
  2748. I,L : Integer;
  2749. B : Boolean;
  2750. RT,RV : TFPExpressionResult;
  2751. begin
  2752. FArgs[0].GetNodeValue(RT);
  2753. L:=Length(FArgs);
  2754. I:=2;
  2755. B:=False;
  2756. While (Not B) and (I<L) do
  2757. begin
  2758. FArgs[i].GetNodeValue(RV);
  2759. Case RT.ResultType of
  2760. rtBoolean : B:=RT.ResBoolean=RV.ResBoolean;
  2761. rtInteger : B:=RT.ResInteger=RV.ResInteger;
  2762. rtFloat : B:=RT.ResFloat=RV.ResFloat;
  2763. rtCurrency : B:=RT.resCurrency=RV.resCurrency;
  2764. rtDateTime : B:=RT.ResDateTime=RV.ResDateTime;
  2765. rtString : B:=RT.ResString=RV.ResString;
  2766. end;
  2767. If Not B then
  2768. Inc(I,2);
  2769. end;
  2770. // Set result type.
  2771. Result.ResultType:=FArgs[1].NodeType;
  2772. If B then
  2773. FArgs[I+1].GetNodeValue(Result)
  2774. else if ((L mod 2)=0) then
  2775. FArgs[1].GetNodeValue(Result);
  2776. end;
  2777. procedure TCaseOperation.Check;
  2778. Var
  2779. T,V : TResultType;
  2780. I : Integer;
  2781. N : TFPExprNode;
  2782. begin
  2783. If (Length(FArgs)<3) then
  2784. RaiseParserError(SErrCaseNeeds3);
  2785. If ((Length(FArgs) mod 2)=1) then
  2786. RaiseParserError(SErrCaseEvenCount);
  2787. T:=FArgs[0].NodeType;
  2788. V:=FArgs[1].NodeType;
  2789. For I:=2 to Length(Fargs)-1 do
  2790. begin
  2791. N:=FArgs[I];
  2792. // Even argument types (labels) must equal tag.
  2793. If ((I mod 2)=0) then
  2794. begin
  2795. If Not (N is TFPConstExpression) then
  2796. RaiseParserError(SErrCaseLabelNotAConst,[I div 2,N.AsString]);
  2797. If (N.NodeType<>T) then
  2798. RaiseParserError(SErrCaseLabelType,[I div 2,N.AsString,ResultTypeName(T),ResultTypeName(N.NodeType)]);
  2799. end
  2800. else // Odd argument types (values) must match first.
  2801. begin
  2802. If (N.NodeType<>V) then
  2803. RaiseParserError(SErrCaseValueType,[(I-1)div 2,N.AsString,ResultTypeName(V),ResultTypeName(N.NodeType)]);
  2804. end
  2805. end;
  2806. end;
  2807. procedure TCaseOperation.InitAggregate;
  2808. Var
  2809. I : Integer;
  2810. begin
  2811. inherited InitAggregate;
  2812. if Assigned(FCondition) then
  2813. FCondition.InitAggregate;
  2814. For I:=0 to Length(Fargs)-1 do
  2815. FArgs[i].InitAggregate;
  2816. end;
  2817. procedure TCaseOperation.UpdateAggregate;
  2818. Var
  2819. I : Integer;
  2820. begin
  2821. inherited UpdateAggregate;
  2822. if Assigned(FCondition) then
  2823. FCondition.UpdateAggregate;
  2824. For I:=0 to Length(Fargs)-1 do
  2825. FArgs[i].InitAggregate;
  2826. end;
  2827. Function TCaseOperation.HasAggregate : Boolean;
  2828. Var
  2829. I,L : Integer;
  2830. begin
  2831. Result:=inherited HasAggregate;
  2832. L:=Length(Fargs);
  2833. I:=0;
  2834. While (Not Result) and (I<L) do
  2835. begin
  2836. Result:=Result or FArgs[i].HasAggregate;
  2837. Inc(I)
  2838. end;
  2839. end;
  2840. function TCaseOperation.NodeType: TResultType;
  2841. begin
  2842. Result:=FArgs[1].NodeType;
  2843. end;
  2844. constructor TCaseOperation.Create(Args: TExprArgumentArray);
  2845. begin
  2846. Fargs:=Args;
  2847. end;
  2848. destructor TCaseOperation.destroy;
  2849. Var
  2850. I : Integer;
  2851. begin
  2852. For I:=0 to Length(FArgs)-1 do
  2853. FreeAndNil(Fargs[I]);
  2854. inherited destroy;
  2855. end;
  2856. function TCaseOperation.AsString: AnsiString;
  2857. Var
  2858. I : integer;
  2859. begin
  2860. Result:='';
  2861. For I:=0 to Length(FArgs)-1 do
  2862. begin
  2863. If (Result<>'') then
  2864. Result:=Result+', ';
  2865. Result:=Result+FArgs[i].AsString;
  2866. end;
  2867. Result:='Case('+Result+')';
  2868. end;
  2869. { TFPBooleanResultOperation }
  2870. procedure TFPBooleanResultOperation.Check;
  2871. begin
  2872. inherited Check;
  2873. CheckSameNodeTypes;
  2874. end;
  2875. function TFPBooleanResultOperation.NodeType: TResultType;
  2876. begin
  2877. Result:=rtBoolean;
  2878. end;
  2879. { TFPEqualOperation }
  2880. function TFPEqualOperation.AsString: AnsiString;
  2881. begin
  2882. Result:=Left.AsString+' = '+Right.AsString;
  2883. end;
  2884. Procedure TFPEqualOperation.GetNodeValue(var Result : TFPExpressionResult);
  2885. Var
  2886. RRes : TFPExpressionResult;
  2887. begin
  2888. Left.GetNodeValue(Result);
  2889. Right.GetNodeValue(RRes);
  2890. Case Result.ResultType of
  2891. rtBoolean : Result.resBoolean:=Result.ResBoolean=RRes.ResBoolean;
  2892. rtInteger : Result.resBoolean:=Result.ResInteger=RRes.ResInteger;
  2893. rtFloat : Result.resBoolean:=Result.ResFloat=RRes.ResFloat;
  2894. rtCurrency : Result.resBoolean:=Result.resCurrency=RRes.resCurrency;
  2895. rtDateTime : Result.resBoolean:=Result.ResDateTime=RRes.ResDateTime;
  2896. rtString : Result.resBoolean:=Result.ResString=RRes.ResString;
  2897. end;
  2898. Result.ResultType:=rtBoolean;
  2899. end;
  2900. { TFPUnequalOperation }
  2901. function TFPUnequalOperation.AsString: AnsiString;
  2902. begin
  2903. Result:=Left.AsString+' <> '+Right.AsString;
  2904. end;
  2905. Procedure TFPUnequalOperation.GetNodeValue(var Result : TFPExpressionResult);
  2906. begin
  2907. Inherited GetNodeValue(Result);
  2908. Result.ResBoolean:=Not Result.ResBoolean;
  2909. end;
  2910. { TFPLessThanOperation }
  2911. function TFPLessThanOperation.AsString: AnsiString;
  2912. begin
  2913. Result:=Left.AsString+' < '+Right.AsString;
  2914. end;
  2915. procedure TFPLessThanOperation.GetNodeValue(var Result : TFPExpressionResult);
  2916. Var
  2917. RRes : TFPExpressionResult;
  2918. begin
  2919. Left.GetNodeValue(Result);
  2920. Right.GetNodeValue(RRes);
  2921. Case Result.ResultType of
  2922. rtInteger : Result.resBoolean:=Result.ResInteger<RRes.ResInteger;
  2923. rtFloat : Result.resBoolean:=Result.ResFloat<RRes.ResFloat;
  2924. rtCurrency : Result.resBoolean:=Result.resCurrency<RRes.resCurrency;
  2925. rtDateTime : Result.resBoolean:=Result.ResDateTime<RRes.ResDateTime;
  2926. rtString : Result.resBoolean:=Result.ResString<RRes.ResString;
  2927. end;
  2928. Result.ResultType:=rtBoolean;
  2929. end;
  2930. { TFPGreaterThanOperation }
  2931. function TFPGreaterThanOperation.AsString: AnsiString;
  2932. begin
  2933. Result:=Left.AsString+' > '+Right.AsString;
  2934. end;
  2935. Procedure TFPGreaterThanOperation.GetNodeValue(var Result : TFPExpressionResult);
  2936. Var
  2937. RRes : TFPExpressionResult;
  2938. begin
  2939. Left.GetNodeValue(Result);
  2940. Right.GetNodeValue(RRes);
  2941. Case Result.ResultType of
  2942. rtInteger : case Right.NodeType of
  2943. rtInteger : Result.resBoolean:=Result.ResInteger>RRes.ResInteger;
  2944. rtFloat : Result.resBoolean:=Result.ResInteger>RRes.ResFloat;
  2945. rtCurrency : Result.resBoolean:=Result.ResInteger>RRes.resCurrency;
  2946. end;
  2947. rtFloat : case Right.NodeType of
  2948. rtInteger : Result.resBoolean:=Result.ResFloat>RRes.ResInteger;
  2949. rtFloat : Result.resBoolean:=Result.ResFloat>RRes.ResFloat;
  2950. rtCurrency : Result.resBoolean:=Result.ResFloat>RRes.ResCurrency;
  2951. end;
  2952. rtCurrency : case Right.NodeType of
  2953. rtInteger : Result.resBoolean:=Result.ResCurrency>RRes.ResInteger;
  2954. rtFloat : Result.resBoolean:=Result.ResCurrency>RRes.ResFloat;
  2955. rtCurrency : Result.resBoolean:=Result.ResCurrency>RRes.ResCurrency;
  2956. end;
  2957. rtDateTime : Result.resBoolean:=Result.ResDateTime>RRes.ResDateTime;
  2958. rtString : Result.resBoolean:=Result.ResString>RRes.ResString;
  2959. end;
  2960. Result.ResultType:=rtBoolean;
  2961. end;
  2962. { TFPGreaterThanEqualOperation }
  2963. function TFPGreaterThanEqualOperation.AsString: AnsiString;
  2964. begin
  2965. Result:=Left.AsString+' >= '+Right.AsString;
  2966. end;
  2967. Procedure TFPGreaterThanEqualOperation.GetNodeValue(var Result : TFPExpressionResult);
  2968. begin
  2969. Inherited GetNodeValue(Result);
  2970. Result.ResBoolean:=Not Result.ResBoolean;
  2971. end;
  2972. { TFPLessThanEqualOperation }
  2973. function TFPLessThanEqualOperation.AsString: AnsiString;
  2974. begin
  2975. Result:=Left.AsString+' <= '+Right.AsString;
  2976. end;
  2977. Procedure TFPLessThanEqualOperation.GetNodeValue(var Result : TFPExpressionResult);
  2978. begin
  2979. Inherited GetNodeValue(Result);
  2980. Result.ResBoolean:=Not Result.ResBoolean;
  2981. end;
  2982. { TFPOrderingOperation }
  2983. procedure TFPOrderingOperation.Check;
  2984. Const
  2985. AllowedTypes =[rtInteger,rtfloat,rtCurrency,rtDateTime,rtString];
  2986. begin
  2987. CheckNodeType(Left,AllowedTypes);
  2988. CheckNodeType(Right,AllowedTypes);
  2989. inherited Check;
  2990. end;
  2991. { TMathOperation }
  2992. procedure TMathOperation.Check;
  2993. Const
  2994. AllowedTypes =[rtInteger,rtfloat,rtCurrency,rtDateTime,rtString];
  2995. begin
  2996. inherited Check;
  2997. CheckNodeType(Left,AllowedTypes);
  2998. CheckNodeType(Right,AllowedTypes);
  2999. CheckSameNodeTypes;
  3000. end;
  3001. function TMathOperation.NodeType: TResultType;
  3002. begin
  3003. Result:=Left.NodeType;
  3004. end;
  3005. { TFPAddOperation }
  3006. function TFPAddOperation.AsString: AnsiString;
  3007. begin
  3008. Result:=Left.AsString+' + '+Right.asString;
  3009. end;
  3010. Procedure TFPAddOperation.GetNodeValue(var Result : TFPExpressionResult);
  3011. Var
  3012. RRes : TFPExpressionResult;
  3013. begin
  3014. Left.GetNodeValue(Result);
  3015. Right.GetNodeValue(RRes);
  3016. case Result.ResultType of
  3017. rtInteger : Result.ResInteger:=Result.ResInteger+RRes.ResInteger;
  3018. rtString : Result.ResString:=Result.ResString+RRes.ResString;
  3019. rtDateTime : Result.ResDateTime:=Result.ResDateTime+RRes.ResDateTime;
  3020. rtFloat : Result.ResFloat:=Result.ResFloat+RRes.ResFloat;
  3021. rtCurrency : Result.ResCurrency:=Result.ResCurrency+RRes.ResCurrency;
  3022. end;
  3023. Result.ResultType:=NodeType;
  3024. end;
  3025. { TFPSubtractOperation }
  3026. procedure TFPSubtractOperation.check;
  3027. Const
  3028. AllowedTypes =[rtInteger,rtfloat,rtCurrency,rtDateTime];
  3029. begin
  3030. CheckNodeType(Left,AllowedTypes);
  3031. CheckNodeType(Right,AllowedTypes);
  3032. inherited check;
  3033. end;
  3034. function TFPSubtractOperation.AsString: AnsiString;
  3035. begin
  3036. Result:=Left.AsString+' - '+Right.asString;
  3037. end;
  3038. Procedure TFPSubtractOperation.GetNodeValue(var Result : TFPExpressionResult);
  3039. Var
  3040. RRes : TFPExpressionResult;
  3041. begin
  3042. Left.GetNodeValue(Result);
  3043. Right.GetNodeValue(RRes);
  3044. case Result.ResultType of
  3045. rtInteger : Result.ResInteger:=Result.ResInteger-RRes.ResInteger;
  3046. rtDateTime : Result.ResDateTime:=Result.ResDateTime-RRes.ResDateTime;
  3047. rtFloat : Result.ResFloat:=Result.ResFloat-RRes.ResFloat;
  3048. rtCurrency : Result.resCurrency:=Result.resCurrency-RRes.ResCurrency;
  3049. end;
  3050. end;
  3051. { TFPMultiplyOperation }
  3052. procedure TFPMultiplyOperation.check;
  3053. Const
  3054. AllowedTypes =[rtInteger,rtCurrency,rtfloat];
  3055. begin
  3056. CheckNodeType(Left,AllowedTypes);
  3057. CheckNodeType(Right,AllowedTypes);
  3058. Inherited;
  3059. end;
  3060. function TFPMultiplyOperation.AsString: AnsiString;
  3061. begin
  3062. Result:=Left.AsString+' * '+Right.asString;
  3063. end;
  3064. Procedure TFPMultiplyOperation.GetNodeValue(var Result : TFPExpressionResult);
  3065. Var
  3066. RRes : TFPExpressionResult;
  3067. begin
  3068. Left.GetNodeValue(Result);
  3069. Right.GetNodeValue(RRes);
  3070. case Result.ResultType of
  3071. rtInteger : Result.ResInteger:=Result.ResInteger*RRes.ResInteger;
  3072. rtFloat : Result.ResFloat:=Result.ResFloat*RRes.ResFloat;
  3073. rtCurrency : Result.ResCurrency:=Result.ResCurrency*RRes.ResCurrency;
  3074. end;
  3075. end;
  3076. { TFPDivideOperation }
  3077. procedure TFPDivideOperation.check;
  3078. Const
  3079. AllowedTypes =[rtInteger,rtCurrency,rtfloat];
  3080. begin
  3081. CheckNodeType(Left,AllowedTypes);
  3082. CheckNodeType(Right,AllowedTypes);
  3083. inherited check;
  3084. end;
  3085. function TFPDivideOperation.AsString: AnsiString;
  3086. begin
  3087. Result:=Left.AsString+' / '+Right.asString;
  3088. end;
  3089. function TFPDivideOperation.NodeType: TResultType;
  3090. begin
  3091. if (Left.NodeType=rtCurrency) and (Right.NodeType=rtCurrency) then
  3092. Result:=rtCurrency
  3093. else
  3094. Result:=rtFloat;
  3095. end;
  3096. Procedure TFPDivideOperation.GetNodeValue(var Result : TFPExpressionResult);
  3097. Var
  3098. RRes : TFPExpressionResult;
  3099. begin
  3100. Left.GetNodeValue(Result);
  3101. Right.GetNodeValue(RRes);
  3102. case Result.ResultType of
  3103. rtInteger :
  3104. if RRes.ResInteger<>0 then
  3105. Result.ResFloat:=Result.ResInteger/RRes.ResInteger
  3106. else
  3107. RaiseParserError(SErrDivisionByZero, [ResultTypeName(rtInteger)]);
  3108. rtFloat :
  3109. if RRes.ResFloat<>0 then
  3110. Result.ResFloat:=Result.ResFloat/RRes.ResFloat
  3111. else
  3112. RaiseParserError(SErrDivisionByZero, [ResultTypeName(rtInteger)]);
  3113. rtCurrency :
  3114. if NodeType=rtCurrency then
  3115. if RRes.ResCurrency <> 0 then
  3116. Result.ResCurrency:=Result.ResCurrency/RRes.ResCurrency
  3117. else
  3118. RaiseParserError(SErrDivisionByZero, [ResultTypeName(rtCurrency)])
  3119. else
  3120. if RRes.ResFloat<> 0 then
  3121. Result.ResFloat:=Result.ResFloat/RRes.ResFloat
  3122. else
  3123. RaiseParserError(SErrDivisionByZero, [ResultTypeName(rtFloat)]);
  3124. end;
  3125. Result.ResultType:=NodeType;
  3126. end;
  3127. { TFPPowerOperation }
  3128. procedure TFPPowerOperation.Check;
  3129. const
  3130. AllowedTypes = [rtInteger, rtCurrency, rtFloat];
  3131. begin
  3132. CheckNodeType(Left, AllowedTypes);
  3133. CheckNodeType(Right, AllowedTypes);
  3134. end;
  3135. function TFPPowerOperation.AsString: AnsiString;
  3136. begin
  3137. Result := Left.AsString + '^' + Right.AsString;
  3138. end;
  3139. function TFPPowerOperation.NodeType: TResultType;
  3140. begin
  3141. Result := rtFloat;
  3142. end;
  3143. function power(base,exponent: TExprFloat): TExprFloat;
  3144. // Adapted from unit "math"
  3145. var
  3146. ex: Integer;
  3147. begin
  3148. if Exponent = 0.0 then
  3149. result := 1.0
  3150. else if (base = 0.0) and (exponent > 0.0) then
  3151. result := 0.0
  3152. else if (base < 0.0) and (frac(exponent) = 0.0) then
  3153. begin
  3154. ex := round(exponent);
  3155. result := exp( exponent * ln(-base));
  3156. if odd(ex) then result := -result;
  3157. end
  3158. else
  3159. result := exp( exponent * ln(base) );
  3160. end;
  3161. procedure TFPPowerOperation.GetNodeValue(var Result: TFPExpressionResult);
  3162. var
  3163. RRes: TFPExpressionResult;
  3164. begin
  3165. Left.GetNodeValue(Result);
  3166. Right.GetNodeValue(RRes);
  3167. Result.ResFloat := power(ArgToFloat(Result), ArgToFloat(RRes));
  3168. Result.ResultType := rtFloat;
  3169. end;
  3170. { TFPConvertNode }
  3171. function TFPConvertNode.AsString: AnsiString;
  3172. begin
  3173. Result:=Operand.AsString;
  3174. end;
  3175. { TIntToFloatNode }
  3176. procedure TIntConvertNode.Check;
  3177. begin
  3178. inherited Check;
  3179. CheckNodeType(Operand,[rtInteger])
  3180. end;
  3181. function TIntToFloatNode.NodeType: TResultType;
  3182. begin
  3183. Result:=rtFloat;
  3184. end;
  3185. Procedure TIntToFloatNode.GetNodeValue(var Result : TFPExpressionResult);
  3186. begin
  3187. Operand.GetNodeValue(Result);
  3188. Result.ResFloat:=Result.ResInteger;
  3189. Result.ResultType:=rtFloat;
  3190. end;
  3191. { TIntToDateTimeNode }
  3192. function TIntToDateTimeNode.NodeType: TResultType;
  3193. begin
  3194. Result:=rtDatetime;
  3195. end;
  3196. procedure TIntToDateTimeNode.GetNodeValue(var Result : TFPExpressionResult);
  3197. begin
  3198. Operand.GetnodeValue(Result);
  3199. Result.ResDateTime:=Result.ResInteger;
  3200. Result.ResultType:=rtDateTime;
  3201. end;
  3202. { TFloatToDateTimeNode }
  3203. procedure TFloatToDateTimeNode.Check;
  3204. begin
  3205. inherited Check;
  3206. CheckNodeType(Operand,[rtFloat]);
  3207. end;
  3208. function TFloatToDateTimeNode.NodeType: TResultType;
  3209. begin
  3210. Result:=rtDateTime;
  3211. end;
  3212. Procedure TFloatToDateTimeNode.GetNodeValue(var Result : TFPExpressionResult);
  3213. begin
  3214. Operand.GetNodeValue(Result);
  3215. Result.ResDateTime:=Result.ResFloat;
  3216. Result.ResultType:=rtDateTime;
  3217. end;
  3218. { TCurrencyToDateTimeNode }
  3219. procedure TCurrencyToDateTimeNode.Check;
  3220. begin
  3221. inherited Check;
  3222. CheckNodeType(Operand,[rtCurrency]);
  3223. end;
  3224. function TCurrencyToDateTimeNode.NodeType: TResultType;
  3225. begin
  3226. Result:=rtDateTime;
  3227. end;
  3228. Procedure TCurrencyToDateTimeNode.GetNodeValue(var Result : TFPExpressionResult);
  3229. begin
  3230. Operand.GetNodeValue(Result);
  3231. Result.ResDateTime:=Result.ResCurrency;
  3232. Result.ResultType:=rtDateTime;
  3233. end;
  3234. { TCurrencyToFloatNode }
  3235. procedure TCurrencyToFloatNode.Check;
  3236. begin
  3237. inherited Check;
  3238. CheckNodeType(Operand,[rtCurrency]);
  3239. end;
  3240. function TCurrencyToFloatNode.NodeType: TResultType;
  3241. begin
  3242. Result:=rtFloat;
  3243. end;
  3244. Procedure TCurrencyToFloatNode.GetNodeValue(var Result : TFPExpressionResult);
  3245. begin
  3246. Operand.GetNodeValue(Result);
  3247. Result.ResFloat:=Result.ResCurrency;
  3248. Result.ResultType:=rtFloat;
  3249. end;
  3250. { TFPExprIdentifierNode }
  3251. constructor TFPExprIdentifierNode.CreateIdentifier(AID: TFPExprIdentifierDef);
  3252. begin
  3253. Inherited Create;
  3254. FID:=AID;
  3255. PResult:[email protected];
  3256. FResultType:=FID.ResultType;
  3257. end;
  3258. function TFPExprIdentifierNode.NodeType: TResultType;
  3259. begin
  3260. Result:=FResultType;
  3261. end;
  3262. Procedure TFPExprIdentifierNode.GetNodeValue(var Result : TFPExpressionResult);
  3263. begin
  3264. if Identifier.EventBasedVariable then
  3265. Identifier.FetchValue;
  3266. Result:=PResult^;
  3267. Result.ResultType:=FResultType;
  3268. end;
  3269. { TFPExprVariable }
  3270. procedure TFPExprVariable.Check;
  3271. begin
  3272. // Do nothing;
  3273. end;
  3274. function TFPExprVariable.AsString: AnsiString;
  3275. begin
  3276. Result:=FID.Name;
  3277. end;
  3278. { TFPExprFunction }
  3279. procedure TFPExprFunction.CalcParams;
  3280. Var
  3281. I : Integer;
  3282. begin
  3283. For I:=0 to Length(FArgumentParams)-1 do
  3284. begin
  3285. FArgumentNodes[i].GetNodeValue(FArgumentParams[i]);
  3286. end;
  3287. end;
  3288. Function TFPExprFunction.ConvertArgument(aIndex : Integer; aNode : TFPExprNode; aType : TResultType) : TFPExprNode;
  3289. Var
  3290. N : TFPExprNode;
  3291. begin
  3292. // Automatically convert integers to floats for float/currency parameters
  3293. N:=TFPExpressionParser.ConvertNode(aNode,aType);
  3294. if (aNode=N) then
  3295. // No conversion was performed, raise error
  3296. RaiseParserError(SErrInvalidArgumentType,[aIndex,ResultTypeName(aType),ResultTypeName(aNode.NodeType)]);
  3297. Result:=N;
  3298. end;
  3299. function TFPExprFunction.HasAggregate: Boolean;
  3300. var
  3301. I: Integer;
  3302. begin
  3303. Result := true;
  3304. if IsAggregate then
  3305. exit;
  3306. For I:=0 to Length(FArgumentNodes)-1 do
  3307. if FArgumentNodes[I].HasAggregate then
  3308. exit;
  3309. Result := false;
  3310. end;
  3311. procedure TFPExprFunction.Check;
  3312. Var
  3313. I : Integer;
  3314. rtp,rta : TResultType;
  3315. begin
  3316. If (Length(FArgumentNodes)<>FID.ArgumentCount) and not FID.VariableArgumentCount then
  3317. RaiseParserError(ErrInvalidArgumentCount,[FID.Name]);
  3318. For I:=0 to Length(FArgumentNodes)-1 do
  3319. begin
  3320. if (i < Length(FID.ParameterTypes)) then
  3321. rtp := CharToResultType(FID.ParameterTypes[i+1])
  3322. else if FID.VariableArgumentCount then
  3323. rtp := CharToResultType(FID.ParameterTypes[Length(FID.ParameterTypes)]);
  3324. rta:=FArgumentNodes[i].NodeType;
  3325. If (rtp<>rta) then
  3326. FArgumentNodes[i]:=ConvertArgument(I+1,FArgumentNodes[i],rtp);
  3327. end;
  3328. end;
  3329. constructor TFPExprFunction.CreateFunction(AID: TFPExprIdentifierDef; const Args: TExprArgumentArray);
  3330. begin
  3331. Inherited CreateIdentifier(AID);
  3332. FArgumentNodes:=Args;
  3333. SetLength(FArgumentParams,Length(Args));
  3334. end;
  3335. destructor TFPExprFunction.Destroy;
  3336. Var
  3337. I : Integer;
  3338. begin
  3339. For I:=0 to Length(FArgumentNodes)-1 do
  3340. FreeAndNil(FArgumentNodes[I]);
  3341. inherited Destroy;
  3342. end;
  3343. procedure TFPExprFunction.InitAggregate;
  3344. var
  3345. I: Integer;
  3346. begin
  3347. For I:=0 to Length(FArgumentNodes)-1 do
  3348. FArgumentNodes[i].InitAggregate;
  3349. end;
  3350. procedure TFPExprFunction.UpdateAggregate;
  3351. var
  3352. I: Integer;
  3353. begin
  3354. For I:=0 to Length(FArgumentNodes)-1 do
  3355. FArgumentNodes[i].UpdateAggregate;
  3356. end;
  3357. function TFPExprFunction.AsString: AnsiString;
  3358. Var
  3359. S : AnsiString;
  3360. I : Integer;
  3361. begin
  3362. S:='';
  3363. For I:=0 to length(FArgumentNodes)-1 do
  3364. begin
  3365. If (S<>'') then
  3366. S:=S+',';
  3367. S:=S+FArgumentNodes[I].AsString;
  3368. end;
  3369. If (S<>'') then
  3370. S:='('+S+')';
  3371. Result:=FID.Name+S;
  3372. end;
  3373. { TFPFunctionCallBack }
  3374. constructor TFPFunctionCallBack.CreateFunction(AID: TFPExprIdentifierDef;
  3375. Const Args : TExprArgumentArray);
  3376. begin
  3377. Inherited;
  3378. FCallBack:=AID.OnGetFunctionValueCallBack;
  3379. end;
  3380. Procedure TFPFunctionCallBack.GetNodeValue(var Result : TFPExpressionResult);
  3381. begin
  3382. If Length(FArgumentParams)>0 then
  3383. CalcParams;
  3384. FCallBack(Result,FArgumentParams);
  3385. Result.ResultType:=NodeType;
  3386. end;
  3387. { TFPFunctionEventHandler }
  3388. constructor TFPFunctionEventHandler.CreateFunction(AID: TFPExprIdentifierDef;
  3389. Const Args : TExprArgumentArray);
  3390. begin
  3391. Inherited;
  3392. FCallBack:=AID.OnGetFunctionValue;
  3393. end;
  3394. Procedure TFPFunctionEventHandler.GetNodeValue(var Result : TFPExpressionResult);
  3395. begin
  3396. If Length(FArgumentParams)>0 then
  3397. CalcParams;
  3398. FCallBack(Result,FArgumentParams);
  3399. Result.ResultType:=NodeType;
  3400. end;
  3401. { ---------------------------------------------------------------------
  3402. Standard Builtins support
  3403. ---------------------------------------------------------------------}
  3404. { Template for builtin.
  3405. Procedure MyCallback (Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3406. begin
  3407. end;
  3408. }
  3409. function ArgToFloat(Arg: TFPExpressionResult): TExprFloat;
  3410. // Utility function for the built-in math functions. Accepts also integers
  3411. // in place of the floating point arguments. To be called in builtins or
  3412. // user-defined callbacks having float results.
  3413. begin
  3414. if Arg.ResultType = rtInteger then
  3415. result := Arg.resInteger
  3416. else if Arg.ResultType = rtCurrency then
  3417. result := Arg.resCurrency
  3418. else
  3419. result := Arg.resFloat;
  3420. end;
  3421. // Math builtins
  3422. Procedure BuiltInCos(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3423. begin
  3424. Result.resFloat:=Cos(ArgToFloat(Args[0]));
  3425. end;
  3426. Procedure BuiltInSin(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3427. begin
  3428. Result.resFloat:=Sin(ArgToFloat(Args[0]));
  3429. end;
  3430. Procedure BuiltInArcTan(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3431. begin
  3432. Result.resFloat:=Arctan(ArgToFloat(Args[0]));
  3433. end;
  3434. Procedure BuiltInAbs(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3435. begin
  3436. Result.resFloat:=Abs(ArgToFloat(Args[0]));
  3437. end;
  3438. Procedure BuiltInSqr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3439. begin
  3440. Result.resFloat:=Sqr(ArgToFloat(Args[0]));
  3441. end;
  3442. Procedure BuiltInSqrt(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3443. begin
  3444. Result.resFloat:=Sqrt(ArgToFloat(Args[0]));
  3445. end;
  3446. Procedure BuiltInExp(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3447. begin
  3448. Result.resFloat:=Exp(ArgToFloat(Args[0]));
  3449. end;
  3450. Procedure BuiltInLn(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3451. begin
  3452. Result.resFloat:=Ln(ArgToFloat(Args[0]));
  3453. end;
  3454. Const
  3455. L10 = ln(10);
  3456. Procedure BuiltInLog(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3457. begin
  3458. Result.resFloat:=Ln(ArgToFloat(Args[0]))/L10;
  3459. end;
  3460. Procedure BuiltInRound(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3461. begin
  3462. Result.resInteger:=Round(ArgToFloat(Args[0]));
  3463. end;
  3464. Procedure BuiltInTrunc(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3465. begin
  3466. Result.resInteger:=Trunc(ArgToFloat(Args[0]));
  3467. end;
  3468. Procedure BuiltInInt(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3469. begin
  3470. Result.resFloat:=Int(ArgToFloat(Args[0]));
  3471. end;
  3472. Procedure BuiltInFrac(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3473. begin
  3474. Result.resFloat:=frac(ArgToFloat(Args[0]));
  3475. end;
  3476. // builtins
  3477. Procedure BuiltInLength(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3478. begin
  3479. Result.resInteger:=Length(Args[0].resString);
  3480. end;
  3481. Procedure BuiltInCopy(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3482. begin
  3483. Result.resString:=Copy(Args[0].resString,Args[1].resInteger,Args[2].resInteger);
  3484. end;
  3485. Procedure BuiltInDelete(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3486. begin
  3487. Result.resString:=Args[0].resString;
  3488. Delete(Result.resString,Args[1].resInteger,Args[2].resInteger);
  3489. end;
  3490. Procedure BuiltInPos(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3491. begin
  3492. Result.resInteger:=Pos(Args[0].resString,Args[1].resString);
  3493. end;
  3494. Procedure BuiltInUppercase(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3495. begin
  3496. Result.resString:=Uppercase(Args[0].resString);
  3497. end;
  3498. Procedure BuiltInLowercase(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3499. begin
  3500. Result.resString:=Lowercase(Args[0].resString);
  3501. end;
  3502. Procedure BuiltInStringReplace(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3503. Var
  3504. F : TReplaceFlags;
  3505. begin
  3506. F:=[];
  3507. If Args[3].resBoolean then
  3508. Include(F,rfReplaceAll);
  3509. If Args[4].resBoolean then
  3510. Include(F,rfIgnoreCase);
  3511. Result.resString:=StringReplace(Args[0].resString,Args[1].resString,Args[2].resString,f);
  3512. end;
  3513. Procedure BuiltInCompareText(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3514. begin
  3515. Result.resInteger:=CompareText(Args[0].resString,Args[1].resString);
  3516. end;
  3517. // Date/Time builtins
  3518. Procedure BuiltInDate(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3519. begin
  3520. Result.resDateTime:=Date;
  3521. end;
  3522. Procedure BuiltInTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3523. begin
  3524. Result.resDateTime:=Time;
  3525. end;
  3526. Procedure BuiltInNow(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3527. begin
  3528. Result.resDateTime:=Now;
  3529. end;
  3530. Procedure BuiltInDayofWeek(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3531. begin
  3532. Result.resInteger:=DayOfWeek(Args[0].resDateTime);
  3533. end;
  3534. Procedure BuiltInExtractYear(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3535. Var
  3536. Y,M,D : Word;
  3537. begin
  3538. DecodeDate(Args[0].resDateTime,Y,M,D);
  3539. Result.resInteger:=Y;
  3540. end;
  3541. Procedure BuiltInExtractMonth(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3542. Var
  3543. Y,M,D : Word;
  3544. begin
  3545. DecodeDate(Args[0].resDateTime,Y,M,D);
  3546. Result.resInteger:=M;
  3547. end;
  3548. Procedure BuiltInExtractDay(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3549. Var
  3550. Y,M,D : Word;
  3551. begin
  3552. DecodeDate(Args[0].resDateTime,Y,M,D);
  3553. Result.resInteger:=D;
  3554. end;
  3555. Procedure BuiltInExtractHour(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3556. Var
  3557. H,M,S,MS : Word;
  3558. begin
  3559. DecodeTime(Args[0].resDateTime,H,M,S,MS);
  3560. Result.resInteger:=H;
  3561. end;
  3562. Procedure BuiltInExtractMin(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3563. Var
  3564. H,M,S,MS : Word;
  3565. begin
  3566. DecodeTime(Args[0].resDateTime,H,M,S,MS);
  3567. Result.resInteger:=M;
  3568. end;
  3569. Procedure BuiltInExtractSec(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3570. Var
  3571. H,M,S,MS : Word;
  3572. begin
  3573. DecodeTime(Args[0].resDateTime,H,M,S,MS);
  3574. Result.resInteger:=S;
  3575. end;
  3576. Procedure BuiltInExtractMSec(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3577. Var
  3578. H,M,S,MS : Word;
  3579. begin
  3580. DecodeTime(Args[0].resDateTime,H,M,S,MS);
  3581. Result.resInteger:=MS;
  3582. end;
  3583. Procedure BuiltInEncodedate(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3584. begin
  3585. Result.resDateTime:=Encodedate(Args[0].resInteger,Args[1].resInteger,Args[2].resInteger);
  3586. end;
  3587. Procedure BuiltInEncodeTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3588. begin
  3589. Result.resDateTime:=EncodeTime(Args[0].resInteger,Args[1].resInteger,Args[2].resInteger,Args[3].resInteger);
  3590. end;
  3591. Procedure BuiltInEncodeDateTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3592. begin
  3593. Result.resDateTime:=EncodeDate(Args[0].resInteger,Args[1].resInteger,Args[2].resInteger)
  3594. +EncodeTime(Args[3].resInteger,Args[4].resInteger,Args[5].resInteger,Args[6].resInteger);
  3595. end;
  3596. Procedure BuiltInShortDayName(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3597. begin
  3598. Result.resString:=DefaultFormatSettings.ShortDayNames[Args[0].resInteger];
  3599. end;
  3600. Procedure BuiltInShortMonthName(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3601. begin
  3602. Result.resString:=DefaultFormatSettings.ShortMonthNames[Args[0].resInteger];
  3603. end;
  3604. Procedure BuiltInLongDayName(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3605. begin
  3606. Result.resString:=DefaultFormatSettings.LongDayNames[Args[0].resInteger];
  3607. end;
  3608. Procedure BuiltInLongMonthName(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3609. begin
  3610. Result.resString:=DefaultFormatSettings.LongMonthNames[Args[0].resInteger];
  3611. end;
  3612. Procedure BuiltInFormatDateTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3613. begin
  3614. Result.resString:=FormatDateTime(Args[0].resString,Args[1].resDateTime);
  3615. end;
  3616. // Conversion
  3617. Procedure BuiltInIntToStr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3618. begin
  3619. Result.resString:=IntToStr(Args[0].resinteger);
  3620. end;
  3621. Procedure BuiltInStrToInt(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3622. begin
  3623. Result.resInteger:=StrToInt(Args[0].resString);
  3624. end;
  3625. Procedure BuiltInStrToIntDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3626. begin
  3627. Result.resInteger:=StrToIntDef(Args[0].resString,Args[1].resInteger);
  3628. end;
  3629. Procedure BuiltInFloatToStr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3630. begin
  3631. Result.resString:=FloatToStr(Args[0].resFloat);
  3632. end;
  3633. Procedure BuiltInStrToFloat(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3634. begin
  3635. Result.resFloat:=StrToFloat(Args[0].resString);
  3636. end;
  3637. Procedure BuiltInStrToFloatDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3638. begin
  3639. Result.resFloat:=StrToFloatDef(Args[0].resString,Args[1].resFloat);
  3640. end;
  3641. Procedure BuiltInDateToStr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3642. begin
  3643. Result.resString:=DateToStr(Args[0].resDateTime);
  3644. end;
  3645. Procedure BuiltInTimeToStr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3646. begin
  3647. Result.resString:=TimeToStr(Args[0].resDateTime);
  3648. end;
  3649. Procedure BuiltInStrToDate(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3650. begin
  3651. Result.resDateTime:=StrToDate(Args[0].resString);
  3652. end;
  3653. Procedure BuiltInStrToDateDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3654. begin
  3655. Result.resDateTime:=StrToDateDef(Args[0].resString,Args[1].resDateTime);
  3656. end;
  3657. Procedure BuiltInStrToTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3658. begin
  3659. Result.resDateTime:=StrToTime(Args[0].resString);
  3660. end;
  3661. Procedure BuiltInStrToTimeDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3662. begin
  3663. Result.resDateTime:=StrToTimeDef(Args[0].resString,Args[1].resDateTime);
  3664. end;
  3665. Procedure BuiltInStrToDateTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3666. begin
  3667. Result.resDateTime:=StrToDateTime(Args[0].resString);
  3668. end;
  3669. Procedure BuiltInStrToDateTimeDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3670. begin
  3671. Result.resDateTime:=StrToDateTimeDef(Args[0].resString,Args[1].resDateTime);
  3672. end;
  3673. procedure BuiltInFormatFloat(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3674. begin
  3675. result.ResString := FormatFloat(Args[0].resString, Args[1].ResFloat);
  3676. end;
  3677. Procedure BuiltInBoolToStr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3678. begin
  3679. Result.resString:=BoolToStr(Args[0].resBoolean);
  3680. end;
  3681. Procedure BuiltInStrToBool(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3682. begin
  3683. Result.resBoolean:=StrToBool(Args[0].resString);
  3684. end;
  3685. Procedure BuiltInStrToBoolDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3686. begin
  3687. Result.resBoolean:=StrToBoolDef(Args[0].resString,Args[1].resBoolean);
  3688. end;
  3689. // Boolean
  3690. Procedure BuiltInShl(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3691. begin
  3692. Result.resInteger:=Args[0].resInteger shl Args[1].resInteger
  3693. end;
  3694. Procedure BuiltInShr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3695. begin
  3696. Result.resInteger:=Args[0].resInteger shr Args[1].resInteger
  3697. end;
  3698. Procedure BuiltinIFS(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3699. begin
  3700. If Args[0].resBoolean then
  3701. Result.resString:=Args[1].resString
  3702. else
  3703. Result.resString:=Args[2].resString
  3704. end;
  3705. Procedure BuiltinIFI(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3706. begin
  3707. If Args[0].resBoolean then
  3708. Result.resinteger:=Args[1].resinteger
  3709. else
  3710. Result.resinteger:=Args[2].resinteger
  3711. end;
  3712. Procedure BuiltinIFF(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3713. begin
  3714. If Args[0].resBoolean then
  3715. Result.resfloat:=Args[1].resfloat
  3716. else
  3717. Result.resfloat:=Args[2].resfloat
  3718. end;
  3719. Procedure BuiltinIFD(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  3720. begin
  3721. If Args[0].resBoolean then
  3722. Result.resDateTime:=Args[1].resDateTime
  3723. else
  3724. Result.resDateTime:=Args[2].resDateTime
  3725. end;
  3726. procedure RegisterStdBuiltins(AManager: TExprBuiltInManager; Categories: TBuiltInCategories = AllBuiltIns);
  3727. begin
  3728. With AManager do
  3729. begin
  3730. if bcMath in Categories then
  3731. begin
  3732. AddFloatVariable(bcMath,'pi',Pi);
  3733. // Math functions
  3734. AddFunction(bcMath,'cos','F','F',@BuiltinCos);
  3735. AddFunction(bcMath,'sin','F','F',@BuiltinSin);
  3736. AddFunction(bcMath,'arctan','F','F',@BuiltinArctan);
  3737. AddFunction(bcMath,'abs','F','F',@BuiltinAbs);
  3738. AddFunction(bcMath,'sqr','F','F',@BuiltinSqr);
  3739. AddFunction(bcMath,'sqrt','F','F',@BuiltinSqrt);
  3740. AddFunction(bcMath,'exp','F','F',@BuiltinExp);
  3741. AddFunction(bcMath,'ln','F','F',@BuiltinLn);
  3742. AddFunction(bcMath,'log','F','F',@BuiltinLog);
  3743. AddFunction(bcMath,'frac','F','F',@BuiltinFrac);
  3744. AddFunction(bcMath,'int','F','F',@BuiltinInt);
  3745. AddFunction(bcMath,'round','I','F',@BuiltinRound);
  3746. AddFunction(bcMath,'trunc','I','F',@BuiltinTrunc);
  3747. end;
  3748. if bcStrings in Categories then
  3749. begin
  3750. //
  3751. AddFunction(bcStrings,'length','I','S',@BuiltinLength);
  3752. AddFunction(bcStrings,'copy','S','SII',@BuiltinCopy);
  3753. AddFunction(bcStrings,'delete','S','SII',@BuiltinDelete);
  3754. AddFunction(bcStrings,'pos','I','SS',@BuiltinPos);
  3755. AddFunction(bcStrings,'lowercase','S','S',@BuiltinLowercase);
  3756. AddFunction(bcStrings,'uppercase','S','S',@BuiltinUppercase);
  3757. AddFunction(bcStrings,'stringreplace','S','SSSBB',@BuiltinStringReplace);
  3758. AddFunction(bcStrings,'comparetext','I','SS',@BuiltinCompareText);
  3759. end;
  3760. if bcDateTime in Categories then
  3761. begin
  3762. // Date/Time
  3763. AddFunction(bcDateTime,'date','D','',@BuiltinDate);
  3764. AddFunction(bcDateTime,'time','D','',@BuiltinTime);
  3765. AddFunction(bcDateTime,'now','D','',@BuiltinNow);
  3766. AddFunction(bcDateTime,'dayofweek','I','D',@BuiltinDayofweek);
  3767. AddFunction(bcDateTime,'extractyear','I','D',@BuiltinExtractYear);
  3768. AddFunction(bcDateTime,'extractmonth','I','D',@BuiltinExtractMonth);
  3769. AddFunction(bcDateTime,'extractday','I','D',@BuiltinExtractDay);
  3770. AddFunction(bcDateTime,'extracthour','I','D',@BuiltinExtractHour);
  3771. AddFunction(bcDateTime,'extractmin','I','D',@BuiltinExtractMin);
  3772. AddFunction(bcDateTime,'extractsec','I','D',@BuiltinExtractSec);
  3773. AddFunction(bcDateTime,'extractmsec','I','D',@BuiltinExtractMSec);
  3774. AddFunction(bcDateTime,'encodedate','D','III',@BuiltinEncodedate);
  3775. AddFunction(bcDateTime,'encodetime','D','IIII',@BuiltinEncodeTime);
  3776. AddFunction(bcDateTime,'encodedatetime','D','IIIIIII',@BuiltinEncodeDateTime);
  3777. AddFunction(bcDateTime,'shortdayname','S','I',@BuiltinShortDayName);
  3778. AddFunction(bcDateTime,'shortmonthname','S','I',@BuiltinShortMonthName);
  3779. AddFunction(bcDateTime,'longdayname','S','I',@BuiltinLongDayName);
  3780. AddFunction(bcDateTime,'longmonthname','S','I',@BuiltinLongMonthName);
  3781. end;
  3782. if bcBoolean in Categories then
  3783. begin
  3784. // Boolean
  3785. AddFunction(bcBoolean,'shl','I','II',@BuiltinShl);
  3786. AddFunction(bcBoolean,'shr','I','II',@BuiltinShr);
  3787. AddFunction(bcBoolean,'IFS','S','BSS',@BuiltinIFS);
  3788. AddFunction(bcBoolean,'IFF','F','BFF',@BuiltinIFF);
  3789. AddFunction(bcBoolean,'IFD','D','BDD',@BuiltinIFD);
  3790. AddFunction(bcBoolean,'IFI','I','BII',@BuiltinIFI);
  3791. end;
  3792. if (bcConversion in Categories) then
  3793. begin
  3794. // Conversion
  3795. AddFunction(bcConversion,'inttostr','S','I',@BuiltInIntToStr);
  3796. AddFunction(bcConversion,'strtoint','I','S',@BuiltInStrToInt);
  3797. AddFunction(bcConversion,'strtointdef','I','SI',@BuiltInStrToIntDef);
  3798. AddFunction(bcConversion,'floattostr','S','F',@BuiltInFloatToStr);
  3799. AddFunction(bcConversion,'strtofloat','F','S',@BuiltInStrToFloat);
  3800. AddFunction(bcConversion,'strtofloatdef','F','SF',@BuiltInStrToFloatDef);
  3801. AddFunction(bcConversion,'booltostr','S','B',@BuiltInBoolToStr);
  3802. AddFunction(bcConversion,'strtobool','B','S',@BuiltInStrToBool);
  3803. AddFunction(bcConversion,'strtobooldef','B','SB',@BuiltInStrToBoolDef);
  3804. AddFunction(bcConversion,'datetostr','S','D',@BuiltInDateToStr);
  3805. AddFunction(bcConversion,'timetostr','S','D',@BuiltInTimeToStr);
  3806. AddFunction(bcConversion,'strtodate','D','S',@BuiltInStrToDate);
  3807. AddFunction(bcConversion,'strtodatedef','D','SD',@BuiltInStrToDateDef);
  3808. AddFunction(bcConversion,'strtotime','D','S',@BuiltInStrToTime);
  3809. AddFunction(bcConversion,'strtotimedef','D','SD',@BuiltInStrToTimeDef);
  3810. AddFunction(bcConversion,'strtodatetime','D','S',@BuiltInStrToDateTime);
  3811. AddFunction(bcConversion,'strtodatetimedef','D','SD',@BuiltInStrToDateTimeDef);
  3812. AddFunction(bcConversion,'formatfloat','S','SF',@BuiltInFormatFloat);
  3813. AddFunction(bcConversion,'formatdatetime','S','SD',@BuiltinFormatDateTime);
  3814. end;
  3815. if bcAggregate in Categories then
  3816. begin
  3817. AddFunction(bcAggregate,'count','I','',TAggregateCount);
  3818. AddFunction(bcAggregate,'sum','F','F',TAggregateSum);
  3819. AddFunction(bcAggregate,'avg','F','F',TAggregateAvg);
  3820. AddFunction(bcAggregate,'min','F','F',TAggregateMin);
  3821. AddFunction(bcAggregate,'max','F','F',TAggregateMax);
  3822. end;
  3823. end;
  3824. end;
  3825. { TFPBuiltInExprIdentifierDef }
  3826. procedure TFPBuiltInExprIdentifierDef.Assign(Source: TPersistent);
  3827. begin
  3828. inherited Assign(Source);
  3829. If Source is TFPBuiltInExprIdentifierDef then
  3830. FCategory:=(Source as TFPBuiltInExprIdentifierDef).Category;
  3831. end;
  3832. procedure InitFileFormatSettings;
  3833. begin
  3834. FileFormatSettings := DefaultFormatSettings;
  3835. FileFormatSettings.DecimalSeparator := '.';
  3836. FileFormatSettings.DateSeparator := '-';
  3837. FileFormatSettings.TimeSeparator := ':';
  3838. FileFormatsettings.ShortDateFormat := 'yyyy-mm-dd';
  3839. FileFormatSettings.LongTimeFormat := 'hh:nn:ss';
  3840. end;
  3841. initialization
  3842. RegisterStdBuiltins(BuiltinIdentifiers);
  3843. InitFileFormatSettings;
  3844. finalization
  3845. FreeBuiltins;
  3846. end.