fpexprpars.pas 117 KB

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