pparser.pp 166 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544
  1. {
  2. This file is part of the Free Component Library
  3. Pascal source parser
  4. Copyright (c) 2000-2005 by
  5. Areca Systems GmbH / Sebastian Guenther, [email protected]
  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 PParser;
  15. interface
  16. uses SysUtils, Classes, PasTree, PScanner;
  17. // message numbers
  18. const
  19. nErrNoSourceGiven = 2001;
  20. nErrMultipleSourceFiles = 2002;
  21. nParserError = 2003;
  22. nParserErrorAtToken = 2004;
  23. nParserUngetTokenError = 2005;
  24. nParserExpectTokenError = 2006;
  25. nParserForwardNotInterface = 2007;
  26. nParserExpectVisibility = 2008;
  27. nParserStrangeVisibility = 2009;
  28. nParserExpectToken2Error = 2010;
  29. nParserExpectedCommaRBracket = 2011;
  30. nParserExpectedCommaSemicolon = 2012;
  31. nParserExpectedAssignIn = 2013;
  32. nParserExpectedCommaColon = 2014;
  33. nErrUnknownOperatorType = 2015;
  34. nParserOnlyOneArgumentCanHaveDefault = 2016;
  35. nParserExpectedLBracketColon = 2017;
  36. nParserExpectedSemiColonEnd = 2018;
  37. nParserExpectedConstVarID = 2019;
  38. nParserExpectedNested = 2020;
  39. nParserExpectedColonID = 2021;
  40. nParserSyntaxError = 2022;
  41. nParserTypeSyntaxError = 2023;
  42. nParserArrayTypeSyntaxError = 2024;
  43. nParserExpectedIdentifier = 2026;
  44. nParserNotAProcToken = 2026;
  45. nRangeExpressionExpected = 2027;
  46. nParserExpectCase = 2028;
  47. nParserHelperNotAllowed = 2029;
  48. nLogStartImplementation = 2030;
  49. nLogStartInterface = 2031;
  50. nParserNoConstructorAllowed = 2032;
  51. nParserNoFieldsAllowed = 2033;
  52. nParserInvalidRecordVisibility = 2034;
  53. nErrRecordConstantsNotAllowed = 2035;
  54. nErrRecordMethodsNotAllowed = 2036;
  55. nErrRecordPropertiesNotAllowed = 2037;
  56. nErrRecordVisibilityNotAllowed = 2038;
  57. nParserTypeNotAllowedHere = 2039;
  58. nParserNotAnOperand = 2040;
  59. nParserArrayPropertiesCannotHaveDefaultValue = 2041;
  60. nParserDefaultPropertyMustBeArray = 2042;
  61. nParserUnknownProcedureType = 2043;
  62. nParserGenericArray1Element = 2044;
  63. nParserGenericClassOrArray = 2045;
  64. nParserDuplicateIdentifier = 2046;
  65. nParserDefaultParameterRequiredFor = 2047;
  66. nParserOnlyOneVariableCanBeInitialized = 2048;
  67. nParserExpectedTypeButGot = 2049;
  68. nParserPropertyArgumentsCanNotHaveDefaultValues = 2050;
  69. nParserExpectedExternalClassName = 2051;
  70. // resourcestring patterns of messages
  71. resourcestring
  72. SErrNoSourceGiven = 'No source file specified';
  73. SErrMultipleSourceFiles = 'Please specify only one source file';
  74. SParserError = 'Error';
  75. SParserErrorAtToken = '%s at token "%s" in file %s at line %d column %d';
  76. SParserUngetTokenError = 'Internal error: Cannot unget more tokens, history buffer is full';
  77. SParserExpectTokenError = 'Expected "%s"';
  78. SParserForwardNotInterface = 'The use of a FORWARD procedure modifier is not allowed in the interface';
  79. SParserExpectVisibility = 'Expected visibility specifier';
  80. SParserStrangeVisibility = 'Strange strict visibility encountered : "%s"';
  81. SParserExpectToken2Error = 'Expected "%s" or "%s"';
  82. SParserExpectedCommaRBracket = 'Expected "," or ")"';
  83. SParserExpectedCommaSemicolon = 'Expected "," or ";"';
  84. SParserExpectedAssignIn = 'Expected := or in';
  85. SParserExpectedCommaColon = 'Expected "," or ":"';
  86. SErrUnknownOperatorType = 'Unknown operator type: %s';
  87. SParserOnlyOneArgumentCanHaveDefault = 'A default value can only be assigned to 1 parameter';
  88. SParserExpectedLBracketColon = 'Expected "(" or ":"';
  89. SParserExpectedSemiColonEnd = 'Expected ";" or "End"';
  90. SParserExpectedConstVarID = 'Expected "const", "var" or identifier';
  91. SParserExpectedNested = 'Expected nested keyword';
  92. SParserExpectedColonID = 'Expected ":" or identifier';
  93. SParserSyntaxError = 'Syntax error';
  94. SParserTypeSyntaxError = 'Syntax error in type';
  95. SParserArrayTypeSyntaxError = 'Syntax error in array type';
  96. SParserExpectedIdentifier = 'Identifier expected';
  97. SParserNotAProcToken = 'Not a procedure or function token';
  98. SRangeExpressionExpected = 'Range expression expected';
  99. SParserExpectCase = 'Case label expression expected';
  100. SParserHelperNotAllowed = 'Helper objects not allowed for "%s"';
  101. SLogStartImplementation = 'Start parsing implementation section.';
  102. SLogStartInterface = 'Start parsing interface section';
  103. SParserNoConstructorAllowed = 'Constructors or Destructors are not allowed in Interfaces or Record helpers';
  104. SParserNoFieldsAllowed = 'Fields are not allowed in Interfaces';
  105. SParserInvalidRecordVisibility = 'Records can only have public and (strict) private as visibility specifiers';
  106. SErrRecordConstantsNotAllowed = 'Record constants not allowed at this location.';
  107. SErrRecordMethodsNotAllowed = 'Record methods not allowed at this location.';
  108. SErrRecordPropertiesNotAllowed = 'Record properties not allowed at this location.';
  109. SErrRecordVisibilityNotAllowed = 'Record visibilities not allowed at this location.';
  110. SParserTypeNotAllowedHere = 'Type "%s" not allowed here';
  111. SParserNotAnOperand = 'Not an operand: (%d : %s)';
  112. SParserArrayPropertiesCannotHaveDefaultValue = 'Array properties cannot have default value';
  113. SParserDefaultPropertyMustBeArray = 'The default property must be an array property';
  114. SParserUnknownProcedureType = 'Unknown procedure type "%d"';
  115. SParserGenericArray1Element = 'Generic arrays can have only 1 template element';
  116. SParserGenericClassOrArray = 'Generic can only be used with classes or arrays';
  117. SParserDuplicateIdentifier = 'Duplicate identifier "%s"';
  118. SParserDefaultParameterRequiredFor = 'Default parameter required for "%s"';
  119. SParserOnlyOneVariableCanBeInitialized = 'Only one variable can be initialized';
  120. SParserExpectedTypeButGot = 'Expected type, but got %s';
  121. SParserPropertyArgumentsCanNotHaveDefaultValues = 'Property arguments can not have default values';
  122. SParserExpectedExternalClassName = 'Expected external class name';
  123. type
  124. TPasScopeType = (
  125. stModule, // e.g. unit, program, library
  126. stUsesList,
  127. stTypeSection,
  128. stTypeDef, // e.g. a TPasType
  129. stConstDef, // e.g. a TPasConst
  130. stProcedure, // also method, procedure, constructor, destructor, ...
  131. stProcedureHeader,
  132. stExceptOnExpr,
  133. stExceptOnStatement,
  134. stDeclaration, // e.g. a TPasProperty, TPasVariable, TPasArgument
  135. stAncestors // the list of ancestors and interfaces of a class
  136. );
  137. TPasScopeTypes = set of TPasScopeType;
  138. TPasParserLogHandler = Procedure (Sender : TObject; Const Msg : String) of object;
  139. TPParserLogEvent = (pleInterface,pleImplementation);
  140. TPParserLogEvents = set of TPParserLogEvent;
  141. TPasParser = Class;
  142. { TPasTreeContainer }
  143. TPasTreeContainer = class
  144. private
  145. FCurrentParser: TPasParser;
  146. FNeedComments: Boolean;
  147. FOnLog: TPasParserLogHandler;
  148. FPParserLogEvents: TPParserLogEvents;
  149. FScannerLogEvents: TPScannerLogEvents;
  150. protected
  151. FPackage: TPasPackage;
  152. FInterfaceOnly : Boolean;
  153. procedure SetCurrentParser(AValue: TPasParser); virtual;
  154. public
  155. function CreateElement(AClass: TPTreeElement; const AName: String;
  156. AParent: TPasElement; const ASourceFilename: String;
  157. ASourceLinenumber: Integer): TPasElement;overload;
  158. function CreateElement(AClass: TPTreeElement; const AName: String;
  159. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  160. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;overload;
  161. virtual; abstract;
  162. function CreateElement(AClass: TPTreeElement; const AName: String;
  163. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  164. const ASrcPos: TPasSourcePos): TPasElement; overload;
  165. virtual;
  166. function CreateFunctionType(const AName, AResultName: String; AParent: TPasElement;
  167. UseParentAsResultParent: Boolean; const ASrcPos: TPasSourcePos): TPasFunctionType;
  168. function FindElement(const AName: String): TPasElement; virtual; abstract;
  169. procedure FinishScope(ScopeType: TPasScopeType; El: TPasElement); virtual;
  170. function FindModule(const AName: String): TPasModule; virtual;
  171. property Package: TPasPackage read FPackage;
  172. property InterfaceOnly : Boolean Read FInterfaceOnly Write FInterFaceOnly;
  173. property ScannerLogEvents : TPScannerLogEvents Read FScannerLogEvents Write FScannerLogEvents;
  174. property ParserLogEvents : TPParserLogEvents Read FPParserLogEvents Write FPParserLogEvents;
  175. property OnLog : TPasParserLogHandler Read FOnLog Write FOnLog;
  176. property CurrentParser : TPasParser Read FCurrentParser Write SetCurrentParser;
  177. property NeedComments : Boolean Read FNeedComments Write FNeedComments;
  178. end;
  179. EParserError = class(Exception)
  180. private
  181. FFilename: String;
  182. FRow, FColumn: Integer;
  183. public
  184. constructor Create(const AReason, AFilename: String;
  185. ARow, AColumn: Integer);
  186. property Filename: String read FFilename;
  187. property Row: Integer read FRow;
  188. property Column: Integer read FColumn;
  189. end;
  190. TProcType = (ptProcedure, ptFunction, ptOperator, ptClassOperator, ptConstructor, ptDestructor,
  191. ptClassProcedure, ptClassFunction, ptClassConstructor, ptClassDestructor);
  192. TExprKind = (ek_Normal, ek_PropertyIndex);
  193. TIndentAction = (iaNone,iaIndent,iaUndent);
  194. { TPasParser }
  195. TPasParser = class
  196. private
  197. FCurModule: TPasModule;
  198. FFileResolver: TBaseFileResolver;
  199. FImplicitUses: TStrings;
  200. FLastMsg: string;
  201. FLastMsgArgs: TMessageArgs;
  202. FLastMsgNumber: integer;
  203. FLastMsgPattern: string;
  204. FLastMsgType: TMessageType;
  205. FLogEvents: TPParserLogEvents;
  206. FOnLog: TPasParserLogHandler;
  207. FOptions: TPOptions;
  208. FScanner: TPascalScanner;
  209. FEngine: TPasTreeContainer;
  210. FCurToken: TToken;
  211. FCurTokenString: String;
  212. FCurComments : TStrings;
  213. FSavedComments : String;
  214. // UngetToken support:
  215. FTokenBuffer: array[0..1] of TToken;
  216. FTokenStringBuffer: array[0..1] of String;
  217. FCommentsBuffer: array[0..1] of TStrings;
  218. FTokenBufferIndex: Integer; // current index in FTokenBuffer
  219. FTokenBufferSize: Integer; // maximum valid index in FTokenBuffer
  220. FDumpIndent : String;
  221. function CheckOverloadList(AList: TFPList; AName: String; out OldMember: TPasElement): TPasOverloadedProc;
  222. procedure DumpCurToken(Const Msg : String; IndentAction : TIndentAction = iaNone);
  223. function GetCurrentModeSwitches: TModeSwitches;
  224. Procedure SetCurrentModeSwitches(AValue: TModeSwitches);
  225. function GetVariableModifiers(Parent: TPasElement; Out VarMods: TVariableModifiers; Out LibName, ExportName: TPasExpr; ExternalClass : Boolean): string;
  226. function GetVariableValueAndLocation(Parent : TPasElement; Out Value : TPasExpr; Out Location: String): Boolean;
  227. procedure HandleProcedureModifier(Parent: TPasElement; pm : TProcedureModifier);
  228. procedure HandleProcedureTypeModifier(ProcType: TPasProcedureType; ptm : TProcTypeModifier);
  229. procedure ParseClassLocalConsts(AType: TPasClassType; AVisibility: TPasMemberVisibility);
  230. procedure ParseClassLocalTypes(AType: TPasClassType; AVisibility: TPasMemberVisibility);
  231. procedure ParseVarList(Parent: TPasElement; VarList: TFPList; AVisibility: TPasMemberVisibility; Full: Boolean);
  232. procedure SetOptions(AValue: TPOptions);
  233. protected
  234. Function SaveComments : String;
  235. Function SaveComments(Const AValue : String) : String;
  236. function LogEvent(E : TPParserLogEvent) : Boolean; inline;
  237. Procedure DoLog(MsgType: TMessageType; MsgNumber: integer; Const Msg : String; SkipSourceInfo : Boolean = False);overload;
  238. Procedure DoLog(MsgType: TMessageType; MsgNumber: integer; Const Fmt : String; Args : Array of const;SkipSourceInfo : Boolean = False);overload;
  239. function GetProcTypeFromToken(tk: TToken; IsClass: Boolean=False ): TProcType;
  240. procedure ParseAsmBlock(AsmBlock: TPasImplAsmStatement); virtual;
  241. procedure ParseRecordFieldList(ARec: TPasRecordType; AEndToken: TToken; AllowMethods : Boolean);
  242. procedure ParseRecordVariantParts(ARec: TPasRecordType; AEndToken: TToken);
  243. function GetProcedureClass(ProcType : TProcType): TPTreeElement;
  244. procedure ParseClassFields(AType: TPasClassType; const AVisibility: TPasMemberVisibility; IsClassField : Boolean);
  245. procedure ParseClassMembers(AType: TPasClassType);
  246. procedure ProcessMethod(AType: TPasClassType; IsClass : Boolean; AVisibility : TPasMemberVisibility);
  247. procedure ReadGenericArguments(List : TFPList;Parent : TPasElement);
  248. function CheckProcedureArgs(Parent: TPasElement;
  249. Args: TFPList; // list of TPasArgument
  250. Mandatory: Boolean): boolean;
  251. function CheckVisibility(S: String; var AVisibility: TPasMemberVisibility): Boolean;
  252. procedure ParseExc(MsgNumber: integer; const Msg: String);
  253. procedure ParseExc(MsgNumber: integer; const Fmt: String; Args : Array of const);
  254. procedure ParseExcExpectedIdentifier;
  255. procedure ParseExcSyntaxError;
  256. procedure ParseExcTokenError(const Arg: string);
  257. function OpLevel(t: TToken): Integer;
  258. Function TokenToExprOp (AToken : TToken) : TExprOpCode;
  259. function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement): TPasElement;overload;
  260. function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; const ASrcPos: TPasSourcePos): TPasElement;overload;
  261. function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility): TPasElement;overload;
  262. function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility; const ASrcPos: TPasSourcePos): TPasElement;overload;
  263. function CreatePrimitiveExpr(AParent: TPasElement; AKind: TPasExprKind; const AValue: String): TPrimitiveExpr;
  264. function CreateBoolConstExpr(AParent: TPasElement; AKind: TPasExprKind; const ABoolValue : Boolean): TBoolConstExpr;
  265. function CreateBinaryExpr(AParent : TPasElement; xleft, xright: TPasExpr; AOpCode: TExprOpCode): TBinaryExpr;
  266. procedure AddToBinaryExprChain(var ChainFirst: TPasExpr;
  267. Element: TPasExpr; AOpCode: TExprOpCode);
  268. procedure AddParamsToBinaryExprChain(var ChainFirst: TPasExpr;
  269. Params: TParamsExpr);
  270. {$IFDEF VerbosePasParser}
  271. procedure WriteBinaryExprChain(Prefix: string; First, Last: TPasExpr);
  272. {$ENDIF}
  273. function CreateUnaryExpr(AParent : TPasElement; AOperand: TPasExpr; AOpCode: TExprOpCode): TUnaryExpr;
  274. function CreateArrayValues(AParent : TPasElement): TArrayValues;
  275. function CreateFunctionType(const AName, AResultName: String; AParent: TPasElement;
  276. UseParentAsResultParent: Boolean; const NamePos: TPasSourcePos): TPasFunctionType;
  277. function CreateInheritedExpr(AParent : TPasElement): TInheritedExpr;
  278. function CreateSelfExpr(AParent : TPasElement): TSelfExpr;
  279. function CreateNilExpr(AParent : TPasElement): TNilExpr;
  280. function CreateRecordValues(AParent : TPasElement): TRecordValues;
  281. Function IsCurTokenHint(out AHint : TPasMemberHint) : Boolean; overload;
  282. Function IsCurTokenHint: Boolean; overload;
  283. Function TokenIsCallingConvention(const S : String; out CC : TCallingConvention) : Boolean; virtual;
  284. Function TokenIsProcedureModifier(Parent : TPasElement; const S : String; Out PM : TProcedureModifier) : Boolean; virtual;
  285. Function TokenIsProcedureTypeModifier(Parent : TPasElement; const S : String; Out PTM : TProcTypeModifier) : Boolean; virtual;
  286. Function CheckHint(Element : TPasElement; ExpectSemiColon : Boolean) : TPasMemberHints;
  287. function ParseParams(AParent : TPasElement;paramskind: TPasExprKind; AllowFormatting : Boolean = False): TParamsExpr;
  288. function ParseExpIdent(AParent : TPasElement): TPasExpr;
  289. procedure DoParseClassType(AType: TPasClassType);
  290. function DoParseExpression(AParent: TPaselement;InitExpr: TPasExpr=nil; AllowEqual : Boolean = True): TPasExpr;
  291. function DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
  292. function CheckPackMode: TPackMode;
  293. function CheckUseUnit(ASection: TPasSection; AUnitName : string): TPasElement;
  294. procedure CheckImplicitUsedUnits(ASection: TPasSection);
  295. // Overload handling
  296. procedure AddProcOrFunction(Decs: TPasDeclarations; AProc: TPasProcedure);
  297. function CheckIfOverloaded(AParent: TPasElement; const AName: String): TPasElement;
  298. public
  299. constructor Create(AScanner: TPascalScanner; AFileResolver: TBaseFileResolver; AEngine: TPasTreeContainer);
  300. Destructor Destroy; override;
  301. procedure SetLastMsg(MsgType: TMessageType; MsgNumber: integer; Const Fmt : String; Args : Array of const);
  302. // General parsing routines
  303. function CurTokenName: String;
  304. function CurTokenText: String;
  305. Function CurComments : TStrings;
  306. Function SavedComments : String;
  307. procedure NextToken; // read next non whitespace, non space
  308. procedure UngetToken;
  309. procedure CheckToken(tk: TToken);
  310. procedure ExpectToken(tk: TToken);
  311. function ExpectIdentifier: String;
  312. Function CurTokenIsIdentifier(Const S : String) : Boolean;
  313. // Expression parsing
  314. function isEndOfExp(AllowEqual : Boolean = False): Boolean;
  315. // Type declarations
  316. function ParseComplexType(Parent : TPasElement = Nil): TPasType;
  317. function ParseTypeDecl(Parent: TPasElement): TPasType;
  318. function ParseType(Parent: TPasElement; const NamePos: TPasSourcePos; const TypeName: String = ''; Full: Boolean = false; GenericArgs: TFPList = nil): TPasType;
  319. function ParseReferenceToProcedureType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasProcedureType;
  320. function ParseProcedureType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String; const PT: TProcType): TPasProcedureType;
  321. function ParseStringType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasAliasType;
  322. function ParseSimpleType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String; IsFull : Boolean = False): TPasType;
  323. function ParseAliasType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasTypeAliasType;
  324. function ParsePointerType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasPointerType;
  325. Function ParseArrayType(Parent : TPasElement; Const NamePos: TPasSourcePos; Const TypeName : String; PackMode : TPackMode) : TPasArrayType;
  326. Function ParseFileType(Parent : TPasElement; Const NamePos: TPasSourcePos; Const TypeName : String) : TPasFileType;
  327. Function ParseRecordDecl(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName : string; const Packmode : TPackMode = pmNone) : TPasRecordType;
  328. function ParseEnumType(Parent: TPasElement; Const NamePos: TPasSourcePos; const TypeName: String): TPasEnumType;
  329. function ParseSetType(Parent: TPasElement; Const NamePos: TPasSourcePos; const TypeName: String; AIsPacked : Boolean = False): TPasSetType;
  330. function ParseSpecializeType(Parent: TPasElement; Const TypeName: String): TPasClassType;
  331. Function ParseClassDecl(Parent: TPasElement; Const NamePos: TPasSourcePos; Const AClassName: String; AObjKind: TPasObjKind; PackMode : TPackMode= pmNone; GenericArgs: TFPList = nil): TPasType;
  332. Function ParseProperty(Parent : TPasElement; Const AName : String; AVisibility : TPasMemberVisibility; IsClassField: boolean) : TPasProperty;
  333. function ParseRangeType(AParent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String; Full: Boolean = True): TPasRangeType;
  334. procedure ParseExportDecl(Parent: TPasElement; List: TFPList);
  335. // Constant declarations
  336. function ParseConstDecl(Parent: TPasElement): TPasConst;
  337. function ParseResourcestringDecl(Parent: TPasElement): TPasResString;
  338. // Variable handling. This includes parts of records
  339. procedure ParseVarDecl(Parent: TPasElement; List: TFPList);
  340. procedure ParseInlineVarDecl(Parent: TPasElement; List: TFPList; AVisibility : TPasMemberVisibility = visDefault; ClosingBrace: Boolean = False);
  341. // Main scope parsing
  342. procedure ParseMain(var Module: TPasModule);
  343. procedure ParseUnit(var Module: TPasModule);
  344. procedure ParseProgram(var Module: TPasModule; SkipHeader : Boolean = False);
  345. procedure ParseLibrary(var Module: TPasModule);
  346. procedure ParseOptionalUsesList(ASection: TPasSection);
  347. procedure ParseUsesList(ASection: TPasSection);
  348. procedure ParseInterface;
  349. procedure ParseImplementation;
  350. procedure ParseInitialization;
  351. procedure ParseFinalization;
  352. procedure ParseDeclarations(Declarations: TPasDeclarations);
  353. procedure ParseStatement(Parent: TPasImplBlock; out NewImplElement: TPasImplElement);
  354. procedure ParseLabels(AParent: TPasElement);
  355. procedure ParseProcBeginBlock(Parent: TProcedureBody);
  356. procedure ParseProcAsmBlock(Parent: TProcedureBody);
  357. // Function/Procedure declaration
  358. function ParseProcedureOrFunctionDecl(Parent: TPasElement; ProcType: TProcType;AVisibility : TPasMemberVisibility = VisDefault): TPasProcedure;
  359. procedure ParseArgList(Parent: TPasElement;
  360. Args: TFPList; // list of TPasArgument
  361. EndToken: TToken);
  362. procedure ParseProcedureOrFunctionHeader(Parent: TPasElement; Element: TPasProcedureType; ProcType: TProcType; OfObjectPossible: Boolean);
  363. procedure ParseProcedureBody(Parent: TPasElement);
  364. // Properties for external access
  365. property FileResolver: TBaseFileResolver read FFileResolver;
  366. property Scanner: TPascalScanner read FScanner;
  367. property Engine: TPasTreeContainer read FEngine;
  368. property CurToken: TToken read FCurToken;
  369. property CurTokenString: String read FCurTokenString;
  370. Property Options : TPOptions Read FOptions Write SetOptions;
  371. Property CurrentModeswitches : TModeSwitches Read GetCurrentModeSwitches Write SetCurrentModeSwitches;
  372. Property CurModule : TPasModule Read FCurModule;
  373. Property LogEvents : TPParserLogEvents Read FLogEvents Write FLogEvents;
  374. Property OnLog : TPasParserLogHandler Read FOnLog Write FOnLog;
  375. property ImplicitUses: TStrings read FImplicitUses;
  376. property LastMsg: string read FLastMsg write FLastMsg;
  377. property LastMsgNumber: integer read FLastMsgNumber write FLastMsgNumber;
  378. property LastMsgType: TMessageType read FLastMsgType write FLastMsgType;
  379. property LastMsgPattern: string read FLastMsgPattern write FLastMsgPattern;
  380. property LastMsgArgs: TMessageArgs read FLastMsgArgs write FLastMsgArgs;
  381. end;
  382. function ParseSource(AEngine: TPasTreeContainer;
  383. const FPCCommandLine, OSTarget, CPUTarget: String;
  384. UseStreams : Boolean = False): TPasModule;
  385. Function IsHintToken(T : String; Out AHint : TPasMemberHint) : boolean;
  386. Function IsProcModifier(S : String; Out PM : TProcedureModifier) : Boolean;
  387. Function IsCallingConvention(S : String; out CC : TCallingConvention) : Boolean;
  388. Function TokenToAssignKind( tk : TToken) : TAssignKind;
  389. implementation
  390. const
  391. WhitespaceTokensToIgnore = [tkWhitespace, tkComment, tkLineEnding, tkTab];
  392. type
  393. TDeclType = (declNone, declConst, declResourcestring, declType,
  394. declVar, declThreadvar, declProperty, declExports);
  395. Function IsHintToken(T : String; Out AHint : TPasMemberHint) : boolean;
  396. Const
  397. MemberHintTokens : Array[TPasMemberHint] of string =
  398. ('deprecated','library','platform','experimental','unimplemented');
  399. Var
  400. I : TPasMemberHint;
  401. begin
  402. t:=LowerCase(t);
  403. Result:=False;
  404. For I:=Low(TPasMemberHint) to High(TPasMemberHint) do
  405. begin
  406. result:=(t=MemberHintTokens[i]);
  407. if Result then
  408. begin
  409. aHint:=I;
  410. exit;
  411. end;
  412. end;
  413. end;
  414. Function IsCallingConvention(S : String; out CC : TCallingConvention) : Boolean;
  415. Var
  416. CCNames : Array[TCallingConvention] of String
  417. = ('','register','pascal','cdecl','stdcall','oldfpccall','safecall','syscall');
  418. Var
  419. C : TCallingConvention;
  420. begin
  421. S:=Lowercase(s);
  422. Result:=False;
  423. for C:=Low(TCallingConvention) to High(TCallingConvention) do
  424. begin
  425. Result:=(CCNames[c]<>'') and (s=CCnames[c]);
  426. If Result then
  427. begin
  428. CC:=C;
  429. exit;
  430. end;
  431. end;
  432. end;
  433. Function IsProcModifier(S : String; Out PM : TProcedureModifier) : Boolean;
  434. Var
  435. P : TProcedureModifier;
  436. begin
  437. S:=LowerCase(S);
  438. Result:=False;
  439. For P:=Low(TProcedureModifier) to High(TProcedureModifier) do
  440. begin
  441. Result:=s=ModifierNames[P];
  442. If Result then
  443. begin
  444. PM:=P;
  445. exit;
  446. end;
  447. end;
  448. end;
  449. Function TokenToAssignKind( tk : TToken) : TAssignKind;
  450. begin
  451. case tk of
  452. tkAssign : Result:=akDefault;
  453. tkAssignPlus : Result:=akAdd;
  454. tkAssignMinus : Result:=akMinus;
  455. tkAssignMul : Result:=akMul;
  456. tkAssignDivision : Result:=akDivision;
  457. else
  458. Raise Exception.CreateFmt('Not an assignment token : %s',[TokenInfos[tk]]);
  459. end;
  460. end;
  461. function ParseSource(AEngine: TPasTreeContainer;
  462. const FPCCommandLine, OSTarget, CPUTarget: String;
  463. UseStreams : Boolean = False): TPasModule;
  464. var
  465. FileResolver: TFileResolver;
  466. Parser: TPasParser;
  467. Start, CurPos: PChar;
  468. Filename: String;
  469. Scanner: TPascalScanner;
  470. procedure ProcessCmdLinePart;
  471. var
  472. l: Integer;
  473. s: String;
  474. begin
  475. l := CurPos - Start;
  476. SetLength(s, l);
  477. if l > 0 then
  478. Move(Start^, s[1], l)
  479. else
  480. exit;
  481. if (s[1] = '-') and (length(s)>1) then
  482. begin
  483. case s[2] of
  484. 'd': // -d define
  485. Scanner.AddDefine(UpperCase(Copy(s, 3, Length(s))));
  486. 'F': // -F
  487. if (length(s)>2) and (s[3] = 'i') then // -Fi include path
  488. FileResolver.AddIncludePath(Copy(s, 4, Length(s)));
  489. 'I': // -I include path
  490. FileResolver.AddIncludePath(Copy(s, 3, Length(s)));
  491. 'S': // -S mode
  492. if (length(s)>2) then
  493. case S[3] of
  494. 'c' : Scanner.Options:=Scanner.Options+[po_cassignments];
  495. 'd' : Scanner.SetCompilerMode('DELPHI');
  496. '2' : Scanner.SetCompilerMode('OBJFPC');
  497. end;
  498. 'M' :
  499. begin
  500. delete(S,1,2);
  501. Scanner.SetCompilerMode(S);
  502. end;
  503. end;
  504. end else
  505. if Filename <> '' then
  506. raise Exception.Create(SErrMultipleSourceFiles)
  507. else
  508. Filename := s;
  509. end;
  510. var
  511. s: String;
  512. begin
  513. Result := nil;
  514. FileResolver := nil;
  515. Scanner := nil;
  516. Parser := nil;
  517. try
  518. FileResolver := TFileResolver.Create;
  519. FileResolver.UseStreams:=UseStreams;
  520. Scanner := TPascalScanner.Create(FileResolver);
  521. Scanner.AddDefine('FPK');
  522. Scanner.AddDefine('FPC');
  523. SCanner.LogEvents:=AEngine.ScannerLogEvents;
  524. SCanner.OnLog:=AEngine.Onlog;
  525. // TargetOS
  526. s := UpperCase(OSTarget);
  527. Scanner.AddDefine(s);
  528. if s = 'LINUX' then
  529. Scanner.AddDefine('UNIX')
  530. else if s = 'FREEBSD' then
  531. begin
  532. Scanner.AddDefine('BSD');
  533. Scanner.AddDefine('UNIX');
  534. end else if s = 'NETBSD' then
  535. begin
  536. Scanner.AddDefine('BSD');
  537. Scanner.AddDefine('UNIX');
  538. end else if s = 'SUNOS' then
  539. begin
  540. Scanner.AddDefine('SOLARIS');
  541. Scanner.AddDefine('UNIX');
  542. end else if s = 'GO32V2' then
  543. Scanner.AddDefine('DPMI')
  544. else if s = 'BEOS' then
  545. Scanner.AddDefine('UNIX')
  546. else if s = 'QNX' then
  547. Scanner.AddDefine('UNIX')
  548. else if s = 'AROS' then
  549. Scanner.AddDefine('HASAMIGA')
  550. else if s = 'MORPHOS' then
  551. Scanner.AddDefine('HASAMIGA')
  552. else if s = 'AMIGA' then
  553. Scanner.AddDefine('HASAMIGA');
  554. // TargetCPU
  555. s := UpperCase(CPUTarget);
  556. Scanner.AddDefine('CPU'+s);
  557. if (s='X86_64') then
  558. Scanner.AddDefine('CPU64')
  559. else
  560. Scanner.AddDefine('CPU32');
  561. Parser := TPasParser.Create(Scanner, FileResolver, AEngine);
  562. Filename := '';
  563. Parser.LogEvents:=AEngine.ParserLogEvents;
  564. Parser.OnLog:=AEngine.Onlog;
  565. if FPCCommandLine<>'' then
  566. begin
  567. Start := @FPCCommandLine[1];
  568. CurPos := Start;
  569. while CurPos[0] <> #0 do
  570. begin
  571. if CurPos[0] = ' ' then
  572. begin
  573. ProcessCmdLinePart;
  574. Start := CurPos + 1;
  575. end;
  576. Inc(CurPos);
  577. end;
  578. ProcessCmdLinePart;
  579. end;
  580. if Filename = '' then
  581. raise Exception.Create(SErrNoSourceGiven);
  582. FileResolver.AddIncludePath(ExtractFilePath(FileName));
  583. Scanner.OpenFile(Filename);
  584. Parser.ParseMain(Result);
  585. finally
  586. Parser.Free;
  587. Scanner.Free;
  588. FileResolver.Free;
  589. end;
  590. end;
  591. { ---------------------------------------------------------------------
  592. TPasTreeContainer
  593. ---------------------------------------------------------------------}
  594. procedure TPasTreeContainer.SetCurrentParser(AValue: TPasParser);
  595. begin
  596. if FCurrentParser=AValue then Exit;
  597. FCurrentParser:=AValue;
  598. end;
  599. function TPasTreeContainer.CreateElement(AClass: TPTreeElement;
  600. const AName: String; AParent: TPasElement; const ASourceFilename: String;
  601. ASourceLinenumber: Integer): TPasElement;
  602. begin
  603. Result := CreateElement(AClass, AName, AParent, visDefault, ASourceFilename,
  604. ASourceLinenumber);
  605. end;
  606. function TPasTreeContainer.CreateElement(AClass: TPTreeElement;
  607. const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility;
  608. const ASrcPos: TPasSourcePos): TPasElement;
  609. begin
  610. Result := CreateElement(AClass, AName, AParent, AVisibility, ASrcPos.FileName,
  611. ASrcPos.Row);
  612. end;
  613. function TPasTreeContainer.CreateFunctionType(const AName, AResultName: String;
  614. AParent: TPasElement; UseParentAsResultParent: Boolean;
  615. const ASrcPos: TPasSourcePos): TPasFunctionType;
  616. var
  617. ResultParent: TPasElement;
  618. begin
  619. Result := TPasFunctionType(CreateElement(TPasFunctionType, AName, AParent,
  620. visDefault, ASrcPos));
  621. if UseParentAsResultParent then
  622. ResultParent := AParent
  623. else
  624. ResultParent := Result;
  625. TPasFunctionType(Result).ResultEl :=
  626. TPasResultElement(CreateElement(TPasResultElement, AResultName, ResultParent,
  627. visDefault, ASrcPos));
  628. end;
  629. procedure TPasTreeContainer.FinishScope(ScopeType: TPasScopeType;
  630. El: TPasElement);
  631. begin
  632. if ScopeType=stModule then ;
  633. if El=nil then ;
  634. end;
  635. function TPasTreeContainer.FindModule(const AName: String): TPasModule;
  636. begin
  637. if AName='' then ;
  638. Result := nil;
  639. end;
  640. { ---------------------------------------------------------------------
  641. EParserError
  642. ---------------------------------------------------------------------}
  643. constructor EParserError.Create(const AReason, AFilename: String;
  644. ARow, AColumn: Integer);
  645. begin
  646. inherited Create(AReason);
  647. FFilename := AFilename;
  648. FRow := ARow;
  649. FColumn := AColumn;
  650. end;
  651. { ---------------------------------------------------------------------
  652. TPasParser
  653. ---------------------------------------------------------------------}
  654. procedure TPasParser.ParseExc(MsgNumber: integer; const Msg: String);
  655. begin
  656. ParseExc(MsgNumber,Msg,[]);
  657. end;
  658. procedure TPasParser.ParseExc(MsgNumber: integer; const Fmt: String;
  659. Args: array of const);
  660. begin
  661. {$IFDEF VerbosePasParser}
  662. writeln('TPasParser.ParseExc Token="',CurTokenText,'"');
  663. {$ENDIF}
  664. SetLastMsg(mtError,MsgNumber,Fmt,Args);
  665. raise EParserError.Create(SafeFormat(SParserErrorAtToken,
  666. [FLastMsg, CurTokenName, Scanner.CurFilename, Scanner.CurRow, Scanner.CurColumn])
  667. {$ifdef addlocation}+' ('+inttostr(scanner.currow)+' '+inttostr(scanner.curcolumn)+')'{$endif},
  668. Scanner.CurFilename, Scanner.CurRow, Scanner.CurColumn);
  669. end;
  670. procedure TPasParser.ParseExcExpectedIdentifier;
  671. begin
  672. ParseExc(nParserExpectedIdentifier,SParserExpectedIdentifier);
  673. end;
  674. procedure TPasParser.ParseExcSyntaxError;
  675. begin
  676. ParseExc(nParserSyntaxError,SParserSyntaxError);
  677. end;
  678. procedure TPasParser.ParseExcTokenError(const Arg: string);
  679. begin
  680. ParseExc(nParserExpectTokenError,SParserExpectTokenError,[Arg]);
  681. end;
  682. constructor TPasParser.Create(AScanner: TPascalScanner;
  683. AFileResolver: TBaseFileResolver; AEngine: TPasTreeContainer);
  684. begin
  685. inherited Create;
  686. FScanner := AScanner;
  687. FFileResolver := AFileResolver;
  688. FEngine := AEngine;
  689. FCommentsBuffer[0]:=TStringList.Create;
  690. FCommentsBuffer[1]:=TStringList.Create;
  691. if Assigned(FEngine) then
  692. begin
  693. FEngine.CurrentParser:=Self;
  694. If FEngine.NeedComments then
  695. FScanner.SkipComments:=Not FEngine.NeedComments;
  696. end;
  697. FImplicitUses := TStringList.Create;
  698. FImplicitUses.Add('System'); // system always implicitely first.
  699. end;
  700. destructor TPasParser.Destroy;
  701. begin
  702. if Assigned(FEngine) then
  703. begin
  704. FEngine.CurrentParser:=Nil;
  705. FEngine:=nil;
  706. end;
  707. FreeAndNil(FImplicitUses);
  708. FreeAndNil(FCommentsBuffer[0]);
  709. FreeAndNil(FCommentsBuffer[1]);
  710. inherited Destroy;
  711. end;
  712. function TPasParser.CurTokenName: String;
  713. begin
  714. if CurToken = tkIdentifier then
  715. Result := 'Identifier ' + FCurTokenString
  716. else
  717. Result := TokenInfos[CurToken];
  718. end;
  719. function TPasParser.CurTokenText: String;
  720. begin
  721. case CurToken of
  722. tkIdentifier, tkString, tkNumber, tkChar:
  723. Result := FCurTokenString;
  724. else
  725. Result := TokenInfos[CurToken];
  726. end;
  727. end;
  728. function TPasParser.CurComments: TStrings;
  729. begin
  730. Result:=FCurComments;
  731. end;
  732. function TPasParser.SavedComments: String;
  733. begin
  734. Result:=FSavedComments;
  735. end;
  736. procedure TPasParser.NextToken;
  737. Var
  738. T : TStrings;
  739. begin
  740. if FTokenBufferIndex < FTokenBufferSize then
  741. begin
  742. // Get token from buffer
  743. FCurToken := FTokenBuffer[FTokenBufferIndex];
  744. FCurTokenString := FTokenStringBuffer[FTokenBufferIndex];
  745. FCurComments:=FCommentsBuffer[FTokenBufferIndex];
  746. Inc(FTokenBufferIndex);
  747. //writeln('TPasParser.NextToken From Buf ',CurTokenText,' id=',FTokenBufferIndex);
  748. end else
  749. begin
  750. { We have to fetch a new token. But first check, wether there is space left
  751. in the token buffer.}
  752. if FTokenBufferSize = 2 then
  753. begin
  754. FTokenBuffer[0] := FTokenBuffer[1];
  755. FTokenStringBuffer[0] := FTokenStringBuffer[1];
  756. T:=FCommentsBuffer[0];
  757. FCommentsBuffer[0]:=FCommentsBuffer[1];
  758. FCommentsBuffer[1]:=T;
  759. Dec(FTokenBufferSize);
  760. Dec(FTokenBufferIndex);
  761. end;
  762. // Fetch new token
  763. try
  764. FCommentsBuffer[FTokenBufferSize].Clear;
  765. repeat
  766. FCurToken := Scanner.FetchToken;
  767. if FCurToken=tkComment then
  768. FCommentsBuffer[FTokenBufferSize].Add(Scanner.CurTokenString);
  769. until not (FCurToken in WhitespaceTokensToIgnore);
  770. except
  771. on e: EScannerError do
  772. begin
  773. if po_KeepScannerError in Options then
  774. raise e
  775. else
  776. begin
  777. FLastMsgType := mtError;
  778. FLastMsgNumber := Scanner.LastMsgNumber;
  779. FLastMsgPattern := Scanner.LastMsgPattern;
  780. FLastMsg := Scanner.LastMsg;
  781. FLastMsgArgs := Scanner.LastMsgArgs;
  782. raise EParserError.Create(e.Message,
  783. Scanner.CurFilename, Scanner.CurRow, Scanner.CurColumn);
  784. end;
  785. end;
  786. end;
  787. FCurTokenString := Scanner.CurTokenString;
  788. FTokenBuffer[FTokenBufferSize] := FCurToken;
  789. FTokenStringBuffer[FTokenBufferSize] := FCurTokenString;
  790. FCurComments:=FCommentsBuffer[FTokenBufferSize];
  791. Inc(FTokenBufferSize);
  792. Inc(FTokenBufferIndex);
  793. // writeln('TPasParser.NextToken New ',CurTokenText,' id=',FTokenBufferIndex,' comments = ',FCurComments.text);
  794. end;
  795. end;
  796. procedure TPasParser.UngetToken;
  797. begin
  798. if FTokenBufferIndex = 0 then
  799. ParseExc(nParserUngetTokenError,SParserUngetTokenError)
  800. else begin
  801. Dec(FTokenBufferIndex);
  802. if FTokenBufferIndex>0 then
  803. begin
  804. FCurToken := FTokenBuffer[FTokenBufferIndex-1];
  805. FCurTokenString := FTokenStringBuffer[FTokenBufferIndex-1];
  806. FCurComments:=FCommentsBuffer[FTokenBufferIndex-1];
  807. end else begin
  808. FCurToken := tkWhitespace;
  809. FCurTokenString := '';
  810. FCurComments.Clear;
  811. end;
  812. //writeln('TPasParser.UngetToken ',CurTokenText,' id=',FTokenBufferIndex);
  813. end;
  814. end;
  815. procedure TPasParser.CheckToken(tk: TToken);
  816. begin
  817. if (CurToken<>tk) then
  818. begin
  819. {$IFDEF VerbosePasParser}
  820. writeln('TPasParser.ParseExcTokenError String="',CurTokenString,'" Text="',CurTokenText,'" CurToken=',CurToken,' tk=',tk);
  821. {$ENDIF}
  822. ParseExcTokenError(TokenInfos[tk]);
  823. end;
  824. end;
  825. procedure TPasParser.ExpectToken(tk: TToken);
  826. begin
  827. NextToken;
  828. CheckToken(tk);
  829. end;
  830. function TPasParser.ExpectIdentifier: String;
  831. begin
  832. ExpectToken(tkIdentifier);
  833. Result := CurTokenString;
  834. end;
  835. function TPasParser.CurTokenIsIdentifier(const S: String): Boolean;
  836. begin
  837. Result:=(Curtoken=tkIdentifier) and (CompareText(S,CurtokenText)=0);
  838. end;
  839. function TPasParser.IsCurTokenHint(out AHint: TPasMemberHint): Boolean;
  840. begin
  841. Result:=CurToken=tklibrary;
  842. if Result then
  843. AHint:=hLibrary
  844. else if (CurToken=tkIdentifier) then
  845. Result:=IsHintToken(CurTokenString,ahint);
  846. end;
  847. function TPasParser.IsCurTokenHint: Boolean;
  848. var
  849. dummy : TPasMemberHint;
  850. begin
  851. Result:=IsCurTokenHint(dummy);
  852. end;
  853. function TPasParser.TokenIsCallingConvention(const S: String; out
  854. CC: TCallingConvention): Boolean;
  855. begin
  856. Result:=IsCallingConvention(S,CC);
  857. end;
  858. function TPasParser.TokenIsProcedureModifier(Parent: TPasElement;
  859. const S: String; out PM: TProcedureModifier): Boolean;
  860. begin
  861. Result:=IsProcModifier(S,PM);
  862. if Result and (PM in [pmPublic,pmForward]) then
  863. begin
  864. While (Parent<>Nil) and Not ((Parent is TPasClassType) or (Parent is TPasRecordType)) do
  865. Parent:=Parent.Parent;
  866. Result:=Not Assigned(Parent);
  867. end;
  868. end;
  869. function TPasParser.TokenIsProcedureTypeModifier(Parent: TPasElement;
  870. const S: String; out PTM: TProcTypeModifier): Boolean;
  871. begin
  872. if CompareText(S,ProcTypeModifiers[ptmVarargs])=0 then
  873. begin
  874. Result:=true;
  875. PTM:=ptmVarargs;
  876. end
  877. else if CompareText(S,ProcTypeModifiers[ptmStatic])=0 then
  878. begin
  879. Result:=true;
  880. PTM:=ptmStatic;
  881. end
  882. else
  883. Result:=false;
  884. if Parent=nil then;
  885. end;
  886. function TPasParser.CheckHint(Element: TPasElement; ExpectSemiColon: Boolean
  887. ): TPasMemberHints;
  888. Var
  889. Found : Boolean;
  890. h : TPasMemberHint;
  891. begin
  892. Result:=[];
  893. Repeat
  894. NextToken;
  895. Found:=IsCurTokenHint(h);
  896. If Found then
  897. begin
  898. Include(Result,h);
  899. if (h=hDeprecated) then
  900. begin
  901. NextToken;
  902. if (Curtoken<>tkString) then
  903. UnGetToken
  904. else if assigned(Element) then
  905. Element.HintMessage:=CurTokenString;
  906. end;
  907. end;
  908. Until Not Found;
  909. UnGetToken;
  910. If Assigned(Element) then
  911. Element.Hints:=Result;
  912. if ExpectSemiColon then
  913. ExpectToken(tkSemiColon);
  914. end;
  915. function TPasParser.CheckPackMode: TPackMode;
  916. begin
  917. NextToken;
  918. Case CurToken of
  919. tkPacked : Result:=pmPacked;
  920. tkbitpacked : Result:=pmBitPacked;
  921. else
  922. result:=pmNone;
  923. end;
  924. if (Result<>pmNone) then
  925. begin
  926. NextToken;
  927. if Not (CurToken in [tkArray, tkRecord, tkObject, tkClass, tkSet]) then
  928. ParseExcTokenError('SET, ARRAY, RECORD, OBJECT or CLASS');
  929. end;
  930. end;
  931. Function IsSimpleTypeToken(Var AName : String) : Boolean;
  932. Const
  933. SimpleTypeCount = 15;
  934. SimpleTypeNames : Array[1..SimpleTypeCount] of string =
  935. ('byte','boolean','char','integer','int64','longint','longword','double',
  936. 'shortint','smallint','string','word','qword','cardinal','widechar');
  937. SimpleTypeCaseNames : Array[1..SimpleTypeCount] of string =
  938. ('Byte','Boolean','Char','Integer','Int64','LongInt','LongWord','Double',
  939. 'ShortInt','SmallInt','String','Word','QWord','Cardinal','WideChar');
  940. Var
  941. S : String;
  942. I : Integer;
  943. begin
  944. S:=LowerCase(AName);
  945. I:=SimpleTypeCount;
  946. While (I>0) and (s<>SimpleTypeNames[i]) do
  947. Dec(I);
  948. Result:=(I>0);
  949. if Result Then
  950. AName:=SimpleTypeCaseNames[I];
  951. end;
  952. function TPasParser.ParseStringType(Parent: TPasElement;
  953. const NamePos: TPasSourcePos; const TypeName: String): TPasAliasType;
  954. Var
  955. S : String;
  956. ok: Boolean;
  957. begin
  958. Result := TPasAliasType(CreateElement(TPasAliasType, TypeName, Parent, NamePos));
  959. ok:=false;
  960. try
  961. If (Result.Name='') then
  962. Result.Name:='string';
  963. NextToken;
  964. if CurToken=tkSquaredBraceOpen then
  965. begin
  966. S:='';
  967. NextToken;
  968. While Not (Curtoken in [tkSquaredBraceClose,tkEOF]) do
  969. begin
  970. S:=S+CurTokenString;
  971. NextToken;
  972. end;
  973. end
  974. else
  975. UngetToken;
  976. Result.DestType:=TPasStringType(CreateElement(TPasStringType,'string',Parent));
  977. TPasStringType(Result.DestType).LengthExpr:=S;
  978. ok:=true;
  979. finally
  980. if not ok then
  981. Result.Release;
  982. end;
  983. end;
  984. function TPasParser.ParseSimpleType(Parent: TPasElement;
  985. const NamePos: TPasSourcePos; const TypeName: String; IsFull: Boolean
  986. ): TPasType;
  987. Type
  988. TSimpleTypeKind = (stkAlias,stkString,stkRange,stkSpecialize);
  989. Var
  990. Ref: TPasElement;
  991. K : TSimpleTypeKind;
  992. Name : String;
  993. SS : Boolean;
  994. CT : TPasClassType;
  995. begin
  996. Name := CurTokenString;
  997. NextToken;
  998. while CurToken=tkDot do
  999. begin
  1000. ExpectIdentifier;
  1001. Name := Name+'.'+CurTokenString;
  1002. NextToken;
  1003. end;
  1004. // Current token is first token after identifier.
  1005. if IsFull then
  1006. begin
  1007. if (CurToken=tkSemicolon) or isCurTokenHint then // Type A = B;
  1008. K:=stkAlias
  1009. else if (CurToken=tkSquaredBraceOpen) then
  1010. begin
  1011. // Todo: check via resolver
  1012. if ((LowerCase(Name)='string') or (LowerCase(Name)='ansistring')) then // Type A = String[12];
  1013. K:=stkString
  1014. else
  1015. ParseExcSyntaxError;
  1016. end
  1017. else if (CurToken in [tkBraceOpen,tkDotDot]) then // Type A = B..C;
  1018. K:=stkRange
  1019. else if (CurToken = tkLessThan) then // A = B<t>;
  1020. K:=stkSpecialize
  1021. else
  1022. ParseExcTokenError(';');
  1023. UnGetToken;
  1024. end
  1025. else if (CurToken = tkLessThan) then // A = B<t>;
  1026. begin
  1027. K:=stkSpecialize;
  1028. UnGetToken;
  1029. end
  1030. else if (CurToken in [tkBraceOpen,tkDotDot]) then // A: B..C;
  1031. begin
  1032. K:=stkRange;
  1033. UnGetToken;
  1034. end
  1035. else
  1036. begin
  1037. UnGetToken;
  1038. K:=stkAlias;
  1039. if (not (po_resolvestandardtypes in Options)) and (LowerCase(Name)='string') then
  1040. K:=stkString;
  1041. end;
  1042. Case K of
  1043. stkString:
  1044. begin
  1045. Result:=ParseStringType(Parent,NamePos,TypeName);
  1046. end;
  1047. stkSpecialize:
  1048. begin
  1049. CT := TPasClassType(CreateElement(TPasClassType, TypeName, Parent, Scanner.CurSourcePos));
  1050. try
  1051. CT.ObjKind := okSpecialize;
  1052. CT.AncestorType := TPasUnresolvedTypeRef.Create(Name,Parent);
  1053. CT.IsShortDefinition:=True;
  1054. ReadGenericArguments(CT.GenericTemplateTypes,CT);
  1055. Result:=CT;
  1056. CT:=Nil;
  1057. Finally
  1058. FreeAndNil(CT);
  1059. end;
  1060. end;
  1061. stkRange:
  1062. begin
  1063. UnGetToken;
  1064. Result:=ParseRangeType(Parent,NamePos,TypeName,False);
  1065. end;
  1066. stkAlias:
  1067. begin
  1068. Ref:=Nil;
  1069. SS:=(not (po_resolvestandardtypes in FOptions)) and isSimpleTypeToken(Name);
  1070. if not SS then
  1071. begin
  1072. Ref:=Engine.FindElement(Name);
  1073. if Ref=nil then
  1074. begin
  1075. {$IFDEF VerbosePasResolver}
  1076. if po_resolvestandardtypes in FOptions then
  1077. begin
  1078. writeln('ERROR: TPasParser.ParseSimpleType resolver failed to raise an error');
  1079. ParseExcExpectedIdentifier;
  1080. end;
  1081. {$ENDIF}
  1082. end
  1083. else if not (Ref is TPasType) then
  1084. ParseExc(nParserExpectedTypeButGot,SParserExpectedTypeButGot,[Ref.ElementTypeName]);
  1085. end;
  1086. if (Ref=Nil) then
  1087. Ref:=TPasUnresolvedTypeRef(CreateElement(TPasUnresolvedTypeRef,Name,Parent))
  1088. else
  1089. Ref.AddRef;
  1090. if isFull then
  1091. begin
  1092. Result := TPasAliasType(CreateElement(TPasAliasType, TypeName, Parent, NamePos));
  1093. TPasAliasType(Result).DestType:=Ref as TPasType;
  1094. end
  1095. else
  1096. Result:=Ref as TPasType
  1097. end;
  1098. end;
  1099. end;
  1100. // On entry, we're on the TYPE token
  1101. function TPasParser.ParseAliasType(Parent: TPasElement;
  1102. const NamePos: TPasSourcePos; const TypeName: String): TPasTypeAliasType;
  1103. var
  1104. ok: Boolean;
  1105. begin
  1106. Result := TPasTypeAliasType(CreateElement(TPasTypeAliasType, TypeName, Parent, NamePos));
  1107. ok:=false;
  1108. try
  1109. Result.DestType := ParseType(Result,NamePos,'');
  1110. ok:=true;
  1111. finally
  1112. if not ok then
  1113. Result.Release;
  1114. end;
  1115. end;
  1116. function TPasParser.ParsePointerType(Parent: TPasElement;
  1117. const NamePos: TPasSourcePos; const TypeName: String): TPasPointerType;
  1118. var
  1119. ok: Boolean;
  1120. begin
  1121. Result := TPasPointerType(CreateElement(TPasPointerType, TypeName, Parent, NamePos));
  1122. ok:=false;
  1123. Try
  1124. TPasPointerType(Result).DestType := ParseType(Result,Scanner.CurSourcePos);
  1125. ok:=true;
  1126. finally
  1127. if not ok then
  1128. Result.Release;
  1129. end;
  1130. end;
  1131. function TPasParser.ParseEnumType(Parent: TPasElement;
  1132. const NamePos: TPasSourcePos; const TypeName: String): TPasEnumType;
  1133. Var
  1134. EnumValue: TPasEnumValue;
  1135. ok: Boolean;
  1136. begin
  1137. Result := TPasEnumType(CreateElement(TPasEnumType, TypeName, Parent, NamePos));
  1138. ok:=false;
  1139. try
  1140. while True do
  1141. begin
  1142. NextToken;
  1143. SaveComments;
  1144. EnumValue := TPasEnumValue(CreateElement(TPasEnumValue, CurTokenString, Result));
  1145. Result.Values.Add(EnumValue);
  1146. NextToken;
  1147. if CurToken = tkBraceClose then
  1148. break
  1149. else if CurToken in [tkEqual,tkAssign] then
  1150. begin
  1151. NextToken;
  1152. EnumValue.Value:=DoParseExpression(Result);
  1153. // UngetToken;
  1154. if CurToken = tkBraceClose then
  1155. Break
  1156. else if not (CurToken=tkComma) then
  1157. ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
  1158. end
  1159. else if not (CurToken=tkComma) then
  1160. ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket)
  1161. end;
  1162. ok:=true;
  1163. finally
  1164. if not ok then
  1165. Result.Release;
  1166. end;
  1167. Engine.FinishScope(stTypeDef,Result);
  1168. end;
  1169. function TPasParser.ParseSetType(Parent: TPasElement;
  1170. const NamePos: TPasSourcePos; const TypeName: String; AIsPacked : Boolean = False): TPasSetType;
  1171. var
  1172. ok: Boolean;
  1173. begin
  1174. Result := TPasSetType(CreateElement(TPasSetType, TypeName, Parent, NamePos));
  1175. Result.IsPacked:=AIsPacked;
  1176. ok:=false;
  1177. try
  1178. ExpectToken(tkOf);
  1179. Result.EnumType := ParseType(Result,Scanner.CurSourcePos);
  1180. ok:=true;
  1181. finally
  1182. if not ok then
  1183. Result.Release;
  1184. end;
  1185. Engine.FinishScope(stTypeDef,Result);
  1186. end;
  1187. function TPasParser.ParseType(Parent: TPasElement;
  1188. const NamePos: TPasSourcePos; const TypeName: String = ''; Full: Boolean = false; GenericArgs : TFPList = Nil
  1189. ): TPasType;
  1190. Const
  1191. // These types are allowed only when full type declarations
  1192. FullTypeTokens = [tkGeneric,{tkSpecialize,}tkClass,tkInterface,tkDispInterface,tkType];
  1193. // Parsing of these types already takes care of hints
  1194. NoHintTokens = [tkProcedure,tkFunction];
  1195. var
  1196. PM : TPackMode;
  1197. CH , isHelper,ok: Boolean; // Check hint ?
  1198. begin
  1199. Result := nil;
  1200. // NextToken and check pack mode
  1201. Pm:=CheckPackMode;
  1202. if Full then
  1203. CH:=Not (CurToken in NoHintTokens)
  1204. else
  1205. begin
  1206. CH:=False;
  1207. if (CurToken in FullTypeTokens) then
  1208. ParseExc(nParserTypeNotAllowedHere,SParserTypeNotAllowedHere,[CurtokenText]);
  1209. end;
  1210. ok:=false;
  1211. Try
  1212. case CurToken of
  1213. // types only allowed when full
  1214. tkObject: Result := ParseClassDecl(Parent, NamePos, TypeName, okObject,PM);
  1215. tkDispInterface:
  1216. Result := ParseClassDecl(Parent, NamePos, TypeName, okDispInterface);
  1217. tkInterface:
  1218. Result := ParseClassDecl(Parent, NamePos, TypeName, okInterface);
  1219. tkSpecialize: Result:=ParseSpecializeType(Parent,TypeName);
  1220. tkClass: Result := ParseClassDecl(Parent, NamePos, TypeName, okClass, PM, GenericArgs);
  1221. tkType:
  1222. begin
  1223. NextToken;
  1224. isHelper:=CurTokenIsIdentifier('helper');
  1225. UnGetToken;
  1226. if isHelper then
  1227. Result:=ParseClassDecl(Parent,NamePos,TypeName,okTypeHelper,PM)
  1228. else
  1229. Result:=ParseAliasType(Parent,NamePos,TypeName);
  1230. end;
  1231. // Always allowed
  1232. tkIdentifier:
  1233. begin
  1234. if CurTokenIsIdentifier('reference') then
  1235. begin
  1236. CH:=False;
  1237. Result:=ParseReferencetoProcedureType(Parent,NamePos,TypeName)
  1238. end
  1239. else
  1240. Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
  1241. end;
  1242. tkCaret: Result:=ParsePointerType(Parent,NamePos,TypeName);
  1243. tkFile: Result:=ParseFileType(Parent,NamePos,TypeName);
  1244. tkArray: Result:=ParseArrayType(Parent,NamePos,TypeName,pm);
  1245. tkBraceOpen: Result:=ParseEnumType(Parent,NamePos,TypeName);
  1246. tkSet: Result:=ParseSetType(Parent,NamePos,TypeName,pm=pmPacked);
  1247. tkProcedure: Result:=ParseProcedureType(Parent,NamePos,TypeName,ptProcedure);
  1248. tkFunction: Result:=ParseProcedureType(Parent,NamePos,TypeName,ptFunction);
  1249. tkRecord:
  1250. begin
  1251. NextToken;
  1252. if CurTokenIsIdentifier('Helper') then
  1253. begin
  1254. UnGetToken;
  1255. Result:=ParseClassDecl(Parent,NamePos,TypeName,okRecordHelper,PM);
  1256. end
  1257. else
  1258. begin
  1259. UnGetToken;
  1260. Result := ParseRecordDecl(Parent,NamePos,TypeName,PM);
  1261. end;
  1262. end;
  1263. tkNumber,tkMinus,tkChar:
  1264. begin
  1265. UngetToken;
  1266. Result:=ParseRangeType(Parent,NamePos,TypeName,Full);
  1267. end;
  1268. else
  1269. ParseExcExpectedIdentifier;
  1270. end;
  1271. if CH then
  1272. CheckHint(Result,True);
  1273. ok:=true;
  1274. finally
  1275. if not ok then
  1276. if Result<>nil then
  1277. Result.Release;
  1278. end;
  1279. end;
  1280. function TPasParser.ParseReferenceToProcedureType(Parent: TPasElement; const NamePos: TPasSourcePos; const TypeName: String
  1281. ): TPasProcedureType;
  1282. begin
  1283. if not CurTokenIsIdentifier('reference') then
  1284. ParseExcTokenError('reference');
  1285. ExpectToken(tkTo);
  1286. NextToken;
  1287. Case CurToken of
  1288. tkprocedure : Result:=ParseProcedureType(Parent,NamePos,TypeName,ptProcedure);
  1289. tkfunction : Result:=ParseProcedureType(Parent,NamePos,TypeName,ptFunction);
  1290. else
  1291. ParseExcTokenError('procedure or function');
  1292. end;
  1293. Result.IsReferenceTo:=True;
  1294. end;
  1295. function TPasParser.ParseComplexType(Parent : TPasElement = Nil): TPasType;
  1296. begin
  1297. NextToken;
  1298. case CurToken of
  1299. tkProcedure:
  1300. begin
  1301. Result := TPasProcedureType(CreateElement(TPasProcedureType, '', Parent));
  1302. ParseProcedureOrFunctionHeader(Result, TPasProcedureType(Result), ptProcedure, True);
  1303. if CurToken = tkSemicolon then
  1304. UngetToken; // Unget semicolon
  1305. end;
  1306. tkFunction:
  1307. begin
  1308. Result := CreateFunctionType('', 'Result', Parent, False, Scanner.CurSourcePos);
  1309. ParseProcedureOrFunctionHeader(Result, TPasFunctionType(Result), ptFunction, True);
  1310. if CurToken = tkSemicolon then
  1311. UngetToken; // Unget semicolon
  1312. end;
  1313. else
  1314. UngetToken;
  1315. Result := ParseType(Parent,Scanner.CurSourcePos);
  1316. end;
  1317. end;
  1318. function TPasParser.ParseArrayType(Parent: TPasElement;
  1319. const NamePos: TPasSourcePos; const TypeName: String; PackMode: TPackMode
  1320. ): TPasArrayType;
  1321. Var
  1322. S : String;
  1323. ok: Boolean;
  1324. RangeExpr: TPasExpr;
  1325. begin
  1326. Result := TPasArrayType(CreateElement(TPasArrayType, TypeName, Parent, NamePos));
  1327. ok:=false;
  1328. try
  1329. Result.PackMode:=PackMode;
  1330. NextToken;
  1331. S:='';
  1332. case CurToken of
  1333. tkSquaredBraceOpen:
  1334. begin
  1335. repeat
  1336. NextToken;
  1337. if po_arrayrangeexpr in Options then
  1338. begin
  1339. RangeExpr:=DoParseExpression(Result);
  1340. Result.AddRange(RangeExpr);
  1341. end
  1342. else if CurToken<>tkSquaredBraceClose then
  1343. S:=S+CurTokenText;
  1344. if CurToken=tkSquaredBraceClose then
  1345. break
  1346. else if CurToken=tkComma then
  1347. continue
  1348. else if po_arrayrangeexpr in Options then
  1349. ParseExcTokenError(']');
  1350. until false;
  1351. Result.IndexRange:=S;
  1352. ExpectToken(tkOf);
  1353. Result.ElType := ParseType(Result,Scanner.CurSourcePos);
  1354. end;
  1355. tkOf:
  1356. begin
  1357. NextToken;
  1358. if CurToken = tkConst then
  1359. else
  1360. begin
  1361. UngetToken;
  1362. Result.ElType := ParseType(Result,Scanner.CurSourcePos);
  1363. end
  1364. end
  1365. else
  1366. ParseExc(nParserArrayTypeSyntaxError,SParserArrayTypeSyntaxError);
  1367. end;
  1368. ok:=true;
  1369. finally
  1370. if not ok then
  1371. Result.Release;
  1372. end;
  1373. Engine.FinishScope(stTypeDef,Result);
  1374. end;
  1375. function TPasParser.ParseFileType(Parent: TPasElement;
  1376. const NamePos: TPasSourcePos; const TypeName: String): TPasFileType;
  1377. begin
  1378. Result:=TPasFileType(CreateElement(TPasFileType, TypeName, Parent, NamePos));
  1379. NextToken;
  1380. If CurToken=tkOf then
  1381. Result.ElType := ParseType(Result,Scanner.CurSourcePos)
  1382. else
  1383. ungettoken;
  1384. end;
  1385. function TPasParser.isEndOfExp(AllowEqual : Boolean = False):Boolean;
  1386. const
  1387. EndExprToken = [
  1388. tkEOF, tkBraceClose, tkSquaredBraceClose, tkSemicolon, tkComma, tkColon,
  1389. tkdo, tkdownto, tkelse, tkend, tkof, tkthen, tkto
  1390. ];
  1391. begin
  1392. Result:=(CurToken in EndExprToken) or IsCurTokenHint;
  1393. if Not (Result or AllowEqual) then
  1394. Result:=(Curtoken=tkEqual);
  1395. end;
  1396. function TPasParser.ParseParams(AParent: TPasElement; paramskind: TPasExprKind;
  1397. AllowFormatting: Boolean = False): TParamsExpr;
  1398. var
  1399. params : TParamsExpr;
  1400. p : TPasExpr;
  1401. PClose : TToken;
  1402. begin
  1403. Result:=nil;
  1404. if paramskind in [pekArrayParams, pekSet] then begin
  1405. if CurToken<>tkSquaredBraceOpen then
  1406. ParseExc(nParserExpectTokenError,SParserExpectTokenError,['[']);
  1407. PClose:=tkSquaredBraceClose;
  1408. end else begin
  1409. if CurToken<>tkBraceOpen then
  1410. ParseExc(nParserExpectTokenError,SParserExpectTokenError,['(']);
  1411. PClose:=tkBraceClose;
  1412. end;
  1413. params:=TParamsExpr(CreateElement(TParamsExpr,'',AParent));
  1414. try
  1415. params.Kind:=paramskind;
  1416. NextToken;
  1417. if not isEndOfExp then begin
  1418. repeat
  1419. p:=DoParseExpression(params);
  1420. if not Assigned(p) then
  1421. ParseExcSyntaxError;
  1422. params.AddParam(p);
  1423. if (CurToken=tkColon) then
  1424. if Not AllowFormatting then
  1425. ParseExc(nParserExpectTokenError,SParserExpectTokenError,[','])
  1426. else
  1427. begin
  1428. NextToken;
  1429. p.format1:=DoParseExpression(p);
  1430. if (CurToken=tkColon) then
  1431. begin
  1432. NextToken;
  1433. p.format2:=DoParseExpression(p);
  1434. end;
  1435. end;
  1436. if not (CurToken in [tkComma, PClose]) then
  1437. ParseExc(nParserExpectTokenError,SParserExpectTokenError,[',']);
  1438. if CurToken = tkComma then begin
  1439. NextToken;
  1440. if CurToken = PClose then begin
  1441. //ErrorExpected(parser, 'identifier');
  1442. ParseExcSyntaxError;
  1443. end;
  1444. end;
  1445. until CurToken=PClose;
  1446. end;
  1447. NextToken;
  1448. Result:=params;
  1449. finally
  1450. if not Assigned(Result) then params.Release;
  1451. end;
  1452. end;
  1453. function TPasParser.TokenToExprOp(AToken: TToken): TExprOpCode;
  1454. begin
  1455. Case AToken of
  1456. tkMul : Result:=eopMultiply;
  1457. tkPlus : Result:=eopAdd;
  1458. tkMinus : Result:=eopSubtract;
  1459. tkDivision : Result:=eopDivide;
  1460. tkLessThan : Result:=eopLessThan;
  1461. tkEqual : Result:=eopEqual;
  1462. tkGreaterThan : Result:=eopGreaterThan;
  1463. tkAt : Result:=eopAddress;
  1464. tkNotEqual : Result:=eopNotEqual;
  1465. tkLessEqualThan : Result:=eopLessthanEqual;
  1466. tkGreaterEqualThan : Result:=eopGreaterThanEqual;
  1467. tkPower : Result:=eopPower;
  1468. tkSymmetricalDifference : Result:=eopSymmetricalDifference;
  1469. tkIs : Result:=eopIs;
  1470. tkAs : Result:=eopAs;
  1471. tkSHR : Result:=eopSHR;
  1472. tkSHL : Result:=eopSHL;
  1473. tkAnd : Result:=eopAnd;
  1474. tkOr : Result:=eopOR;
  1475. tkXor : Result:=eopXOR;
  1476. tkMod : Result:=eopMod;
  1477. tkDiv : Result:=eopDiv;
  1478. tkNot : Result:=eopNot;
  1479. tkIn : Result:=eopIn;
  1480. tkDot : Result:=eopSubIdent;
  1481. tkCaret : Result:=eopDeref;
  1482. else
  1483. ParseExc(nParserNotAnOperand,SParserNotAnOperand,[AToken,TokenInfos[AToken]]);
  1484. end;
  1485. end;
  1486. function TPasParser.ParseExpIdent(AParent: TPasElement): TPasExpr;
  1487. Function IsWriteOrstr(P : TPasExpr) : boolean;
  1488. Var
  1489. N : String;
  1490. begin
  1491. Result:=P is TPrimitiveExpr;
  1492. if Result then
  1493. begin
  1494. N:=LowerCase(TPrimitiveExpr(P).Value);
  1495. // We should actually resolve this to system.NNN
  1496. Result:=(N='write') or (N='str') or (N='writeln');
  1497. end;
  1498. end;
  1499. Procedure HandleSelf(Var Last: TPasExpr);
  1500. Var
  1501. b : TBinaryExpr;
  1502. optk : TToken;
  1503. begin
  1504. NextToken;
  1505. if CurToken = tkDot then
  1506. begin // self.Write(EscapeText(AText));
  1507. optk:=CurToken;
  1508. NextToken;
  1509. b:=CreateBinaryExpr(AParent,Last, ParseExpIdent(AParent), TokenToExprOp(optk));
  1510. if not Assigned(b.right) then
  1511. begin
  1512. b.Release;
  1513. ParseExcExpectedIdentifier;
  1514. end;
  1515. Last:=b;
  1516. end;
  1517. UngetToken;
  1518. end;
  1519. var
  1520. Last,func, Expr: TPasExpr;
  1521. prm : TParamsExpr;
  1522. b : TBinaryExpr;
  1523. optk : TToken;
  1524. ok: Boolean;
  1525. begin
  1526. Result:=nil;
  1527. case CurToken of
  1528. tkString: Last:=CreatePrimitiveExpr(AParent,pekString,CurTokenString);
  1529. tkChar: Last:=CreatePrimitiveExpr(AParent,pekString, CurTokenText);
  1530. tkNumber: Last:=CreatePrimitiveExpr(AParent,pekNumber, CurTokenString);
  1531. tkIdentifier:
  1532. begin
  1533. if CompareText(CurTokenText,'self')=0 then
  1534. begin
  1535. Last:=CreateSelfExpr(AParent);
  1536. HandleSelf(Last)
  1537. end
  1538. Else
  1539. Last:=CreatePrimitiveExpr(AParent,pekIdent, CurTokenText)
  1540. end;
  1541. tkfalse, tktrue: Last:=CreateBoolConstExpr(Aparent,pekBoolConst, CurToken=tktrue);
  1542. tknil: Last:=CreateNilExpr(AParent);
  1543. tkSquaredBraceOpen: Last:=ParseParams(AParent,pekSet);
  1544. tkinherited:
  1545. begin
  1546. //inherited; inherited function
  1547. Last:=CreateInheritedExpr(AParent);
  1548. NextToken;
  1549. if (CurToken=tkIdentifier) then
  1550. begin
  1551. b:=CreateBinaryExpr(AParent,Last, DoParseExpression(AParent), eopNone);
  1552. if not Assigned(b.right) then
  1553. begin
  1554. b.Release;
  1555. ParseExcExpectedIdentifier;
  1556. end;
  1557. Last:=b;
  1558. end;
  1559. UngetToken;
  1560. end;
  1561. tkself:
  1562. begin
  1563. Last:=CreateSelfExpr(AParent);
  1564. HandleSelf(Last);
  1565. end;
  1566. tkAt:
  1567. begin
  1568. // P:=@function;
  1569. NextToken;
  1570. if (length(CurTokenText)=0) or not (CurTokenText[1] in ['A'..'_']) then
  1571. begin
  1572. UngetToken;
  1573. ParseExcExpectedIdentifier;
  1574. end;
  1575. Last:=CreatePrimitiveExpr(AParent,pekString, '@'+CurTokenText);
  1576. end;
  1577. tkCaret:
  1578. begin
  1579. // ^A..^_ characters. See #16341
  1580. NextToken;
  1581. if not (length(CurTokenText)=1) or not (CurTokenText[1] in ['A'..'_']) then
  1582. begin
  1583. UngetToken;
  1584. ParseExcExpectedIdentifier;
  1585. end;
  1586. Last:=CreatePrimitiveExpr(AParent,pekString, '^'+CurTokenText);
  1587. end;
  1588. else
  1589. ParseExcExpectedIdentifier;
  1590. end;
  1591. Result:=Last;
  1592. func:=Last;
  1593. if Last.Kind<>pekSet then NextToken;
  1594. ok:=false;
  1595. try
  1596. if Last.Kind in [pekIdent,pekSelf] then
  1597. begin
  1598. while CurToken in [tkDot] do
  1599. begin
  1600. NextToken;
  1601. if CurToken in [tkIdentifier,tktrue,tkfalse] then // true and false are also identifiers
  1602. begin
  1603. expr:=CreatePrimitiveExpr(AParent,pekIdent,CurTokenString);
  1604. AddToBinaryExprChain(Result,expr,eopSubIdent);
  1605. func:=expr;
  1606. NextToken;
  1607. end
  1608. else
  1609. begin
  1610. UngetToken;
  1611. ParseExcExpectedIdentifier;
  1612. end;
  1613. end;
  1614. repeat
  1615. case CurToken of
  1616. tkBraceOpen,tkSquaredBraceOpen:
  1617. begin
  1618. if CurToken=tkBraceOpen then
  1619. prm:=ParseParams(AParent,pekFuncParams,isWriteOrStr(func))
  1620. else
  1621. prm:=ParseParams(AParent,pekArrayParams);
  1622. if not Assigned(prm) then Exit;
  1623. AddParamsToBinaryExprChain(Result,prm);
  1624. end;
  1625. tkCaret:
  1626. begin
  1627. Result:=CreateUnaryExpr(AParent,Result,TokenToExprOp(CurToken));
  1628. NextToken;
  1629. end;
  1630. else
  1631. break;
  1632. end;
  1633. until false;
  1634. // Needed for TSDOBaseDataObjectClass(Self.ClassType).Create
  1635. if CurToken in [tkDot,tkas] then
  1636. begin
  1637. optk:=CurToken;
  1638. NextToken;
  1639. Expr:=ParseExpIdent(AParent);
  1640. if Expr=nil then
  1641. ParseExcExpectedIdentifier;
  1642. if optk=tkDot then
  1643. AddToBinaryExprChain(Result,Expr,TokenToExprOp(optk))
  1644. else
  1645. begin
  1646. // a as b
  1647. Result:=CreateBinaryExpr(AParent,Result,Expr,TokenToExprOp(tkas));
  1648. end;
  1649. end;
  1650. end;
  1651. ok:=true;
  1652. finally
  1653. if not ok then
  1654. Result.Release;
  1655. end;
  1656. end;
  1657. function TPasParser.OpLevel(t: TToken): Integer;
  1658. begin
  1659. case t of
  1660. // tkDot:
  1661. // Result:=5;
  1662. tknot,tkAt:
  1663. Result:=4;
  1664. tkMul, tkDivision, tkdiv, tkmod, tkand, tkShl,tkShr, tkas, tkPower :
  1665. Result:=3;
  1666. tkPlus, tkMinus, tkor, tkxor:
  1667. Result:=2;
  1668. tkEqual, tkNotEqual, tkLessThan, tkLessEqualThan, tkGreaterThan, tkGreaterEqualThan, tkin, tkis:
  1669. Result:=1;
  1670. else
  1671. Result:=0;
  1672. end;
  1673. end;
  1674. function TPasParser.DoParseExpression(AParent : TPaselement;InitExpr: TPasExpr; AllowEqual : Boolean = True): TPasExpr;
  1675. var
  1676. expstack : TFPList;
  1677. opstack : array of TToken;
  1678. opstackTop: integer;
  1679. pcount : Integer;
  1680. x : TPasExpr;
  1681. i : Integer;
  1682. tempop : TToken;
  1683. NotBinary : Boolean;
  1684. const
  1685. PrefixSym = [tkPlus, tkMinus, tknot, tkAt]; // + - not @
  1686. BinaryOP = [tkMul, tkDivision, tkdiv, tkmod, tkDotDot,
  1687. tkand, tkShl,tkShr, tkas, tkPower,
  1688. tkPlus, tkMinus, tkor, tkxor, tkSymmetricalDifference,
  1689. tkEqual, tkNotEqual, tkLessThan, tkLessEqualThan,
  1690. tkGreaterThan, tkGreaterEqualThan, tkin, tkis];
  1691. function PopExp: TPasExpr; inline;
  1692. begin
  1693. if expstack.Count>0 then begin
  1694. Result:=TPasExpr(expstack[expstack.Count-1]);
  1695. expstack.Delete(expstack.Count-1);
  1696. end else
  1697. Result:=nil;
  1698. end;
  1699. procedure PushOper(token: TToken); inline;
  1700. begin
  1701. inc(opstackTop);
  1702. if opstackTop=length(opstack) then
  1703. SetLength(opstack,length(opstack)*2+4);
  1704. opstack[opstackTop]:=token;
  1705. end;
  1706. function PeekOper: TToken; inline;
  1707. begin
  1708. if opstackTop>=0 then Result:=opstack[opstackTop]
  1709. else Result:=tkEOF;
  1710. end;
  1711. function PopOper: TToken; inline;
  1712. begin
  1713. Result:=PeekOper;
  1714. if Result<>tkEOF then dec(opstackTop);
  1715. end;
  1716. procedure PopAndPushOperator;
  1717. var
  1718. t : TToken;
  1719. xright : TPasExpr;
  1720. xleft : TPasExpr;
  1721. bin : TBinaryExpr;
  1722. begin
  1723. t:=PopOper;
  1724. xright:=PopExp;
  1725. xleft:=PopExp;
  1726. if t=tkDotDot then
  1727. begin
  1728. bin:=CreateBinaryExpr(AParent,xleft,xright,eopNone);
  1729. bin.Kind:=pekRange;
  1730. end
  1731. else
  1732. bin:=CreateBinaryExpr(AParent,xleft,xright,TokenToExprOp(t));
  1733. expstack.Add(bin);
  1734. end;
  1735. Var
  1736. AllowedBinaryOps : Set of TToken;
  1737. begin
  1738. AllowedBinaryOps:=BinaryOP;
  1739. if Not AllowEqual then
  1740. Exclude(AllowedBinaryOps,tkEqual);
  1741. //DumpCurToken('Entry',iaIndent);
  1742. Result:=nil;
  1743. expstack := TFPList.Create;
  1744. SetLength(opstack,4);
  1745. opstackTop:=-1;
  1746. try
  1747. repeat
  1748. NotBinary:=True;
  1749. pcount:=0;
  1750. if not Assigned(InitExpr) then
  1751. begin
  1752. // the first part of the expression has been parsed externally.
  1753. // this is used by Constant Expression parser (CEP) parsing only,
  1754. // whenever it makes a false assuming on constant expression type.
  1755. // i.e: SI_PAD_SIZE = ((128/sizeof(longint)) - 3);
  1756. //
  1757. // CEP assumes that it's array or record, because the expression
  1758. // starts with "(". After the first part is parsed, the CEP meets "-"
  1759. // that assures, it's not an array expression. The CEP should give the
  1760. // first part back to the expression parser, to get the correct
  1761. // token tree according to the operations priority.
  1762. //
  1763. // quite ugly. type information is required for CEP to work clean
  1764. while CurToken in PrefixSym do
  1765. begin
  1766. PushOper(CurToken);
  1767. inc(pcount);
  1768. NextToken;
  1769. end;
  1770. if (CurToken = tkBraceOpen) then
  1771. begin
  1772. NextToken;
  1773. x:=DoParseExpression(AParent);
  1774. if (CurToken<>tkBraceClose) then
  1775. begin
  1776. x.Release;
  1777. CheckToken(tkBraceClose);
  1778. end;
  1779. NextToken;
  1780. // for expressions like (ppdouble)^^;
  1781. while (x<>Nil) and (CurToken=tkCaret) do
  1782. begin
  1783. NextToken;
  1784. x:=CreateUnaryExpr(AParent,x, TokenToExprOp(tkCaret));
  1785. end;
  1786. // for expressions like (TObject(m)).Free;
  1787. if (x<>Nil) and (CurToken=tkDot) then
  1788. begin
  1789. NextToken;
  1790. x:=CreateBinaryExpr(AParent,x, ParseExpIdent(AParent), TokenToExprOp(tkDot));
  1791. end;
  1792. end
  1793. else
  1794. begin
  1795. x:=ParseExpIdent(AParent);
  1796. end;
  1797. if not Assigned(x) then
  1798. ParseExcSyntaxError;
  1799. expstack.Add(x);
  1800. for i:=1 to pcount do
  1801. begin
  1802. tempop:=PopOper;
  1803. x:=popexp;
  1804. if (tempop=tkMinus) and (x.Kind=pekRange) then
  1805. begin
  1806. TBinaryExpr(x).Left:=CreateUnaryExpr(x, TBinaryExpr(x).left, eopSubtract);
  1807. expstack.Add(x);
  1808. end
  1809. else
  1810. expstack.Add(CreateUnaryExpr(AParent, x, TokenToExprOp(tempop) ));
  1811. end;
  1812. end
  1813. else
  1814. begin
  1815. expstack.Add(InitExpr);
  1816. InitExpr:=nil;
  1817. end;
  1818. if (CurToken in AllowedBinaryOPs) then
  1819. begin
  1820. // Adjusting order of the operations
  1821. NotBinary:=False;
  1822. tempop:=PeekOper;
  1823. while (opstackTop>=0) and (OpLevel(tempop)>=OpLevel(CurToken)) do begin
  1824. PopAndPushOperator;
  1825. tempop:=PeekOper;
  1826. end;
  1827. PushOper(CurToken);
  1828. NextToken;
  1829. end;
  1830. //Writeln('Bin ',NotBinary ,' or EOE ',isEndOfExp, ' Ex ',Assigned(x),' stack ',ExpStack.Count);
  1831. until NotBinary or isEndOfExp(AllowEqual);
  1832. if not NotBinary then ParseExcExpectedIdentifier;
  1833. while opstackTop>=0 do PopAndPushOperator;
  1834. // only 1 expression should be on the stack, at the end of the correct expression
  1835. if expstack.Count<>1 then
  1836. ParseExcSyntaxError;
  1837. if expstack.Count=1 then
  1838. begin
  1839. Result:=TPasExpr(expstack[0]);
  1840. Result.Parent:=AParent;
  1841. end;
  1842. finally
  1843. {if Not Assigned(Result) then
  1844. DumpCurToken('Exiting (no result)',iaUndent)
  1845. else
  1846. DumpCurtoken('Exiting (Result: "'+Result.GetDeclaration(true)+'") ',iaUndent);}
  1847. if not Assigned(Result) then begin
  1848. // expression error!
  1849. for i:=0 to expstack.Count-1 do
  1850. TPasExpr(expstack[i]).Release;
  1851. end;
  1852. SetLength(opstack,0);
  1853. expstack.Free;
  1854. end;
  1855. end;
  1856. function GetExprIdent(p: TPasExpr): String;
  1857. begin
  1858. Result:='';
  1859. if not Assigned(p) then exit;
  1860. if (p.ClassType=TPrimitiveExpr) and (p.Kind=pekIdent) then
  1861. Result:=TPrimitiveExpr(p).Value
  1862. else if (p.ClassType=TSelfExpr) then
  1863. Result:='Self';
  1864. end;
  1865. function TPasParser.DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
  1866. var
  1867. x : TPasExpr;
  1868. n : AnsiString;
  1869. r : TRecordValues;
  1870. a : TArrayValues;
  1871. function lastfield:boolean;
  1872. begin
  1873. result:= CurToken<>tkSemicolon;
  1874. if not result then
  1875. begin
  1876. nexttoken;
  1877. if curtoken=tkbraceclose then
  1878. result:=true
  1879. else
  1880. ungettoken;
  1881. end;
  1882. end;
  1883. begin
  1884. if CurToken <> tkBraceOpen then
  1885. Result:=DoParseExpression(AParent)
  1886. else begin
  1887. Result:=nil;
  1888. NextToken;
  1889. x:=DoParseConstValueExpression(AParent);
  1890. case CurToken of
  1891. tkComma: // array of values (a,b,c);
  1892. try
  1893. a:=CreateArrayValues(AParent);
  1894. a.AddValues(x);
  1895. x:=nil;
  1896. repeat
  1897. NextToken;
  1898. x:=DoParseConstValueExpression(AParent);
  1899. a.AddValues(x);
  1900. x:=nil;
  1901. until CurToken<>tkComma;
  1902. Result:=a;
  1903. finally
  1904. if Result=nil then
  1905. begin
  1906. a.Free;
  1907. x.Free;
  1908. end;
  1909. end;
  1910. tkColon: // record field (a:xxx;b:yyy;c:zzz);
  1911. begin
  1912. r:=nil;
  1913. try
  1914. n:=GetExprIdent(x);
  1915. ReleaseAndNil(TPasElement(x));
  1916. r:=CreateRecordValues(AParent);
  1917. NextToken;
  1918. x:=DoParseConstValueExpression(AParent);
  1919. r.AddField(n, x);
  1920. x:=nil;
  1921. if not lastfield then
  1922. repeat
  1923. n:=ExpectIdentifier;
  1924. ExpectToken(tkColon);
  1925. NextToken;
  1926. x:=DoParseConstValueExpression(AParent);
  1927. r.AddField(n, x);
  1928. x:=nil;
  1929. until lastfield; // CurToken<>tkSemicolon;
  1930. Result:=r;
  1931. finally
  1932. if Result=nil then
  1933. begin
  1934. r.Free;
  1935. x.Free;
  1936. end;
  1937. end;
  1938. end;
  1939. else
  1940. // Binary expression! ((128 div sizeof(longint)) - 3);
  1941. Result:=DoParseExpression(AParent,x);
  1942. if CurToken<>tkBraceClose then
  1943. begin
  1944. ReleaseAndNil(TPasElement(Result));
  1945. ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
  1946. end;
  1947. NextToken;
  1948. if CurToken <> tkSemicolon then // the continue of expression
  1949. Result:=DoParseExpression(AParent,Result);
  1950. Exit;
  1951. end;
  1952. if CurToken<>tkBraceClose then
  1953. begin
  1954. ReleaseAndNil(TPasElement(Result));
  1955. ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
  1956. end;
  1957. NextToken;
  1958. end;
  1959. end;
  1960. function TPasParser.CheckOverloadList(AList: TFPList; AName: String; out
  1961. OldMember: TPasElement): TPasOverloadedProc;
  1962. Var
  1963. I : Integer;
  1964. begin
  1965. Result:=Nil;
  1966. I:=0;
  1967. While (Result=Nil) and (I<AList.Count) do
  1968. begin
  1969. OldMember:=TPasElement(AList[i]);
  1970. if CompareText(OldMember.Name, AName) = 0 then
  1971. begin
  1972. if OldMember is TPasOverloadedProc then
  1973. Result:=TPasOverloadedProc(OldMember)
  1974. else
  1975. begin
  1976. Result:=TPasOverloadedProc(CreateElement(TPasOverloadedProc, AName, OldMember.Parent));
  1977. Result.Visibility:=OldMember.Visibility;
  1978. Result.Overloads.Add(OldMember);
  1979. Result.SourceFilename:=OldMember.SourceFilename;
  1980. Result.SourceLinenumber:=OldMember.SourceLinenumber;
  1981. Result.DocComment:=Oldmember.DocComment;
  1982. AList[i] := Result;
  1983. end;
  1984. end;
  1985. Inc(I);
  1986. end;
  1987. If Result=Nil then
  1988. OldMember:=Nil;
  1989. end;
  1990. procedure TPasParser.AddProcOrFunction(Decs: TPasDeclarations;
  1991. AProc: TPasProcedure);
  1992. var
  1993. I : Integer;
  1994. OldMember: TPasElement;
  1995. OverloadedProc: TPasOverloadedProc;
  1996. begin
  1997. With Decs do
  1998. begin
  1999. if not (po_nooverloadedprocs in Options) then
  2000. OverloadedProc:=CheckOverloadList(Functions,AProc.Name,OldMember)
  2001. else
  2002. OverloadedProc:=nil;
  2003. If (OverloadedProc<>Nil) then
  2004. begin
  2005. OverLoadedProc.Overloads.Add(AProc);
  2006. if (OldMember<>OverloadedProc) then
  2007. begin
  2008. I:=Declarations.IndexOf(OldMember);
  2009. If I<>-1 then
  2010. Declarations[i]:=OverloadedProc;
  2011. end;
  2012. end
  2013. else
  2014. begin
  2015. Declarations.Add(AProc);
  2016. Functions.Add(AProc);
  2017. end;
  2018. end;
  2019. end;
  2020. // Return the parent of a function declaration. This is AParent,
  2021. // except when AParent is a class, and the function is overloaded.
  2022. // Then the parent is the overload object.
  2023. function TPasParser.CheckIfOverloaded(AParent: TPasElement; const AName: String): TPasElement;
  2024. var
  2025. Member: TPasElement;
  2026. OverloadedProc: TPasOverloadedProc;
  2027. begin
  2028. Result:=AParent;
  2029. If (not (po_nooverloadedprocs in Options)) and (AParent is TPasClassType) then
  2030. begin
  2031. OverloadedProc:=CheckOverLoadList(TPasClassType(AParent).Members,AName,Member);
  2032. If (OverloadedProc<>Nil) then
  2033. Result:=OverloadedProc;
  2034. end;
  2035. end;
  2036. procedure TPasParser.ParseMain(var Module: TPasModule);
  2037. begin
  2038. Module:=nil;
  2039. NextToken;
  2040. SaveComments;
  2041. case CurToken of
  2042. tkUnit:
  2043. ParseUnit(Module);
  2044. tkProgram:
  2045. ParseProgram(Module);
  2046. tkLibrary:
  2047. ParseLibrary(Module);
  2048. else
  2049. ungettoken;
  2050. ParseProgram(Module,True);
  2051. // ParseExcTokenError('unit');
  2052. end;
  2053. end;
  2054. // Starts after the "unit" token
  2055. procedure TPasParser.ParseUnit(var Module: TPasModule);
  2056. var
  2057. AUnitName: String;
  2058. begin
  2059. Module := nil;
  2060. AUnitName := ExpectIdentifier;
  2061. NextToken;
  2062. while CurToken = tkDot do
  2063. begin
  2064. ExpectIdentifier;
  2065. AUnitName := AUnitName + '.' + CurTokenString;
  2066. NextToken;
  2067. end;
  2068. UngetToken;
  2069. Module := TPasModule(CreateElement(TPasModule, AUnitName,
  2070. Engine.Package));
  2071. FCurModule:=Module;
  2072. try
  2073. if Assigned(Engine.Package) then
  2074. begin
  2075. Module.PackageName := Engine.Package.Name;
  2076. Engine.Package.Modules.Add(Module);
  2077. end;
  2078. CheckHint(Module,True);
  2079. // ExpectToken(tkSemicolon);
  2080. ExpectToken(tkInterface);
  2081. If LogEvent(pleInterface) then
  2082. DoLog(mtInfo,nLogStartInterface,SLogStartInterface);
  2083. ParseInterface;
  2084. Engine.FinishScope(stModule,Module);
  2085. finally
  2086. FCurModule:=nil;
  2087. end;
  2088. end;
  2089. // Starts after the "program" token
  2090. procedure TPasParser.ParseProgram(var Module: TPasModule; SkipHeader : Boolean = False);
  2091. Var
  2092. PP : TPasProgram;
  2093. Section : TProgramSection;
  2094. N : String;
  2095. begin
  2096. if SkipHeader then
  2097. N:=ChangeFileExt(Scanner.CurFilename,'')
  2098. else
  2099. N:=ExpectIdentifier;
  2100. Module := nil;
  2101. PP:=TPasProgram(CreateElement(TPasProgram, N, Engine.Package));
  2102. Module :=PP;
  2103. FCurModule:=Module;
  2104. try
  2105. if Assigned(Engine.Package) then
  2106. begin
  2107. Module.PackageName := Engine.Package.Name;
  2108. Engine.Package.Modules.Add(Module);
  2109. end;
  2110. if not SkipHeader then
  2111. begin
  2112. NextToken;
  2113. If (CurToken=tkBraceOpen) then
  2114. begin
  2115. PP.InputFile:=ExpectIdentifier;
  2116. NextToken;
  2117. if Not (CurToken in [tkBraceClose,tkComma]) then
  2118. ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
  2119. If (CurToken=tkComma) then
  2120. PP.OutPutFile:=ExpectIdentifier;
  2121. ExpectToken(tkBraceClose);
  2122. NextToken;
  2123. end;
  2124. if (CurToken<>tkSemicolon) then
  2125. ParseExcTokenError(';');
  2126. end;
  2127. Section := TProgramSection(CreateElement(TProgramSection, '', CurModule));
  2128. PP.ProgramSection := Section;
  2129. ParseOptionalUsesList(Section);
  2130. ParseDeclarations(Section);
  2131. Engine.FinishScope(stModule,Module);
  2132. finally
  2133. FCurModule:=nil;
  2134. end;
  2135. end;
  2136. procedure TPasParser.ParseLibrary(var Module: TPasModule);
  2137. Var
  2138. PP : TPasLibrary;
  2139. Section : TLibrarySection;
  2140. begin
  2141. Module := nil;
  2142. PP:=TPasLibrary(CreateElement(TPasLibrary, ExpectIdentifier, Engine.Package));
  2143. Module :=PP;
  2144. FCurModule:=Module;
  2145. try
  2146. if Assigned(Engine.Package) then
  2147. begin
  2148. Module.PackageName := Engine.Package.Name;
  2149. Engine.Package.Modules.Add(Module);
  2150. end;
  2151. NextToken;
  2152. if (CurToken<>tkSemicolon) then
  2153. ParseExcTokenError(';');
  2154. Section := TLibrarySection(CreateElement(TLibrarySection, '', CurModule));
  2155. PP.LibrarySection := Section;
  2156. ParseOptionalUsesList(Section);
  2157. ParseDeclarations(Section);
  2158. Engine.FinishScope(stModule,Module);
  2159. finally
  2160. FCurModule:=nil;
  2161. end;
  2162. end;
  2163. procedure TPasParser.ParseOptionalUsesList(ASection: TPasSection);
  2164. // checks if next token is Uses keyword and read uses list
  2165. begin
  2166. NextToken;
  2167. if CurToken=tkuses then
  2168. ParseUsesList(ASection)
  2169. else begin
  2170. CheckImplicitUsedUnits(ASection);
  2171. Engine.FinishScope(stUsesList,ASection);
  2172. UngetToken;
  2173. end;
  2174. end;
  2175. // Starts after the "interface" token
  2176. procedure TPasParser.ParseInterface;
  2177. var
  2178. Section: TInterfaceSection;
  2179. begin
  2180. Section := TInterfaceSection(CreateElement(TInterfaceSection, '', CurModule));
  2181. CurModule.InterfaceSection := Section;
  2182. ParseOptionalUsesList(Section);
  2183. ParseDeclarations(Section); // this also parses the Implementation section
  2184. end;
  2185. // Starts after the "implementation" token
  2186. procedure TPasParser.ParseImplementation;
  2187. var
  2188. Section: TImplementationSection;
  2189. begin
  2190. Section := TImplementationSection(CreateElement(TImplementationSection, '', CurModule));
  2191. CurModule.ImplementationSection := Section;
  2192. ParseOptionalUsesList(Section);
  2193. ParseDeclarations(Section);
  2194. end;
  2195. procedure TPasParser.ParseInitialization;
  2196. var
  2197. Section: TInitializationSection;
  2198. SubBlock: TPasImplElement;
  2199. begin
  2200. Section := TInitializationSection(CreateElement(TInitializationSection, '', CurModule));
  2201. CurModule.InitializationSection := Section;
  2202. repeat
  2203. NextToken;
  2204. if (CurToken=tkend) then
  2205. begin
  2206. ExpectToken(tkDot);
  2207. exit;
  2208. end
  2209. else if (CurToken=tkfinalization) then
  2210. begin
  2211. ParseFinalization;
  2212. exit;
  2213. end
  2214. else if CurToken<>tkSemiColon then
  2215. begin
  2216. UngetToken;
  2217. ParseStatement(Section,SubBlock);
  2218. if SubBlock=nil then
  2219. ExpectToken(tkend);
  2220. end;
  2221. until false;
  2222. end;
  2223. procedure TPasParser.ParseFinalization;
  2224. var
  2225. Section: TFinalizationSection;
  2226. SubBlock: TPasImplElement;
  2227. begin
  2228. Section := TFinalizationSection(CreateElement(TFinalizationSection, '', CurModule));
  2229. CurModule.FinalizationSection := Section;
  2230. repeat
  2231. NextToken;
  2232. if (CurToken=tkend) then
  2233. begin
  2234. ExpectToken(tkDot);
  2235. exit;
  2236. end
  2237. else if CurToken<>tkSemiColon then
  2238. begin
  2239. UngetToken;
  2240. ParseStatement(Section,SubBlock);
  2241. if SubBlock=nil then
  2242. ExpectToken(tkend);
  2243. end;
  2244. until false;
  2245. UngetToken;
  2246. end;
  2247. function TPasParser.GetProcTypeFromToken(tk: TToken; IsClass: Boolean
  2248. ): TProcType;
  2249. begin
  2250. Case tk of
  2251. tkProcedure :
  2252. if IsClass then
  2253. Result:=ptClassProcedure
  2254. else
  2255. Result:=ptProcedure;
  2256. tkFunction:
  2257. if IsClass then
  2258. Result:=ptClassFunction
  2259. else
  2260. Result:=ptFunction;
  2261. tkConstructor:
  2262. if IsClass then
  2263. Result:=ptClassConstructor
  2264. else
  2265. Result:=ptConstructor;
  2266. tkDestructor:
  2267. if IsClass then
  2268. Result:=ptClassDestructor
  2269. else
  2270. Result:=ptDestructor;
  2271. tkOperator:
  2272. if IsClass then
  2273. Result:=ptClassOperator
  2274. else
  2275. Result:=ptOperator;
  2276. else
  2277. ParseExc(nParserNotAProcToken,SParserNotAProcToken);
  2278. end;
  2279. end;
  2280. procedure TPasParser.ParseDeclarations(Declarations: TPasDeclarations);
  2281. var
  2282. CurBlock: TDeclType;
  2283. procedure SetBlock(NewBlock: TDeclType);
  2284. begin
  2285. if CurBlock=NewBlock then exit;
  2286. if CurBlock=declType then
  2287. Engine.FinishScope(stTypeSection,Declarations);
  2288. CurBlock:=NewBlock;
  2289. Scanner.SetForceCaret(NewBlock=declType);
  2290. end;
  2291. var
  2292. ConstEl: TPasConst;
  2293. ResStrEl: TPasResString;
  2294. TypeEl: TPasType;
  2295. ClassEl: TPasClassType;
  2296. ArrEl : TPasArrayType;
  2297. List: TFPList;
  2298. i,j: Integer;
  2299. VarEl: TPasVariable;
  2300. ExpEl: TPasExportSymbol;
  2301. PropEl : TPasProperty;
  2302. TypeName: String;
  2303. PT : TProcType;
  2304. NamePos: TPasSourcePos;
  2305. ok: Boolean;
  2306. Proc: TPasProcedure;
  2307. begin
  2308. CurBlock := declNone;
  2309. while True do
  2310. begin
  2311. NextToken;
  2312. // writeln('TPasParser.ParseSection Token=',CurTokenString,' ',CurToken, ' ',scanner.CurFilename);
  2313. case CurToken of
  2314. tkend:
  2315. begin
  2316. If (CurModule is TPasProgram) and (CurModule.InitializationSection=Nil) then
  2317. ParseExcTokenError('begin');
  2318. ExpectToken(tkDot);
  2319. break;
  2320. end;
  2321. tkimplementation:
  2322. if (Declarations is TInterfaceSection) then
  2323. begin
  2324. If Not Engine.InterfaceOnly then
  2325. begin
  2326. If LogEvent(pleImplementation) then
  2327. DoLog(mtInfo,nLogStartImplementation,SLogStartImplementation);
  2328. SetBlock(declNone);
  2329. ParseImplementation;
  2330. end;
  2331. break;
  2332. end;
  2333. tkinitialization:
  2334. if (Declarations is TInterfaceSection)
  2335. or ((Declarations is TImplementationSection) and not (Declarations is TProgramSection)) then
  2336. begin
  2337. SetBlock(declNone);
  2338. ParseInitialization;
  2339. break;
  2340. end;
  2341. tkfinalization:
  2342. if (Declarations is TInterfaceSection)
  2343. or ((Declarations is TImplementationSection) and not (Declarations is TProgramSection)) then
  2344. begin
  2345. SetBlock(declNone);
  2346. ParseFinalization;
  2347. break;
  2348. end;
  2349. tkUses:
  2350. if Declarations.ClassType=TInterfaceSection then
  2351. ParseExcTokenError(TokenInfos[tkimplementation])
  2352. else if Declarations is TPasSection then
  2353. ParseExcTokenError(TokenInfos[tkend])
  2354. else
  2355. ParseExcSyntaxError;
  2356. tkConst:
  2357. SetBlock(declConst);
  2358. tkexports:
  2359. SetBlock(declExports);
  2360. tkResourcestring:
  2361. SetBlock(declResourcestring);
  2362. tkType:
  2363. SetBlock(declType);
  2364. tkVar:
  2365. SetBlock(declVar);
  2366. tkThreadVar:
  2367. SetBlock(declThreadVar);
  2368. tkProperty:
  2369. SetBlock(declProperty);
  2370. tkProcedure, tkFunction, tkConstructor, tkDestructor,tkOperator:
  2371. begin
  2372. SetBlock(declNone);
  2373. SaveComments;
  2374. pt:=GetProcTypeFromToken(CurToken);
  2375. AddProcOrFunction(Declarations, ParseProcedureOrFunctionDecl(Declarations, pt));
  2376. end;
  2377. tkClass:
  2378. begin
  2379. SetBlock(declNone);
  2380. SaveComments;
  2381. NextToken;
  2382. If CurToken in [tkprocedure,tkFunction,tkConstructor, tkDestructor] then
  2383. begin
  2384. pt:=GetProcTypeFromToken(CurToken,True);
  2385. AddProcOrFunction(Declarations,ParseProcedureOrFunctionDecl(Declarations, pt));
  2386. end
  2387. else
  2388. ExpectToken(tkprocedure);
  2389. end;
  2390. tkIdentifier:
  2391. begin
  2392. SaveComments;
  2393. case CurBlock of
  2394. declConst:
  2395. begin
  2396. ConstEl := ParseConstDecl(Declarations);
  2397. Declarations.Declarations.Add(ConstEl);
  2398. Declarations.Consts.Add(ConstEl);
  2399. end;
  2400. declResourcestring:
  2401. begin
  2402. ResStrEl := ParseResourcestringDecl(Declarations);
  2403. Declarations.Declarations.Add(ResStrEl);
  2404. Declarations.ResStrings.Add(ResStrEl);
  2405. end;
  2406. declType:
  2407. begin
  2408. TypeEl := ParseTypeDecl(Declarations);
  2409. // Scanner.SetForceCaret(OldForceCaret); // It may have been switched off
  2410. if Assigned(TypeEl) then // !!!
  2411. begin
  2412. Declarations.Declarations.Add(TypeEl);
  2413. if (TypeEl.ClassType = TPasClassType)
  2414. and (not (po_keepclassforward in Options)) then
  2415. begin
  2416. // Remove previous forward declarations, if necessary
  2417. for i := 0 to Declarations.Classes.Count - 1 do
  2418. begin
  2419. ClassEl := TPasClassType(Declarations.Classes[i]);
  2420. if CompareText(ClassEl.Name, TypeEl.Name) = 0 then
  2421. begin
  2422. Declarations.Classes.Delete(i);
  2423. for j := 0 to Declarations.Declarations.Count - 1 do
  2424. if CompareText(TypeEl.Name,
  2425. TPasElement(Declarations.Declarations[j]).Name) = 0 then
  2426. begin
  2427. Declarations.Declarations.Delete(j);
  2428. break;
  2429. end;
  2430. ClassEl.Release;
  2431. break;
  2432. end;
  2433. end;
  2434. // Add the new class to the class list
  2435. Declarations.Classes.Add(TypeEl)
  2436. end else
  2437. Declarations.Types.Add(TypeEl);
  2438. end;
  2439. end;
  2440. declExports:
  2441. begin
  2442. List := TFPList.Create;
  2443. try
  2444. ok:=false;
  2445. try
  2446. ParseExportDecl(Declarations, List);
  2447. ok:=true;
  2448. finally
  2449. if not ok then
  2450. for i := 0 to List.Count - 1 do
  2451. TPasExportSymbol(List[i]).Release;
  2452. end;
  2453. for i := 0 to List.Count - 1 do
  2454. begin
  2455. ExpEl := TPasExportSymbol(List[i]);
  2456. Declarations.Declarations.Add(ExpEl);
  2457. Declarations.ExportSymbols.Add(ExpEl);
  2458. end;
  2459. finally
  2460. List.Free;
  2461. end;
  2462. end;
  2463. declVar, declThreadVar:
  2464. begin
  2465. List := TFPList.Create;
  2466. try
  2467. ParseVarDecl(Declarations, List);
  2468. for i := 0 to List.Count - 1 do
  2469. begin
  2470. VarEl := TPasVariable(List[i]);
  2471. Engine.FinishScope(stDeclaration,VarEl);
  2472. Declarations.Declarations.Add(VarEl);
  2473. Declarations.Variables.Add(VarEl);
  2474. end;
  2475. CheckToken(tkSemicolon);
  2476. finally
  2477. List.Free;
  2478. end;
  2479. end;
  2480. declProperty:
  2481. begin
  2482. PropEl:=ParseProperty(Declarations,CurtokenString,visDefault,false);
  2483. Declarations.Declarations.Add(PropEl);
  2484. Declarations.Properties.Add(PropEl);
  2485. end;
  2486. else
  2487. ParseExcSyntaxError;
  2488. end;
  2489. end;
  2490. tkGeneric:
  2491. begin
  2492. if CurBlock <> declType then
  2493. ParseExcSyntaxError;
  2494. TypeName := ExpectIdentifier;
  2495. NamePos:=Scanner.CurSourcePos;
  2496. List:=TFPList.Create;
  2497. try
  2498. ReadGenericArguments(List,Nil);
  2499. ExpectToken(tkEqual);
  2500. NextToken;
  2501. Case CurToken of
  2502. tkObject,
  2503. tkClass :
  2504. begin
  2505. ClassEl := TPasClassType(CreateElement(TPasClassType,
  2506. TypeName, Declarations, NamePos));
  2507. ClassEl.SetGenericTemplates(List);
  2508. NextToken;
  2509. DoParseClassType(ClassEl);
  2510. Declarations.Declarations.Add(ClassEl);
  2511. Declarations.Classes.Add(ClassEl);
  2512. CheckHint(classel,True);
  2513. end;
  2514. tkArray:
  2515. begin
  2516. if List.Count<>1 then
  2517. ParseExc(nParserGenericArray1Element,sParserGenericArray1Element);
  2518. ArrEl:=TPasArrayType(ParseArrayType(Declarations,NamePos,TypeName,pmNone));
  2519. CheckHint(ArrEl,True);
  2520. ArrEl.ElType.Release;
  2521. ArrEl.elType:=TPasGenericTemplateType(List[0]);
  2522. Declarations.Declarations.Add(ArrEl);
  2523. Declarations.Types.Add(ArrEl);
  2524. end;
  2525. else
  2526. ParseExc(nParserGenericClassOrArray,SParserGenericClassOrArray);
  2527. end;
  2528. finally
  2529. List.Free;
  2530. end;
  2531. end;
  2532. tkbegin:
  2533. begin
  2534. if Declarations is TProcedureBody then
  2535. begin
  2536. Proc:=Declarations.Parent as TPasProcedure;
  2537. if pmAssembler in Proc.Modifiers then
  2538. ParseExc(nParserExpectTokenError,SParserExpectTokenError,['asm']);
  2539. SetBlock(declNone);
  2540. ParseProcBeginBlock(TProcedureBody(Declarations));
  2541. break;
  2542. end
  2543. else if (Declarations is TInterfaceSection)
  2544. or (Declarations is TImplementationSection) then
  2545. begin
  2546. SetBlock(declNone);
  2547. ParseInitialization;
  2548. break;
  2549. end
  2550. else
  2551. ParseExcSyntaxError;
  2552. end;
  2553. tkasm:
  2554. begin
  2555. if Declarations is TProcedureBody then
  2556. begin
  2557. Proc:=Declarations.Parent as TPasProcedure;
  2558. if not (pmAssembler in Proc.Modifiers) then
  2559. ParseExc(nParserExpectTokenError,SParserExpectTokenError,['begin']);
  2560. SetBlock(declNone);
  2561. ParseProcAsmBlock(TProcedureBody(Declarations));
  2562. break;
  2563. end
  2564. else
  2565. ParseExcSyntaxError;
  2566. end;
  2567. tklabel:
  2568. begin
  2569. SetBlock(declNone);
  2570. if not (Declarations is TInterfaceSection) then
  2571. ParseLabels(Declarations);
  2572. end;
  2573. else
  2574. ParseExcSyntaxError;
  2575. end;
  2576. end;
  2577. SetBlock(declNone);
  2578. end;
  2579. function TPasParser.CheckUseUnit(ASection: TPasSection; AUnitName: string
  2580. ): TPasElement;
  2581. procedure CheckDuplicateInUsesList(AUnitName : string; UsesList: TFPList);
  2582. var
  2583. i: Integer;
  2584. begin
  2585. if UsesList=nil then exit;
  2586. for i:=0 to UsesList.Count-1 do
  2587. if CompareText(AUnitName,TPasModule(UsesList[i]).Name)=0 then
  2588. ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
  2589. end;
  2590. begin
  2591. if CompareText(AUnitName,CurModule.Name)=0 then
  2592. begin
  2593. // System is implicit, except when parsing system unit.
  2594. if CompareText(AUnitName,'System')=0 then
  2595. exit;
  2596. ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
  2597. end;
  2598. CheckDuplicateInUsesList(AUnitName,ASection.UsesList);
  2599. if ASection.ClassType=TImplementationSection then
  2600. CheckDuplicateInUsesList(AUnitName,CurModule.InterfaceSection.UsesList);
  2601. result := Engine.FindModule(AUnitName); // should we resolve module here when "IN" filename is not known yet?
  2602. if Assigned(result) then
  2603. result.AddRef
  2604. else
  2605. Result := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef,
  2606. AUnitName, ASection));
  2607. ASection.UsesList.Add(Result);
  2608. end;
  2609. procedure TPasParser.CheckImplicitUsedUnits(ASection: TPasSection);
  2610. var
  2611. i: Integer;
  2612. begin
  2613. If not (ASection.ClassType=TImplementationSection) Then // interface,program,library,package
  2614. begin
  2615. // load implicit units, like 'System'
  2616. for i:=0 to ImplicitUses.Count-1 do
  2617. CheckUseUnit(ASection,ImplicitUses[i]);
  2618. end;
  2619. end;
  2620. // Starts after the "uses" token
  2621. procedure TPasParser.ParseUsesList(ASection: TPasSection);
  2622. var
  2623. AUnitName: String;
  2624. Element: TPasElement;
  2625. begin
  2626. CheckImplicitUsedUnits(ASection);
  2627. Repeat
  2628. AUnitName := ExpectIdentifier;
  2629. NextToken;
  2630. while CurToken = tkDot do
  2631. begin
  2632. ExpectIdentifier;
  2633. AUnitName := AUnitName + '.' + CurTokenString;
  2634. NextToken;
  2635. end;
  2636. Element := CheckUseUnit(ASection,AUnitName);
  2637. if (CurToken=tkin) then
  2638. begin
  2639. ExpectToken(tkString);
  2640. if (Element is TPasModule) and (TPasmodule(Element).filename='') then
  2641. TPasModule(Element).FileName:=curtokenstring
  2642. else if (Element is TPasUnresolvedUnitRef) then
  2643. TPasUnresolvedUnitRef(Element).FileName:=curtokenstring;
  2644. NextToken;
  2645. end;
  2646. if Not (CurToken in [tkComma,tkSemicolon]) then
  2647. ParseExc(nParserExpectedCommaSemicolon,SParserExpectedCommaSemicolon);
  2648. Until (CurToken=tkSemicolon);
  2649. Engine.FinishScope(stUsesList,ASection);
  2650. end;
  2651. // Starts after the variable name
  2652. function TPasParser.ParseConstDecl(Parent: TPasElement): TPasConst;
  2653. var
  2654. OldForceCaret,ok: Boolean;
  2655. begin
  2656. SaveComments;
  2657. Result := TPasConst(CreateElement(TPasConst, CurTokenString, Parent));
  2658. if Parent is TPasClassType then
  2659. Include(Result.VarModifiers,vmClass);
  2660. ok:=false;
  2661. try
  2662. NextToken;
  2663. if CurToken = tkColon then
  2664. begin
  2665. OldForceCaret:=Scanner.SetForceCaret(True);
  2666. try
  2667. Result.VarType := ParseType(Result,Scanner.CurSourcePos);
  2668. finally
  2669. Scanner.SetForceCaret(OldForceCaret);
  2670. end;
  2671. { if Result.VarType is TPasRangeType then
  2672. Ungettoken; // Range type stops on token after last range token}
  2673. end
  2674. else
  2675. UngetToken;
  2676. ExpectToken(tkEqual);
  2677. NextToken;
  2678. Result.Expr:=DoParseConstValueExpression(Result);
  2679. UngetToken;
  2680. CheckHint(Result,True);
  2681. ok:=true;
  2682. finally
  2683. if not ok then
  2684. ReleaseAndNil(TPasElement(Result));
  2685. end;
  2686. Engine.FinishScope(stConstDef,Result);
  2687. end;
  2688. // Starts after the variable name
  2689. function TPasParser.ParseResourcestringDecl(Parent: TPasElement): TPasResString;
  2690. var
  2691. ok: Boolean;
  2692. begin
  2693. SaveComments;
  2694. Result := TPasResString(CreateElement(TPasResString, CurTokenString, Parent));
  2695. ok:=false;
  2696. try
  2697. ExpectToken(tkEqual);
  2698. NextToken; // skip tkEqual
  2699. Result.Expr:=DoParseConstValueExpression(Result);
  2700. UngetToken;
  2701. CheckHint(Result,True);
  2702. ok:=true;
  2703. finally
  2704. if not ok then
  2705. ReleaseAndNil(TPasElement(Result));
  2706. end;
  2707. end;
  2708. procedure TPasParser.ReadGenericArguments(List : TFPList;Parent : TPasElement);
  2709. Var
  2710. N : String;
  2711. begin
  2712. ExpectToken(tkLessThan);
  2713. repeat
  2714. N:=ExpectIdentifier;
  2715. List.Add(CreateElement(TPasGenericTemplateType,N,Parent));
  2716. NextToken;
  2717. if not (CurToken in [tkComma, tkGreaterThan]) then
  2718. ParseExc(nParserExpectToken2Error,SParserExpectToken2Error,
  2719. [TokenInfos[tkComma], TokenInfos[tkGreaterThan]]);
  2720. until CurToken = tkGreaterThan;
  2721. end;
  2722. // Starts after the type name
  2723. function TPasParser.ParseRangeType(AParent: TPasElement;
  2724. const NamePos: TPasSourcePos; const TypeName: String; Full: Boolean
  2725. ): TPasRangeType;
  2726. Var
  2727. PE : TPasExpr;
  2728. ok: Boolean;
  2729. begin
  2730. Result := TPasRangeType(CreateElement(TPasRangeType, TypeName, AParent, NamePos));
  2731. ok:=false;
  2732. try
  2733. if Full then
  2734. begin
  2735. If not (CurToken=tkEqual) then
  2736. ParseExcTokenError(TokenInfos[tkEqual]);
  2737. end;
  2738. NextToken;
  2739. PE:=DoParseExpression(Result,Nil,False);
  2740. if not ((PE is TBinaryExpr) and (TBinaryExpr(PE).Kind=pekRange)) then
  2741. begin
  2742. PE.Release;
  2743. ParseExc(nRangeExpressionExpected,SRangeExpressionExpected);
  2744. end;
  2745. Result.RangeExpr:=PE as TBinaryExpr;
  2746. UngetToken;
  2747. ok:=true;
  2748. finally
  2749. if not ok then
  2750. Result.Release;
  2751. end;
  2752. Engine.FinishScope(stTypeDef,Result);
  2753. end;
  2754. // Starts after Exports, on first identifier.
  2755. procedure TPasParser.ParseExportDecl(Parent: TPasElement; List: TFPList);
  2756. Var
  2757. E : TPasExportSymbol;
  2758. begin
  2759. Repeat
  2760. if List.Count<>0 then
  2761. ExpectIdentifier;
  2762. E:=TPasExportSymbol(CreateElement(TPasExportSymbol,CurtokenString,Parent));
  2763. List.Add(E);
  2764. NextToken;
  2765. if CurTokenIsIdentifier('INDEX') then
  2766. begin
  2767. NextToken;
  2768. E.Exportindex:=DoParseExpression(E,Nil)
  2769. end
  2770. else if CurTokenIsIdentifier('NAME') then
  2771. begin
  2772. NextToken;
  2773. E.ExportName:=DoParseExpression(E,Nil)
  2774. end;
  2775. if not (CurToken in [tkComma,tkSemicolon]) then
  2776. ParseExc(nParserExpectedCommaSemicolon,SParserExpectedCommaSemicolon);
  2777. until (CurToken=tkSemicolon);
  2778. end;
  2779. function TPasParser.ParseSpecializeType(Parent: TPasElement;
  2780. const TypeName: String): TPasClassType;
  2781. begin
  2782. NextToken;
  2783. Result:=ParseSimpleType(Parent,Scanner.CurSourcePos,TypeName) as TPasClassType;
  2784. end;
  2785. function TPasParser.ParseProcedureType(Parent: TPasElement;
  2786. const NamePos: TPasSourcePos; const TypeName: String; const PT: TProcType
  2787. ): TPasProcedureType;
  2788. var
  2789. ok: Boolean;
  2790. begin
  2791. if PT in [ptFunction,ptClassFunction] then
  2792. Result := CreateFunctionType(TypeName, 'Result', Parent, False, NamePos)
  2793. else
  2794. Result := TPasProcedureType(CreateElement(TPasProcedureType, TypeName, Parent, NamePos));
  2795. ok:=false;
  2796. try
  2797. ParseProcedureOrFunctionHeader(Result, TPasProcedureType(Result), PT, True);
  2798. ok:=true;
  2799. finally
  2800. if not ok then
  2801. Result.Release;
  2802. end;
  2803. end;
  2804. function TPasParser.ParseTypeDecl(Parent: TPasElement): TPasType;
  2805. var
  2806. TypeName: String;
  2807. NamePos: TPasSourcePos;
  2808. OldForceCaret : Boolean;
  2809. List : TFPList;
  2810. begin
  2811. TypeName := CurTokenString;
  2812. NamePos:=Scanner.CurSourcePos;
  2813. List:=Nil;
  2814. OldForceCaret:=Scanner.SetForceCaret(True);
  2815. try
  2816. NextToken;
  2817. if (CurToken=tkLessThan) and (msDelphi in CurrentModeswitches) then
  2818. List:=TFPList.Create;
  2819. UnGetToken; // ReadGenericArguments starts at <
  2820. if Assigned(List) then
  2821. ReadGenericArguments(List,Parent);
  2822. ExpectToken(tkEqual);
  2823. Result:=ParseType(Parent,NamePos,TypeName,True,List);
  2824. finally
  2825. Scanner.SetForceCaret(OldForceCaret);
  2826. List.Free;
  2827. end;
  2828. end;
  2829. function TPasParser.GetVariableValueAndLocation(Parent: TPasElement; out
  2830. Value: TPasExpr; out Location: String): Boolean;
  2831. begin
  2832. Value:=Nil;
  2833. NextToken;
  2834. Result:=CurToken=tkEqual;
  2835. if Result then
  2836. begin
  2837. NextToken;
  2838. Value := DoParseConstValueExpression(Parent);
  2839. // NextToken;
  2840. end;
  2841. if (CurToken=tkAbsolute) then
  2842. begin
  2843. Result:=True;
  2844. ExpectIdentifier;
  2845. Location:=CurTokenText;
  2846. NextToken;
  2847. if CurToken=tkDot then
  2848. begin
  2849. ExpectIdentifier;
  2850. Location:=Location+'.'+CurTokenText;
  2851. end
  2852. else
  2853. UnGetToken;
  2854. end
  2855. else
  2856. UngetToken;
  2857. end;
  2858. function TPasParser.GetVariableModifiers(Parent: TPasElement; out
  2859. VarMods: TVariableModifiers; out LibName, ExportName: TPasExpr;
  2860. ExternalClass: Boolean): string;
  2861. Var
  2862. S : String;
  2863. ExtMod: TVariableModifier;
  2864. begin
  2865. Result := '';
  2866. LibName := nil;
  2867. ExportName := nil;
  2868. VarMods := [];
  2869. NextToken;
  2870. If CurTokenIsIdentifier('cvar') and not ExternalClass then
  2871. begin
  2872. Result:=';cvar';
  2873. Include(VarMods,vmcvar);
  2874. ExpectToken(tkSemicolon);
  2875. NextToken;
  2876. end;
  2877. s:=LowerCase(CurTokenText);
  2878. if s='external' then
  2879. ExtMod:=vmExternal
  2880. else if (s='public') and not externalclass then
  2881. ExtMod:=vmPublic
  2882. else if (s='export') and not externalclass then
  2883. ExtMod:=vmExport
  2884. else
  2885. begin
  2886. UngetToken;
  2887. exit;
  2888. end;
  2889. Include(varMods,ExtMod);
  2890. Result:=Result+';'+CurTokenText;
  2891. NextToken;
  2892. if not (CurToken in [tkString,tkIdentifier]) then
  2893. begin
  2894. if (CurToken=tkSemicolon) and (ExtMod in [vmExternal,vmPublic]) then
  2895. exit;
  2896. ParseExcSyntaxError;
  2897. end;
  2898. // export name exportname;
  2899. // public;
  2900. // public name exportname;
  2901. // external;
  2902. // external libname;
  2903. // external libname name exportname;
  2904. // external name exportname;
  2905. if (ExtMod=vmExternal) and (CurToken in [tkString,tkIdentifier])
  2906. and Not (CurTokenIsIdentifier('name')) and not ExternalClass then
  2907. begin
  2908. Result := Result + ' ' + CurTokenText;
  2909. LibName:=DoParseExpression(Parent);
  2910. end;
  2911. if not CurTokenIsIdentifier('name') then
  2912. ParseExcSyntaxError;
  2913. NextToken;
  2914. if not (CurToken in [tkChar,tkString,tkIdentifier]) then
  2915. ParseExcTokenError(TokenInfos[tkString]);
  2916. Result := Result + ' ' + CurTokenText;
  2917. ExportName:=DoParseExpression(Parent);
  2918. end;
  2919. // Full means that a full variable declaration is being parsed.
  2920. procedure TPasParser.ParseVarList(Parent: TPasElement; VarList: TFPList;
  2921. AVisibility: TPasMemberVisibility; Full : Boolean);
  2922. // on Exception the VarList is restored, no need to Release the new elements
  2923. var
  2924. i, OldListCount: Integer;
  2925. Value , aLibName, aExpName: TPasExpr;
  2926. VarType: TPasType;
  2927. VarEl: TPasVariable;
  2928. H : TPasMemberHints;
  2929. VarMods: TVariableModifiers;
  2930. D,Mods,Loc: string;
  2931. OldForceCaret,ok,ExternalClass: Boolean;
  2932. begin
  2933. Value:=Nil;
  2934. aLibName:=nil;
  2935. aExpName:=nil;
  2936. OldListCount:=VarList.Count;
  2937. ok:=false;
  2938. try
  2939. D:=SaveComments; // This means we support only one comment per 'list'.
  2940. VarEl:=nil;
  2941. Repeat
  2942. // create the TPasVariable here, so that SourceLineNumber is correct
  2943. VarEl:=TPasVariable(CreateElement(TPasVariable,CurTokenString,Parent,AVisibility));
  2944. VarList.Add(VarEl);
  2945. NextToken;
  2946. if Not (CurToken in [tkComma,tkColon]) then
  2947. ParseExc(nParserExpectedCommaColon,SParserExpectedCommaColon);
  2948. if CurToken=tkComma then
  2949. ExpectIdentifier;
  2950. Until (CurToken=tkColon);
  2951. OldForceCaret:=Scanner.SetForceCaret(True);
  2952. try
  2953. VarType := ParseComplexType(VarEl);
  2954. finally
  2955. Scanner.SetForceCaret(OldForceCaret);
  2956. end;
  2957. // read type
  2958. for i := OldListCount to VarList.Count - 1 do
  2959. begin
  2960. VarEl:=TPasVariable(VarList[i]);
  2961. // Writeln(VarEl.Name, AVisibility);
  2962. VarEl.VarType := VarType;
  2963. //VarType.Parent := VarEl; // this is wrong for references
  2964. if (i>=OldListCount) then
  2965. VarType.AddRef;
  2966. end;
  2967. H:=CheckHint(Nil,False);
  2968. If Full then
  2969. GetVariableValueAndLocation(Parent,Value,Loc);
  2970. if (Value<>nil) and (VarList.Count>OldListCount+1) then
  2971. ParseExc(nParserOnlyOneVariableCanBeInitialized,SParserOnlyOneVariableCanBeInitialized);
  2972. TPasVariable(VarList[OldListCount]).Expr:=Value;
  2973. Value:=nil;
  2974. // Note: external members are allowed for non external classes too
  2975. ExternalClass:=(msExternalClass in CurrentModeSwitches)
  2976. and (Parent is TPasClassType);
  2977. H:=H+CheckHint(Nil,False);
  2978. if Full or Externalclass then
  2979. begin
  2980. NextToken;
  2981. If Curtoken<>tkSemicolon then
  2982. UnGetToken;
  2983. Mods:=GetVariableModifiers(Parent,VarMods,aLibName,aExpName,ExternalClass);
  2984. if (mods='') and (CurToken<>tkSemicolon) then
  2985. NextToken;
  2986. end
  2987. else
  2988. begin
  2989. NextToken;
  2990. VarMods:=[];
  2991. Mods:='';
  2992. end;
  2993. SaveComments(D);
  2994. // connect
  2995. for i := OldListCount to VarList.Count - 1 do
  2996. begin
  2997. VarEl:=TPasVariable(VarList[i]);
  2998. // Writeln(VarEl.Name, AVisibility);
  2999. // Procedure declaration eats the hints.
  3000. if Assigned(VarType) and (VarType is TPasProcedureType) then
  3001. VarEl.Hints:=VarType.Hints
  3002. else
  3003. VarEl.Hints:=H;
  3004. VarEl.Modifiers:=Mods;
  3005. VarEl.VarModifiers:=VarMods;
  3006. VarEl.AbsoluteLocation:=Loc;
  3007. if aLibName<>nil then
  3008. begin
  3009. VarEl.LibraryName:=aLibName;
  3010. aLibName.AddRef;
  3011. end;
  3012. if aExpName<>nil then
  3013. begin
  3014. VarEl.ExportName:=aExpName;
  3015. aExpName.AddRef;
  3016. end;
  3017. end;
  3018. ok:=true;
  3019. finally
  3020. if aLibName<>nil then aLibName.Release;
  3021. if aExpName<>nil then aExpName.Release;
  3022. if not ok then
  3023. begin
  3024. if Value<>nil then Value.Release;
  3025. for i:=OldListCount to VarList.Count-1 do
  3026. TPasElement(VarList[i]).Release;
  3027. VarList.Count:=OldListCount;
  3028. end;
  3029. end;
  3030. end;
  3031. procedure TPasParser.SetOptions(AValue: TPOptions);
  3032. begin
  3033. if FOptions=AValue then Exit;
  3034. FOptions:=AValue;
  3035. If Assigned(FScanner) then
  3036. FScanner.Options:=AValue;
  3037. end;
  3038. function TPasParser.SaveComments: String;
  3039. begin
  3040. if Engine.NeedComments then
  3041. FSavedComments:=CurComments.Text; // Expensive, so don't do unless needed.
  3042. Result:=FSavedComments;
  3043. end;
  3044. function TPasParser.SaveComments(const AValue: String): String;
  3045. begin
  3046. FSavedComments:=AValue;
  3047. Result:=FSavedComments;
  3048. end;
  3049. function TPasParser.LogEvent(E: TPParserLogEvent): Boolean;
  3050. begin
  3051. Result:=E in FLogEvents;
  3052. end;
  3053. procedure TPasParser.SetLastMsg(MsgType: TMessageType; MsgNumber: integer;
  3054. const Fmt: String; Args: array of const);
  3055. begin
  3056. FLastMsgType := MsgType;
  3057. FLastMsgNumber := MsgNumber;
  3058. FLastMsgPattern := Fmt;
  3059. FLastMsg := SafeFormat(Fmt,Args);
  3060. CreateMsgArgs(FLastMsgArgs,Args);
  3061. end;
  3062. procedure TPasParser.DoLog(MsgType: TMessageType; MsgNumber: integer;
  3063. const Msg: String; SkipSourceInfo: Boolean);
  3064. begin
  3065. DoLog(MsgType,MsgNumber,Msg,[],SkipSourceInfo);
  3066. end;
  3067. procedure TPasParser.DoLog(MsgType: TMessageType; MsgNumber: integer;
  3068. const Fmt: String; Args: array of const; SkipSourceInfo: Boolean);
  3069. begin
  3070. SetLastMsg(MsgType,MsgNumber,Fmt,Args);
  3071. If Assigned(FOnLog) then
  3072. if SkipSourceInfo or not assigned(scanner) then
  3073. FOnLog(Self,FLastMsg)
  3074. else
  3075. FOnLog(Self,Format('%s(%d) : %s',[Scanner.CurFilename,Scanner.CurRow,FLastMsg]));
  3076. end;
  3077. procedure TPasParser.ParseInlineVarDecl(Parent: TPasElement; List: TFPList;
  3078. AVisibility: TPasMemberVisibility = VisDefault; ClosingBrace: Boolean = False);
  3079. Var
  3080. tt : TTokens;
  3081. begin
  3082. ParseVarList(Parent,List,AVisibility,False);
  3083. tt:=[tkEnd,tkSemicolon];
  3084. if ClosingBrace then
  3085. include(tt,tkBraceClose);
  3086. if not (CurToken in tt) then
  3087. ParseExc(nParserExpectedSemiColonEnd,SParserExpectedSemiColonEnd);
  3088. end;
  3089. // Starts after the variable name
  3090. procedure TPasParser.ParseVarDecl(Parent: TPasElement; List: TFPList);
  3091. begin
  3092. ParseVarList(Parent,List,visDefault,True);
  3093. end;
  3094. // Starts after the opening bracket token
  3095. procedure TPasParser.ParseArgList(Parent: TPasElement; Args: TFPList; EndToken: TToken);
  3096. var
  3097. IsUntyped, ok, LastHadDefaultValue: Boolean;
  3098. Name : String;
  3099. Value : TPasExpr;
  3100. i, OldArgCount: Integer;
  3101. Arg: TPasArgument;
  3102. Access: TArgumentAccess;
  3103. ArgType: TPasType;
  3104. begin
  3105. LastHadDefaultValue := false;
  3106. while True do
  3107. begin
  3108. OldArgCount:=Args.Count;
  3109. Access := argDefault;
  3110. IsUntyped := False;
  3111. ArgType := nil;
  3112. while True do
  3113. begin
  3114. NextToken;
  3115. if CurToken = tkConst then
  3116. begin
  3117. Access := argConst;
  3118. Name := ExpectIdentifier;
  3119. end else if CurToken = tkConstRef then
  3120. begin
  3121. Access := argConstref;
  3122. Name := ExpectIdentifier;
  3123. end else if CurToken = tkVar then
  3124. begin
  3125. Access := ArgVar;
  3126. Name := ExpectIdentifier;
  3127. end else if (CurToken = tkIdentifier) and (UpperCase(CurTokenString) = 'OUT') then
  3128. begin
  3129. Access := ArgOut;
  3130. Name := ExpectIdentifier;
  3131. end else if CurToken = tkIdentifier then
  3132. Name := CurTokenString
  3133. else
  3134. ParseExc(nParserExpectedConstVarID,SParserExpectedConstVarID);
  3135. Arg := TPasArgument(CreateElement(TPasArgument, Name, Parent));
  3136. Arg.Access := Access;
  3137. Args.Add(Arg);
  3138. NextToken;
  3139. if CurToken = tkColon then
  3140. break
  3141. else if ((CurToken = tkSemicolon) or (CurToken = tkBraceClose)) and
  3142. (Access <> argDefault) then
  3143. begin
  3144. // found an untyped const or var argument
  3145. UngetToken;
  3146. IsUntyped := True;
  3147. break
  3148. end
  3149. else if CurToken <> tkComma then
  3150. ParseExc(nParserExpectedCommaColon,SParserExpectedCommaColon);
  3151. end;
  3152. Value:=Nil;
  3153. if not IsUntyped then
  3154. begin
  3155. Arg := TPasArgument(Args[0]);
  3156. ArgType := ParseType(Arg,Scanner.CurSourcePos);
  3157. ok:=false;
  3158. try
  3159. NextToken;
  3160. if CurToken = tkEqual then
  3161. begin
  3162. if (Args.Count>OldArgCount+1) then
  3163. begin
  3164. ArgType.Release;
  3165. ArgType:=nil;
  3166. ParseExc(nParserOnlyOneArgumentCanHaveDefault,SParserOnlyOneArgumentCanHaveDefault);
  3167. end;
  3168. if Parent is TPasProperty then
  3169. ParseExc(nParserPropertyArgumentsCanNotHaveDefaultValues,
  3170. SParserPropertyArgumentsCanNotHaveDefaultValues);
  3171. NextToken;
  3172. Value := DoParseExpression(Parent,Nil);
  3173. // After this, we're on ), which must be unget.
  3174. LastHadDefaultValue:=true;
  3175. end
  3176. else if LastHadDefaultValue then
  3177. ParseExc(nParserDefaultParameterRequiredFor,
  3178. SParserDefaultParameterRequiredFor,[TPasArgument(Args[OldArgCount]).Name]);
  3179. UngetToken;
  3180. ok:=true;
  3181. finally
  3182. if (not ok) and (ArgType<>nil) then
  3183. ArgType.Release;
  3184. end;
  3185. end;
  3186. for i := OldArgCount to Args.Count - 1 do
  3187. begin
  3188. Arg := TPasArgument(Args[i]);
  3189. Arg.ArgType := ArgType;
  3190. if Assigned(ArgType) then
  3191. begin
  3192. if (i > OldArgCount) then
  3193. ArgType.AddRef;
  3194. end;
  3195. Arg.ValueExpr := Value;
  3196. Value:=Nil; // Only the first gets a value. OK, since Var A,B : Integer = 1 is not allowed.
  3197. end;
  3198. for i := OldArgCount to Args.Count - 1 do
  3199. Engine.FinishScope(stDeclaration,TPasArgument(Args[i]));
  3200. NextToken;
  3201. if (CurToken = tkIdentifier) and (LowerCase(CurTokenString) = 'location') then
  3202. begin
  3203. NextToken; // remove 'location'
  3204. NextToken; // remove register
  3205. end;
  3206. if CurToken = EndToken then
  3207. break;
  3208. end;
  3209. end;
  3210. function TPasParser.CheckProcedureArgs(Parent: TPasElement; Args: TFPList;
  3211. Mandatory: Boolean): boolean;
  3212. begin
  3213. NextToken;
  3214. case CurToken of
  3215. tkBraceOpen:
  3216. begin
  3217. Result:=true;
  3218. NextToken;
  3219. if (CurToken<>tkBraceClose) then
  3220. begin
  3221. UngetToken;
  3222. ParseArgList(Parent, Args, tkBraceClose);
  3223. end;
  3224. end;
  3225. tkSemicolon,tkColon,tkof,tkis,tkIdentifier:
  3226. begin
  3227. Result:=false;
  3228. if Mandatory then
  3229. ParseExc(nParserExpectedLBracketColon,SParserExpectedLBracketColon)
  3230. else
  3231. UngetToken;
  3232. end
  3233. else
  3234. ParseExcTokenError(';');
  3235. end;
  3236. end;
  3237. procedure TPasParser.HandleProcedureModifier(Parent: TPasElement; pm: TProcedureModifier);
  3238. Var
  3239. Tok : String;
  3240. P : TPasProcedure;
  3241. E : TPasExpr;
  3242. procedure AddModifier;
  3243. begin
  3244. if pm in P.Modifiers then
  3245. ParseExcSyntaxError;
  3246. P.AddModifier(pm);
  3247. end;
  3248. begin
  3249. P:=TPasProcedure(Parent);
  3250. if pm<>pmPublic then
  3251. AddModifier;
  3252. Case pm of
  3253. pmExternal:
  3254. begin
  3255. NextToken;
  3256. if CurToken in [tkString,tkIdentifier] then
  3257. begin
  3258. // external libname
  3259. // external libname name XYZ
  3260. // external name XYZ
  3261. Tok:=UpperCase(CurTokenString);
  3262. if Not ((CurToken=tkIdentifier) and (Tok='NAME')) then
  3263. begin
  3264. E:=DoParseExpression(Parent);
  3265. if Assigned(P) then
  3266. P.LibraryExpr:=E;
  3267. end;
  3268. if CurToken=tkSemicolon then
  3269. UnGetToken
  3270. else
  3271. begin
  3272. Tok:=UpperCase(CurTokenString);
  3273. if ((CurToken=tkIdentifier) and (Tok='NAME')) then
  3274. begin
  3275. NextToken;
  3276. if not (CurToken in [tkChar,tkString,tkIdentifier]) then
  3277. ParseExcTokenError(TokenInfos[tkString]);
  3278. E:=DoParseExpression(Parent);
  3279. if Assigned(P) then
  3280. P.LibrarySymbolName:=E;
  3281. end;
  3282. end;
  3283. end
  3284. else
  3285. UngetToken;
  3286. end;
  3287. pmPublic:
  3288. begin
  3289. NextToken;
  3290. If not CurTokenIsIdentifier('name') then
  3291. begin
  3292. if P.Parent is TPasClassType then
  3293. begin
  3294. // public section starts
  3295. UngetToken;
  3296. UngetToken;
  3297. exit;
  3298. end;
  3299. AddModifier;
  3300. CheckToken(tkSemicolon);
  3301. exit;
  3302. end
  3303. else
  3304. begin
  3305. AddModifier;
  3306. NextToken; // Should be export name string.
  3307. if not (CurToken in [tkString,tkIdentifier]) then
  3308. ParseExcTokenError(TokenInfos[tkString]);
  3309. E:=DoParseExpression(Parent);
  3310. if Parent is TPasProcedure then
  3311. TPasProcedure(Parent).PublicName:=E;
  3312. if (CurToken <> tkSemicolon) then
  3313. ParseExcTokenError(TokenInfos[tkSemicolon]);
  3314. end;
  3315. end;
  3316. pmForward:
  3317. begin
  3318. if (Parent.Parent is TInterfaceSection) then
  3319. begin
  3320. ParseExc(nParserForwardNotInterface,SParserForwardNotInterface);
  3321. UngetToken;
  3322. end;
  3323. end;
  3324. pmMessage:
  3325. begin
  3326. Repeat
  3327. NextToken;
  3328. If CurToken<>tkSemicolon then
  3329. begin
  3330. if Parent is TPasProcedure then
  3331. TPasProcedure(Parent).MessageName:=CurtokenString;
  3332. If (CurToken=tkString) and (Parent is TPasProcedure) then
  3333. TPasProcedure(Parent).Messagetype:=pmtString;
  3334. end;
  3335. until CurToken = tkSemicolon;
  3336. UngetToken;
  3337. end;
  3338. pmDispID:
  3339. begin
  3340. TPasProcedure(Parent).DispIDExpr:=DoParseExpression(Parent,Nil);
  3341. if CurToken = tkSemicolon then
  3342. UngetToken;
  3343. end;
  3344. end; // Case
  3345. end;
  3346. procedure TPasParser.HandleProcedureTypeModifier(ProcType: TPasProcedureType;
  3347. ptm: TProcTypeModifier);
  3348. begin
  3349. if ptm in ProcType.Modifiers then
  3350. ParseExcSyntaxError;
  3351. Include(ProcType.Modifiers,ptm);
  3352. end;
  3353. // Next token is expected to be a "(", ";" or for a function ":". The caller
  3354. // will get the token after the final ";" as next token.
  3355. procedure TPasParser.ParseProcedureOrFunctionHeader(Parent: TPasElement;
  3356. Element: TPasProcedureType; ProcType: TProcType; OfObjectPossible: Boolean);
  3357. Function FindInSection(AName : String;ASection : TPasSection) : Boolean;
  3358. Var
  3359. I : integer;
  3360. Cn,FN : String;
  3361. CT : TPasClassType;
  3362. begin
  3363. // ToDo: add an event for the resolver to use a faster lookup
  3364. I:=ASection.Functions.Count-1;
  3365. While (I>=0) and (CompareText(TPasElement(ASection.Functions[I]).Name,AName)<>0) do
  3366. Dec(I);
  3367. Result:=I<>-1;
  3368. I:=Pos('.',AName);
  3369. if (Not Result) and (I<>0) then
  3370. begin
  3371. CN:=Copy(AName,1,I-1);
  3372. FN:=Aname;
  3373. Delete(FN,1,I);
  3374. I:=Asection.Classes.Count-1;
  3375. While Not Result and (I>=0) do
  3376. begin
  3377. CT:=TPasClassType(ASection.Classes[i]);
  3378. if CompareText(CT.Name,CN)=0 then
  3379. Result:=CT.FindMember(TPasFunction, FN)<>Nil;
  3380. Dec(I);
  3381. end;
  3382. end;
  3383. end;
  3384. procedure ConsumeSemi;
  3385. begin
  3386. NextToken;
  3387. if (CurToken <> tkSemicolon) and IsCurTokenHint then
  3388. UngetToken;
  3389. end;
  3390. function DoCheckHint : Boolean;
  3391. var
  3392. ahint : TPasMemberHint;
  3393. begin
  3394. Result:= IsCurTokenHint(ahint);
  3395. if Result then // deprecated,platform,experimental,library, unimplemented etc
  3396. begin
  3397. Element.Hints:=Element.Hints+[ahint];
  3398. if aHint=hDeprecated then
  3399. begin
  3400. NextToken;
  3401. if (CurToken<>tkString) then
  3402. UngetToken
  3403. else
  3404. Element.HintMessage:=CurTokenString;
  3405. end;
  3406. end;
  3407. end;
  3408. Var
  3409. Tok : String;
  3410. CC : TCallingConvention;
  3411. PM : TProcedureModifier;
  3412. Done: Boolean;
  3413. ResultEl: TPasResultElement;
  3414. OK,IsProc : Boolean;
  3415. PTM: TProcTypeModifier;
  3416. ModCount: Integer;
  3417. LastToken: TToken;
  3418. begin
  3419. // Element must be non-nil. Removed all checks for not-nil.
  3420. // If it is nil, the following fails anyway.
  3421. CheckProcedureArgs(Element,Element.Args,ProcType in [ptOperator,ptClassOperator]);
  3422. IsProc:=Parent is TPasProcedure;
  3423. case ProcType of
  3424. ptFunction,ptClassFunction:
  3425. begin
  3426. NextToken;
  3427. if CurToken = tkColon then
  3428. begin
  3429. ResultEl:=TPasFunctionType(Element).ResultEl;
  3430. ResultEl.ResultType := ParseType(ResultEl,Scanner.CurSourcePos);
  3431. end
  3432. // In Delphi mode, the implementation in the implementation section can be without result as it was declared
  3433. // We actually check if the function exists in the interface section.
  3434. else if (msDelphi in CurrentModeswitches) and
  3435. (Assigned(CurModule.ImplementationSection) or
  3436. (CurModule is TPasProgram)) then
  3437. begin
  3438. if Assigned(CurModule.InterfaceSection) then
  3439. OK:=FindInSection(Parent.Name,CurModule.InterfaceSection)
  3440. else if (CurModule is TPasProgram) and Assigned(TPasProgram(CurModule).ProgramSection) then
  3441. OK:=FindInSection(Parent.Name,TPasProgram(CurModule).ProgramSection);
  3442. if Not OK then
  3443. CheckToken(tkColon)
  3444. else
  3445. begin
  3446. CheckToken(tkSemiColon);
  3447. UngetToken;
  3448. end;
  3449. end
  3450. else
  3451. begin
  3452. // Raise error
  3453. CheckToken(tkColon);
  3454. end;
  3455. end;
  3456. ptOperator,ptClassOperator:
  3457. begin
  3458. NextToken;
  3459. ResultEl:=TPasFunctionType(Element).ResultEl;
  3460. if (CurToken=tkIdentifier) then
  3461. begin
  3462. ResultEl.Name := CurTokenName;
  3463. ExpectToken(tkColon);
  3464. end
  3465. else
  3466. if (CurToken=tkColon) then
  3467. ResultEl.Name := 'Result'
  3468. else
  3469. ParseExc(nParserExpectedColonID,SParserExpectedColonID);
  3470. ResultEl.ResultType := ParseType(ResultEl,Scanner.CurSourcePos)
  3471. end;
  3472. end;
  3473. if OfObjectPossible then
  3474. begin
  3475. NextToken;
  3476. if (CurToken = tkOf) then
  3477. begin
  3478. ExpectToken(tkObject);
  3479. Element.IsOfObject := True;
  3480. end
  3481. else if (CurToken = tkIs) then
  3482. begin
  3483. expectToken(tkIdentifier);
  3484. if (lowerCase(CurTokenString)<>'nested') then
  3485. ParseExc(nParserExpectedNested,SParserExpectedNested);
  3486. Element.IsNested:=True;
  3487. end
  3488. else
  3489. UnGetToken;
  3490. end;
  3491. ModCount:=0;
  3492. Repeat
  3493. inc(ModCount);
  3494. LastToken:=CurToken;
  3495. NextToken;
  3496. if (ModCount=1) and (CurToken = tkEqual) then
  3497. begin
  3498. // for example: const p: procedure = nil;
  3499. UngetToken;
  3500. exit;
  3501. end;
  3502. If CurToken=tkSemicolon then
  3503. begin
  3504. if LastToken=tkSemicolon then
  3505. ParseExcSyntaxError;
  3506. end
  3507. else if TokenIsCallingConvention(CurTokenString,cc) then
  3508. begin
  3509. Element.CallingConvention:=Cc;
  3510. if cc = ccSysCall then
  3511. begin
  3512. // remove LibBase
  3513. NextToken;
  3514. if CurToken=tkSemiColon then
  3515. UngetToken
  3516. else
  3517. // remove legacy or basesysv on MorphOS syscalls
  3518. begin
  3519. if CurTokenIsIdentifier('legacy') or CurTokenIsIdentifier('BaseSysV') then
  3520. NextToken;
  3521. NextToken; // remove offset
  3522. end;
  3523. end;
  3524. ExpectToken(tkSemicolon);
  3525. end
  3526. else if IsProc and TokenIsProcedureModifier(Parent,CurTokenString,PM) then
  3527. HandleProcedureModifier(Parent,PM)
  3528. else if TokenIsProcedureTypeModifier(Parent,CurTokenString,PTM) then
  3529. HandleProcedureTypeModifier(Element,PTM)
  3530. else if (CurToken=tklibrary) then // library is a token and a directive.
  3531. begin
  3532. Tok:=UpperCase(CurTokenString);
  3533. NextToken;
  3534. If (tok<>'NAME') then
  3535. Element.Hints:=Element.Hints+[hLibrary]
  3536. else
  3537. begin
  3538. NextToken; // Should be export name string.
  3539. ExpectToken(tkSemicolon);
  3540. end;
  3541. end
  3542. else if DoCheckHint then
  3543. ConsumeSemi
  3544. else if (CurToken=tkIdentifier) and (CompareText(CurTokenText,'alias')=0) then
  3545. begin
  3546. ExpectToken(tkColon);
  3547. ExpectToken(tkString);
  3548. if (Parent is TPasProcedure) then
  3549. (Parent as TPasProcedure).AliasName:=CurTokenText;
  3550. ExpectToken(tkSemicolon);
  3551. end
  3552. else if (CurToken = tkSquaredBraceOpen) then
  3553. begin
  3554. repeat
  3555. NextToken
  3556. until CurToken = tkSquaredBraceClose;
  3557. ExpectToken(tkSemicolon);
  3558. end
  3559. else
  3560. CheckToken(tkSemicolon);
  3561. Done:=(CurToken=tkSemiColon);
  3562. if Done then
  3563. begin
  3564. NextToken;
  3565. Done:=Not ((Curtoken=tkSquaredBraceOpen) or
  3566. TokenIsProcedureModifier(Parent,CurtokenString,PM) or
  3567. TokenIsProcedureTypeModifier(Parent,CurtokenString,PTM) or
  3568. IsCurTokenHint() or
  3569. TokenIsCallingConvention(CurTokenString,cc) or
  3570. (CurToken=tkIdentifier) and (CompareText(CurTokenText,'alias')=0));
  3571. // DumpCurToken('Done '+IntToStr(Ord(Done)));
  3572. UngetToken;
  3573. end;
  3574. // Writeln('Done: ',TokenInfos[Curtoken],' ',CurtokenString);
  3575. Until Done;
  3576. if DoCheckHint then // deprecated,platform,experimental,library, unimplemented etc
  3577. ConsumeSemi;
  3578. if (ProcType in [ptOperator,ptClassOperator]) and (Parent is TPasOperator) then
  3579. TPasOperator(Parent).CorrectName;
  3580. Engine.FinishScope(stProcedureHeader,Element);
  3581. if (Parent is TPasProcedure)
  3582. and (not TPasProcedure(Parent).IsForward)
  3583. and (not TPasProcedure(Parent).IsExternal)
  3584. and ((Parent.Parent is TImplementationSection)
  3585. or (Parent.Parent is TProcedureBody))
  3586. then
  3587. ParseProcedureBody(Parent);
  3588. if Parent is TPasProcedure then
  3589. Engine.FinishScope(stProcedure,Parent);
  3590. end;
  3591. // starts after the semicolon
  3592. procedure TPasParser.ParseProcedureBody(Parent: TPasElement);
  3593. var
  3594. Body: TProcedureBody;
  3595. begin
  3596. Body := TProcedureBody(CreateElement(TProcedureBody, '', Parent));
  3597. TPasProcedure(Parent).Body:=Body;
  3598. ParseDeclarations(Body);
  3599. end;
  3600. function TPasParser.ParseProperty(Parent: TPasElement; const AName: String;
  3601. AVisibility: TPasMemberVisibility; IsClassField: boolean): TPasProperty;
  3602. function GetAccessorName(aParent: TPasElement; out Expr: TPasExpr): String;
  3603. var
  3604. Params: TParamsExpr;
  3605. Param: TPasExpr;
  3606. begin
  3607. ExpectIdentifier;
  3608. Result := CurTokenString;
  3609. Expr := CreatePrimitiveExpr(aParent,pekIdent,CurTokenString);
  3610. // read .subident.subident...
  3611. repeat
  3612. NextToken;
  3613. if CurToken <> tkDot then break;
  3614. ExpectIdentifier;
  3615. Result := Result + '.' + CurTokenString;
  3616. AddToBinaryExprChain(Expr,CreatePrimitiveExpr(aParent,pekIdent,CurTokenString),eopSubIdent);
  3617. until false;
  3618. // read optional array index
  3619. if CurToken <> tkSquaredBraceOpen then
  3620. UnGetToken
  3621. else
  3622. begin
  3623. Result := Result + '[';
  3624. Params:=TParamsExpr(CreateElement(TParamsExpr,'',aParent));
  3625. Params.Kind:=pekArrayParams;
  3626. AddParamsToBinaryExprChain(Expr,Params);
  3627. NextToken;
  3628. case CurToken of
  3629. tkChar: Param:=CreatePrimitiveExpr(aParent,pekString, CurTokenText);
  3630. tkNumber: Param:=CreatePrimitiveExpr(aParent,pekNumber, CurTokenString);
  3631. tkIdentifier: Param:=CreatePrimitiveExpr(aParent,pekIdent, CurTokenText);
  3632. tkfalse, tktrue: Param:=CreateBoolConstExpr(aParent,pekBoolConst, CurToken=tktrue);
  3633. else
  3634. ParseExcExpectedIdentifier;
  3635. end;
  3636. Params.AddParam(Param);
  3637. Result := Result + CurTokenString;
  3638. ExpectToken(tkSquaredBraceClose);
  3639. Result := Result + ']';
  3640. end;
  3641. repeat
  3642. NextToken;
  3643. if CurToken <> tkDot then
  3644. begin
  3645. UngetToken;
  3646. break;
  3647. end;
  3648. ExpectIdentifier;
  3649. Result := Result + '.' + CurTokenString;
  3650. AddToBinaryExprChain(Expr,CreatePrimitiveExpr(aParent,pekIdent,CurTokenString),eopSubIdent);
  3651. until false;
  3652. end;
  3653. var
  3654. isArray , ok: Boolean;
  3655. h : TPasMemberHint;
  3656. begin
  3657. Result:=TPasProperty(CreateElement(TPasProperty,AName,Parent,AVisibility));
  3658. if IsClassField then
  3659. Include(Result.VarModifiers,vmClass);
  3660. ok:=false;
  3661. try
  3662. NextToken;
  3663. isArray:=CurToken=tkSquaredBraceOpen;
  3664. if isArray then
  3665. begin
  3666. ParseArgList(Result, Result.Args, tkSquaredBraceClose);
  3667. NextToken;
  3668. end;
  3669. if CurToken = tkColon then
  3670. begin
  3671. Result.VarType := ParseType(Result,Scanner.CurSourcePos);
  3672. NextToken;
  3673. end;
  3674. if CurTokenIsIdentifier('INDEX') then
  3675. begin
  3676. NextToken;
  3677. Result.IndexExpr := DoParseExpression(Result);
  3678. end;
  3679. if CurTokenIsIdentifier('READ') then
  3680. begin
  3681. Result.ReadAccessorName := GetAccessorName(Result,Result.ReadAccessor);
  3682. NextToken;
  3683. end;
  3684. if CurTokenIsIdentifier('WRITE') then
  3685. begin
  3686. Result.WriteAccessorName := GetAccessorName(Result,Result.WriteAccessor);
  3687. NextToken;
  3688. end;
  3689. if CurTokenIsIdentifier('READONLY') then
  3690. begin
  3691. Result.DispIDReadOnly:=True;
  3692. NextToken;
  3693. end;
  3694. if CurTokenIsIdentifier('DISPID') then
  3695. begin
  3696. NextToken;
  3697. Result.DispIDExpr := DoParseExpression(Result,Nil);
  3698. NextToken;
  3699. end;
  3700. if CurTokenIsIdentifier('IMPLEMENTS') then
  3701. begin
  3702. Result.ImplementsName := GetAccessorName(Result,Result.ImplementsFunc);
  3703. NextToken;
  3704. end;
  3705. if CurTokenIsIdentifier('STORED') then
  3706. begin
  3707. NextToken;
  3708. if CurToken = tkTrue then
  3709. Result.StoredAccessorName := 'True'
  3710. else if CurToken = tkFalse then
  3711. Result.StoredAccessorName := 'False'
  3712. else if CurToken = tkIdentifier then
  3713. begin
  3714. UngetToken;
  3715. Result.StoredAccessorName := GetAccessorName(Result,Result.StoredAccessor);
  3716. end
  3717. else
  3718. ParseExcSyntaxError;
  3719. NextToken;
  3720. end;
  3721. if CurTokenIsIdentifier('DEFAULT') then
  3722. begin
  3723. if isArray then
  3724. ParseExc(nParserArrayPropertiesCannotHaveDefaultValue,SParserArrayPropertiesCannotHaveDefaultValue);
  3725. NextToken;
  3726. Result.DefaultExpr := DoParseExpression(Result);
  3727. // NextToken;
  3728. end
  3729. else if CurtokenIsIdentifier('NODEFAULT') then
  3730. begin
  3731. Result.IsNodefault:=true;
  3732. if Result.DefaultExpr<>nil then
  3733. ParseExcSyntaxError;
  3734. NextToken;
  3735. end;
  3736. // Here the property ends. There can still be a 'default'
  3737. if CurToken = tkSemicolon then
  3738. NextToken;
  3739. if CurTokenIsIdentifier('DEFAULT') then
  3740. begin
  3741. if (Result.VarType<>Nil) and (not isArray) then
  3742. ParseExc(nParserDefaultPropertyMustBeArray,SParserDefaultPropertyMustBeArray);
  3743. NextToken;
  3744. if CurToken = tkSemicolon then
  3745. begin
  3746. Result.IsDefault := True;
  3747. NextToken;
  3748. end
  3749. end;
  3750. // Handle hints
  3751. while IsCurTokenHint(h) do
  3752. begin
  3753. Result.Hints:=Result.Hints+[h];
  3754. NextToken;
  3755. if CurToken=tkSemicolon then
  3756. NextToken;
  3757. end;
  3758. UngetToken;
  3759. ok:=true;
  3760. finally
  3761. if not ok then
  3762. Result.Release;
  3763. end;
  3764. Engine.FinishScope(stDeclaration,Result);
  3765. end;
  3766. // Starts after the "begin" token
  3767. procedure TPasParser.ParseProcBeginBlock(Parent: TProcedureBody);
  3768. var
  3769. BeginBlock: TPasImplBeginBlock;
  3770. SubBlock: TPasImplElement;
  3771. begin
  3772. BeginBlock := TPasImplBeginBlock(CreateElement(TPasImplBeginBlock, '', Parent));
  3773. Parent.Body := BeginBlock;
  3774. repeat
  3775. NextToken;
  3776. // writeln('TPasParser.ParseProcBeginBlock ',curtokenstring);
  3777. if CurToken=tkend then
  3778. break
  3779. else if CurToken<>tkSemiColon then
  3780. begin
  3781. UngetToken;
  3782. ParseStatement(BeginBlock,SubBlock);
  3783. if SubBlock=nil then
  3784. ExpectToken(tkend);
  3785. end;
  3786. until false;
  3787. ExpectToken(tkSemicolon);
  3788. // writeln('TPasParser.ParseProcBeginBlock ended ',curtokenstring);
  3789. end;
  3790. procedure TPasParser.ParseProcAsmBlock(Parent: TProcedureBody);
  3791. var
  3792. AsmBlock: TPasImplAsmStatement;
  3793. begin
  3794. AsmBlock:=TPasImplAsmStatement(CreateElement(TPasImplAsmStatement,'',Parent));
  3795. Parent.Body:=AsmBlock;
  3796. ParseAsmBlock(AsmBlock);
  3797. ExpectToken(tkSemicolon);
  3798. end;
  3799. procedure TPasParser.ParseAsmBlock(AsmBlock: TPasImplAsmStatement);
  3800. begin
  3801. if po_asmwhole in Options then
  3802. begin
  3803. FTokenBufferIndex:=1;
  3804. FTokenBufferSize:=1;
  3805. FCommentsBuffer[0].Clear;
  3806. repeat
  3807. Scanner.ReadNonPascalTillEndToken(true);
  3808. case Scanner.CurToken of
  3809. tkLineEnding:
  3810. AsmBlock.Tokens.Add(Scanner.CurTokenString);
  3811. tkend:
  3812. begin
  3813. FTokenBuffer[0] := tkend;
  3814. FTokenStringBuffer[0] := Scanner.CurTokenString;
  3815. break;
  3816. end
  3817. else
  3818. begin
  3819. // missing end
  3820. FTokenBuffer[0] := tkEOF;
  3821. FTokenStringBuffer[0] := '';
  3822. end;
  3823. end;
  3824. until false;
  3825. FCurToken := FTokenBuffer[0];
  3826. FCurTokenString := FTokenStringBuffer[0];
  3827. FCurComments:=FCommentsBuffer[0];
  3828. CheckToken(tkend);
  3829. end
  3830. else
  3831. begin
  3832. NextToken;
  3833. While CurToken<>tkEnd do
  3834. begin
  3835. // ToDo: allow @@end
  3836. AsmBlock.Tokens.Add(CurTokenText);
  3837. NextToken;
  3838. end;
  3839. end;
  3840. // NextToken; // Eat end.
  3841. // Do not consume end. Current token will normally be end;
  3842. end;
  3843. // Next token is start of (compound) statement
  3844. // After parsing CurToken is on last token of statement
  3845. procedure TPasParser.ParseStatement(Parent: TPasImplBlock;
  3846. out NewImplElement: TPasImplElement);
  3847. var
  3848. CurBlock: TPasImplBlock;
  3849. {$IFDEF VerbosePasParser}
  3850. function i: string;
  3851. var
  3852. c: TPasElement;
  3853. begin
  3854. Result:='ParseImplCompoundStatement ';
  3855. c:=CurBlock;
  3856. while c<>nil do begin
  3857. Result:=Result+' ';
  3858. c:=c.Parent;
  3859. end;
  3860. end;
  3861. {$ENDIF}
  3862. function CloseBlock: boolean; // true if parent reached
  3863. begin
  3864. if CurBlock.ClassType=TPasImplExceptOn then
  3865. Engine.FinishScope(stExceptOnStatement,CurBlock);
  3866. CurBlock:=CurBlock.Parent as TPasImplBlock;
  3867. Result:=CurBlock=Parent;
  3868. end;
  3869. function CloseStatement(CloseIfs: boolean): boolean; // true if parent reached
  3870. begin
  3871. if CurBlock=Parent then exit(true);
  3872. while CurBlock.CloseOnSemicolon
  3873. or (CloseIfs and (CurBlock is TPasImplIfElse)) do
  3874. if CloseBlock then exit(true);
  3875. Result:=false;
  3876. end;
  3877. procedure CreateBlock(NewBlock: TPasImplBlock);
  3878. begin
  3879. CurBlock.AddElement(NewBlock);
  3880. CurBlock:=NewBlock;
  3881. if NewImplElement=nil then NewImplElement:=CurBlock;
  3882. end;
  3883. var
  3884. SubBlock: TPasImplElement;
  3885. CmdElem: TPasImplElement;
  3886. left, right: TPasExpr;
  3887. El : TPasImplElement;
  3888. ak : TAssignKind;
  3889. lt : TLoopType;
  3890. ok: Boolean;
  3891. SrcPos: TPasSourcePos;
  3892. Name: String;
  3893. TypeEl: TPasType;
  3894. begin
  3895. NewImplElement:=nil;
  3896. CurBlock := Parent;
  3897. while True do
  3898. begin
  3899. NextToken;
  3900. // WriteLn({$IFDEF VerbosePasParser}i,{$ENDIF}' Token=',CurTokenText);
  3901. case CurToken of
  3902. tkasm:
  3903. begin
  3904. El:=TPasImplElement(CreateElement(TPasImplAsmStatement,'',CurBlock));
  3905. ParseAsmBlock(TPasImplAsmStatement(El));
  3906. CurBlock.AddElement(El);
  3907. if NewImplElement=nil then NewImplElement:=CurBlock;
  3908. if CloseStatement(true) then
  3909. break;
  3910. end;
  3911. tkbegin:
  3912. begin
  3913. El:=TPasImplElement(CreateElement(TPasImplBeginBlock,'',CurBlock));
  3914. CreateBlock(TPasImplBeginBlock(El));
  3915. end;
  3916. tkrepeat:
  3917. begin
  3918. El:=TPasImplRepeatUntil(CreateElement(TPasImplRepeatUntil,'',CurBlock));
  3919. CreateBlock(TPasImplRepeatUntil(El));
  3920. end;
  3921. tkIf:
  3922. begin
  3923. NextToken;
  3924. Left:=DoParseExpression(CurBlock);
  3925. UngetToken;
  3926. El:=TPasImplIfElse(CreateElement(TPasImplIfElse,'',CurBlock));
  3927. TPasImplIfElse(El).ConditionExpr:=Left;
  3928. Left.Parent:=El;
  3929. //WriteLn(i,'IF Condition="',Condition,'" Token=',CurTokenText);
  3930. CreateBlock(TPasImplIfElse(El));
  3931. ExpectToken(tkthen);
  3932. end;
  3933. tkelse:
  3934. if (CurBlock is TPasImplIfElse) then
  3935. begin
  3936. if TPasImplIfElse(CurBlock).IfBranch=nil then
  3937. begin
  3938. El:=TPasImplCommand(CreateElement(TPasImplCommand,'', CurBlock));
  3939. CurBlock.AddElement(El);
  3940. end;
  3941. if TPasImplIfElse(CurBlock).ElseBranch<>nil then
  3942. begin
  3943. // this and the following 3 may solve TPasImplIfElse.AddElement BUG
  3944. // ifs without begin end
  3945. // if .. then
  3946. // if .. then
  3947. // else
  3948. // else
  3949. CloseBlock;
  3950. CloseStatement(false);
  3951. end;
  3952. // Case ... else without semicolon in front.
  3953. end else if (CurBlock is TPasImplCaseStatement) then
  3954. begin
  3955. UngetToken;
  3956. CloseStatement(False);
  3957. exit;
  3958. end else if (CurBlock is TPasImplWhileDo) then
  3959. begin
  3960. CloseBlock;
  3961. UngetToken;
  3962. end else if (CurBlock is TPasImplForLoop) then
  3963. begin
  3964. //if .. then for .. do smt else ..
  3965. CloseBlock;
  3966. UngetToken;
  3967. end else if (CurBlock is TPasImplWithDo) then
  3968. begin
  3969. //if .. then with .. do smt else ..
  3970. CloseBlock;
  3971. UngetToken;
  3972. end else if (CurBlock is TPasImplRaise) then
  3973. begin
  3974. //if .. then Raise Exception else ..
  3975. CloseBlock;
  3976. UngetToken;
  3977. end else if (CurBlock is TPasImplTryExcept) then
  3978. begin
  3979. CloseBlock;
  3980. El:=TPasImplTryExceptElse(CreateElement(TPasImplTryExceptElse,'',CurBlock));
  3981. TPasImplTry(CurBlock).ElseBranch:=TPasImplTryExceptElse(El);
  3982. CurBlock:=TPasImplTryExceptElse(El);
  3983. end else
  3984. ParseExcSyntaxError;
  3985. tkwhile:
  3986. begin
  3987. // while Condition do
  3988. NextToken;
  3989. left:=DoParseExpression(CurBlock);
  3990. UngetToken;
  3991. //WriteLn(i,'WHILE Condition="',Condition,'" Token=',CurTokenText);
  3992. El:=TPasImplWhileDo(CreateElement(TPasImplWhileDo,'',CurBlock));
  3993. TPasImplWhileDo(El).ConditionExpr:=left;
  3994. CreateBlock(TPasImplWhileDo(El));
  3995. ExpectToken(tkdo);
  3996. end;
  3997. tkgoto:
  3998. begin
  3999. NextToken;
  4000. curblock.AddCommand('goto '+curtokenstring);
  4001. // expecttoken(tkSemiColon);
  4002. end;
  4003. tkfor:
  4004. begin
  4005. // for VarName := StartValue to EndValue do
  4006. // for VarName in Expression do
  4007. El:=TPasImplForLoop(CreateElement(TPasImplForLoop,'',CurBlock));
  4008. ok:=false;
  4009. Try
  4010. ExpectIdentifier;
  4011. Left:=CreatePrimitiveExpr(El,pekIdent,CurTokenString);
  4012. TPasImplForLoop(El).VariableName:=Left;
  4013. repeat
  4014. NextToken;
  4015. case CurToken of
  4016. tkAssign:
  4017. begin
  4018. lt:=ltNormal;
  4019. break;
  4020. end;
  4021. tkin:
  4022. begin
  4023. lt:=ltIn;
  4024. break;
  4025. end;
  4026. tkDot:
  4027. begin
  4028. ExpectIdentifier;
  4029. AddToBinaryExprChain(Left,
  4030. CreatePrimitiveExpr(El,pekIdent,CurTokenString), eopSubIdent);
  4031. TPasImplForLoop(El).VariableName:=Left;
  4032. end;
  4033. else
  4034. ParseExc(nParserExpectedAssignIn,SParserExpectedAssignIn);
  4035. end;
  4036. until false;
  4037. NextToken;
  4038. TPasImplForLoop(El).StartExpr:=DoParseExpression(El);
  4039. if (Lt=ltNormal) then
  4040. begin
  4041. if Not (CurToken in [tkTo,tkDownTo]) then
  4042. ParseExcTokenError(TokenInfos[tkTo]);
  4043. if CurToken=tkdownto then
  4044. Lt:=ltDown;
  4045. NextToken;
  4046. TPasImplForLoop(El).EndExpr:=DoParseExpression(El);
  4047. end;
  4048. TPasImplForLoop(El).LoopType:=lt;
  4049. if (CurToken<>tkDo) then
  4050. ParseExcTokenError(TokenInfos[tkDo]);
  4051. ok:=true;
  4052. finally
  4053. if not ok then
  4054. El.Release;
  4055. end;
  4056. CreateBlock(TPasImplForLoop(El));
  4057. //WriteLn(i,'FOR "',VarName,'" := ',StartValue,' to ',EndValue,' Token=',CurTokenText);
  4058. end;
  4059. tkwith:
  4060. begin
  4061. // with Expr do
  4062. // with Expr, Expr do
  4063. SrcPos:=Scanner.CurSourcePos;
  4064. NextToken;
  4065. Left:=DoParseExpression(CurBlock);
  4066. //writeln(i,'WITH Expr="',Expr,'" Token=',CurTokenText);
  4067. El:=TPasImplWithDo(CreateElement(TPasImplWithDo,'',CurBlock,SrcPos));
  4068. TPasImplWithDo(El).AddExpression(Left);
  4069. Left.Parent:=El;
  4070. CreateBlock(TPasImplWithDo(El));
  4071. repeat
  4072. if CurToken=tkdo then break;
  4073. if CurToken<>tkComma then
  4074. ParseExcTokenError(TokenInfos[tkdo]);
  4075. NextToken;
  4076. Left:=DoParseExpression(CurBlock);
  4077. //writeln(i,'WITH ...,Expr="',Expr,'" Token=',CurTokenText);
  4078. TPasImplWithDo(CurBlock).AddExpression(Left);
  4079. until false;
  4080. end;
  4081. tkcase:
  4082. begin
  4083. NextToken;
  4084. Left:=DoParseExpression(CurBlock);
  4085. UngetToken;
  4086. //writeln(i,'CASE OF Expr="',Expr,'" Token=',CurTokenText);
  4087. ExpectToken(tkof);
  4088. El:=TPasImplCaseOf(CreateElement(TPasImplCaseOf,'',CurBlock));
  4089. TPasImplCaseOf(El).CaseExpr:=Left;
  4090. Left.Parent:=El;
  4091. CreateBlock(TPasImplCaseOf(El));
  4092. repeat
  4093. NextToken;
  4094. //writeln(i,'CASE OF Token=',CurTokenText);
  4095. case CurToken of
  4096. tkend:
  4097. begin
  4098. if CurBlock.Elements.Count=0 then
  4099. ParseExc(nParserExpectCase,SParserExpectCase);
  4100. break; // end without else
  4101. end;
  4102. tkelse:
  4103. begin
  4104. // create case-else block
  4105. El:=TPasImplCaseElse(CreateElement(TPasImplCaseElse,'',CurBlock));
  4106. TPasImplCaseOf(CurBlock).ElseBranch:=TPasImplCaseElse(El);
  4107. CreateBlock(TPasImplCaseElse(El));
  4108. break;
  4109. end
  4110. else
  4111. // read case values
  4112. if (curToken=tkIdentifier) and (LowerCase(CurtokenString)='otherwise') then
  4113. begin
  4114. // create case-else block
  4115. El:=TPasImplCaseElse(CreateElement(TPasImplCaseElse,'',CurBlock));
  4116. TPasImplCaseOf(CurBlock).ElseBranch:=TPasImplCaseElse(El);
  4117. CreateBlock(TPasImplCaseElse(El));
  4118. break;
  4119. end
  4120. else
  4121. repeat
  4122. Left:=DoParseExpression(CurBlock);
  4123. //writeln(i,'CASE value="',Expr,'" Token=',CurTokenText);
  4124. if CurBlock is TPasImplCaseStatement then
  4125. TPasImplCaseStatement(CurBlock).Expressions.Add(Left)
  4126. else
  4127. begin
  4128. El:=TPasImplCaseStatement(CreateElement(TPasImplCaseStatement,'',CurBlock));
  4129. TPasImplCaseStatement(El).AddExpression(Left);
  4130. CurBlock.AddElement(El);
  4131. CurBlock:=TPasImplCaseStatement(El);
  4132. end;
  4133. //writeln(i,'CASE after value Token=',CurTokenText);
  4134. if (CurToken=tkComma) then
  4135. NextToken
  4136. else if (CurToken<>tkColon) then
  4137. ParseExcTokenError(TokenInfos[tkComma]);
  4138. until Curtoken=tkColon;
  4139. // read statement
  4140. ParseStatement(CurBlock,SubBlock);
  4141. CloseBlock;
  4142. if CurToken<>tkSemicolon then
  4143. begin
  4144. NextToken;
  4145. if not (CurToken in [tkSemicolon,tkelse,tkend]) then
  4146. ParseExcTokenError(TokenInfos[tkSemicolon]);
  4147. if CurToken<>tkSemicolon then
  4148. UngetToken;
  4149. end;
  4150. end;
  4151. until false;
  4152. if CurToken=tkend then
  4153. begin
  4154. if CloseBlock then break;
  4155. if CloseStatement(false) then break;
  4156. end;
  4157. end;
  4158. tktry:
  4159. begin
  4160. El:=TPasImplTry(CreateElement(TPasImplTry,'',CurBlock));
  4161. CreateBlock(TPasImplTry(El));
  4162. end;
  4163. tkfinally:
  4164. begin
  4165. if CloseStatement(true) then
  4166. begin
  4167. UngetToken;
  4168. break;
  4169. end;
  4170. if CurBlock is TPasImplTry then
  4171. begin
  4172. El:=TPasImplTryFinally(CreateElement(TPasImplTryFinally,'',CurBlock));
  4173. TPasImplTry(CurBlock).FinallyExcept:=TPasImplTryFinally(El);
  4174. CurBlock:=TPasImplTryFinally(El);
  4175. end else
  4176. ParseExcSyntaxError;
  4177. end;
  4178. tkexcept:
  4179. begin
  4180. if CloseStatement(true) then
  4181. begin
  4182. UngetToken;
  4183. break;
  4184. end;
  4185. if CurBlock is TPasImplTry then
  4186. begin
  4187. //writeln(i,'EXCEPT');
  4188. El:=TPasImplTryExcept(CreateElement(TPasImplTryExcept,'',CurBlock));
  4189. TPasImplTry(CurBlock).FinallyExcept:=TPasImplTryExcept(El);
  4190. CurBlock:=TPasImplTryExcept(El);
  4191. end else
  4192. ParseExcSyntaxError;
  4193. end;
  4194. tkon:
  4195. begin
  4196. // in try except:
  4197. // on E: Exception do
  4198. // on Exception do
  4199. if CurBlock is TPasImplTryExcept then
  4200. begin
  4201. ExpectIdentifier;
  4202. El:=TPasImplExceptOn(CreateElement(TPasImplExceptOn,'',CurBlock));
  4203. SrcPos:=Scanner.CurSourcePos;
  4204. Name:=CurTokenString;
  4205. NextToken;
  4206. //writeln('ON t=',Name,' Token=',CurTokenText);
  4207. if CurToken=tkColon then
  4208. begin
  4209. // the first expression was the variable name
  4210. NextToken;
  4211. TypeEl:=ParseSimpleType(El,SrcPos,'');
  4212. TPasImplExceptOn(El).TypeEl:=TypeEl;
  4213. TPasImplExceptOn(El).VarEl:=TPasVariable(CreateElement(TPasVariable,
  4214. Name,El,SrcPos));
  4215. TPasImplExceptOn(El).VarEl.VarType:=TypeEl;
  4216. TypeEl.AddRef;
  4217. end
  4218. else
  4219. begin
  4220. UngetToken;
  4221. TPasImplExceptOn(El).TypeEl:=ParseSimpleType(El,SrcPos,'');
  4222. end;
  4223. Engine.FinishScope(stExceptOnExpr,El);
  4224. CurBlock.AddElement(El);
  4225. CurBlock:=TPasImplExceptOn(El);
  4226. ExpectToken(tkDo);
  4227. end else
  4228. ParseExcSyntaxError;
  4229. end;
  4230. tkraise:
  4231. begin
  4232. El:=TPasImplRaise(CreateElement(TPasImplRaise,'',CurBlock));
  4233. CreateBlock(TPasImplRaise(El));
  4234. NextToken;
  4235. If Curtoken in [tkElse,tkEnd,tkSemicolon] then
  4236. UnGetToken
  4237. else
  4238. begin
  4239. TPasImplRaise(El).ExceptObject:=DoParseExpression(El);
  4240. if (CurToken=tkIdentifier) and (Uppercase(CurtokenString)='AT') then
  4241. begin
  4242. NextToken;
  4243. TPasImplRaise(El).ExceptAddr:=DoParseExpression(El);
  4244. end;
  4245. if Curtoken in [tkSemicolon,tkEnd] then
  4246. UngetToken
  4247. end;
  4248. end;
  4249. tkend:
  4250. begin
  4251. if CloseStatement(true) then
  4252. begin
  4253. UngetToken;
  4254. break;
  4255. end;
  4256. if CurBlock is TPasImplBeginBlock then
  4257. begin
  4258. if CloseBlock then break; // close end
  4259. if CloseStatement(false) then break;
  4260. end else if CurBlock is TPasImplCaseElse then
  4261. begin
  4262. if CloseBlock then break; // close else
  4263. if CloseBlock then break; // close caseof
  4264. if CloseStatement(false) then break;
  4265. end else if CurBlock is TPasImplTryHandler then
  4266. begin
  4267. if CloseBlock then break; // close finally/except
  4268. if CloseBlock then break; // close try
  4269. if CloseStatement(false) then break;
  4270. end else
  4271. ParseExcSyntaxError;
  4272. end;
  4273. tkSemiColon:
  4274. if CloseStatement(true) then break;
  4275. tkuntil:
  4276. begin
  4277. if CloseStatement(true) then
  4278. begin
  4279. UngetToken;
  4280. break;
  4281. end;
  4282. if CurBlock is TPasImplRepeatUntil then
  4283. begin
  4284. NextToken;
  4285. Left:=DoParseExpression(CurBlock);
  4286. UngetToken;
  4287. TPasImplRepeatUntil(CurBlock).ConditionExpr:=Left;
  4288. //WriteLn(i,'UNTIL Condition="',Condition,'" Token=',CurTokenString);
  4289. if CloseBlock then break;
  4290. end else
  4291. ParseExcSyntaxError;
  4292. end;
  4293. tkEOF:
  4294. CheckToken(tkend);
  4295. tkBraceOpen,tkIdentifier,tkNumber,tkSquaredBraceOpen,tkMinus,tkPlus,tkinherited:
  4296. begin
  4297. left:=DoParseExpression(CurBlock);
  4298. case CurToken of
  4299. tkAssign,
  4300. tkAssignPlus,
  4301. tkAssignMinus,
  4302. tkAssignMul,
  4303. tkAssignDivision:
  4304. begin
  4305. // assign statement
  4306. Ak:=TokenToAssignKind(CurToken);
  4307. NextToken;
  4308. right:=DoParseExpression(CurBlock); // this may solve TPasImplWhileDo.AddElement BUG
  4309. El:=TPasImplAssign(CreateElement(TPasImplAssign,'',CurBlock));
  4310. left.Parent:=El;
  4311. right.Parent:=El;
  4312. TPasImplAssign(El).left:=Left;
  4313. TPasImplAssign(El).right:=Right;
  4314. TPasImplAssign(El).Kind:=ak;
  4315. CurBlock.AddElement(El);
  4316. CmdElem:=TPasImplAssign(El);
  4317. UngetToken;
  4318. end;
  4319. tkColon:
  4320. begin
  4321. if not (left is TPrimitiveExpr) then
  4322. ParseExcTokenError(TokenInfos[tkSemicolon]);
  4323. // label mark. todo: check mark identifier in the list of labels
  4324. El:=TPasImplLabelMark(CreateElement(TPasImplLabelMark,'', CurBlock));
  4325. TPasImplLabelMark(El).LabelId:=TPrimitiveExpr(left).Value;
  4326. CurBlock.AddElement(El);
  4327. CmdElem:=TPasImplLabelMark(El);
  4328. left.Free;
  4329. end;
  4330. else
  4331. // simple statement (function call)
  4332. El:=TPasImplSimple(CreateElement(TPasImplSimple,'',CurBlock));
  4333. TPasImplSimple(El).expr:=Left;
  4334. CurBlock.AddElement(El);
  4335. CmdElem:=TPasImplSimple(El);
  4336. UngetToken;
  4337. end;
  4338. if not (CmdElem is TPasImplLabelMark) then
  4339. if NewImplElement=nil then NewImplElement:=CmdElem;
  4340. end;
  4341. else
  4342. ParseExcSyntaxError;
  4343. end;
  4344. end;
  4345. end;
  4346. procedure TPasParser.ParseLabels(AParent: TPasElement);
  4347. var
  4348. Labels: TPasLabels;
  4349. begin
  4350. Labels:=TPasLabels(CreateElement(TPasLabels, '', AParent));
  4351. repeat
  4352. Labels.Labels.Add(ExpectIdentifier);
  4353. NextToken;
  4354. if not (CurToken in [tkSemicolon, tkComma]) then
  4355. ParseExcTokenError(TokenInfos[tkSemicolon]);
  4356. until CurToken=tkSemicolon;
  4357. end;
  4358. // Starts after the "procedure" or "function" token
  4359. function TPasParser.GetProcedureClass(ProcType: TProcType): TPTreeElement;
  4360. begin
  4361. Case ProcType of
  4362. ptFunction : Result:=TPasFunction;
  4363. ptClassFunction : Result:=TPasClassFunction;
  4364. ptClassProcedure : Result:=TPasClassProcedure;
  4365. ptClassConstructor : Result:=TPasClassConstructor;
  4366. ptClassDestructor : Result:=TPasClassDestructor;
  4367. ptProcedure : Result:=TPasProcedure;
  4368. ptConstructor : Result:=TPasConstructor;
  4369. ptDestructor : Result:=TPasDestructor;
  4370. ptOperator : Result:=TPasOperator;
  4371. ptClassOperator : Result:=TPasClassOperator;
  4372. else
  4373. ParseExc(nParserUnknownProcedureType,SParserUnknownProcedureType,[Ord(ProcType)]);
  4374. end;
  4375. end;
  4376. function TPasParser.ParseProcedureOrFunctionDecl(Parent: TPasElement; ProcType: TProcType;AVisibility : TPasMemberVisibility = VisDefault): TPasProcedure;
  4377. function ExpectProcName: string;
  4378. Var
  4379. L : TFPList;
  4380. I : Integer;
  4381. begin
  4382. Result:=ExpectIdentifier;
  4383. //writeln('ExpectProcName ',Parent.Classname);
  4384. if Parent is TImplementationSection then
  4385. begin
  4386. NextToken;
  4387. While CurToken in [tkDot,tkLessThan] do
  4388. begin
  4389. if CurToken=tkDot then
  4390. Result:=Result+'.'+ExpectIdentifier
  4391. else
  4392. begin // <> can be ignored, we read the list but discard its content
  4393. UnGetToken;
  4394. L:=TFPList.Create;
  4395. Try
  4396. ReadGenericArguments(L,Parent);
  4397. finally
  4398. For I:=0 to L.Count-1 do
  4399. TPasElement(L[i]).Release;
  4400. L.Free;
  4401. end;
  4402. end;
  4403. NextToken;
  4404. end;
  4405. UngetToken;
  4406. end;
  4407. end;
  4408. var
  4409. Name: String;
  4410. PC : TPTreeElement;
  4411. Ot : TOperatorType;
  4412. IsTokenBased , ok: Boolean;
  4413. begin
  4414. If (Not (ProcType in [ptOperator,ptClassOperator])) then
  4415. Name:=ExpectProcName
  4416. else
  4417. begin
  4418. NextToken;
  4419. IsTokenBased:=Curtoken<>tkIdentifier;
  4420. if IsTokenBased then
  4421. OT:=TPasOperator.TokenToOperatorType(CurTokenText)
  4422. else
  4423. OT:=TPasOperator.NameToOperatorType(CurTokenString);
  4424. if (ot=otUnknown) then
  4425. ParseExc(nErrUnknownOperatorType,SErrUnknownOperatorType,[CurTokenString]);
  4426. Name:=OperatorNames[Ot];
  4427. end;
  4428. PC:=GetProcedureClass(ProcType);
  4429. Parent:=CheckIfOverLoaded(Parent,Name);
  4430. Result:=TPasProcedure(CreateElement(PC,Name,Parent,AVisibility));
  4431. ok:=false;
  4432. try
  4433. if Not (ProcType in [ptFunction, ptClassFunction, ptOperator, ptClassOperator]) then
  4434. Result.ProcType := TPasProcedureType(CreateElement(TPasProcedureType, '', Result))
  4435. else
  4436. begin
  4437. Result.ProcType := CreateFunctionType('', 'Result', Result, True, Scanner.CurSourcePos);
  4438. if (ProcType in [ptOperator, ptClassOperator]) then
  4439. begin
  4440. TPasOperator(Result).TokenBased:=IsTokenBased;
  4441. TPasOperator(Result).OperatorType:=OT;
  4442. TPasOperator(Result).CorrectName;
  4443. end;
  4444. end;
  4445. ParseProcedureOrFunctionHeader(Result, Result.ProcType, ProcType, False);
  4446. Result.Hints:=Result.ProcType.Hints;
  4447. Result.HintMessage:=Result.ProcType.HintMessage;
  4448. // + is detected as 'positive', but is in fact Add if there are 2 arguments.
  4449. if (ProcType in [ptOperator, ptClassOperator]) then
  4450. With TPasOperator(Result) do
  4451. begin
  4452. if (OperatorType in [otPositive, otNegative]) then
  4453. begin
  4454. if (ProcType.Args.Count>1) then
  4455. begin
  4456. Case OperatorType of
  4457. otPositive : OperatorType:=otPlus;
  4458. otNegative : OperatorType:=otMinus;
  4459. end;
  4460. Name:=OperatorNames[OperatorType];
  4461. TPasOperator(Result).CorrectName;
  4462. end;
  4463. end;
  4464. end;
  4465. ok:=true;
  4466. finally
  4467. if not ok then
  4468. Result.Release;
  4469. end;
  4470. end;
  4471. // Current token is the first token after tkOf
  4472. procedure TPasParser.ParseRecordVariantParts(ARec: TPasRecordType;
  4473. AEndToken: TToken);
  4474. Var
  4475. M : TPasRecordType;
  4476. V : TPasVariant;
  4477. Done : Boolean;
  4478. begin
  4479. Repeat
  4480. V:=TPasVariant(CreateElement(TPasVariant, '', ARec));
  4481. ARec.Variants.Add(V);
  4482. Repeat
  4483. NextToken;
  4484. V.Values.Add(DoParseExpression(ARec));
  4485. if Not (CurToken in [tkComma,tkColon]) then
  4486. ParseExc(nParserExpectedCommaColon,SParserExpectedCommaColon);
  4487. Until (curToken=tkColon);
  4488. ExpectToken(tkBraceOpen);
  4489. NextToken;
  4490. M:=TPasRecordType(CreateElement(TPasRecordType,'',V));
  4491. V.Members:=M;
  4492. ParseRecordFieldList(M,tkBraceClose,False);
  4493. // Current token is closing ), so we eat that
  4494. NextToken;
  4495. // If there is a semicolon, we eat that too.
  4496. if CurToken=tkSemicolon then
  4497. NextToken;
  4498. // ParseExpression starts with a nexttoken.
  4499. // So we need to determine the next token, and if it is an ending token, unget.
  4500. Done:=CurToken=AEndToken;
  4501. If not Done then
  4502. Ungettoken;
  4503. Until Done;
  4504. end;
  4505. procedure TPasParser.DumpCurToken(const Msg: String; IndentAction: TIndentAction
  4506. );
  4507. begin
  4508. if IndentAction=iaUndent then
  4509. FDumpIndent:=copy(FDumpIndent,1,Length(FDumpIndent)-2);
  4510. Writeln(FDumpIndent,Msg,' : ',TokenInfos[CurToken],' "',CurTokenString,'", Position: ',Scanner.CurFilename,'(',Scanner.CurRow,',',SCanner.CurColumn,') : ',Scanner.CurLine);
  4511. if IndentAction=iaIndent then
  4512. FDumpIndent:=FDumpIndent+' ';
  4513. Flush(output);
  4514. end;
  4515. function TPasParser.GetCurrentModeSwitches: TModeSwitches;
  4516. begin
  4517. if Assigned(FScanner) then
  4518. Result:=FScanner.CurrentModeSwitches
  4519. else
  4520. Result:=[msNone];
  4521. end;
  4522. procedure TPasParser.SetCurrentModeSwitches(AValue: TModeSwitches);
  4523. begin
  4524. if Assigned(FScanner) then
  4525. FScanner.CurrentModeSwitches:=AValue;
  4526. end;
  4527. // Starts on first token after Record or (. Ends on AEndToken
  4528. procedure TPasParser.ParseRecordFieldList(ARec: TPasRecordType;
  4529. AEndToken: TToken; AllowMethods: Boolean);
  4530. Var
  4531. VariantName : String;
  4532. v : TPasmemberVisibility;
  4533. Proc: TPasProcedure;
  4534. ProcType: TProcType;
  4535. Prop : TPasProperty;
  4536. Cons : TPasConst;
  4537. isClass : Boolean;
  4538. NamePos: TPasSourcePos;
  4539. OldCount, i: Integer;
  4540. begin
  4541. v:=visDefault;
  4542. isClass:=False;
  4543. while CurToken<>AEndToken do
  4544. begin
  4545. SaveComments;
  4546. Case CurToken of
  4547. tkConst:
  4548. begin
  4549. if Not AllowMethods then
  4550. ParseExc(nErrRecordConstantsNotAllowed,SErrRecordConstantsNotAllowed);
  4551. ExpectToken(tkIdentifier);
  4552. Cons:=ParseConstDecl(ARec);
  4553. Cons.Visibility:=v;
  4554. ARec.members.Add(Cons);
  4555. end;
  4556. tkClass:
  4557. begin
  4558. if Not AllowMethods then
  4559. ParseExc(nErrRecordMethodsNotAllowed,SErrRecordMethodsNotAllowed);
  4560. if isClass then
  4561. ParseExc(nParserTypeSyntaxError,SParserTypeSyntaxError);
  4562. isClass:=True;
  4563. end;
  4564. tkProperty:
  4565. begin
  4566. if Not AllowMethods then
  4567. ParseExc(nErrRecordPropertiesNotAllowed,SErrRecordPropertiesNotAllowed);
  4568. ExpectToken(tkIdentifier);
  4569. Prop:=ParseProperty(ARec,CurtokenString,v,isClass);
  4570. Arec.Members.Add(Prop);
  4571. end;
  4572. tkOperator,
  4573. tkProcedure,
  4574. tkConstructor,
  4575. tkFunction :
  4576. begin
  4577. if Not AllowMethods then
  4578. ParseExc(nErrRecordMethodsNotAllowed,SErrRecordMethodsNotAllowed);
  4579. ProcType:=GetProcTypeFromToken(CurToken,isClass);
  4580. Proc:=ParseProcedureOrFunctionDecl(ARec,ProcType,v);
  4581. if Proc.Parent is TPasOverloadedProc then
  4582. TPasOverloadedProc(Proc.Parent).Overloads.Add(Proc)
  4583. else
  4584. ARec.Members.Add(Proc);
  4585. end;
  4586. tkGeneric, // Counts as field name
  4587. tkIdentifier :
  4588. begin
  4589. if CheckVisibility(CurtokenString,v) then
  4590. begin
  4591. If not (msAdvancedRecords in Scanner.CurrentModeSwitches) then
  4592. ParseExc(nErrRecordVisibilityNotAllowed,SErrRecordVisibilityNotAllowed);
  4593. if not (v in [visPrivate,visPublic,visStrictPrivate]) then
  4594. ParseExc(nParserInvalidRecordVisibility,SParserInvalidRecordVisibility);
  4595. NextToken;
  4596. Continue;
  4597. end;
  4598. OldCount:=ARec.Members.Count;
  4599. ParseInlineVarDecl(ARec, ARec.Members, v, AEndToken=tkBraceClose);
  4600. for i:=OldCount to ARec.Members.Count-1 do
  4601. Engine.FinishScope(stDeclaration,TPasVariable(ARec.Members[i]));
  4602. end;
  4603. tkCase :
  4604. begin
  4605. ARec.Variants:=TFPList.Create;
  4606. NextToken;
  4607. VariantName:=CurTokenString;
  4608. NamePos:=Scanner.CurSourcePos;
  4609. NextToken;
  4610. If CurToken=tkColon then
  4611. begin
  4612. ARec.VariantEl:=TPasVariable(CreateElement(TPasVariable,VariantName,ARec,NamePos));
  4613. TPasVariable(ARec.VariantEl).VarType:=ParseType(ARec,Scanner.CurSourcePos);
  4614. end
  4615. else
  4616. begin
  4617. UnGetToken;
  4618. UnGetToken;
  4619. ARec.VariantEl:=ParseType(ARec,Scanner.CurSourcePos);
  4620. end;
  4621. ExpectToken(tkOf);
  4622. ParseRecordVariantParts(ARec,AEndToken);
  4623. end;
  4624. else
  4625. ParseExc(nParserTypeSyntaxError,SParserTypeSyntaxError);
  4626. end;
  4627. If CurToken<>tkClass then
  4628. isClass:=False;
  4629. if CurToken<>AEndToken then
  4630. NextToken;
  4631. end;
  4632. end;
  4633. // Starts after the "record" token
  4634. function TPasParser.ParseRecordDecl(Parent: TPasElement;
  4635. const NamePos: TPasSourcePos; const TypeName: string;
  4636. const Packmode: TPackMode): TPasRecordType;
  4637. var
  4638. ok: Boolean;
  4639. begin
  4640. Result := TPasRecordType(CreateElement(TPasRecordType, TypeName, Parent, NamePos));
  4641. ok:=false;
  4642. try
  4643. Result.PackMode:=PackMode;
  4644. NextToken;
  4645. ParseRecordFieldList(Result,tkEnd,true);
  4646. Engine.FinishScope(stTypeDef,Result);
  4647. ok:=true;
  4648. finally
  4649. if not ok then
  4650. Result.Release;
  4651. end;
  4652. end;
  4653. Function IsVisibility(S : String; var AVisibility :TPasMemberVisibility) : Boolean;
  4654. Const
  4655. VNames : array[TPasMemberVisibility] of string =
  4656. ('', 'private', 'protected', 'public', 'published', 'automated', '', '');
  4657. Var
  4658. V : TPasMemberVisibility;
  4659. begin
  4660. Result:=False;
  4661. S:=lowerCase(S);
  4662. For V :=Low(TPasMemberVisibility) to High(TPasMemberVisibility) do
  4663. begin
  4664. Result:=(VNames[V]<>'') and (S=VNames[V]);
  4665. if Result then
  4666. begin
  4667. AVisibility := v;
  4668. Exit;
  4669. end;
  4670. end;
  4671. end;
  4672. function TPasParser.CheckVisibility(S: String;
  4673. var AVisibility: TPasMemberVisibility): Boolean;
  4674. Var
  4675. B : Boolean;
  4676. begin
  4677. s := LowerCase(CurTokenString);
  4678. B:=(S='strict');
  4679. if B then
  4680. begin
  4681. NextToken;
  4682. s:=LowerCase(CurTokenString);
  4683. end;
  4684. Result:=isVisibility(S,AVisibility);
  4685. if Result then
  4686. begin
  4687. if B then
  4688. case AVisibility of
  4689. visPrivate : AVisibility:=visStrictPrivate;
  4690. visProtected : AVisibility:=visStrictProtected;
  4691. else
  4692. ParseExc(nParserStrangeVisibility,SParserStrangeVisibility,[S]);
  4693. end
  4694. end
  4695. else if B then
  4696. ParseExc(nParserExpectVisibility,SParserExpectVisibility);
  4697. end;
  4698. procedure TPasParser.ProcessMethod(AType: TPasClassType; IsClass : Boolean; AVisibility : TPasMemberVisibility);
  4699. var
  4700. Proc: TPasProcedure;
  4701. ProcType: TProcType;
  4702. begin
  4703. ProcType:=GetProcTypeFromToken(CurToken,isClass);
  4704. Proc:=ParseProcedureOrFunctionDecl(AType,ProcType,AVisibility);
  4705. if Proc.Parent is TPasOverloadedProc then
  4706. TPasOverloadedProc(Proc.Parent).Overloads.Add(Proc)
  4707. else
  4708. AType.Members.Add(Proc);
  4709. end;
  4710. procedure TPasParser.ParseClassFields(AType: TPasClassType;
  4711. const AVisibility: TPasMemberVisibility; IsClassField: Boolean);
  4712. Var
  4713. VarList: TFPList;
  4714. Element: TPasElement;
  4715. I : Integer;
  4716. isStatic : Boolean;
  4717. VarEl: TPasVariable;
  4718. begin
  4719. VarList := TFPList.Create;
  4720. try
  4721. ParseInlineVarDecl(AType, VarList, AVisibility, False);
  4722. if CurToken=tkSemicolon then
  4723. begin
  4724. NextToken;
  4725. isStatic:=CurTokenIsIdentifier('static');
  4726. if isStatic then
  4727. ExpectToken(tkSemicolon)
  4728. else
  4729. UngetToken;
  4730. end;
  4731. for i := 0 to VarList.Count - 1 do
  4732. begin
  4733. Element := TPasElement(VarList[i]);
  4734. Element.Visibility := AVisibility;
  4735. if (Element is TPasVariable) then
  4736. begin
  4737. VarEl:=TPasVariable(Element);
  4738. if IsClassField then
  4739. Include(VarEl.VarModifiers,vmClass);
  4740. if isStatic then
  4741. Include(VarEl.VarModifiers,vmStatic);
  4742. Engine.FinishScope(stDeclaration,VarEl);
  4743. end;
  4744. AType.Members.Add(Element);
  4745. end;
  4746. finally
  4747. VarList.Free;
  4748. end;
  4749. end;
  4750. procedure TPasParser.ParseClassLocalTypes(AType: TPasClassType; AVisibility : TPasMemberVisibility);
  4751. Var
  4752. T : TPasType;
  4753. Done : Boolean;
  4754. begin
  4755. // Writeln('Parsing local types');
  4756. Repeat
  4757. T:=ParseTypeDecl(AType);
  4758. T.Visibility:=AVisibility;
  4759. AType.Members.Add(t);
  4760. // Writeln(CurtokenString,' ',TokenInfos[Curtoken]);
  4761. NextToken;
  4762. Done:=(Curtoken<>tkIdentifier) or CheckVisibility(CurtokenString,AVisibility);
  4763. if Done then
  4764. UngetToken;
  4765. Until Done;
  4766. end;
  4767. procedure TPasParser.ParseClassLocalConsts(AType: TPasClassType; AVisibility : TPasMemberVisibility);
  4768. Var
  4769. C : TPasConst;
  4770. Done : Boolean;
  4771. begin
  4772. // Writeln('Parsing local consts');
  4773. Repeat
  4774. C:=ParseConstDecl(AType);
  4775. C.Visibility:=AVisibility;
  4776. AType.Members.Add(C);
  4777. // Writeln(CurtokenString,' ',TokenInfos[Curtoken]);
  4778. NextToken;
  4779. Done:=(Curtoken<>tkIdentifier) or CheckVisibility(CurtokenString,AVisibility);
  4780. if Done then
  4781. UngetToken;
  4782. Until Done;
  4783. end;
  4784. procedure TPasParser.ParseClassMembers(AType: TPasClassType);
  4785. Var
  4786. CurVisibility : TPasMemberVisibility;
  4787. begin
  4788. CurVisibility := visDefault;
  4789. while (CurToken<>tkEnd) do
  4790. begin
  4791. case CurToken of
  4792. tkType:
  4793. begin
  4794. ExpectToken(tkIdentifier);
  4795. SaveComments;
  4796. ParseClassLocalTypes(AType,CurVisibility);
  4797. end;
  4798. tkConst:
  4799. begin
  4800. ExpectToken(tkIdentifier);
  4801. SaveComments;
  4802. ParseClassLocalConsts(AType,CurVisibility);
  4803. end;
  4804. tkVar,
  4805. tkIdentifier:
  4806. begin
  4807. if (AType.ObjKind in [okInterface,okDispInterface]) then
  4808. ParseExc(nParserNoFieldsAllowed,SParserNoFieldsAllowed);
  4809. if CurToken=tkVar then
  4810. ExpectToken(tkIdentifier);
  4811. SaveComments;
  4812. if Not CheckVisibility(CurtokenString,CurVisibility) then
  4813. ParseClassFields(AType,CurVisibility,false);
  4814. end;
  4815. tkProcedure,tkFunction,tkConstructor,tkDestructor:
  4816. begin
  4817. SaveComments;
  4818. if (Curtoken in [tkConstructor,tkDestructor]) and (AType.ObjKind in [okInterface,okDispInterface,okRecordHelper]) then
  4819. ParseExc(nParserNoConstructorAllowed,SParserNoConstructorAllowed);
  4820. ProcessMethod(AType,False,CurVisibility);
  4821. end;
  4822. tkclass:
  4823. begin
  4824. SaveComments;
  4825. NextToken;
  4826. if CurToken in [tkConstructor,tkDestructor,tkProcedure,tkFunction] then
  4827. ProcessMethod(AType,True,CurVisibility)
  4828. else if CurToken = tkVar then
  4829. begin
  4830. ExpectToken(tkIdentifier);
  4831. ParseClassFields(AType,CurVisibility,true);
  4832. end
  4833. else if CurToken=tkProperty then
  4834. begin
  4835. ExpectToken(tkIdentifier);
  4836. AType.Members.Add(ParseProperty(AType,CurtokenString,CurVisibility,true));
  4837. end
  4838. else
  4839. ParseExc(nParserTypeSyntaxError,SParserTypeSyntaxError)
  4840. end;
  4841. tkProperty:
  4842. begin
  4843. SaveComments;
  4844. ExpectIdentifier;
  4845. AType.Members.Add(ParseProperty(AType,CurtokenString,CurVisibility,false));
  4846. end
  4847. else
  4848. CheckToken(tkIdentifier);
  4849. end;
  4850. NextToken;
  4851. end;
  4852. end;
  4853. procedure TPasParser.DoParseClassType(AType: TPasClassType);
  4854. var
  4855. Element : TPasElement;
  4856. s: String;
  4857. CT : TPasClassType;
  4858. begin
  4859. ct:=Nil;
  4860. // nettism/new delphi features
  4861. if (CurToken=tkIdentifier) and (Atype.ObjKind in [okClass,okGeneric]) then
  4862. begin
  4863. s := LowerCase(CurTokenString);
  4864. if (s = 'sealed') or (s = 'abstract') then
  4865. begin
  4866. AType.Modifiers.Add(s);
  4867. NextToken;
  4868. end;
  4869. end;
  4870. // Parse ancestor list
  4871. AType.IsForward:=(CurToken=tkSemiColon);
  4872. if (CurToken=tkBraceOpen) then
  4873. begin
  4874. AType.AncestorType := ParseType(AType,Scanner.CurSourcePos);
  4875. NextToken;
  4876. if curToken=tkLessthan then
  4877. CT := TPasClassType(CreateElement(TPasClassType, AType.AncestorType.Name, AType.Parent, Scanner.CurSourcePos));
  4878. UnGetToken ;
  4879. if Assigned(CT) then
  4880. try
  4881. CT.ObjKind := okSpecialize;
  4882. CT.AncestorType := TPasUnresolvedTypeRef.Create(AType.AncestorType.Name,AType.Parent);
  4883. CT.IsShortDefinition:=True;
  4884. ReadGenericArguments(CT.GenericTemplateTypes,CT);
  4885. AType.AncestorType.Release;
  4886. AType.AncestorType:=CT;
  4887. CT:=Nil;
  4888. Finally
  4889. FreeAndNil(CT);
  4890. end;
  4891. while True do
  4892. begin
  4893. NextToken;
  4894. if CurToken = tkBraceClose then
  4895. break ;
  4896. UngetToken;
  4897. ExpectToken(tkComma);
  4898. Element:=ParseType(AType,Scanner.CurSourcePos,'',False); // search interface.
  4899. if assigned(element) then
  4900. AType.Interfaces.add(element);
  4901. end;
  4902. NextToken;
  4903. AType.IsShortDefinition:=(CurToken=tkSemicolon);
  4904. end;
  4905. if (AType.ObjKind in [okClassHelper,okRecordHelper]) then
  4906. begin
  4907. if (CurToken<>tkFor) then
  4908. ParseExcTokenError(TokenInfos[tkFor]);
  4909. AType.HelperForType:=ParseType(AType,Scanner.CurSourcePos);
  4910. NextToken;
  4911. end;
  4912. Engine.FinishScope(stAncestors,AType);
  4913. if (AType.IsShortDefinition or AType.IsForward) then
  4914. UngetToken
  4915. else
  4916. begin
  4917. if (AType.ObjKind in [okInterface,okDispInterface]) and (CurToken = tkSquaredBraceOpen) then
  4918. begin
  4919. NextToken;
  4920. AType.GUIDExpr:=DoParseExpression(AType);
  4921. if (CurToken<>tkSquaredBraceClose) then
  4922. ParseExcTokenError(TokenInfos[tkSquaredBraceClose]);
  4923. NextToken;
  4924. end;
  4925. ParseClassMembers(AType);
  4926. end;
  4927. end;
  4928. function TPasParser.ParseClassDecl(Parent: TPasElement;
  4929. const NamePos: TPasSourcePos; const AClassName: String;
  4930. AObjKind: TPasObjKind; PackMode: TPackMode; GenericArgs: TFPList): TPasType;
  4931. Var
  4932. ok: Boolean;
  4933. FT : TPasType;
  4934. AExternalNameSpace,AExternalName : String;
  4935. PCT:TPasClassType;
  4936. begin
  4937. NextToken;
  4938. FT:=Nil;
  4939. if (AObjKind = okClass) and (CurToken = tkOf) then
  4940. begin
  4941. Result := TPasClassOfType(CreateElement(TPasClassOfType, AClassName,
  4942. Parent, NamePos));
  4943. ExpectIdentifier;
  4944. UngetToken; // Only names are allowed as following type
  4945. TPasClassOfType(Result).DestType := ParseType(Result,Scanner.CurSourcePos);
  4946. Engine.FinishScope(stTypeDef,Result);
  4947. exit;
  4948. end;
  4949. if ((AobjKind in [okClass,OKInterface]) and (msExternalClass in CurrentModeswitches) and CurTokenIsIdentifier('external')) then
  4950. begin
  4951. NextToken;
  4952. if CurToken<>tkString then
  4953. UnGetToken
  4954. else
  4955. AExternalNameSpace:=CurTokenString;
  4956. ExpectIdentifier;
  4957. If Not CurTokenIsIdentifier('Name') then
  4958. ParseExc(nParserExpectedExternalClassName,SParserExpectedExternalClassName);
  4959. NextToken;
  4960. if not (CurToken in [tkChar,tkString]) then
  4961. CheckToken(tkString);
  4962. AExternalName:=CurTokenString;
  4963. NextToken;
  4964. end
  4965. else
  4966. begin
  4967. AExternalNameSpace:='';
  4968. AExternalName:='';
  4969. end;
  4970. if (CurTokenIsIdentifier('Helper')) then
  4971. begin
  4972. if Not (AObjKind in [okClass,okTypeHelper,okRecordHelper]) then
  4973. ParseExc(nParserHelperNotAllowed,SParserHelperNotAllowed,[ObjKindNames[AObjKind]]);
  4974. Case AObjKind of
  4975. okClass:
  4976. AObjKind:=okClassHelper;
  4977. okTypeHelper:
  4978. begin
  4979. ExpectToken(tkFor);
  4980. FT:=ParseType(Parent,Scanner.CurSourcePos,'',False);
  4981. end
  4982. end;
  4983. NextToken;
  4984. end;
  4985. PCT := TPasClassType(CreateElement(TPasClassType, AClassName,
  4986. Parent, NamePos));
  4987. Result:=PCT;
  4988. PCT.HelperForType:=FT;
  4989. PCT.IsExternal:=(AExternalName<>'');
  4990. if AExternalName<>'' then
  4991. PCT.ExternalName:=AnsiDequotedStr(AExternalName,'''');
  4992. if AExternalNameSpace<>'' then
  4993. PCT.ExternalNameSpace:=AnsiDequotedStr(AExternalNameSpace,'''');
  4994. ok:=false;
  4995. try
  4996. PCT.ObjKind := AObjKind;
  4997. PCT.PackMode:=PackMode;
  4998. if Assigned(GenericArgs) then
  4999. PCT.SetGenericTemplates(GenericArgs);
  5000. DoParseClassType(PCT);
  5001. Engine.FinishScope(stTypeDef,Result);
  5002. ok:=true;
  5003. finally
  5004. if not ok then
  5005. Result.Release;
  5006. end;
  5007. end;
  5008. function TPasParser.CreateElement(AClass: TPTreeElement; const AName: String;
  5009. AParent: TPasElement): TPasElement;
  5010. begin
  5011. Result := Engine.CreateElement(AClass, AName, AParent, visDefault, Scanner.CurSourcePos);
  5012. end;
  5013. function TPasParser.CreateElement(AClass: TPTreeElement; const AName: String;
  5014. AParent: TPasElement; const ASrcPos: TPasSourcePos): TPasElement;
  5015. begin
  5016. Result := Engine.CreateElement(AClass, AName, AParent, visDefault, ASrcPos);
  5017. end;
  5018. function TPasParser.CreateElement(AClass: TPTreeElement; const AName: String;
  5019. AParent: TPasElement; AVisibility: TPasMemberVisibility): TPasElement;
  5020. begin
  5021. Result := Engine.CreateElement(AClass, AName, AParent, AVisibility,
  5022. Scanner.CurSourcePos);
  5023. end;
  5024. function TPasParser.CreateElement(AClass: TPTreeElement; const AName: String;
  5025. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  5026. const ASrcPos: TPasSourcePos): TPasElement;
  5027. begin
  5028. Result := Engine.CreateElement(AClass, AName, AParent, AVisibility, ASrcPos);
  5029. end;
  5030. function TPasParser.CreatePrimitiveExpr(AParent: TPasElement;
  5031. AKind: TPasExprKind; const AValue: String): TPrimitiveExpr;
  5032. begin
  5033. Result:=TPrimitiveExpr(CreateElement(TPrimitiveExpr,'',AParent));
  5034. Result.Kind:=AKind;
  5035. Result.Value:=AValue;
  5036. end;
  5037. function TPasParser.CreateBoolConstExpr(AParent: TPasElement;
  5038. AKind: TPasExprKind; const ABoolValue: Boolean): TBoolConstExpr;
  5039. begin
  5040. Result:=TBoolConstExpr(CreateElement(TBoolConstExpr,'',AParent));
  5041. Result.Kind:=AKind;
  5042. Result.Value:=ABoolValue;
  5043. end;
  5044. function TPasParser.CreateBinaryExpr(AParent: TPasElement; xleft,
  5045. xright: TPasExpr; AOpCode: TExprOpCode): TBinaryExpr;
  5046. begin
  5047. Result:=TBinaryExpr(CreateElement(TBinaryExpr,'',AParent));
  5048. Result.OpCode:=AOpCode;
  5049. Result.Kind:=pekBinary;
  5050. if xleft<>nil then
  5051. begin
  5052. Result.left:=xleft;
  5053. xleft.Parent:=Result;
  5054. end;
  5055. if xright<>nil then
  5056. begin
  5057. Result.right:=xright;
  5058. xright.Parent:=Result;
  5059. end;
  5060. end;
  5061. procedure TPasParser.AddToBinaryExprChain(var ChainFirst: TPasExpr;
  5062. Element: TPasExpr; AOpCode: TExprOpCode);
  5063. begin
  5064. if Element=nil then
  5065. exit
  5066. else if ChainFirst=nil then
  5067. begin
  5068. // empty chain => simply add element, no need to create TBinaryExpr
  5069. ChainFirst:=Element;
  5070. end
  5071. else
  5072. begin
  5073. // create new binary, old becomes left, Element right
  5074. ChainFirst:=CreateBinaryExpr(ChainFirst.Parent,ChainFirst,Element,AOpCode);
  5075. end;
  5076. end;
  5077. procedure TPasParser.AddParamsToBinaryExprChain(var ChainFirst: TPasExpr;
  5078. Params: TParamsExpr);
  5079. // append Params to chain, using the last(right) element as Params.Value
  5080. var
  5081. Bin: TBinaryExpr;
  5082. begin
  5083. if Params.Value<>nil then
  5084. ParseExcSyntaxError;
  5085. if ChainFirst=nil then
  5086. ParseExcSyntaxError;
  5087. if ChainFirst is TBinaryExpr then
  5088. begin
  5089. Bin:=TBinaryExpr(ChainFirst);
  5090. if Bin.left=nil then
  5091. ParseExcSyntaxError;
  5092. if Bin.right=nil then
  5093. ParseExcSyntaxError;
  5094. Params.Value:=Bin.right;
  5095. Params.Value.Parent:=Params;
  5096. Bin.right:=Params;
  5097. Params.Parent:=Bin;
  5098. end
  5099. else
  5100. begin
  5101. Params.Value:=ChainFirst;
  5102. Params.Parent:=ChainFirst.Parent;
  5103. ChainFirst.Parent:=Params;
  5104. ChainFirst:=Params;
  5105. end;
  5106. end;
  5107. {$IFDEF VerbosePasParser}
  5108. procedure TPasParser.WriteBinaryExprChain(Prefix: string; First, Last: TPasExpr
  5109. );
  5110. var
  5111. i: Integer;
  5112. begin
  5113. if First=nil then
  5114. begin
  5115. write(Prefix,'First=nil');
  5116. if Last=nil then
  5117. writeln('=Last')
  5118. else
  5119. begin
  5120. writeln(', ERROR Last=',Last.ClassName);
  5121. ParseExcSyntaxError;
  5122. end;
  5123. end
  5124. else if Last=nil then
  5125. begin
  5126. writeln(Prefix,'ERROR Last=nil First=',First.ClassName);
  5127. ParseExcSyntaxError;
  5128. end
  5129. else if First is TBinaryExpr then
  5130. begin
  5131. i:=0;
  5132. while First is TBinaryExpr do
  5133. begin
  5134. writeln(Prefix,Space(i*2),'bin.left=',TBinaryExpr(First).left.ClassName);
  5135. if First=Last then break;
  5136. First:=TBinaryExpr(First).right;
  5137. inc(i);
  5138. end;
  5139. if First<>Last then
  5140. begin
  5141. writeln(Prefix,Space(i*2),'ERROR Last is not last in chain');
  5142. ParseExcSyntaxError;
  5143. end;
  5144. if not (Last is TBinaryExpr) then
  5145. begin
  5146. writeln(Prefix,Space(i*2),'ERROR Last is not TBinaryExpr: ',Last.ClassName);
  5147. ParseExcSyntaxError;
  5148. end;
  5149. if TBinaryExpr(Last).right=nil then
  5150. begin
  5151. writeln(Prefix,Space(i*2),'ERROR Last.right=nil');
  5152. ParseExcSyntaxError;
  5153. end;
  5154. writeln(Prefix,Space(i*2),'last.right=',TBinaryExpr(Last).right.ClassName);
  5155. end
  5156. else if First=Last then
  5157. writeln(Prefix,'First=Last=',First.ClassName)
  5158. else
  5159. begin
  5160. write(Prefix,'ERROR First=',First.ClassName);
  5161. if Last<>nil then
  5162. writeln(' Last=',Last.ClassName)
  5163. else
  5164. writeln(' Last=nil');
  5165. end;
  5166. end;
  5167. {$ENDIF}
  5168. function TPasParser.CreateUnaryExpr(AParent: TPasElement; AOperand: TPasExpr;
  5169. AOpCode: TExprOpCode): TUnaryExpr;
  5170. begin
  5171. Result:=TUnaryExpr(CreateElement(TUnaryExpr,'',AParent));
  5172. Result.Kind:=pekUnary;
  5173. Result.Operand:=AOperand;
  5174. Result.Operand.Parent:=Result;
  5175. Result.OpCode:=AOpCode;
  5176. end;
  5177. function TPasParser.CreateArrayValues(AParent: TPasElement): TArrayValues;
  5178. begin
  5179. Result:=TArrayValues(CreateElement(TArrayValues,'',AParent));
  5180. Result.Kind:=pekListOfExp;
  5181. end;
  5182. function TPasParser.CreateFunctionType(const AName, AResultName: String;
  5183. AParent: TPasElement; UseParentAsResultParent: Boolean;
  5184. const NamePos: TPasSourcePos): TPasFunctionType;
  5185. begin
  5186. Result:=Engine.CreateFunctionType(AName,AResultName,
  5187. AParent,UseParentAsResultParent,
  5188. NamePos);
  5189. end;
  5190. function TPasParser.CreateInheritedExpr(AParent: TPasElement): TInheritedExpr;
  5191. begin
  5192. Result:=TInheritedExpr(CreateElement(TInheritedExpr,'',AParent));
  5193. Result.Kind:=pekInherited;
  5194. end;
  5195. function TPasParser.CreateSelfExpr(AParent: TPasElement): TSelfExpr;
  5196. begin
  5197. Result:=TSelfExpr(CreateElement(TSelfExpr,'Self',AParent));
  5198. Result.Kind:=pekSelf;
  5199. end;
  5200. function TPasParser.CreateNilExpr(AParent: TPasElement): TNilExpr;
  5201. begin
  5202. Result:=TNilExpr(CreateElement(TNilExpr,'nil',AParent));
  5203. Result.Kind:=pekNil;
  5204. end;
  5205. function TPasParser.CreateRecordValues(AParent: TPasElement): TRecordValues;
  5206. begin
  5207. Result:=TRecordValues(CreateElement(TRecordValues,'',AParent));
  5208. Result.Kind:=pekListOfExp;
  5209. end;
  5210. end.