fpexprpars.pp 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406
  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. ttMul, ttLeft, ttRight, ttLessThanEqual, ttLargerThanEqual,
  22. ttunequal, ttNumber, ttString, ttIdentifier,
  23. ttComma, ttand, ttOr,ttXor,ttTrue,ttFalse,ttnot,ttif,
  24. ttCase,ttEOF);
  25. TExprFloat = Double;
  26. Const
  27. ttDelimiters = [ttPlus, ttMinus, ttLessThan, ttLargerThan, ttEqual, ttDiv,
  28. ttMul, ttLeft, ttRight, ttLessThanEqual, ttLargerThanEqual,
  29. ttunequal];
  30. ttComparisons = [ttLargerThan,ttLessthan,
  31. ttLargerThanEqual,ttLessthanEqual,
  32. ttEqual,ttUnequal];
  33. Type
  34. TFPExpressionParser = Class;
  35. TExprBuiltInManager = Class;
  36. { TFPExpressionScanner }
  37. TFPExpressionScanner = Class(TObject)
  38. FSource : String;
  39. LSource,
  40. FPos : Integer;
  41. FChar : PChar;
  42. FToken : String;
  43. FTokenType : TTokenType;
  44. private
  45. function GetCurrentChar: Char;
  46. procedure ScanError(Msg: String);
  47. protected
  48. procedure SetSource(const AValue: String); virtual;
  49. function DoIdentifier: TTokenType;
  50. function DoNumber: TTokenType;
  51. function DoDelimiter: TTokenType;
  52. function DoString: TTokenType;
  53. Function NextPos : Char; // inline;
  54. procedure SkipWhiteSpace; // inline;
  55. function IsWordDelim(C : Char) : Boolean; // inline;
  56. function IsDelim(C : Char) : Boolean; // inline;
  57. function IsDigit(C : Char) : Boolean; // inline;
  58. function IsAlpha(C : Char) : Boolean; // inline;
  59. public
  60. Constructor Create;
  61. Function GetToken : TTokenType;
  62. Property Token : String Read FToken;
  63. Property TokenType : TTokenType Read FTokenType;
  64. Property Source : String Read FSource Write SetSource;
  65. Property Pos : Integer Read FPos;
  66. Property CurrentChar : Char Read GetCurrentChar;
  67. end;
  68. EExprScanner = Class(Exception);
  69. TResultType = (rtBoolean,rtInteger,rtFloat,rtDateTime,rtString);
  70. TResultTypes = set of TResultType;
  71. TFPExpressionResult = record
  72. ResString : String;
  73. Case ResultType : TResultType of
  74. rtBoolean : (ResBoolean : Boolean);
  75. rtInteger : (ResInteger : Int64);
  76. rtFloat : (ResFloat : TExprFloat);
  77. rtDateTime : (ResDateTime : TDatetime);
  78. rtString : ();
  79. end;
  80. PFPExpressionResult = ^TFPExpressionResult;
  81. TExprParameterArray = Array of TFPExpressionResult;
  82. { TFPExprNode }
  83. TFPExprNode = Class(TObject)
  84. Protected
  85. Procedure CheckNodeType(Anode : TFPExprNode; Allowed : TResultTypes);
  86. // A procedure with var saves an implicit try/finally in each node
  87. // A marked difference in execution speed.
  88. Procedure GetNodeValue(var Result : TFPExpressionResult); virtual; abstract;
  89. Public
  90. Procedure Check; virtual; abstract;
  91. Function NodeType : TResultType; virtual; abstract;
  92. Function NodeValue : TFPExpressionResult;
  93. Function AsString : string; virtual; abstract;
  94. end;
  95. TExprArgumentArray = Array of TFPExprNode;
  96. { TFPBinaryOperation }
  97. TFPBinaryOperation = Class(TFPExprNode)
  98. private
  99. FLeft: TFPExprNode;
  100. FRight: TFPExprNode;
  101. Protected
  102. Procedure CheckSameNodeTypes;
  103. Public
  104. Constructor Create(ALeft,ARight : TFPExprNode);
  105. Destructor Destroy; override;
  106. Procedure Check; override;
  107. Property left : TFPExprNode Read FLeft;
  108. Property Right : TFPExprNode Read FRight;
  109. end;
  110. TFPBinaryOperationClass = Class of TFPBinaryOperation;
  111. { TFPBooleanOperation }
  112. TFPBooleanOperation = Class(TFPBinaryOperation)
  113. Public
  114. Procedure Check; override;
  115. Function NodeType : TResultType; override;
  116. end;
  117. { TFPBinaryAndOperation }
  118. TFPBinaryAndOperation = Class(TFPBooleanOperation)
  119. Protected
  120. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  121. Public
  122. Function AsString : string ; override;
  123. end;
  124. { TFPBinaryOrOperation }
  125. TFPBinaryOrOperation = Class(TFPBooleanOperation)
  126. Protected
  127. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  128. Public
  129. Function AsString : string ; override;
  130. end;
  131. { TFPBinaryXOrOperation }
  132. TFPBinaryXOrOperation = Class(TFPBooleanOperation)
  133. Protected
  134. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  135. Public
  136. Function AsString : string ; override;
  137. end;
  138. { TFPBooleanResultOperation }
  139. TFPBooleanResultOperation = Class(TFPBinaryOperation)
  140. Public
  141. Procedure Check; override;
  142. Function NodeType : TResultType; override;
  143. end;
  144. TFPBooleanResultOperationClass = Class of TFPBooleanResultOperation;
  145. { TFPEqualOperation }
  146. TFPEqualOperation = Class(TFPBooleanResultOperation)
  147. Protected
  148. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  149. Public
  150. Function AsString : string ; override;
  151. end;
  152. { TFPUnequalOperation }
  153. TFPUnequalOperation = Class(TFPEqualOperation)
  154. Protected
  155. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  156. Public
  157. Function AsString : string ; override;
  158. end;
  159. { TFPOrderingOperation }
  160. TFPOrderingOperation = Class(TFPBooleanResultOperation)
  161. Procedure Check; override;
  162. end;
  163. { TFPLessThanOperation }
  164. TFPLessThanOperation = Class(TFPOrderingOperation)
  165. Protected
  166. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  167. Public
  168. Function AsString : string ; override;
  169. end;
  170. { TFPGreaterThanOperation }
  171. TFPGreaterThanOperation = Class(TFPOrderingOperation)
  172. Protected
  173. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  174. Public
  175. Function AsString : string ; override;
  176. end;
  177. { TFPLessThanEqualOperation }
  178. TFPLessThanEqualOperation = Class(TFPGreaterThanOperation)
  179. Protected
  180. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  181. Public
  182. Function AsString : string ; override;
  183. end;
  184. { TFPGreaterThanEqualOperation }
  185. TFPGreaterThanEqualOperation = Class(TFPLessThanOperation)
  186. Protected
  187. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  188. Public
  189. Function AsString : string ; override;
  190. end;
  191. { TIfOperation }
  192. TIfOperation = Class(TFPBinaryOperation)
  193. private
  194. FCondition: TFPExprNode;
  195. protected
  196. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  197. Procedure Check; override;
  198. Function NodeType : TResultType; override;
  199. Public
  200. Constructor Create(ACondition,ALeft,ARight : TFPExprNode);
  201. Destructor destroy; override;
  202. Function AsString : string ; override;
  203. Property Condition : TFPExprNode Read FCondition;
  204. end;
  205. { TCaseOperation }
  206. TCaseOperation = Class(TFPExprNode)
  207. private
  208. FArgs : TExprArgumentArray;
  209. FCondition: TFPExprNode;
  210. protected
  211. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  212. Procedure Check; override;
  213. Function NodeType : TResultType; override;
  214. Public
  215. Constructor Create(Args : TExprArgumentArray);
  216. Destructor destroy; override;
  217. Function AsString : string ; override;
  218. Property Condition : TFPExprNode Read FCondition;
  219. end;
  220. { TMathOperation }
  221. TMathOperation = Class(TFPBinaryOperation)
  222. protected
  223. Procedure Check; override;
  224. Function NodeType : TResultType; override;
  225. end;
  226. { TFPAddOperation }
  227. TFPAddOperation = Class(TMathOperation)
  228. Protected
  229. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  230. Public
  231. Function AsString : string ; override;
  232. end;
  233. { TFPSubtractOperation }
  234. TFPSubtractOperation = Class(TMathOperation)
  235. Protected
  236. Procedure check; override;
  237. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  238. Public
  239. Function AsString : string ; override;
  240. end;
  241. { TFPMultiplyOperation }
  242. TFPMultiplyOperation = Class(TMathOperation)
  243. Protected
  244. Procedure check; override;
  245. Public
  246. Function AsString : string ; override;
  247. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  248. end;
  249. { TFPDivideOperation }
  250. TFPDivideOperation = Class(TMathOperation)
  251. Protected
  252. Procedure check; override;
  253. Public
  254. Function AsString : string ; override;
  255. Function NodeType : TResultType; override;
  256. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  257. end;
  258. { TFPUnaryOperator }
  259. TFPUnaryOperator = Class(TFPExprNode)
  260. private
  261. FOperand: TFPExprNode;
  262. Public
  263. Constructor Create(AOperand : TFPExprNode);
  264. Destructor Destroy; override;
  265. Procedure Check; override;
  266. Property Operand : TFPExprNode Read FOperand;
  267. end;
  268. { TFPConvertNode }
  269. TFPConvertNode = Class(TFPUnaryOperator)
  270. Function AsString : String; override;
  271. end;
  272. { TFPNotNode }
  273. TFPNotNode = Class(TFPUnaryOperator)
  274. Protected
  275. Procedure Check; override;
  276. Public
  277. Function NodeType : TResultType; override;
  278. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  279. Function AsString : String; override;
  280. end;
  281. TIntConvertNode = Class(TFPConvertNode)
  282. Protected
  283. Procedure Check; override;
  284. end;
  285. { TIntToFloatNode }
  286. TIntToFloatNode = Class(TIntConvertNode)
  287. Public
  288. Function NodeType : TResultType; override;
  289. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  290. end;
  291. { TIntToDateTimeNode }
  292. TIntToDateTimeNode = Class(TIntConvertNode)
  293. Public
  294. Function NodeType : TResultType; override;
  295. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  296. end;
  297. { TFloatToDateTimeNode }
  298. TFloatToDateTimeNode = Class(TFPConvertNode)
  299. Protected
  300. Procedure Check; override;
  301. Public
  302. Function NodeType : TResultType; override;
  303. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  304. end;
  305. { TFPNegateOperation }
  306. TFPNegateOperation = Class(TFPUnaryOperator)
  307. Public
  308. Procedure Check; override;
  309. Function NodeType : TResultType; override;
  310. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  311. Function AsString : String; override;
  312. end;
  313. { TFPConstExpression }
  314. TFPConstExpression = Class(TFPExprnode)
  315. private
  316. FValue : TFPExpressionResult;
  317. public
  318. Constructor CreateString(AValue : String);
  319. Constructor CreateInteger(AValue : Int64);
  320. Constructor CreateDateTime(AValue : TDateTime);
  321. Constructor CreateFloat(AValue : TExprFloat);
  322. Constructor CreateBoolean(AValue : Boolean);
  323. Procedure Check; override;
  324. Function NodeType : TResultType; override;
  325. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  326. Function AsString : string ; override;
  327. // For inspection
  328. Property ConstValue : TFPExpressionResult read FValue;
  329. end;
  330. TIdentifierType = (itVariable,itFunctionCallBack,itFunctionHandler);
  331. TFPExprFunctionCallBack = Procedure (Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  332. TFPExprFunctionEvent = Procedure (Var Result : TFPExpressionResult; Const Args : TExprParameterArray) of object;
  333. { TFPExprIdentifierDef }
  334. TFPExprIdentifierDef = Class(TCollectionItem)
  335. private
  336. FStringValue : String;
  337. FValue : TFPExpressionResult;
  338. FArgumentTypes: String;
  339. FIDType: TIdentifierType;
  340. FName: ShortString;
  341. FOnGetValue: TFPExprFunctionEvent;
  342. FOnGetValueCB: TFPExprFunctionCallBack;
  343. function GetAsBoolean: Boolean;
  344. function GetAsDateTime: TDateTime;
  345. function GetAsFloat: TExprFloat;
  346. function GetAsInteger: Int64;
  347. function GetAsString: String;
  348. function GetResultType: TResultType;
  349. function GetValue: String;
  350. procedure SetArgumentTypes(const AValue: String);
  351. procedure SetAsBoolean(const AValue: Boolean);
  352. procedure SetAsDateTime(const AValue: TDateTime);
  353. procedure SetAsFloat(const AValue: TExprFloat);
  354. procedure SetAsInteger(const AValue: Int64);
  355. procedure SetAsString(const AValue: String);
  356. procedure SetName(const AValue: ShortString);
  357. procedure SetResultType(const AValue: TResultType);
  358. procedure SetValue(const AValue: String);
  359. Protected
  360. Procedure CheckResultType(Const AType : TResultType);
  361. Procedure CheckVariable;
  362. Public
  363. Function ArgumentCount : Integer;
  364. Procedure Assign(Source : TPersistent); override;
  365. Property AsFloat : TExprFloat Read GetAsFloat Write SetAsFloat;
  366. Property AsInteger : Int64 Read GetAsInteger Write SetAsInteger;
  367. Property AsString : String Read GetAsString Write SetAsString;
  368. Property AsBoolean : Boolean Read GetAsBoolean Write SetAsBoolean;
  369. Property AsDateTime : TDateTime Read GetAsDateTime Write SetAsDateTime;
  370. Property OnGetFunctionValueCallBack : TFPExprFunctionCallBack Read FOnGetValueCB Write FOnGetValueCB;
  371. Published
  372. Property IdentifierType : TIdentifierType Read FIDType Write FIDType;
  373. Property Name : ShortString Read FName Write SetName;
  374. Property Value : String Read GetValue Write SetValue;
  375. Property ParameterTypes : String Read FArgumentTypes Write SetArgumentTypes;
  376. Property ResultType : TResultType Read GetResultType Write SetResultType;
  377. Property OnGetFunctionValue : TFPExprFunctionEvent Read FOnGetValue Write FOnGetValue;
  378. end;
  379. TBuiltInCategory = (bcStrings,bcDateTime,bcMath,bcBoolean,bcConversion,bcData,bcVaria,bcUser);
  380. TBuiltInCategories = Set of TBuiltInCategory;
  381. { TFPBuiltInExprIdentifierDef }
  382. TFPBuiltInExprIdentifierDef = Class(TFPExprIdentifierDef)
  383. private
  384. FCategory: TBuiltInCategory;
  385. Public
  386. Procedure Assign(Source : TPersistent); override;
  387. Published
  388. Property Category : TBuiltInCategory Read FCategory Write FCategory;
  389. end;
  390. { TFPExprIdentifierDefs }
  391. TFPExprIdentifierDefs = Class(TCollection)
  392. private
  393. FParser: TFPExpressionParser;
  394. function GetI(AIndex : Integer): TFPExprIdentifierDef;
  395. procedure SetI(AIndex : Integer; const AValue: TFPExprIdentifierDef);
  396. Protected
  397. procedure Update(Item: TCollectionItem); override;
  398. Property Parser: TFPExpressionParser Read FParser;
  399. Public
  400. Function IndexOfIdentifier(Const AName : ShortString) : Integer;
  401. Function FindIdentifier(Const AName : ShortString) : TFPExprIdentifierDef;
  402. Function IdentifierByName(Const AName : ShortString) : TFPExprIdentifierDef;
  403. Function AddVariable(Const AName : ShortString; AResultType : TResultType; AValue : String) : TFPExprIdentifierDef;
  404. Function AddBooleanVariable(Const AName : ShortString; AValue : Boolean) : TFPExprIdentifierDef;
  405. Function AddIntegerVariable(Const AName : ShortString; AValue : Integer) : TFPExprIdentifierDef;
  406. Function AddFloatVariable(Const AName : ShortString; AValue : TExprFloat) : TFPExprIdentifierDef;
  407. Function AddStringVariable(Const AName : ShortString; AValue : String) : TFPExprIdentifierDef;
  408. Function AddDateTimeVariable(Const AName : ShortString; AValue : TDateTime) : TFPExprIdentifierDef;
  409. Function AddFunction(Const AName : ShortString; Const AResultType : Char; Const AParamTypes : String; ACallBack : TFPExprFunctionCallBack) : TFPExprIdentifierDef;
  410. Function AddFunction(Const AName : ShortString; Const AResultType : Char; Const AParamTypes : String; ACallBack : TFPExprFunctionEvent) : TFPExprIdentifierDef;
  411. property Identifiers[AIndex : Integer] : TFPExprIdentifierDef Read GetI Write SetI; Default;
  412. end;
  413. { TFPExprIdentifierNode }
  414. TFPExprIdentifierNode = Class(TFPExprNode)
  415. Private
  416. FID : TFPExprIdentifierDef;
  417. PResult : PFPExpressionResult;
  418. FResultType : TResultType;
  419. public
  420. Constructor CreateIdentifier(AID : TFPExprIdentifierDef);
  421. Function NodeType : TResultType; override;
  422. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  423. Property Identifier : TFPExprIdentifierDef Read FID;
  424. end;
  425. { TFPExprVariable }
  426. TFPExprVariable = Class(TFPExprIdentifierNode)
  427. Procedure Check; override;
  428. function AsString: string; override;
  429. end;
  430. { TFPExprFunction }
  431. TFPExprFunction = Class(TFPExprIdentifierNode)
  432. private
  433. FArgumentNodes : TExprArgumentArray;
  434. FargumentParams : TExprParameterArray;
  435. Protected
  436. Procedure CalcParams;
  437. Procedure Check; override;
  438. Public
  439. Constructor CreateFunction(AID : TFPExprIdentifierDef; Const Args : TExprArgumentArray); virtual;
  440. Destructor Destroy; override;
  441. Property ArgumentNodes : TExprArgumentArray Read FArgumentNodes;
  442. Property ArgumentParams : TExprParameterArray Read FArgumentParams;
  443. Function AsString : String; override;
  444. end;
  445. { TFPFunctionCallBack }
  446. TFPFunctionCallBack = Class(TFPExprFunction)
  447. Private
  448. FCallBack : TFPExprFunctionCallBack;
  449. Public
  450. Constructor CreateFunction(AID : TFPExprIdentifierDef; Const Args : TExprArgumentArray); override;
  451. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  452. Property CallBack : TFPExprFunctionCallBack Read FCallBack;
  453. end;
  454. { TFPFunctionEventHandler }
  455. TFPFunctionEventHandler = Class(TFPExprFunction)
  456. Private
  457. FCallBack : TFPExprFunctionEvent;
  458. Public
  459. Constructor CreateFunction(AID : TFPExprIdentifierDef; Const Args : TExprArgumentArray); override;
  460. Procedure GetNodeValue(var Result : TFPExpressionResult); override;
  461. Property CallBack : TFPExprFunctionEvent Read FCallBack;
  462. end;
  463. { TFPExpressionParser }
  464. TFPExpressionParser = class(TComponent)
  465. private
  466. FBuiltIns: TBuiltInCategories;
  467. FExpression: String;
  468. FScanner : TFPExpressionScanner;
  469. FExprNode : TFPExprNode;
  470. FIdentifiers : TFPExprIdentifierDefs;
  471. FHashList : TFPHashObjectlist;
  472. FDirty : Boolean;
  473. procedure CheckEOF;
  474. function ConvertNode(Todo: TFPExprNode; ToType: TResultType): TFPExprNode;
  475. function GetAsBoolean: Boolean;
  476. function GetAsDateTime: TDateTime;
  477. function GetAsFloat: TExprFloat;
  478. function GetAsInteger: Int64;
  479. function GetAsString: String;
  480. function MatchNodes(Todo, Match: TFPExprNode): TFPExprNode;
  481. procedure CheckNodes(var Left, Right: TFPExprNode);
  482. procedure SetBuiltIns(const AValue: TBuiltInCategories);
  483. procedure SetIdentifiers(const AValue: TFPExprIdentifierDefs);
  484. Protected
  485. procedure ParserError(Msg: String);
  486. procedure SetExpression(const AValue: String); virtual;
  487. Procedure CheckResultType(Const Res :TFPExpressionResult; AType : TResultType); inline;
  488. class Function BuiltinsManager : TExprBuiltInManager;
  489. Function Level1 : TFPExprNode;
  490. Function Level2 : TFPExprNode;
  491. Function Level3 : TFPExprNode;
  492. Function Level4 : TFPExprNode;
  493. Function Level5 : TFPExprNode;
  494. Function Level6 : TFPExprNode;
  495. Function Primitive : TFPExprNode;
  496. function GetToken: TTokenType;
  497. Function TokenType : TTokenType;
  498. Function CurrentToken : String;
  499. Procedure CreateHashList;
  500. Property Scanner : TFPExpressionScanner Read FScanner;
  501. Property ExprNode : TFPExprNode Read FExprNode;
  502. Property Dirty : Boolean Read FDirty;
  503. public
  504. Constructor Create(AOwner :TComponent); override;
  505. Destructor Destroy; override;
  506. Function IdentifierByName(AName : ShortString) : TFPExprIdentifierDef;
  507. Procedure Clear;
  508. Procedure EvaluateExpression(Var Result : TFPExpressionResult);
  509. Function Evaluate : TFPExpressionResult;
  510. Function ResultType : TResultType;
  511. Property AsFloat : TExprFloat Read GetAsFloat;
  512. Property AsInteger : Int64 Read GetAsInteger;
  513. Property AsString : String Read GetAsString;
  514. Property AsBoolean : Boolean Read GetAsBoolean;
  515. Property AsDateTime : TDateTime Read GetAsDateTime;
  516. Published
  517. // The Expression to parse
  518. property Expression : String read FExpression write SetExpression;
  519. Property Identifiers : TFPExprIdentifierDefs Read FIdentifiers Write SetIdentifiers;
  520. Property BuiltIns : TBuiltInCategories Read FBuiltIns Write SetBuiltIns;
  521. end;
  522. { TExprBuiltInManager }
  523. TExprBuiltInManager = Class(TComponent)
  524. Private
  525. FDefs : TFPExprIdentifierDefs;
  526. function GetCount: Integer;
  527. function GetI(AIndex : Integer): TFPBuiltInExprIdentifierDef;
  528. protected
  529. Property Defs : TFPExprIdentifierDefs Read FDefs;
  530. Public
  531. Constructor Create(AOwner : TComponent); override;
  532. Destructor Destroy; override;
  533. Function IndexOfIdentifier(Const AName : ShortString) : Integer;
  534. Function FindIdentifier(Const AName : ShortString) : TFPBuiltinExprIdentifierDef;
  535. Function IdentifierByName(Const AName : ShortString) : TFPBuiltinExprIdentifierDef;
  536. Function AddVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AResultType : TResultType; AValue : String) : TFPBuiltInExprIdentifierDef;
  537. Function AddBooleanVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : Boolean) : TFPBuiltInExprIdentifierDef;
  538. Function AddIntegerVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : Integer) : TFPBuiltInExprIdentifierDef;
  539. Function AddFloatVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : TExprFloat) : TFPBuiltInExprIdentifierDef;
  540. Function AddStringVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : String) : TFPBuiltInExprIdentifierDef;
  541. Function AddDateTimeVariable(Const ACategory : TBuiltInCategory; Const AName : ShortString; AValue : TDateTime) : TFPBuiltInExprIdentifierDef;
  542. Function AddFunction(Const ACategory : TBuiltInCategory; Const AName : ShortString; Const AResultType : Char; Const AParamTypes : String; ACallBack : TFPExprFunctionCallBack) : TFPBuiltInExprIdentifierDef;
  543. Function AddFunction(Const ACategory : TBuiltInCategory; Const AName : ShortString; Const AResultType : Char; Const AParamTypes : String; ACallBack : TFPExprFunctionEvent) : TFPBuiltInExprIdentifierDef;
  544. Property IdentifierCount : Integer Read GetCount;
  545. Property Identifiers[AIndex : Integer] :TFPBuiltInExprIdentifierDef Read GetI;
  546. end;
  547. EExprParser = Class(Exception);
  548. Function TokenName (AToken : TTokenType) : String;
  549. Function ResultTypeName (AResult : TResultType) : String;
  550. Function CharToResultType(C : Char) : TResultType;
  551. Function BuiltinIdentifiers : TExprBuiltInManager;
  552. Procedure RegisterStdBuiltins(AManager : TExprBuiltInManager);
  553. Const
  554. AllBuiltIns = [bcStrings,bcDateTime,bcMath,bcBoolean,bcConversion,bcData,bcVaria,bcUser];
  555. implementation
  556. uses typinfo;
  557. { TFPExpressionParser }
  558. const
  559. cNull=#0;
  560. cSingleQuote = '''';
  561. Digits = ['0'..'9','.'];
  562. WhiteSpace = [' ',#13,#10,#9];
  563. Operators = ['+','-','<','>','=','/','*'];
  564. Delimiters = Operators+[',','(',')'];
  565. Symbols = ['%','^']+Delimiters;
  566. WordDelimiters = WhiteSpace + Symbols;
  567. Resourcestring
  568. SBadQuotes = 'Unterminated string';
  569. SUnknownDelimiter = 'Unknown delimiter character: "%s"';
  570. SErrUnknownCharacter = 'Unknown character at pos %d: "%s"';
  571. SErrUnexpectedEndOfExpression = 'Unexpected end of expression';
  572. SErrUnknownComparison = 'Internal error: Unknown comparison';
  573. SErrUnknownBooleanOp = 'Internal error: Unknown boolean operation';
  574. SErrBracketExpected = 'Expected ) bracket at position %d, but got %s';
  575. SerrUnknownTokenAtPos = 'Unknown token at pos %d : %s';
  576. SErrLeftBracketExpected = 'Expected ( bracket at position %d, but got %s';
  577. SErrInvalidFloat = '%s is not a valid floating-point value';
  578. SErrUnknownIdentifier = 'Unknown identifier: %s';
  579. SErrInExpression = 'Cannot evaluate: error in expression';
  580. SErrInExpressionEmpty = 'Cannot evaluate: empty expression';
  581. SErrCommaExpected = 'Expected comma (,) at position %d, but got %s';
  582. SErrInvalidNumberChar = 'Unexpected character in number : %s';
  583. SErrInvalidNumber = 'Invalid numerical value : %s';
  584. SErrNoOperand = 'No operand for unary operation %s';
  585. SErrNoleftOperand = 'No left operand for binary operation %s';
  586. SErrNoRightOperand = 'No left operand for binary operation %s';
  587. SErrNoNegation = 'Cannot negate expression of type %s : %s';
  588. SErrNoNOTOperation = 'Cannot perform "not" on expression of type %s: %s';
  589. SErrTypesDoNotMatch = 'Type mismatch: %s<>%s for expressions "%s" and "%s".';
  590. SErrTypesIncompatible = 'Incompatible types: %s<>%s for expressions "%s" and "%s".';
  591. SErrNoNodeToCheck = 'Internal error: No node to check !';
  592. SInvalidNodeType = 'Node type (%s) not in allowed types (%s) for expression: %s';
  593. SErrUnterminatedExpression = 'Badly terminated expression. Found token at position %d : %s';
  594. SErrDuplicateIdentifier = 'An identifier with name "%s" already exists.';
  595. SErrInvalidResultCharacter = '"%s" is not a valid return type indicator';
  596. ErrInvalidArgumentCount = 'Invalid argument count for function %s';
  597. SErrInvalidArgumentType = 'Invalid type for argument %d: Expected %s, got %s';
  598. SErrInvalidResultType = 'Invalid result type: %s';
  599. SErrNotVariable = 'Identifier %s is not a variable';
  600. SErrInactive = 'Operation not allowed while an expression is active';
  601. SErrIFNeedsBoolean = 'First argument to IF must be of type boolean: %s';
  602. SErrCaseNeeds3 = 'Case statement needs to have at least 4 arguments';
  603. SErrCaseEvenCount = 'Case statement needs to have an even number of arguments';
  604. SErrCaseLabelNotAConst = 'Case label %d "%s" is not a constant expression';
  605. SErrCaseLabelType = 'Case label %d "%s" needs type %s, but has type %s';
  606. SErrCaseValueType = 'Case value %d "%s" needs type %s, but has type %s';
  607. { ---------------------------------------------------------------------
  608. Auxiliary functions
  609. ---------------------------------------------------------------------}
  610. Procedure RaiseParserError(Msg : String);
  611. begin
  612. Raise EExprParser.Create(Msg);
  613. end;
  614. Procedure RaiseParserError(Fmt : String; Args : Array of const);
  615. begin
  616. Raise EExprParser.CreateFmt(Fmt,Args);
  617. end;
  618. Function TokenName (AToken : TTokenType) : String;
  619. begin
  620. Result:=GetEnumName(TypeInfo(TTokenType),Ord(AToken));
  621. end;
  622. Function ResultTypeName (AResult : TResultType) : String;
  623. begin
  624. Result:=GetEnumName(TypeInfo(TResultType),Ord(AResult));
  625. end;
  626. function CharToResultType(C: Char): TResultType;
  627. begin
  628. Case Upcase(C) of
  629. 'S' : Result:=rtString;
  630. 'D' : Result:=rtDateTime;
  631. 'B' : Result:=rtBoolean;
  632. 'I' : Result:=rtInteger;
  633. 'F' : Result:=rtFloat;
  634. else
  635. RaiseParserError(SErrInvalidResultCharacter,[C]);
  636. end;
  637. end;
  638. Var
  639. BuiltIns : TExprBuiltInManager;
  640. Function BuiltinIdentifiers : TExprBuiltInManager;
  641. begin
  642. If (BuiltIns=Nil) then
  643. BuiltIns:=TExprBuiltInManager.Create(Nil);
  644. Result:=BuiltIns;
  645. end;
  646. Procedure FreeBuiltIns;
  647. begin
  648. FreeAndNil(Builtins);
  649. end;
  650. { ---------------------------------------------------------------------
  651. TFPExpressionScanner
  652. ---------------------------------------------------------------------}
  653. function TFPExpressionScanner.IsAlpha(C: Char): Boolean;
  654. begin
  655. Result := C in ['A'..'Z', 'a'..'z'];
  656. end;
  657. constructor TFPExpressionScanner.Create;
  658. begin
  659. Source:='';
  660. end;
  661. procedure TFPExpressionScanner.SetSource(const AValue: String);
  662. begin
  663. FSource:=AValue;
  664. LSource:=Length(FSource);
  665. FTokenType:=ttEOF;
  666. If LSource=0 then
  667. FPos:=0
  668. else
  669. FPos:=1;
  670. FChar:=Pchar(FSource);
  671. FToken:='';
  672. end;
  673. function TFPExpressionScanner.NextPos: Char;
  674. begin
  675. Inc(FPos);
  676. Inc(FChar);
  677. Result:=FChar^;
  678. end;
  679. function TFPExpressionScanner.IsWordDelim(C: Char): Boolean;
  680. begin
  681. Result:=C in WordDelimiters;
  682. end;
  683. function TFPExpressionScanner.IsDelim(C: Char): Boolean;
  684. begin
  685. Result:=C in Delimiters;
  686. end;
  687. function TFPExpressionScanner.IsDigit(C: Char): Boolean;
  688. begin
  689. Result:=C in Digits;
  690. end;
  691. Procedure TFPExpressionScanner.SkipWhiteSpace;
  692. begin
  693. While (FChar^ in WhiteSpace) and (FPos<=LSource) do
  694. NextPos;
  695. end;
  696. Function TFPExpressionScanner.DoDelimiter : TTokenType;
  697. Var
  698. B : Boolean;
  699. C,D : Char;
  700. begin
  701. C:=FChar^;
  702. FToken:=C;
  703. B:=C in ['<','>'];
  704. D:=C;
  705. C:=NextPos;
  706. if B and (C in ['=','>']) then
  707. begin
  708. FToken:=FToken+C;
  709. NextPos;
  710. If (D='>') then
  711. Result:=ttLargerThanEqual
  712. else if (C='>') then
  713. Result:=ttUnequal
  714. else
  715. Result:=ttLessThanEqual;
  716. end
  717. else
  718. Case D of
  719. '+' : Result := ttPlus;
  720. '-' : Result := ttMinus;
  721. '<' : Result := ttLessThan;
  722. '>' : Result := ttLargerThan;
  723. '=' : Result := ttEqual;
  724. '/' : Result := ttDiv;
  725. '*' : Result := ttMul;
  726. '(' : Result := ttLeft;
  727. ')' : Result := ttRight;
  728. ',' : Result := ttComma;
  729. else
  730. ScanError(Format(SUnknownDelimiter,[D]));
  731. end;
  732. end;
  733. Procedure TFPExpressionScanner.ScanError(Msg : String);
  734. begin
  735. Raise EExprScanner.Create(Msg)
  736. end;
  737. Function TFPExpressionScanner.DoString : TTokenType;
  738. Function TerminatingChar(C : Char) : boolean;
  739. begin
  740. Result:=(C=cNull) or
  741. ((C=cSingleQuote) and
  742. Not ((FPos<LSource) and (FSource[FPos+1]=cSingleQuote)));
  743. end;
  744. Var
  745. C : Char;
  746. begin
  747. FToken := '';
  748. C:=NextPos;
  749. while not TerminatingChar(C) do
  750. begin
  751. FToken:=FToken+C;
  752. If C=cSingleQuote then
  753. NextPos;
  754. C:=NextPos;
  755. end;
  756. if (C=cNull) then
  757. ScanError(SBadQuotes);
  758. Result := ttString;
  759. FTokenType:=Result;
  760. NextPos;
  761. end;
  762. function TFPExpressionScanner.GetCurrentChar: Char;
  763. begin
  764. If FChar<>Nil then
  765. Result:=FChar^
  766. else
  767. Result:=#0;
  768. end;
  769. Function TFPExpressionScanner.DoNumber : TTokenType;
  770. Var
  771. C : Char;
  772. X : TExprFloat;
  773. I : Integer;
  774. begin
  775. C:=CurrentChar;
  776. while (not IsWordDelim(C)) and (C<>cNull) do
  777. begin
  778. If Not (IsDigit(C) or ((FToken<>'') and (Upcase(C)='E'))) then
  779. ScanError(Format(SErrInvalidNumberChar,[C]));
  780. FToken := FToken+C;
  781. C:=NextPos;
  782. end;
  783. Val(FToken,X,I);
  784. If (I<>0) then
  785. ScanError(Format(SErrInvalidNumber,[FToken]));
  786. Result:=ttNumber;
  787. end;
  788. Function TFPExpressionScanner.DoIdentifier : TTokenType;
  789. Var
  790. C : Char;
  791. S : String;
  792. begin
  793. C:=CurrentChar;
  794. while (not IsWordDelim(C)) and (C<>cNull) do
  795. begin
  796. FToken:=FToken+C;
  797. C:=NextPos;
  798. end;
  799. S:=LowerCase(Token);
  800. If (S='or') then
  801. Result:=ttOr
  802. else if (S='xor') then
  803. Result:=ttXOr
  804. else if (S='and') then
  805. Result:=ttAnd
  806. else if (S='true') then
  807. Result:=ttTrue
  808. else if (S='false') then
  809. Result:=ttFalse
  810. else if (S='not') then
  811. Result:=ttnot
  812. else if (S='if') then
  813. Result:=ttif
  814. else if (S='case') then
  815. Result:=ttcase
  816. else
  817. Result:=ttIdentifier;
  818. end;
  819. Function TFPExpressionScanner.GetToken : TTokenType;
  820. Var
  821. C : Char;
  822. begin
  823. FToken := '';
  824. SkipWhiteSpace;
  825. C:=FChar^;
  826. if c=cNull then
  827. Result:=ttEOF
  828. else if IsDelim(C) then
  829. Result:=DoDelimiter
  830. else if (C=cSingleQuote) then
  831. Result:=DoString
  832. else if IsDigit(C) then
  833. Result:=DoNumber
  834. else if IsAlpha(C) then
  835. Result:=DoIdentifier
  836. else
  837. ScanError(Format(SErrUnknownCharacter,[FPos,C])) ;
  838. FTokenType:=Result;
  839. end;
  840. { ---------------------------------------------------------------------
  841. TFPExpressionParser
  842. ---------------------------------------------------------------------}
  843. Function TFPExpressionParser.TokenType : TTokenType;
  844. begin
  845. Result:=FScanner.TokenType;
  846. end;
  847. function TFPExpressionParser.CurrentToken: String;
  848. begin
  849. Result:=FScanner.Token;
  850. end;
  851. procedure TFPExpressionParser.CreateHashList;
  852. Var
  853. ID : TFPExpridentifierDef;
  854. BID : TFPBuiltinExpridentifierDef;
  855. I : Integer;
  856. M : TExprBuiltinManager;
  857. begin
  858. FHashList.Clear;
  859. // Builtins
  860. M:=BuiltinsManager;
  861. If (FBuiltins<>[]) and Assigned(M) then
  862. For I:=0 to M.IdentifierCount-1 do
  863. begin
  864. BID:=M.Identifiers[I];
  865. If BID.Category in FBuiltins then
  866. FHashList.Add(LowerCase(BID.Name),BID);
  867. end;
  868. // User
  869. For I:=0 to FIdentifiers.Count-1 do
  870. begin
  871. ID:=FIdentifiers[i];
  872. FHashList.Add(LowerCase(ID.Name),ID);
  873. end;
  874. FDirty:=False;
  875. end;
  876. function TFPExpressionParser.IdentifierByName(AName: ShortString): TFPExprIdentifierDef;
  877. begin
  878. If FDirty then
  879. CreateHashList;
  880. Result:=TFPExprIdentifierDef(FHashList.Find(LowerCase(AName)));
  881. end;
  882. procedure TFPExpressionParser.Clear;
  883. begin
  884. FExpression:='';
  885. FHashList.Clear;
  886. FExprNode.Free;
  887. end;
  888. constructor TFPExpressionParser.Create(AOwner: TComponent);
  889. begin
  890. inherited Create(AOwner);
  891. FIdentifiers:=TFPExprIdentifierDefs.Create(TFPExprIdentifierDef);
  892. FIdentifiers.FParser:=Self;
  893. FScanner:=TFPExpressionScanner.Create;
  894. FHashList:=TFPHashObjectList.Create(False);
  895. end;
  896. destructor TFPExpressionParser.Destroy;
  897. begin
  898. FreeAndNil(FHashList);
  899. FreeAndNil(FExprNode);
  900. FreeAndNil(FIdentifiers);
  901. FreeAndNil(FScanner);
  902. inherited Destroy;
  903. end;
  904. Function TFPExpressionParser.GetToken : TTokenType;
  905. begin
  906. Result:=FScanner.GetToken;
  907. end;
  908. Procedure TFPExpressionParser.CheckEOF;
  909. begin
  910. If (TokenType=ttEOF) then
  911. ParserError(SErrUnexpectedEndOfExpression);
  912. end;
  913. procedure TFPExpressionParser.SetIdentifiers(const AValue: TFPExprIdentifierDefs
  914. );
  915. begin
  916. FIdentifiers.Assign(AValue)
  917. end;
  918. procedure TFPExpressionParser.EvaluateExpression(var Result: TFPExpressionResult);
  919. begin
  920. If (FExpression='') then
  921. ParserError(SErrInExpressionEmpty);
  922. if not Assigned(FExprNode) then
  923. ParserError(SErrInExpression);
  924. FExprNode.GetNodeValue(Result);
  925. end;
  926. procedure TFPExpressionParser.ParserError(Msg: String);
  927. begin
  928. Raise EExprParser.Create(Msg);
  929. end;
  930. function TFPExpressionParser.ConvertNode(Todo : TFPExprNode; ToType : TResultType): TFPExprNode;
  931. begin
  932. Result:=ToDo;
  933. Case ToDo.NodeType of
  934. rtInteger :
  935. Case ToType of
  936. rtFloat : Result:=TIntToFloatNode.Create(Result);
  937. rtDateTime : Result:=TIntToDateTimeNode.Create(Result);
  938. end;
  939. rtFloat :
  940. Case ToType of
  941. rtDateTime : Result:=TFloatToDateTimeNode.Create(Result);
  942. end;
  943. end;
  944. end;
  945. function TFPExpressionParser.GetAsBoolean: Boolean;
  946. var
  947. Res: TFPExpressionResult;
  948. begin
  949. EvaluateExpression(Res);
  950. CheckResultType(Res,rtBoolean);
  951. Result:=Res.ResBoolean;
  952. end;
  953. function TFPExpressionParser.GetAsDateTime: TDateTime;
  954. var
  955. Res: TFPExpressionResult;
  956. begin
  957. EvaluateExpression(Res);
  958. CheckResultType(Res,rtDateTime);
  959. Result:=Res.ResDatetime;
  960. end;
  961. function TFPExpressionParser.GetAsFloat: TExprFloat;
  962. var
  963. Res: TFPExpressionResult;
  964. begin
  965. EvaluateExpression(Res);
  966. CheckResultType(Res,rtFloat);
  967. Result:=Res.ResFloat;
  968. end;
  969. function TFPExpressionParser.GetAsInteger: Int64;
  970. var
  971. Res: TFPExpressionResult;
  972. begin
  973. EvaluateExpression(Res);
  974. CheckResultType(Res,rtInteger);
  975. Result:=Res.ResInteger;
  976. end;
  977. function TFPExpressionParser.GetAsString: String;
  978. var
  979. Res: TFPExpressionResult;
  980. begin
  981. EvaluateExpression(Res);
  982. CheckResultType(Res,rtString);
  983. Result:=Res.ResString;
  984. end;
  985. {
  986. Checks types of todo and match. If ToDO can be converted to it matches
  987. the type of match, then a node is inserted.
  988. For binary operations, this function is called for both operands.
  989. }
  990. function TFPExpressionParser.MatchNodes(Todo,Match : TFPExprNode): TFPExprNode;
  991. Var
  992. TT,MT : TResultType;
  993. begin
  994. Result:=Todo;
  995. TT:=Todo.NodeType;
  996. MT:=Match.NodeType;
  997. If (TT<>MT) then
  998. begin
  999. if (TT=rtInteger) then
  1000. begin
  1001. if (MT in [rtFloat,rtDateTime]) then
  1002. Result:=ConvertNode(Todo,MT);
  1003. end
  1004. else if (TT=rtFloat) then
  1005. begin
  1006. if (MT=rtDateTime) then
  1007. Result:=ConvertNode(Todo,rtDateTime);
  1008. end;
  1009. end;
  1010. end;
  1011. {
  1012. if the result types differ, they are converted to a common type if possible.
  1013. }
  1014. Procedure TFPExpressionParser.CheckNodes(Var Left,Right : TFPExprNode);
  1015. begin
  1016. Left:=MatchNodes(Left,Right);
  1017. Right:=MatchNodes(Right,Left);
  1018. end;
  1019. procedure TFPExpressionParser.SetBuiltIns(const AValue: TBuiltInCategories);
  1020. begin
  1021. if FBuiltIns=AValue then exit;
  1022. FBuiltIns:=AValue;
  1023. FDirty:=True;
  1024. end;
  1025. Function TFPExpressionParser.Level1 : TFPExprNode;
  1026. var
  1027. tt: TTokenType;
  1028. Right : TFPExprNode;
  1029. begin
  1030. {$ifdef debugexpr}Writeln('Level 1 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1031. if TokenType = ttNot then
  1032. begin
  1033. GetToken;
  1034. CheckEOF;
  1035. Right:=Level2;
  1036. Result:=TFPNotNode.Create(Right);
  1037. end
  1038. else
  1039. Result:=Level2;
  1040. Try
  1041. while (TokenType in [ttAnd,ttOr,ttXor]) do
  1042. begin
  1043. tt:=TokenType;
  1044. GetToken;
  1045. CheckEOF;
  1046. Right:=Level2;
  1047. Case tt of
  1048. ttOr : Result:=TFPBinaryOrOperation.Create(Result,Right);
  1049. ttAnd : Result:=TFPBinaryAndOperation.Create(Result,Right);
  1050. ttXor : Result:=TFPBinaryXorOperation.Create(Result,Right);
  1051. Else
  1052. ParserError(SErrUnknownBooleanOp)
  1053. end;
  1054. end;
  1055. Except
  1056. Result.Free;
  1057. Raise;
  1058. end;
  1059. end;
  1060. function TFPExpressionParser.Level2: TFPExprNode;
  1061. var
  1062. Right : TFPExprNode;
  1063. tt : TTokenType;
  1064. C : TFPBinaryOperationClass;
  1065. begin
  1066. {$ifdef debugexpr} Writeln('Level 2 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1067. Result:=Level3;
  1068. try
  1069. if (TokenType in ttComparisons) then
  1070. begin
  1071. tt:=TokenType;
  1072. GetToken;
  1073. CheckEOF;
  1074. Right:=Level3;
  1075. CheckNodes(Result,Right);
  1076. Case tt of
  1077. ttLessthan : C:=TFPLessThanOperation;
  1078. ttLessthanEqual : C:=TFPLessThanEqualOperation;
  1079. ttLargerThan : C:=TFPGreaterThanOperation;
  1080. ttLargerThanEqual : C:=TFPGreaterThanEqualOperation;
  1081. ttEqual : C:=TFPEqualOperation;
  1082. ttUnequal : C:=TFPUnequalOperation;
  1083. Else
  1084. ParserError(SErrUnknownComparison)
  1085. end;
  1086. Result:=C.Create(Result,Right);
  1087. end;
  1088. Except
  1089. Result.Free;
  1090. Raise;
  1091. end;
  1092. end;
  1093. function TFPExpressionParser.Level3: TFPExprNode;
  1094. var
  1095. tt : TTokenType;
  1096. right : TFPExprNode;
  1097. begin
  1098. {$ifdef debugexpr} Writeln('Level 3 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1099. Result:=Level4;
  1100. try
  1101. while TokenType in [ttPlus,ttMinus] do
  1102. begin
  1103. tt:=TokenType;
  1104. GetToken;
  1105. CheckEOF;
  1106. Right:=Level4;
  1107. CheckNodes(Result,Right);
  1108. Case tt of
  1109. ttPlus : Result:=TFPAddOperation.Create(Result,Right);
  1110. ttMinus : Result:=TFPSubtractOperation.Create(Result,Right);
  1111. end;
  1112. end;
  1113. Except
  1114. Result.Free;
  1115. Raise;
  1116. end;
  1117. end;
  1118. function TFPExpressionParser.Level4: TFPExprNode;
  1119. var
  1120. tt : TTokenType;
  1121. right : TFPExprNode;
  1122. begin
  1123. {$ifdef debugexpr} Writeln('Level 4 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1124. Result:=Level5;
  1125. try
  1126. while (TokenType in [ttMul,ttDiv]) do
  1127. begin
  1128. tt:=TokenType;
  1129. GetToken;
  1130. Right:=Level5;
  1131. CheckNodes(Result,Right);
  1132. Case tt of
  1133. ttMul : Result:=TFPMultiplyOperation.Create(Result,Right);
  1134. ttDiv : Result:=TFPDivideOperation.Create(Result,Right);
  1135. end;
  1136. end;
  1137. Except
  1138. Result.Free;
  1139. Raise;
  1140. end;
  1141. end;
  1142. function TFPExpressionParser.Level5: TFPExprNode;
  1143. Var
  1144. B : Boolean;
  1145. begin
  1146. {$ifdef debugexpr} Writeln('Level 5 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1147. B:=False;
  1148. if (TokenType in [ttPlus,ttMinus]) then
  1149. begin
  1150. B:=TokenType=ttMinus;
  1151. GetToken;
  1152. end;
  1153. Result:=Level6;
  1154. If B then
  1155. Result:=TFPNegateOperation.Create(Result);
  1156. end;
  1157. function TFPExpressionParser.Level6: TFPExprNode;
  1158. begin
  1159. {$ifdef debugexpr} Writeln('Level 6 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1160. if (TokenType=ttLeft) then
  1161. begin
  1162. GetToken;
  1163. Result:=Level1;
  1164. try
  1165. if (TokenType<>ttRight) then
  1166. ParserError(Format(SErrBracketExpected,[SCanner.Pos,CurrentToken]));
  1167. GetToken;
  1168. Except
  1169. Result.Free;
  1170. Raise;
  1171. end;
  1172. end
  1173. else
  1174. Result:=Primitive;
  1175. end;
  1176. function TFPExpressionParser.Primitive: TFPExprNode;
  1177. Var
  1178. I : Int64;
  1179. C : Integer;
  1180. X : TExprFloat;
  1181. ACount : Integer;
  1182. IFF : Boolean;
  1183. IFC : Boolean;
  1184. ID : TFPExprIdentifierDef;
  1185. Args : TExprArgumentArray;
  1186. AI : Integer;
  1187. begin
  1188. {$ifdef debugexpr} Writeln('Primitive : ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
  1189. SetLength(Args,0);
  1190. if (TokenType=ttNumber) then
  1191. begin
  1192. if TryStrToInt64(CurrentToken,I) then
  1193. Result:=TFPConstExpression.CreateInteger(I)
  1194. else
  1195. begin
  1196. Val(CurrentToken,X,C);
  1197. If (I=0) then
  1198. Result:=TFPConstExpression.CreateFloat(X)
  1199. else
  1200. ParserError(Format(SErrInvalidFloat,[CurrentToken]));
  1201. end;
  1202. end
  1203. else if (TokenType=ttString) then
  1204. Result:=TFPConstExpression.CreateString(CurrentToken)
  1205. else if (TokenType in [ttTrue,ttFalse]) then
  1206. Result:=TFPConstExpression.CreateBoolean(TokenType=ttTrue)
  1207. else if Not (TokenType in [ttIdentifier,ttIf,ttcase]) then
  1208. ParserError(Format(SerrUnknownTokenAtPos,[Scanner.Pos,CurrentToken]))
  1209. else
  1210. begin
  1211. IFF:=TokenType=ttIf;
  1212. IFC:=TokenType=ttCase;
  1213. if Not (IFF or IFC) then
  1214. begin
  1215. ID:=self.IdentifierByName(CurrentToken);
  1216. If (ID=Nil) then
  1217. ParserError(Format(SErrUnknownIdentifier,[CurrentToken]))
  1218. end;
  1219. // Determine number of arguments
  1220. if Iff then
  1221. ACount:=3
  1222. else if IfC then
  1223. ACount:=-4
  1224. else if (ID.IdentifierType in [itFunctionCallBack,itFunctionHandler]) then
  1225. ACount:=ID.ArgumentCount
  1226. else
  1227. ACount:=0;
  1228. // Parse arguments.
  1229. // Negative is for variable number of arguments, where Abs(value) is the minimum number of arguments
  1230. If (ACount<>0) then
  1231. begin
  1232. GetToken;
  1233. If (TokenType<>ttLeft) then
  1234. ParserError(Format(SErrLeftBracketExpected,[Scanner.Pos,CurrentToken]));
  1235. SetLength(Args,Abs(ACount));
  1236. AI:=0;
  1237. Try
  1238. Repeat
  1239. GetToken;
  1240. // Check if we must enlarge the argument array
  1241. If (ACount<0) and (AI=Length(Args)) then
  1242. begin
  1243. SetLength(Args,AI+1);
  1244. Args[AI]:=Nil;
  1245. end;
  1246. Args[AI]:=Level1;
  1247. Inc(AI);
  1248. If (TokenType<>ttComma) then
  1249. If (AI<Abs(ACount)) then
  1250. ParserError(Format(SErrCommaExpected,[Scanner.Pos,CurrentToken]))
  1251. Until (AI=ACount) or ((ACount<0) and (TokenType=ttRight));
  1252. If TokenType<>ttRight then
  1253. ParserError(Format(SErrBracketExpected,[Scanner.Pos,CurrentToken]));
  1254. except
  1255. On E : Exception do
  1256. begin
  1257. Dec(AI);
  1258. While (AI>=0) do
  1259. begin
  1260. FreeAndNil(Args[Ai]);
  1261. Dec(AI);
  1262. end;
  1263. Raise;
  1264. end;
  1265. end;
  1266. end;
  1267. If Iff then
  1268. Result:=TIfOperation.Create(Args[0],Args[1],Args[2])
  1269. else If IfC then
  1270. Result:=TCaseOperation.Create(Args)
  1271. else
  1272. Case ID.IdentifierType of
  1273. itVariable : Result:= TFPExprVariable.CreateIdentifier(ID);
  1274. itFunctionCallBack : Result:= TFPFunctionCallback.CreateFunction(ID,Args);
  1275. itFunctionHandler : Result:= TFPFunctionEventHandler.CreateFunction(ID,Args);
  1276. end;
  1277. end;
  1278. GetToken;
  1279. end;
  1280. procedure TFPExpressionParser.SetExpression(const AValue: String);
  1281. begin
  1282. if FExpression=AValue then exit;
  1283. FExpression:=AValue;
  1284. FScanner.Source:=AValue;
  1285. If Assigned(FExprNode) then
  1286. FreeAndNil(FExprNode);
  1287. If (FExpression<>'') then
  1288. begin
  1289. GetToken;
  1290. FExprNode:=Level1;
  1291. If (TokenType<>ttEOF) then
  1292. ParserError(Format(SErrUnterminatedExpression,[Scanner.Pos,CurrentToken]));
  1293. FExprNode.Check;
  1294. end
  1295. else
  1296. FExprNode:=Nil;
  1297. end;
  1298. procedure TFPExpressionParser.CheckResultType(const Res: TFPExpressionResult;
  1299. AType: TResultType); inline;
  1300. begin
  1301. If (Res.ResultType<>AType) then
  1302. RaiseParserError(SErrInvalidResultType,[ResultTypeName(Res.ResultType)]);
  1303. end;
  1304. class function TFPExpressionParser.BuiltinsManager: TExprBuiltInManager;
  1305. begin
  1306. Result:=BuiltinIdentifiers;
  1307. end;
  1308. function TFPExpressionParser.Evaluate: TFPExpressionResult;
  1309. begin
  1310. EvaluateExpression(Result);
  1311. end;
  1312. function TFPExpressionParser.ResultType: TResultType;
  1313. begin
  1314. if not Assigned(FExprNode) then
  1315. ParserError(SErrInExpression);
  1316. Result:=FExprNode.NodeType;;
  1317. end;
  1318. { ---------------------------------------------------------------------
  1319. TFPExprIdentifierDefs
  1320. ---------------------------------------------------------------------}
  1321. function TFPExprIdentifierDefs.GetI(AIndex : Integer): TFPExprIdentifierDef;
  1322. begin
  1323. Result:=TFPExprIdentifierDef(Items[AIndex]);
  1324. end;
  1325. procedure TFPExprIdentifierDefs.SetI(AIndex : Integer;
  1326. const AValue: TFPExprIdentifierDef);
  1327. begin
  1328. Items[AIndex]:=AValue;
  1329. end;
  1330. procedure TFPExprIdentifierDefs.Update(Item: TCollectionItem);
  1331. begin
  1332. If Assigned(FParser) then
  1333. FParser.FDirty:=True;
  1334. end;
  1335. function TFPExprIdentifierDefs.IndexOfIdentifier(const AName: ShortString
  1336. ): Integer;
  1337. begin
  1338. Result:=Count-1;
  1339. While (Result>=0) And (CompareText(GetI(Result).Name,AName)<>0) do
  1340. Dec(Result);
  1341. end;
  1342. function TFPExprIdentifierDefs.FindIdentifier(const AName: ShortString
  1343. ): TFPExprIdentifierDef;
  1344. Var
  1345. I : Integer;
  1346. begin
  1347. I:=IndexOfIdentifier(AName);
  1348. If (I=-1) then
  1349. Result:=Nil
  1350. else
  1351. Result:=GetI(I);
  1352. end;
  1353. function TFPExprIdentifierDefs.IdentifierByName(const AName: ShortString
  1354. ): TFPExprIdentifierDef;
  1355. begin
  1356. Result:=FindIdentifier(AName);
  1357. if (Result=Nil) then
  1358. RaiseParserError(SErrUnknownIdentifier,[AName]);
  1359. end;
  1360. function TFPExprIdentifierDefs.AddVariable(Const AName: ShortString;
  1361. AResultType: TResultType; AValue: String): TFPExprIdentifierDef;
  1362. begin
  1363. Result:=Add as TFPExprIdentifierDef;
  1364. Result.IdentifierType:=itVariable;
  1365. Result.Name:=AName;
  1366. Result.ResultType:=AResultType;
  1367. Result.Value:=AValue;
  1368. end;
  1369. function TFPExprIdentifierDefs.AddBooleanVariable(Const AName: ShortString; AValue: Boolean
  1370. ): TFPExprIdentifierDef;
  1371. begin
  1372. Result:=Add as TFPExprIdentifierDef;
  1373. Result.IdentifierType:=itVariable;
  1374. Result.Name:=AName;
  1375. Result.ResultType:=rtBoolean;
  1376. Result.FValue.ResBoolean:=AValue;
  1377. end;
  1378. function TFPExprIdentifierDefs.AddIntegerVariable(Const AName: ShortString; AValue: Integer
  1379. ): TFPExprIdentifierDef;
  1380. begin
  1381. Result:=Add as TFPExprIdentifierDef;
  1382. Result.IdentifierType:=itVariable;
  1383. Result.Name:=AName;
  1384. Result.ResultType:=rtInteger;
  1385. Result.FValue.ResInteger:=AValue;
  1386. end;
  1387. function TFPExprIdentifierDefs.AddFloatVariable(Const AName: ShortString; AValue: TExprFloat
  1388. ): TFPExprIdentifierDef;
  1389. begin
  1390. Result:=Add as TFPExprIdentifierDef;
  1391. Result.IdentifierType:=itVariable;
  1392. Result.Name:=AName;
  1393. Result.ResultType:=rtFloat;
  1394. Result.FValue.ResFloat:=AValue;
  1395. end;
  1396. function TFPExprIdentifierDefs.AddStringVariable(Const AName: ShortString; AValue: String
  1397. ): TFPExprIdentifierDef;
  1398. begin
  1399. Result:=Add as TFPExprIdentifierDef;
  1400. Result.IdentifierType:=itVariable;
  1401. Result.Name:=AName;
  1402. Result.ResultType:=rtString;
  1403. Result.FValue.ResString:=AValue;
  1404. end;
  1405. function TFPExprIdentifierDefs.AddDateTimeVariable(Const AName: ShortString; AValue: TDateTime
  1406. ): TFPExprIdentifierDef;
  1407. begin
  1408. Result:=Add as TFPExprIdentifierDef;
  1409. Result.IdentifierType:=itVariable;
  1410. Result.Name:=AName;
  1411. Result.ResultType:=rtDateTime;
  1412. Result.FValue.ResDateTime:=AValue;
  1413. end;
  1414. function TFPExprIdentifierDefs.AddFunction(const AName: ShortString;
  1415. const AResultType: Char; const AParamTypes: String;
  1416. ACallBack: TFPExprFunctionCallBack): TFPExprIdentifierDef;
  1417. begin
  1418. Result:=Add as TFPExprIdentifierDef;
  1419. Result.Name:=Aname;
  1420. Result.IdentifierType:=itFunctionCallBack;
  1421. Result.ParameterTypes:=AParamTypes;
  1422. Result.ResultType:=CharToResultType(AResultType);
  1423. Result.FOnGetValueCB:=ACallBack;
  1424. end;
  1425. function TFPExprIdentifierDefs.AddFunction(const AName: ShortString;
  1426. const AResultType: Char; const AParamTypes: String;
  1427. ACallBack: TFPExprFunctionEvent): TFPExprIdentifierDef;
  1428. begin
  1429. Result:=Add as TFPExprIdentifierDef;
  1430. Result.Name:=Aname;
  1431. Result.IdentifierType:=itFunctionHandler;
  1432. Result.ParameterTypes:=AParamTypes;
  1433. Result.ResultType:=CharToResultType(AResultType);
  1434. Result.FOnGetValue:=ACallBack;
  1435. end;
  1436. { ---------------------------------------------------------------------
  1437. TFPExprIdentifierDef
  1438. ---------------------------------------------------------------------}
  1439. procedure TFPExprIdentifierDef.SetName(const AValue: ShortString);
  1440. begin
  1441. if FName=AValue then exit;
  1442. If (AValue<>'') then
  1443. If Assigned(Collection) and (TFPExprIdentifierDefs(Collection).IndexOfIdentifier(AValue)<>-1) then
  1444. RaiseParserError(SErrDuplicateIdentifier,[AValue]);
  1445. FName:=AValue;
  1446. end;
  1447. procedure TFPExprIdentifierDef.SetResultType(const AValue: TResultType);
  1448. begin
  1449. If AValue<>FValue.ResultType then
  1450. begin
  1451. FValue.ResultType:=AValue;
  1452. SetValue(FStringValue);
  1453. end;
  1454. end;
  1455. procedure TFPExprIdentifierDef.SetValue(const AValue: String);
  1456. begin
  1457. FStringValue:=AValue;
  1458. If (AValue<>'') then
  1459. Case FValue.ResultType of
  1460. rtBoolean : FValue.ResBoolean:=FStringValue='True';
  1461. rtInteger : FValue.ResInteger:=StrToInt(AValue);
  1462. rtFloat : FValue.ResFloat:=StrToFloat(AValue);
  1463. rtDateTime : FValue.ResDateTime:=StrToDateTime(AValue);
  1464. rtString : FValue.ResString:=AValue;
  1465. end
  1466. else
  1467. Case FValue.ResultType of
  1468. rtBoolean : FValue.ResBoolean:=False;
  1469. rtInteger : FValue.ResInteger:=0;
  1470. rtFloat : FValue.ResFloat:=0.0;
  1471. rtDateTime : FValue.ResDateTime:=0;
  1472. rtString : FValue.ResString:='';
  1473. end
  1474. end;
  1475. procedure TFPExprIdentifierDef.CheckResultType(const AType: TResultType);
  1476. begin
  1477. If FValue.ResultType<>AType then
  1478. RaiseParserError(SErrInvalidResultType,[ResultTypeName(AType)])
  1479. end;
  1480. procedure TFPExprIdentifierDef.CheckVariable;
  1481. begin
  1482. If Identifiertype<>itvariable then
  1483. RaiseParserError(SErrNotVariable,[Name]);
  1484. end;
  1485. function TFPExprIdentifierDef.ArgumentCount: Integer;
  1486. begin
  1487. Result:=Length(FArgumentTypes);
  1488. end;
  1489. procedure TFPExprIdentifierDef.Assign(Source: TPersistent);
  1490. Var
  1491. EID : TFPExprIdentifierDef;
  1492. begin
  1493. if (Source is TFPExprIdentifierDef) then
  1494. begin
  1495. EID:=Source as TFPExprIdentifierDef;
  1496. FStringValue:=EID.FStringValue;
  1497. FValue:=EID.FValue;
  1498. FArgumentTypes:=EID.FArgumentTypes;
  1499. FIDType:=EID.FIDType;
  1500. FName:=EID.FName;
  1501. FOnGetValue:=EID.FOnGetValue;
  1502. FOnGetValueCB:=EID.FOnGetValueCB;
  1503. end
  1504. else
  1505. inherited Assign(Source);
  1506. end;
  1507. procedure TFPExprIdentifierDef.SetArgumentTypes(const AValue: String);
  1508. Var
  1509. I : integer;
  1510. begin
  1511. if FArgumentTypes=AValue then exit;
  1512. For I:=1 to Length(AValue) do
  1513. CharToResultType(AValue[i]);
  1514. FArgumentTypes:=AValue;
  1515. end;
  1516. procedure TFPExprIdentifierDef.SetAsBoolean(const AValue: Boolean);
  1517. begin
  1518. CheckVariable;
  1519. CheckResultType(rtBoolean);
  1520. FValue.ResBoolean:=AValue;
  1521. end;
  1522. procedure TFPExprIdentifierDef.SetAsDateTime(const AValue: TDateTime);
  1523. begin
  1524. CheckVariable;
  1525. CheckResultType(rtDateTime);
  1526. FValue.ResDateTime:=AValue;
  1527. end;
  1528. procedure TFPExprIdentifierDef.SetAsFloat(const AValue: TExprFloat);
  1529. begin
  1530. CheckVariable;
  1531. CheckResultType(rtFloat);
  1532. FValue.ResFloat:=AValue;
  1533. end;
  1534. procedure TFPExprIdentifierDef.SetAsInteger(const AValue: Int64);
  1535. begin
  1536. CheckVariable;
  1537. CheckResultType(rtInteger);
  1538. FValue.ResInteger:=AValue;
  1539. end;
  1540. procedure TFPExprIdentifierDef.SetAsString(const AValue: String);
  1541. begin
  1542. CheckVariable;
  1543. CheckResultType(rtString);
  1544. FValue.resString:=AValue;
  1545. end;
  1546. function TFPExprIdentifierDef.GetValue: String;
  1547. begin
  1548. Case FValue.ResultType of
  1549. rtBoolean : If FValue.ResBoolean then
  1550. Result:='True'
  1551. else
  1552. Result:='False';
  1553. rtInteger : Result:=IntToStr(FValue.ResInteger);
  1554. rtFloat : Result:=FloatToStr(FValue.ResFloat);
  1555. rtDateTime : Result:=FormatDateTime('cccc',FValue.ResDateTime);
  1556. rtString : Result:=FValue.ResString;
  1557. end;
  1558. end;
  1559. function TFPExprIdentifierDef.GetResultType: TResultType;
  1560. begin
  1561. Result:=FValue.ResultType;
  1562. end;
  1563. function TFPExprIdentifierDef.GetAsFloat: TExprFloat;
  1564. begin
  1565. CheckResultType(rtFloat);
  1566. CheckVariable;
  1567. Result:=FValue.ResFloat;
  1568. end;
  1569. function TFPExprIdentifierDef.GetAsBoolean: Boolean;
  1570. begin
  1571. CheckResultType(rtBoolean);
  1572. CheckVariable;
  1573. Result:=FValue.ResBoolean;
  1574. end;
  1575. function TFPExprIdentifierDef.GetAsDateTime: TDateTime;
  1576. begin
  1577. CheckResultType(rtDateTime);
  1578. CheckVariable;
  1579. Result:=FValue.ResDateTime;
  1580. end;
  1581. function TFPExprIdentifierDef.GetAsInteger: Int64;
  1582. begin
  1583. CheckResultType(rtInteger);
  1584. CheckVariable;
  1585. Result:=FValue.ResInteger;
  1586. end;
  1587. function TFPExprIdentifierDef.GetAsString: String;
  1588. begin
  1589. CheckResultType(rtString);
  1590. CheckVariable;
  1591. Result:=FValue.ResString;
  1592. end;
  1593. { ---------------------------------------------------------------------
  1594. TExprBuiltInManager
  1595. ---------------------------------------------------------------------}
  1596. function TExprBuiltInManager.GetCount: Integer;
  1597. begin
  1598. Result:=FDefs.Count;
  1599. end;
  1600. function TExprBuiltInManager.GetI(AIndex : Integer
  1601. ): TFPBuiltInExprIdentifierDef;
  1602. begin
  1603. Result:=TFPBuiltInExprIdentifierDef(FDefs[Aindex])
  1604. end;
  1605. constructor TExprBuiltInManager.Create(AOwner: TComponent);
  1606. begin
  1607. inherited Create(AOwner);
  1608. FDefs:=TFPExprIdentifierDefs.Create(TFPBuiltInExprIdentifierDef)
  1609. end;
  1610. destructor TExprBuiltInManager.Destroy;
  1611. begin
  1612. FreeAndNil(FDefs);
  1613. inherited Destroy;
  1614. end;
  1615. function TExprBuiltInManager.IndexOfIdentifier(const AName: ShortString
  1616. ): Integer;
  1617. begin
  1618. Result:=FDefs.IndexOfIdentifier(AName);
  1619. end;
  1620. function TExprBuiltInManager.FindIdentifier(const AName: ShortString
  1621. ): TFPBuiltinExprIdentifierDef;
  1622. begin
  1623. Result:=TFPBuiltinExprIdentifierDef(FDefs.FindIdentifier(AName));
  1624. end;
  1625. function TExprBuiltInManager.IdentifierByName(const AName: ShortString
  1626. ): TFPBuiltinExprIdentifierDef;
  1627. begin
  1628. Result:=TFPBuiltinExprIdentifierDef(FDefs.IdentifierByName(AName));
  1629. end;
  1630. function TExprBuiltInManager.AddVariable(const ACategory: TBuiltInCategory;
  1631. const AName: ShortString; AResultType: TResultType; AValue: String
  1632. ): TFPBuiltInExprIdentifierDef;
  1633. begin
  1634. Result:=TFPBuiltInExprIdentifierDef(FDefs.Addvariable(AName,AResultType,AValue));
  1635. Result.Category:=ACategory;
  1636. end;
  1637. function TExprBuiltInManager.AddBooleanVariable(
  1638. const ACategory: TBuiltInCategory; const AName: ShortString; AValue: Boolean
  1639. ): TFPBuiltInExprIdentifierDef;
  1640. begin
  1641. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddBooleanvariable(AName,AValue));
  1642. Result.Category:=ACategory;
  1643. end;
  1644. function TExprBuiltInManager.AddIntegerVariable(
  1645. const ACategory: TBuiltInCategory; const AName: ShortString; AValue: Integer
  1646. ): TFPBuiltInExprIdentifierDef;
  1647. begin
  1648. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddIntegerVariable(AName,AValue));
  1649. Result.Category:=ACategory;
  1650. end;
  1651. function TExprBuiltInManager.AddFloatVariable(
  1652. const ACategory: TBuiltInCategory; const AName: ShortString;
  1653. AValue: TExprFloat): TFPBuiltInExprIdentifierDef;
  1654. begin
  1655. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddFloatVariable(AName,AValue));
  1656. Result.Category:=ACategory;
  1657. end;
  1658. function TExprBuiltInManager.AddStringVariable(
  1659. const ACategory: TBuiltInCategory; const AName: ShortString; AValue: String
  1660. ): TFPBuiltInExprIdentifierDef;
  1661. begin
  1662. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddStringVariable(AName,AValue));
  1663. Result.Category:=ACategory;
  1664. end;
  1665. function TExprBuiltInManager.AddDateTimeVariable(
  1666. const ACategory: TBuiltInCategory; const AName: ShortString; AValue: TDateTime
  1667. ): TFPBuiltInExprIdentifierDef;
  1668. begin
  1669. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddDateTimeVariable(AName,AValue));
  1670. Result.Category:=ACategory;
  1671. end;
  1672. function TExprBuiltInManager.AddFunction(const ACategory: TBuiltInCategory;
  1673. const AName: ShortString; const AResultType: Char; const AParamTypes: String;
  1674. ACallBack: TFPExprFunctionCallBack): TFPBuiltInExprIdentifierDef;
  1675. begin
  1676. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddFunction(AName,AResultType,AParamTypes,ACallBack));
  1677. Result.Category:=ACategory;
  1678. end;
  1679. function TExprBuiltInManager.AddFunction(const ACategory: TBuiltInCategory;
  1680. const AName: ShortString; const AResultType: Char; const AParamTypes: String;
  1681. ACallBack: TFPExprFunctionEvent): TFPBuiltInExprIdentifierDef;
  1682. begin
  1683. Result:=TFPBuiltInExprIdentifierDef(FDefs.AddFunction(AName,AResultType,AParamTypes,ACallBack));
  1684. Result.Category:=ACategory;
  1685. end;
  1686. { ---------------------------------------------------------------------
  1687. Various Nodes
  1688. ---------------------------------------------------------------------}
  1689. { TFPBinaryOperation }
  1690. procedure TFPBinaryOperation.CheckSameNodeTypes;
  1691. Var
  1692. LT,RT : TResultType;
  1693. begin
  1694. LT:=Left.NodeType;
  1695. RT:=Right.NodeType;
  1696. if (RT<>LT) then
  1697. RaiseParserError(SErrTypesDoNotMatch,[ResultTypeName(LT),ResultTypeName(RT),Left.AsString,Right.AsString])
  1698. end;
  1699. constructor TFPBinaryOperation.Create(ALeft, ARight: TFPExprNode);
  1700. begin
  1701. FLeft:=ALeft;
  1702. FRight:=ARight;
  1703. end;
  1704. destructor TFPBinaryOperation.Destroy;
  1705. begin
  1706. FreeAndNil(FLeft);
  1707. FreeAndNil(FRight);
  1708. inherited Destroy;
  1709. end;
  1710. procedure TFPBinaryOperation.Check;
  1711. begin
  1712. If Not Assigned(Left) then
  1713. RaiseParserError(SErrNoLeftOperand,[classname]);
  1714. If Not Assigned(Right) then
  1715. RaiseParserError(SErrNoRightOperand,[classname]);
  1716. end;
  1717. { TFPUnaryOperator }
  1718. constructor TFPUnaryOperator.Create(AOperand: TFPExprNode);
  1719. begin
  1720. FOperand:=AOperand;
  1721. end;
  1722. destructor TFPUnaryOperator.Destroy;
  1723. begin
  1724. FreeAndNil(FOperand);
  1725. inherited Destroy;
  1726. end;
  1727. procedure TFPUnaryOperator.Check;
  1728. begin
  1729. If Not Assigned(Operand) then
  1730. RaiseParserError(SErrNoOperand,[Self.className]);
  1731. end;
  1732. { TFPConstExpression }
  1733. constructor TFPConstExpression.CreateString(AValue: String);
  1734. begin
  1735. FValue.ResultType:=rtString;
  1736. FValue.ResString:=AValue;
  1737. end;
  1738. constructor TFPConstExpression.CreateInteger(AValue: Int64);
  1739. begin
  1740. FValue.ResultType:=rtInteger;
  1741. FValue.ResInteger:=AValue;
  1742. end;
  1743. constructor TFPConstExpression.CreateDateTime(AValue: TDateTime);
  1744. begin
  1745. FValue.ResultType:=rtDateTime;
  1746. FValue.ResDateTime:=AValue;
  1747. end;
  1748. constructor TFPConstExpression.CreateFloat(AValue: TExprFloat);
  1749. begin
  1750. Inherited create;
  1751. FValue.ResultType:=rtFloat;
  1752. FValue.ResFloat:=AValue;
  1753. end;
  1754. constructor TFPConstExpression.CreateBoolean(AValue: Boolean);
  1755. begin
  1756. FValue.ResultType:=rtBoolean;
  1757. FValue.ResBoolean:=AValue;
  1758. end;
  1759. procedure TFPConstExpression.Check;
  1760. begin
  1761. // Nothing to check;
  1762. end;
  1763. function TFPConstExpression.NodeType: TResultType;
  1764. begin
  1765. Result:=FValue.ResultType;
  1766. end;
  1767. Procedure TFPConstExpression.GetNodeValue(var Result : TFPExpressionResult);
  1768. begin
  1769. Result:=FValue;
  1770. end;
  1771. function TFPConstExpression.AsString: string ;
  1772. begin
  1773. Case NodeType of
  1774. rtString : Result:=''''+FValue.resString+'''';
  1775. rtInteger : Result:=IntToStr(FValue.resInteger);
  1776. rtDateTime : Result:=''''+FormatDateTime('cccc',FValue.resDateTime)+'''';
  1777. rtBoolean : If FValue.ResBoolean then Result:='True' else Result:='False';
  1778. rtFloat : Str(FValue.ResFloat,Result);
  1779. end;
  1780. end;
  1781. { TFPNegateOperation }
  1782. procedure TFPNegateOperation.Check;
  1783. begin
  1784. Inherited;
  1785. If Not (Operand.NodeType in [rtInteger,rtFloat]) then
  1786. RaiseParserError(SErrNoNegation,[ResultTypeName(Operand.NodeType),Operand.AsString])
  1787. end;
  1788. function TFPNegateOperation.NodeType: TResultType;
  1789. begin
  1790. Result:=Operand.NodeType;
  1791. end;
  1792. Procedure TFPNegateOperation.GetNodeValue(var Result : TFPExpressionResult);
  1793. begin
  1794. Operand.GetNodeValue(Result);
  1795. Case Result.ResultType of
  1796. rtInteger : Result.resInteger:=-Result.ResInteger;
  1797. rtFloat : Result.resFloat:=-Result.ResFloat;
  1798. end;
  1799. end;
  1800. function TFPNegateOperation.AsString: String;
  1801. begin
  1802. Result:='-'+TrimLeft(Operand.AsString);
  1803. end;
  1804. { TFPBinaryAndOperation }
  1805. procedure TFPBooleanOperation.Check;
  1806. begin
  1807. inherited Check;
  1808. CheckNodeType(Left,[rtInteger,rtBoolean]);
  1809. CheckNodeType(Right,[rtInteger,rtBoolean]);
  1810. CheckSameNodeTypes;
  1811. end;
  1812. function TFPBooleanOperation.NodeType: TResultType;
  1813. begin
  1814. Result:=Left.NodeType;
  1815. end;
  1816. Procedure TFPBinaryAndOperation.GetNodeValue(var Result : TFPExpressionResult);
  1817. Var
  1818. RRes : TFPExpressionResult;
  1819. begin
  1820. Left.GetNodeValue(Result);
  1821. Right.GetNodeValue(RRes);
  1822. Case Result.ResultType of
  1823. rtBoolean : Result.resBoolean:=Result.ResBoolean and RRes.ResBoolean;
  1824. rtInteger : Result.resInteger:=Result.ResInteger and RRes.ResInteger;
  1825. end;
  1826. end;
  1827. function TFPBinaryAndOperation.AsString: string;
  1828. begin
  1829. Result:=Left.AsString+' and '+Right.AsString;
  1830. end;
  1831. { TFPExprNode }
  1832. procedure TFPExprNode.CheckNodeType(Anode: TFPExprNode; Allowed: TResultTypes);
  1833. Var
  1834. S : String;
  1835. A : TResultType;
  1836. begin
  1837. If (Anode=Nil) then
  1838. RaiseParserError(SErrNoNodeToCheck);
  1839. If Not (ANode.NodeType in Allowed) then
  1840. begin
  1841. S:='';
  1842. For A:=Low(TResultType) to High(TResultType) do
  1843. If A in Allowed then
  1844. begin
  1845. If S<>'' then
  1846. S:=S+',';
  1847. S:=S+ResultTypeName(A);
  1848. end;
  1849. RaiseParserError(SInvalidNodeType,[ResultTypeName(ANode.NodeType),S,ANode.AsString]);
  1850. end;
  1851. end;
  1852. function TFPExprNode.NodeValue: TFPExpressionResult;
  1853. begin
  1854. GetNodeValue(Result);
  1855. end;
  1856. { TFPBinaryOrOperation }
  1857. function TFPBinaryOrOperation.AsString: string;
  1858. begin
  1859. Result:=Left.AsString+' or '+Right.AsString;
  1860. end;
  1861. Procedure TFPBinaryOrOperation.GetNodeValue(var Result : TFPExpressionResult);
  1862. Var
  1863. RRes : TFPExpressionResult;
  1864. begin
  1865. Left.GetNodeValue(Result);
  1866. Right.GetNodeValue(RRes);
  1867. Case Result.ResultType of
  1868. rtBoolean : Result.resBoolean:=Result.ResBoolean or RRes.ResBoolean;
  1869. rtInteger : Result.resInteger:=Result.ResInteger or RRes.ResInteger;
  1870. end;
  1871. end;
  1872. { TFPBinaryXOrOperation }
  1873. function TFPBinaryXOrOperation.AsString: string;
  1874. begin
  1875. Result:=Left.AsString+' xor '+Right.AsString;
  1876. end;
  1877. Procedure TFPBinaryXOrOperation.GetNodeValue(var Result : TFPExpressionResult);
  1878. Var
  1879. RRes : TFPExpressionResult;
  1880. begin
  1881. Left.GetNodeValue(Result);
  1882. Right.GetNodeValue(RRes);
  1883. Case Result.ResultType of
  1884. rtBoolean : Result.resBoolean:=Result.ResBoolean xor RRes.ResBoolean;
  1885. rtInteger : Result.resInteger:=Result.ResInteger xor RRes.ResInteger;
  1886. end;
  1887. end;
  1888. { TFPNotNode }
  1889. procedure TFPNotNode.Check;
  1890. begin
  1891. If Not (Operand.NodeType in [rtInteger,rtBoolean]) then
  1892. RaiseParserError(SErrNoNotOperation,[ResultTypeName(Operand.NodeType),Operand.AsString])
  1893. end;
  1894. function TFPNotNode.NodeType: TResultType;
  1895. begin
  1896. Result:=Operand.NodeType;
  1897. end;
  1898. procedure TFPNotNode.GetNodeValue(var Result: TFPExpressionResult);
  1899. begin
  1900. Operand.GetNodeValue(Result);
  1901. Case result.ResultType of
  1902. rtInteger : Result.resInteger:=Not Result.resInteger;
  1903. rtBoolean : Result.resBoolean:=Not Result.resBoolean;
  1904. end
  1905. end;
  1906. function TFPNotNode.AsString: String;
  1907. begin
  1908. Result:='not '+Operand.AsString;
  1909. end;
  1910. { TIfOperation }
  1911. constructor TIfOperation.Create(ACondition, ALeft, ARight: TFPExprNode);
  1912. begin
  1913. Inherited Create(ALeft,ARight);
  1914. FCondition:=ACondition;
  1915. end;
  1916. destructor TIfOperation.destroy;
  1917. begin
  1918. FreeAndNil(FCondition);
  1919. inherited destroy;
  1920. end;
  1921. procedure TIfOperation.GetNodeValue(var Result: TFPExpressionResult);
  1922. begin
  1923. FCondition.GetNodeValue(Result);
  1924. If Result.ResBoolean then
  1925. Left.GetNodeValue(Result)
  1926. else
  1927. Right.GetNodeValue(Result)
  1928. end;
  1929. procedure TIfOperation.Check;
  1930. begin
  1931. inherited Check;
  1932. if (Condition.NodeType<>rtBoolean) then
  1933. RaiseParserError(SErrIFNeedsBoolean,[Condition.AsString]);
  1934. CheckSameNodeTypes;
  1935. end;
  1936. function TIfOperation.NodeType: TResultType;
  1937. begin
  1938. Result:=Left.NodeType;
  1939. end;
  1940. function TIfOperation.AsString: string;
  1941. begin
  1942. Result:=Format('if(%s , %s , %s)',[Condition.AsString,Left.AsString,Right.AsString]);
  1943. end;
  1944. { TCaseOperation }
  1945. procedure TCaseOperation.GetNodeValue(var Result: TFPExpressionResult);
  1946. Var
  1947. I,L : Integer;
  1948. B : Boolean;
  1949. RT,RV : TFPExpressionResult;
  1950. begin
  1951. FArgs[0].GetNodeValue(RT);
  1952. L:=Length(FArgs);
  1953. I:=2;
  1954. B:=False;
  1955. While (Not B) and (I<L) do
  1956. begin
  1957. FArgs[i].GetNodeValue(RV);
  1958. Case RT.ResultType of
  1959. rtBoolean : B:=RT.ResBoolean=RV.ResBoolean;
  1960. rtInteger : B:=RT.ResInteger=RV.ResInteger;
  1961. rtFloat : B:=RT.ResFloat=RV.ResFLoat;
  1962. rtDateTime : B:=RT.ResDateTime=RV.ResDateTime;
  1963. rtString : B:=RT.ResString=RV.ResString;
  1964. end;
  1965. If Not B then
  1966. Inc(I,2);
  1967. end;
  1968. // Set result type.
  1969. Result.ResultType:=FArgs[1].NodeType;
  1970. If B then
  1971. FArgs[I+1].GetNodeValue(Result)
  1972. else if ((L mod 2)=0) then
  1973. FArgs[1].GetNodeValue(Result);
  1974. end;
  1975. procedure TCaseOperation.Check;
  1976. Var
  1977. T,V : TResultType;
  1978. I : Integer;
  1979. N : TFPExprNode;
  1980. begin
  1981. If (Length(FArgs)<3) then
  1982. RaiseParserError(SErrCaseNeeds3);
  1983. If ((Length(FArgs) mod 2)=1) then
  1984. RaiseParserError(SErrCaseEvenCount);
  1985. T:=FArgs[0].NodeType;
  1986. V:=FArgs[1].NodeType;
  1987. For I:=2 to Length(Fargs)-1 do
  1988. begin
  1989. N:=FArgs[I];
  1990. // Even argument types (labels) must equal tag.
  1991. If ((I mod 2)=0) then
  1992. begin
  1993. If Not (N is TFPConstExpression) then
  1994. RaiseParserError(SErrCaseLabelNotAConst,[I div 2,N.AsString]);
  1995. If (N.NodeType<>T) then
  1996. RaiseParserError(SErrCaseLabelType,[I div 2,N.AsString,ResultTypeName(T),ResultTypeName(N.NodeType)]);
  1997. end
  1998. else // Odd argument types (values) must match first.
  1999. begin
  2000. If (N.NodeType<>V) then
  2001. RaiseParserError(SErrCaseValueType,[(I-1)div 2,N.AsString,ResultTypeName(V),ResultTypeName(N.NodeType)]);
  2002. end
  2003. end;
  2004. end;
  2005. function TCaseOperation.NodeType: TResultType;
  2006. begin
  2007. Result:=FArgs[1].NodeType;
  2008. end;
  2009. constructor TCaseOperation.Create(Args: TExprArgumentArray);
  2010. begin
  2011. Fargs:=Args;
  2012. end;
  2013. destructor TCaseOperation.destroy;
  2014. Var
  2015. I : Integer;
  2016. begin
  2017. For I:=0 to Length(FArgs)-1 do
  2018. FreeAndNil(Fargs[I]);
  2019. inherited destroy;
  2020. end;
  2021. function TCaseOperation.AsString: string;
  2022. Var
  2023. I : integer;
  2024. begin
  2025. Result:='';
  2026. For I:=0 to Length(FArgs)-1 do
  2027. begin
  2028. If (Result<>'') then
  2029. Result:=Result+', ';
  2030. Result:=Result+FArgs[i].AsString;
  2031. end;
  2032. Result:='Case('+Result+')';
  2033. end;
  2034. { TFPBooleanResultOperation }
  2035. procedure TFPBooleanResultOperation.Check;
  2036. begin
  2037. inherited Check;
  2038. CheckSameNodeTypes;
  2039. end;
  2040. function TFPBooleanResultOperation.NodeType: TResultType;
  2041. begin
  2042. Result:=rtBoolean;
  2043. end;
  2044. { TFPEqualOperation }
  2045. function TFPEqualOperation.AsString: string;
  2046. begin
  2047. Result:=Left.AsString+' = '+Right.AsString;
  2048. end;
  2049. Procedure TFPEqualOperation.GetNodeValue(var Result : TFPExpressionResult);
  2050. Var
  2051. RRes : TFPExpressionResult;
  2052. begin
  2053. Left.GetNodeValue(Result);
  2054. Right.GetNodeValue(RRes);
  2055. Case Result.ResultType of
  2056. rtBoolean : Result.resBoolean:=Result.ResBoolean=RRes.ResBoolean;
  2057. rtInteger : Result.resBoolean:=Result.ResInteger=RRes.ResInteger;
  2058. rtFloat : Result.resBoolean:=Result.ResFloat=RRes.ResFLoat;
  2059. rtDateTime : Result.resBoolean:=Result.ResDateTime=RRes.ResDateTime;
  2060. rtString : Result.resBoolean:=Result.ResString=RRes.ResString;
  2061. end;
  2062. Result.ResultType:=rtBoolean;
  2063. end;
  2064. { TFPUnequalOperation }
  2065. function TFPUnequalOperation.AsString: string;
  2066. begin
  2067. Result:=Left.AsString+' <> '+Right.AsString;
  2068. end;
  2069. Procedure TFPUnequalOperation.GetNodeValue(var Result : TFPExpressionResult);
  2070. begin
  2071. Inherited GetNodeValue(Result);
  2072. Result.ResBoolean:=Not Result.ResBoolean;
  2073. end;
  2074. { TFPLessThanOperation }
  2075. function TFPLessThanOperation.AsString: string;
  2076. begin
  2077. Result:=Left.AsString+' < '+Right.AsString;
  2078. end;
  2079. procedure TFPLessThanOperation.GetNodeValue(var Result : TFPExpressionResult);
  2080. Var
  2081. RRes : TFPExpressionResult;
  2082. begin
  2083. Left.GetNodeValue(Result);
  2084. Right.GetNodeValue(RRes);
  2085. Case Result.ResultType of
  2086. rtInteger : Result.resBoolean:=Result.ResInteger<RRes.ResInteger;
  2087. rtFloat : Result.resBoolean:=Result.ResFloat<RRes.ResFLoat;
  2088. rtDateTime : Result.resBoolean:=Result.ResDateTime<RRes.ResDateTime;
  2089. rtString : Result.resBoolean:=Result.ResString<RRes.ResString;
  2090. end;
  2091. Result.ResultType:=rtBoolean;
  2092. end;
  2093. { TFPGreaterThanOperation }
  2094. function TFPGreaterThanOperation.AsString: string;
  2095. begin
  2096. Result:=Left.AsString+' > '+Right.AsString;
  2097. end;
  2098. Procedure TFPGreaterThanOperation.GetNodeValue(var Result : TFPExpressionResult);
  2099. Var
  2100. RRes : TFPExpressionResult;
  2101. begin
  2102. Left.GetNodeValue(Result);
  2103. Right.GetNodeValue(RRes);
  2104. Case Result.ResultType of
  2105. rtInteger : case Right.NodeType of
  2106. rtInteger : Result.resBoolean:=Result.ResInteger>RRes.ResInteger;
  2107. rtFloat : Result.resBoolean:=Result.ResInteger>RRes.ResFloat;
  2108. end;
  2109. rtFloat : case Right.NodeType of
  2110. rtInteger : Result.resBoolean:=Result.ResFloat>RRes.ResInteger;
  2111. rtFloat : Result.resBoolean:=Result.ResFloat>RRes.ResFLoat;
  2112. end;
  2113. rtDateTime : Result.resBoolean:=Result.ResDateTime>RRes.ResDateTime;
  2114. rtString : Result.resBoolean:=Result.ResString>RRes.ResString;
  2115. end;
  2116. Result.ResultType:=rtBoolean;
  2117. end;
  2118. { TFPGreaterThanEqualOperation }
  2119. function TFPGreaterThanEqualOperation.AsString: string;
  2120. begin
  2121. Result:=Left.AsString+' >= '+Right.AsString;
  2122. end;
  2123. Procedure TFPGreaterThanEqualOperation.GetNodeValue(var Result : TFPExpressionResult);
  2124. begin
  2125. Inherited GetNodeValue(Result);
  2126. Result.ResBoolean:=Not Result.ResBoolean;
  2127. end;
  2128. { TFPLessThanEqualOperation }
  2129. function TFPLessThanEqualOperation.AsString: string;
  2130. begin
  2131. Result:=Left.AsString+' <= '+Right.AsString;
  2132. end;
  2133. Procedure TFPLessThanEqualOperation.GetNodeValue(var Result : TFPExpressionResult);
  2134. begin
  2135. Inherited GetNodeValue(Result);
  2136. Result.ResBoolean:=Not Result.ResBoolean;
  2137. end;
  2138. { TFPOrderingOperation }
  2139. procedure TFPOrderingOperation.Check;
  2140. Const
  2141. AllowedTypes =[rtInteger,rtfloat,rtDateTime,rtString];
  2142. begin
  2143. CheckNodeType(Left,AllowedTypes);
  2144. CheckNodeType(Right,AllowedTypes);
  2145. inherited Check;
  2146. end;
  2147. { TMathOperation }
  2148. procedure TMathOperation.Check;
  2149. Const
  2150. AllowedTypes =[rtInteger,rtfloat,rtDateTime,rtString];
  2151. begin
  2152. inherited Check;
  2153. CheckNodeType(Left,AllowedTypes);
  2154. CheckNodeType(Right,AllowedTypes);
  2155. CheckSameNodeTypes;
  2156. end;
  2157. function TMathOperation.NodeType: TResultType;
  2158. begin
  2159. Result:=Left.NodeType;
  2160. end;
  2161. { TFPAddOperation }
  2162. function TFPAddOperation.AsString: string;
  2163. begin
  2164. Result:=Left.AsString+' + '+Right.asString;
  2165. end;
  2166. Procedure TFPAddOperation.GetNodeValue(var Result : TFPExpressionResult);
  2167. Var
  2168. RRes : TFPExpressionResult;
  2169. begin
  2170. Left.GetNodeValue(Result);
  2171. Right.GetNodeValue(RRes);
  2172. case Result.ResultType of
  2173. rtInteger : Result.ResInteger:=Result.ResInteger+RRes.ResInteger;
  2174. rtString : Result.ResString:=Result.ResString+RRes.ResString;
  2175. rtDateTime : Result.ResDateTime:=Result.ResDateTime+RRes.ResDateTime;
  2176. rtFloat : Result.ResFLoat:=Result.ResFLoat+RRes.ResFLoat;
  2177. end;
  2178. Result.ResultType:=NodeType;
  2179. end;
  2180. { TFPSubtractOperation }
  2181. procedure TFPSubtractOperation.check;
  2182. Const
  2183. AllowedTypes =[rtInteger,rtfloat,rtDateTime];
  2184. begin
  2185. CheckNodeType(Left,AllowedTypes);
  2186. CheckNodeType(Right,AllowedTypes);
  2187. inherited check;
  2188. end;
  2189. function TFPSubtractOperation.AsString: string;
  2190. begin
  2191. Result:=Left.AsString+' - '+Right.asString;
  2192. end;
  2193. Procedure TFPSubtractOperation.GetNodeValue(var Result : TFPExpressionResult);
  2194. Var
  2195. RRes : TFPExpressionResult;
  2196. begin
  2197. Left.GetNodeValue(Result);
  2198. Right.GetNodeValue(RRes);
  2199. case Result.ResultType of
  2200. rtInteger : Result.ResInteger:=Result.ResInteger-RRes.ResInteger;
  2201. rtDateTime : Result.ResDateTime:=Result.ResDateTime-RRes.ResDateTime;
  2202. rtFloat : Result.ResFLoat:=Result.ResFLoat-RRes.ResFLoat;
  2203. end;
  2204. end;
  2205. { TFPMultiplyOperation }
  2206. procedure TFPMultiplyOperation.check;
  2207. Const
  2208. AllowedTypes =[rtInteger,rtfloat];
  2209. begin
  2210. CheckNodeType(Left,AllowedTypes);
  2211. CheckNodeType(Right,AllowedTypes);
  2212. Inherited;
  2213. end;
  2214. function TFPMultiplyOperation.AsString: string;
  2215. begin
  2216. Result:=Left.AsString+' * '+Right.asString;
  2217. end;
  2218. Procedure TFPMultiplyOperation.GetNodeValue(var Result : TFPExpressionResult);
  2219. Var
  2220. RRes : TFPExpressionResult;
  2221. begin
  2222. Left.GetNodeValue(Result);
  2223. Right.GetNodeValue(RRes);
  2224. case Result.ResultType of
  2225. rtInteger : Result.ResInteger:=Result.ResInteger*RRes.ResInteger;
  2226. rtFloat : Result.ResFLoat:=Result.ResFLoat*RRes.ResFLoat;
  2227. end;
  2228. end;
  2229. { TFPDivideOperation }
  2230. procedure TFPDivideOperation.check;
  2231. Const
  2232. AllowedTypes =[rtInteger,rtfloat];
  2233. begin
  2234. CheckNodeType(Left,AllowedTypes);
  2235. CheckNodeType(Right,AllowedTypes);
  2236. inherited check;
  2237. end;
  2238. function TFPDivideOperation.AsString: string;
  2239. begin
  2240. Result:=Left.AsString+' / '+Right.asString;
  2241. end;
  2242. function TFPDivideOperation.NodeType: TResultType;
  2243. begin
  2244. Result:=rtFLoat;
  2245. end;
  2246. Procedure TFPDivideOperation.GetNodeValue(var Result : TFPExpressionResult);
  2247. Var
  2248. RRes : TFPExpressionResult;
  2249. begin
  2250. Left.GetNodeValue(Result);
  2251. Right.GetNodeValue(RRes);
  2252. case Result.ResultType of
  2253. rtInteger : Result.ResFloat:=Result.ResInteger/RRes.ResInteger;
  2254. rtFloat : Result.ResFLoat:=Result.ResFLoat/RRes.ResFLoat;
  2255. end;
  2256. Result.ResultType:=rtFloat;
  2257. end;
  2258. { TFPConvertNode }
  2259. function TFPConvertNode.AsString: String;
  2260. begin
  2261. Result:=Operand.AsString;
  2262. end;
  2263. { TIntToFloatNode }
  2264. procedure TIntConvertNode.Check;
  2265. begin
  2266. inherited Check;
  2267. CheckNodeType(Operand,[rtInteger])
  2268. end;
  2269. function TIntToFloatNode.NodeType: TResultType;
  2270. begin
  2271. Result:=rtFloat;
  2272. end;
  2273. Procedure TIntToFloatNode.GetNodeValue(var Result : TFPExpressionResult);
  2274. begin
  2275. Operand.GetNodeValue(Result);
  2276. Result.ResFloat:=Result.ResInteger;
  2277. Result.ResultType:=rtFloat;
  2278. end;
  2279. { TIntToDateTimeNode }
  2280. function TIntToDateTimeNode.NodeType: TResultType;
  2281. begin
  2282. Result:=rtDatetime;
  2283. end;
  2284. procedure TIntToDateTimeNode.GetNodeValue(var Result : TFPExpressionResult);
  2285. begin
  2286. Operand.GetnodeValue(Result);
  2287. Result.ResDateTime:=Result.ResInteger;
  2288. Result.ResultType:=rtDateTime;
  2289. end;
  2290. { TFloatToDateTimeNode }
  2291. procedure TFloatToDateTimeNode.Check;
  2292. begin
  2293. inherited Check;
  2294. CheckNodeType(Operand,[rtFloat]);
  2295. end;
  2296. function TFloatToDateTimeNode.NodeType: TResultType;
  2297. begin
  2298. Result:=rtDateTime;
  2299. end;
  2300. Procedure TFloatToDateTimeNode.GetNodeValue(var Result : TFPExpressionResult);
  2301. begin
  2302. Operand.GetNodeValue(Result);
  2303. Result.ResDateTime:=Result.ResFloat;
  2304. Result.ResultType:=rtDateTime;
  2305. end;
  2306. { TFPExprIdentifierNode }
  2307. constructor TFPExprIdentifierNode.CreateIdentifier(AID: TFPExprIdentifierDef);
  2308. begin
  2309. Inherited Create;
  2310. FID:=AID;
  2311. PResult:[email protected];
  2312. FResultType:=FID.ResultType;
  2313. end;
  2314. function TFPExprIdentifierNode.NodeType: TResultType;
  2315. begin
  2316. Result:=FResultType;
  2317. end;
  2318. Procedure TFPExprIdentifierNode.GetNodeValue(var Result : TFPExpressionResult);
  2319. begin
  2320. Result:=PResult^;
  2321. Result.ResultType:=FResultType;
  2322. end;
  2323. { TFPExprVariable }
  2324. procedure TFPExprVariable.Check;
  2325. begin
  2326. // Do nothing;
  2327. end;
  2328. function TFPExprVariable.AsString: string;
  2329. begin
  2330. Result:=FID.Name;
  2331. end;
  2332. { TFPExprFunction }
  2333. procedure TFPExprFunction.CalcParams;
  2334. Var
  2335. I : Integer;
  2336. begin
  2337. For I:=0 to Length(FArgumentParams)-1 do
  2338. FArgumentNodes[i].GetNodeValue(FArgumentParams[i]);
  2339. end;
  2340. procedure TFPExprFunction.Check;
  2341. Var
  2342. I : Integer;
  2343. rtp,rta : TResultType;
  2344. begin
  2345. If Length(FArgumentNodes)<>FID.ArgumentCount then
  2346. RaiseParserError(ErrInvalidArgumentCount,[FID.Name]);
  2347. For I:=0 to Length(FArgumentNodes)-1 do
  2348. begin
  2349. rtp:=CharToResultType(FID.ParameterTypes[i+1]);
  2350. rta:=FArgumentNodes[i].NodeType;
  2351. If (rtp<>rta) then
  2352. RaiseParserError(SErrInvalidArgumentType,[I+1,ResultTypeName(rtp),ResultTypeName(rta)])
  2353. end;
  2354. end;
  2355. constructor TFPExprFunction.CreateFunction(AID: TFPExprIdentifierDef;
  2356. const Args: TExprArgumentArray);
  2357. begin
  2358. Inherited CreateIdentifier(AID);
  2359. FArgumentNodes:=Args;
  2360. SetLength(FArgumentParams,Length(Args));
  2361. end;
  2362. destructor TFPExprFunction.Destroy;
  2363. Var
  2364. I : Integer;
  2365. begin
  2366. For I:=0 to Length(FArgumentNodes)-1 do
  2367. FreeAndNil(FArgumentNodes[I]);
  2368. inherited Destroy;
  2369. end;
  2370. function TFPExprFunction.AsString: String;
  2371. Var
  2372. S : String;
  2373. I : Integer;
  2374. begin
  2375. S:='';
  2376. For I:=0 to length(FArgumentNodes)-1 do
  2377. begin
  2378. If (S<>'') then
  2379. S:=S+',';
  2380. S:=S+FArgumentNodes[I].AsString;
  2381. end;
  2382. If (S<>'') then
  2383. S:='('+S+')';
  2384. Result:=FID.Name+S;
  2385. end;
  2386. { TFPFunctionCallBack }
  2387. constructor TFPFunctionCallBack.CreateFunction(AID: TFPExprIdentifierDef;
  2388. Const Args : TExprArgumentArray);
  2389. begin
  2390. Inherited;
  2391. FCallBack:=AID.OnGetFunctionValueCallBack;
  2392. end;
  2393. Procedure TFPFunctionCallBack.GetNodeValue(var Result : TFPExpressionResult);
  2394. begin
  2395. If Length(FArgumentParams)>0 then
  2396. CalcParams;
  2397. FCallBack(Result,FArgumentParams);
  2398. Result.ResultType:=NodeType;
  2399. end;
  2400. { TFPFunctionEventHandler }
  2401. constructor TFPFunctionEventHandler.CreateFunction(AID: TFPExprIdentifierDef;
  2402. Const Args : TExprArgumentArray);
  2403. begin
  2404. Inherited;
  2405. FCallBack:=AID.OnGetFunctionValue;
  2406. end;
  2407. Procedure TFPFunctionEventHandler.GetNodeValue(var Result : TFPExpressionResult);
  2408. begin
  2409. If Length(FArgumentParams)>0 then
  2410. CalcParams;
  2411. FCallBack(Result,FArgumentParams);
  2412. Result.ResultType:=NodeType;
  2413. end;
  2414. { ---------------------------------------------------------------------
  2415. Standard Builtins support
  2416. ---------------------------------------------------------------------}
  2417. { Template for builtin.
  2418. Procedure MyCallback (Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2419. begin
  2420. end;
  2421. }
  2422. // Math builtins
  2423. Procedure BuiltInCos(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2424. begin
  2425. Result.resFloat:=Cos(Args[0].resFloat);
  2426. end;
  2427. Procedure BuiltInSin(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2428. begin
  2429. Result.resFloat:=Sin(Args[0].resFloat);
  2430. end;
  2431. Procedure BuiltInArcTan(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2432. begin
  2433. Result.resFloat:=Arctan(Args[0].resFloat);
  2434. end;
  2435. Procedure BuiltInAbs(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2436. begin
  2437. Result.resFloat:=Abs(Args[0].resFloat);
  2438. end;
  2439. Procedure BuiltInSqr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2440. begin
  2441. Result.resFloat:=Sqr(Args[0].resFloat);
  2442. end;
  2443. Procedure BuiltInSqrt(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2444. begin
  2445. Result.resFloat:=Sqrt(Args[0].resFloat);
  2446. end;
  2447. Procedure BuiltInExp(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2448. begin
  2449. Result.resFloat:=Exp(Args[0].resFloat);
  2450. end;
  2451. Procedure BuiltInLn(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2452. begin
  2453. Result.resFloat:=Ln(Args[0].resFloat);
  2454. end;
  2455. Const
  2456. L10 = ln(10);
  2457. Procedure BuiltInLog(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2458. begin
  2459. Result.resFloat:=Ln(Args[0].resFloat)/L10;
  2460. end;
  2461. Procedure BuiltInRound(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2462. begin
  2463. Result.resInteger:=Round(Args[0].resFloat);
  2464. end;
  2465. Procedure BuiltInTrunc(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2466. begin
  2467. Result.resInteger:=Trunc(Args[0].resFloat);
  2468. end;
  2469. Procedure BuiltInInt(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2470. begin
  2471. Result.resFloat:=Int(Args[0].resFloat);
  2472. end;
  2473. Procedure BuiltInFrac(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2474. begin
  2475. Result.resFloat:=frac(Args[0].resFloat);
  2476. end;
  2477. // String builtins
  2478. Procedure BuiltInLength(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2479. begin
  2480. Result.resInteger:=Length(Args[0].resString);
  2481. end;
  2482. Procedure BuiltInCopy(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2483. begin
  2484. Result.resString:=Copy(Args[0].resString,Args[1].resInteger,Args[2].resInteger);
  2485. end;
  2486. Procedure BuiltInDelete(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2487. begin
  2488. Result.resString:=Args[0].resString;
  2489. Delete(Result.resString,Args[1].resInteger,Args[2].resInteger);
  2490. end;
  2491. Procedure BuiltInPos(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2492. begin
  2493. Result.resInteger:=Pos(Args[0].resString,Args[1].resString);
  2494. end;
  2495. Procedure BuiltInUppercase(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2496. begin
  2497. Result.resString:=Uppercase(Args[0].resString);
  2498. end;
  2499. Procedure BuiltInLowercase(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2500. begin
  2501. Result.resString:=Lowercase(Args[0].resString);
  2502. end;
  2503. Procedure BuiltInStringReplace(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2504. Var
  2505. F : TReplaceFlags;
  2506. begin
  2507. F:=[];
  2508. If Args[3].resBoolean then
  2509. Include(F,rfReplaceAll);
  2510. If Args[4].resBoolean then
  2511. Include(F,rfIgnoreCase);
  2512. Result.resString:=StringReplace(Args[0].resString,Args[1].resString,Args[2].resString,f);
  2513. end;
  2514. Procedure BuiltInCompareText(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2515. begin
  2516. Result.resInteger:=CompareText(Args[0].resString,Args[1].resString);
  2517. end;
  2518. // Date/Time builtins
  2519. Procedure BuiltInDate(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2520. begin
  2521. Result.resDateTime:=Date;
  2522. end;
  2523. Procedure BuiltInTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2524. begin
  2525. Result.resDateTime:=Time;
  2526. end;
  2527. Procedure BuiltInNow(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2528. begin
  2529. Result.resDateTime:=Now;
  2530. end;
  2531. Procedure BuiltInDayofWeek(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2532. begin
  2533. Result.resInteger:=DayOfWeek(Args[0].resDateTime);
  2534. end;
  2535. Procedure BuiltInExtractYear(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2536. Var
  2537. Y,M,D : Word;
  2538. begin
  2539. DecodeDate(Args[0].resDateTime,Y,M,D);
  2540. Result.resInteger:=Y;
  2541. end;
  2542. Procedure BuiltInExtractMonth(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2543. Var
  2544. Y,M,D : Word;
  2545. begin
  2546. DecodeDate(Args[0].resDateTime,Y,M,D);
  2547. Result.resInteger:=M;
  2548. end;
  2549. Procedure BuiltInExtractDay(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2550. Var
  2551. Y,M,D : Word;
  2552. begin
  2553. DecodeDate(Args[0].resDateTime,Y,M,D);
  2554. Result.resInteger:=D;
  2555. end;
  2556. Procedure BuiltInExtractHour(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2557. Var
  2558. H,M,S,MS : Word;
  2559. begin
  2560. DecodeTime(Args[0].resDateTime,H,M,S,MS);
  2561. Result.resInteger:=H;
  2562. end;
  2563. Procedure BuiltInExtractMin(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2564. Var
  2565. H,M,S,MS : Word;
  2566. begin
  2567. DecodeTime(Args[0].resDateTime,H,M,S,MS);
  2568. Result.resInteger:=M;
  2569. end;
  2570. Procedure BuiltInExtractSec(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2571. Var
  2572. H,M,S,MS : Word;
  2573. begin
  2574. DecodeTime(Args[0].resDateTime,H,M,S,MS);
  2575. Result.resInteger:=S;
  2576. end;
  2577. Procedure BuiltInExtractMSec(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2578. Var
  2579. H,M,S,MS : Word;
  2580. begin
  2581. DecodeTime(Args[0].resDateTime,H,M,S,MS);
  2582. Result.resInteger:=MS;
  2583. end;
  2584. Procedure BuiltInEncodedate(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2585. begin
  2586. Result.resDateTime:=Encodedate(Args[0].resInteger,Args[1].resInteger,Args[2].resInteger);
  2587. end;
  2588. Procedure BuiltInEncodeTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2589. begin
  2590. Result.resDateTime:=EncodeTime(Args[0].resInteger,Args[1].resInteger,Args[2].resInteger,Args[3].resInteger);
  2591. end;
  2592. Procedure BuiltInEncodeDateTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2593. begin
  2594. Result.resDateTime:=EncodeDate(Args[0].resInteger,Args[1].resInteger,Args[2].resInteger)
  2595. +EncodeTime(Args[3].resInteger,Args[4].resInteger,Args[5].resInteger,Args[6].resInteger);
  2596. end;
  2597. Procedure BuiltInShortDayName(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2598. begin
  2599. Result.resString:=ShortDayNames[Args[0].resInteger];
  2600. end;
  2601. Procedure BuiltInShortMonthName(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2602. begin
  2603. Result.resString:=ShortMonthNames[Args[0].resInteger];
  2604. end;
  2605. Procedure BuiltInLongDayName(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2606. begin
  2607. Result.resString:=LongDayNames[Args[0].resInteger];
  2608. end;
  2609. Procedure BuiltInLongMonthName(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2610. begin
  2611. Result.resString:=LongMonthNames[Args[0].resInteger];
  2612. end;
  2613. Procedure BuiltInFormatDateTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2614. begin
  2615. Result.resString:=FormatDateTime(Args[0].resString,Args[1].resDateTime);
  2616. end;
  2617. // Conversion
  2618. Procedure BuiltInIntToStr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2619. begin
  2620. Result.resString:=IntToStr(Args[0].resinteger);
  2621. end;
  2622. Procedure BuiltInStrToInt(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2623. begin
  2624. Result.resInteger:=StrToInt(Args[0].resString);
  2625. end;
  2626. Procedure BuiltInStrToIntDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2627. begin
  2628. Result.resInteger:=StrToIntDef(Args[0].resString,Args[1].resInteger);
  2629. end;
  2630. Procedure BuiltInFloatToStr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2631. begin
  2632. Result.resString:=FloatToStr(Args[0].resFloat);
  2633. end;
  2634. Procedure BuiltInStrToFloat(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2635. begin
  2636. Result.resFloat:=StrToFloat(Args[0].resString);
  2637. end;
  2638. Procedure BuiltInStrToFloatDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2639. begin
  2640. Result.resFloat:=StrToFloatDef(Args[0].resString,Args[1].resFloat);
  2641. end;
  2642. Procedure BuiltInDateToStr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2643. begin
  2644. Result.resString:=DateToStr(Args[0].resDateTime);
  2645. end;
  2646. Procedure BuiltInTimeToStr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2647. begin
  2648. Result.resString:=TimeToStr(Args[0].resDateTime);
  2649. end;
  2650. Procedure BuiltInStrToDate(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2651. begin
  2652. Result.resDateTime:=StrToDate(Args[0].resString);
  2653. end;
  2654. Procedure BuiltInStrToDateDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2655. begin
  2656. Result.resDateTime:=StrToDateDef(Args[0].resString,Args[1].resDateTime);
  2657. end;
  2658. Procedure BuiltInStrToTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2659. begin
  2660. Result.resDateTime:=StrToTime(Args[0].resString);
  2661. end;
  2662. Procedure BuiltInStrToTimeDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2663. begin
  2664. Result.resDateTime:=StrToTimeDef(Args[0].resString,Args[1].resDateTime);
  2665. end;
  2666. Procedure BuiltInStrToDateTime(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2667. begin
  2668. Result.resDateTime:=StrToDateTime(Args[0].resString);
  2669. end;
  2670. Procedure BuiltInStrToDateTimeDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2671. begin
  2672. Result.resDateTime:=StrToDateTimeDef(Args[0].resString,Args[1].resDateTime);
  2673. end;
  2674. Procedure BuiltInBoolToStr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2675. begin
  2676. Result.resString:=BoolToStr(Args[0].resBoolean);
  2677. end;
  2678. Procedure BuiltInStrToBool(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2679. begin
  2680. Result.resBoolean:=StrToBool(Args[0].resString);
  2681. end;
  2682. Procedure BuiltInStrToBoolDef(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2683. begin
  2684. Result.resBoolean:=StrToBoolDef(Args[0].resString,Args[1].resBoolean);
  2685. end;
  2686. // Boolean
  2687. Procedure BuiltInShl(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2688. begin
  2689. Result.resInteger:=Args[0].resInteger shl Args[1].resInteger
  2690. end;
  2691. Procedure BuiltInShr(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2692. begin
  2693. Result.resInteger:=Args[0].resInteger shr Args[1].resInteger
  2694. end;
  2695. Procedure BuiltinIFS(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2696. begin
  2697. If Args[0].resBoolean then
  2698. Result.resString:=Args[1].resString
  2699. else
  2700. Result.resString:=Args[2].resString
  2701. end;
  2702. Procedure BuiltinIFI(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2703. begin
  2704. If Args[0].resBoolean then
  2705. Result.resinteger:=Args[1].resinteger
  2706. else
  2707. Result.resinteger:=Args[2].resinteger
  2708. end;
  2709. Procedure BuiltinIFF(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2710. begin
  2711. If Args[0].resBoolean then
  2712. Result.resfloat:=Args[1].resfloat
  2713. else
  2714. Result.resfloat:=Args[2].resfloat
  2715. end;
  2716. Procedure BuiltinIFD(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
  2717. begin
  2718. If Args[0].resBoolean then
  2719. Result.resDateTime:=Args[1].resDateTime
  2720. else
  2721. Result.resDateTime:=Args[2].resDateTime
  2722. end;
  2723. Procedure RegisterStdBuiltins(AManager : TExprBuiltInManager);
  2724. begin
  2725. With AManager do
  2726. begin
  2727. AddFloatVariable(bcMath,'pi',Pi);
  2728. // Math functions
  2729. AddFunction(bcMath,'cos','F','F',@BuiltinCos);
  2730. AddFunction(bcMath,'sin','F','F',@BuiltinSin);
  2731. AddFunction(bcMath,'arctan','F','F',@BuiltinArctan);
  2732. AddFunction(bcMath,'abs','F','F',@BuiltinAbs);
  2733. AddFunction(bcMath,'sqr','F','F',@BuiltinSqr);
  2734. AddFunction(bcMath,'sqrt','F','F',@BuiltinSqrt);
  2735. AddFunction(bcMath,'exp','F','F',@BuiltinExp);
  2736. AddFunction(bcMath,'ln','F','F',@BuiltinLn);
  2737. AddFunction(bcMath,'log','F','F',@BuiltinLog);
  2738. AddFunction(bcMath,'frac','F','F',@BuiltinFrac);
  2739. AddFunction(bcMath,'int','F','F',@BuiltinInt);
  2740. AddFunction(bcMath,'round','I','F',@BuiltinRound);
  2741. AddFunction(bcMath,'trunc','I','F',@BuiltinTrunc);
  2742. // String
  2743. AddFunction(bcStrings,'length','I','S',@BuiltinLength);
  2744. AddFunction(bcStrings,'copy','S','SII',@BuiltinCopy);
  2745. AddFunction(bcStrings,'delete','S','SII',@BuiltinDelete);
  2746. AddFunction(bcStrings,'pos','I','SS',@BuiltinPos);
  2747. AddFunction(bcStrings,'lowercase','S','S',@BuiltinLowercase);
  2748. AddFunction(bcStrings,'uppercase','S','S',@BuiltinUppercase);
  2749. AddFunction(bcStrings,'stringreplace','S','SSSBB',@BuiltinStringReplace);
  2750. AddFunction(bcStrings,'comparetext','I','SS',@BuiltinCompareText);
  2751. // Date/Time
  2752. AddFunction(bcDateTime,'date','D','',@BuiltinDate);
  2753. AddFunction(bcDateTime,'time','D','',@BuiltinTime);
  2754. AddFunction(bcDateTime,'now','D','',@BuiltinNow);
  2755. AddFunction(bcDateTime,'dayofweek','I','D',@BuiltinDayofweek);
  2756. AddFunction(bcDateTime,'extractyear','I','D',@BuiltinExtractYear);
  2757. AddFunction(bcDateTime,'extractmonth','I','D',@BuiltinExtractMonth);
  2758. AddFunction(bcDateTime,'extractday','I','D',@BuiltinExtractDay);
  2759. AddFunction(bcDateTime,'extracthour','I','D',@BuiltinExtractHour);
  2760. AddFunction(bcDateTime,'extractmin','I','D',@BuiltinExtractMin);
  2761. AddFunction(bcDateTime,'extractsec','I','D',@BuiltinExtractSec);
  2762. AddFunction(bcDateTime,'extractmsec','I','D',@BuiltinExtractMSec);
  2763. AddFunction(bcDateTime,'encodedate','D','III',@BuiltinEncodedate);
  2764. AddFunction(bcDateTime,'encodetime','D','IIII',@BuiltinEncodeTime);
  2765. AddFunction(bcDateTime,'encodedatetime','D','IIIIIII',@BuiltinEncodeDateTime);
  2766. AddFunction(bcDateTime,'shortdayname','S','I',@BuiltinShortDayName);
  2767. AddFunction(bcDateTime,'shortmonthname','S','I',@BuiltinShortMonthName);
  2768. AddFunction(bcDateTime,'longdayname','S','I',@BuiltinLongDayName);
  2769. AddFunction(bcDateTime,'longmonthname','S','I',@BuiltinLongMonthName);
  2770. AddFunction(bcDateTime,'formatdatetime','S','SD',@BuiltinFormatDateTime);
  2771. // Boolean
  2772. AddFunction(bcBoolean,'shl','I','II',@BuiltinShl);
  2773. AddFunction(bcBoolean,'shr','I','II',@BuiltinShr);
  2774. AddFunction(bcBoolean,'IFS','S','BSS',@BuiltinIFS);
  2775. AddFunction(bcBoolean,'IFF','F','BFF',@BuiltinIFF);
  2776. AddFunction(bcBoolean,'IFD','D','BDD',@BuiltinIFD);
  2777. AddFunction(bcBoolean,'IFI','I','BII',@BuiltinIFI);
  2778. // Conversion
  2779. AddFunction(bcConversion,'inttostr','S','I',@BuiltInIntToStr);
  2780. AddFunction(bcConversion,'strtoint','I','S',@BuiltInStrToInt);
  2781. AddFunction(bcConversion,'strtointdef','I','SI',@BuiltInStrToIntDef);
  2782. AddFunction(bcConversion,'floattostr','S','F',@BuiltInFloatToStr);
  2783. AddFunction(bcConversion,'strtofloat','F','S',@BuiltInStrToFloat);
  2784. AddFunction(bcConversion,'strtofloatdef','F','SF',@BuiltInStrToFloatDef);
  2785. AddFunction(bcConversion,'booltostr','S','B',@BuiltInBoolToStr);
  2786. AddFunction(bcConversion,'strtobool','B','S',@BuiltInStrToBool);
  2787. AddFunction(bcConversion,'strtobooldef','B','SB',@BuiltInStrToBoolDef);
  2788. AddFunction(bcConversion,'datetostr','S','D',@BuiltInDateToStr);
  2789. AddFunction(bcConversion,'timetostr','S','D',@BuiltInTimeToStr);
  2790. AddFunction(bcConversion,'strtodate','D','S',@BuiltInStrToDate);
  2791. AddFunction(bcConversion,'strtodatedef','D','SD',@BuiltInStrToDateDef);
  2792. AddFunction(bcConversion,'strtotime','D','S',@BuiltInStrToTime);
  2793. AddFunction(bcConversion,'strtotimedef','D','SD',@BuiltInStrToTimeDef);
  2794. AddFunction(bcConversion,'strtodatetime','D','S',@BuiltInStrToDateTime);
  2795. AddFunction(bcConversion,'strtodatetimedef','D','SD',@BuiltInStrToDateTimeDef);
  2796. end;
  2797. end;
  2798. { TFPBuiltInExprIdentifierDef }
  2799. procedure TFPBuiltInExprIdentifierDef.Assign(Source: TPersistent);
  2800. begin
  2801. inherited Assign(Source);
  2802. If Source is TFPBuiltInExprIdentifierDef then
  2803. FCategory:=(Source as TFPBuiltInExprIdentifierDef).Category;
  2804. end;
  2805. initialization
  2806. RegisterStdBuiltins(BuiltinIdentifiers);
  2807. finalization
  2808. FreeBuiltins;
  2809. end.