fpexprpars.pp 121 KB

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