pparser.pp 236 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733
  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. {$ifdef fpc}
  15. {$define UsePChar}
  16. {$define UseAnsiStrings}
  17. {$define HasStreams}
  18. {$IF FPC_FULLVERSION<30101}
  19. {$define EmulateArrayInsert}
  20. {$endif}
  21. {$define HasFS}
  22. {$endif}
  23. {$IFDEF NODEJS}
  24. {$define HasFS}
  25. {$ENDIF}
  26. unit PParser;
  27. interface
  28. uses
  29. {$ifdef NODEJS}
  30. NodeJSFS,
  31. {$endif}
  32. SysUtils, Classes, Types, PasTree, PScanner;
  33. // message numbers
  34. const
  35. nErrNoSourceGiven = 2001;
  36. nErrMultipleSourceFiles = 2002;
  37. nParserError = 2003;
  38. nParserErrorAtToken = 2004;
  39. nParserUngetTokenError = 2005;
  40. nParserExpectTokenError = 2006;
  41. nParserForwardNotInterface = 2007;
  42. nParserExpectVisibility = 2008;
  43. nParserStrangeVisibility = 2009;
  44. nParserExpectToken2Error = 2010;
  45. nParserExpectedCommaRBracket = 2011;
  46. nParserExpectedCommaSemicolon = 2012;
  47. nParserExpectedAssignIn = 2013;
  48. nParserExpectedCommaColon = 2014;
  49. nErrUnknownOperatorType = 2015;
  50. nParserOnlyOneArgumentCanHaveDefault = 2016;
  51. nParserExpectedLBracketColon = 2017;
  52. nParserExpectedSemiColonEnd = 2018;
  53. nParserExpectedConstVarID = 2019;
  54. nParserExpectedNested = 2020;
  55. nParserExpectedColonID = 2021;
  56. nParserSyntaxError = 2022;
  57. nParserTypeSyntaxError = 2023;
  58. nParserArrayTypeSyntaxError = 2024;
  59. nParserExpectedIdentifier = 2026;
  60. nParserNotAProcToken = 2026;
  61. nRangeExpressionExpected = 2027;
  62. nParserExpectCase = 2028;
  63. nParserGenericFunctionNeedsGenericKeyword = 2029;
  64. nLogStartImplementation = 2030;
  65. nLogStartInterface = 2031;
  66. nParserNoConstructorAllowed = 2032;
  67. nParserNoFieldsAllowed = 2033;
  68. nParserInvalidRecordVisibility = 2034;
  69. nErrRecordConstantsNotAllowed = 2035;
  70. nErrRecordMethodsNotAllowed = 2036;
  71. nErrRecordPropertiesNotAllowed = 2037;
  72. nErrRecordTypesNotAllowed = 2038;
  73. nParserTypeNotAllowedHere = 2039;
  74. nParserNotAnOperand = 2040;
  75. nParserArrayPropertiesCannotHaveDefaultValue = 2041;
  76. nParserDefaultPropertyMustBeArray = 2042;
  77. nParserUnknownProcedureType = 2043;
  78. nParserGenericArray1Element = 2044;
  79. nParserTypeParamsNotAllowedOnType = 2045;
  80. nParserDuplicateIdentifier = 2046;
  81. nParserDefaultParameterRequiredFor = 2047;
  82. nParserOnlyOneVariableCanBeInitialized = 2048;
  83. nParserExpectedTypeButGot = 2049;
  84. nParserPropertyArgumentsCanNotHaveDefaultValues = 2050;
  85. nParserExpectedExternalClassName = 2051;
  86. nParserNoConstRangeAllowed = 2052;
  87. nErrRecordVariablesNotAllowed = 2053;
  88. nParserResourcestringsMustBeGlobal = 2054;
  89. nParserOnlyOneVariableCanBeAbsolute = 2055;
  90. nParserXNotAllowedInY = 2056;
  91. nFileSystemsNotSupported = 2057;
  92. // resourcestring patterns of messages
  93. resourcestring
  94. SErrNoSourceGiven = 'No source file specified';
  95. SErrMultipleSourceFiles = 'Please specify only one source file';
  96. SParserError = 'Error';
  97. SParserErrorAtToken = '%s at token "%s" in file %s at line %d column %d';
  98. SParserUngetTokenError = 'Internal error: Cannot unget more tokens, history buffer is full';
  99. SParserExpectTokenError = 'Expected "%s"';
  100. SParserForwardNotInterface = 'The use of a FORWARD procedure modifier is not allowed in the interface';
  101. SParserExpectVisibility = 'Expected visibility specifier';
  102. SParserStrangeVisibility = 'Strange strict visibility encountered : "%s"';
  103. SParserExpectToken2Error = 'Expected "%s" or "%s"';
  104. SParserExpectedCommaRBracket = 'Expected "," or ")"';
  105. SParserExpectedCommaSemicolon = 'Expected "," or ";"';
  106. SParserExpectedAssignIn = 'Expected := or in';
  107. SParserExpectedCommaColon = 'Expected "," or ":"';
  108. SErrUnknownOperatorType = 'Unknown operator type: %s';
  109. SParserOnlyOneArgumentCanHaveDefault = 'A default value can only be assigned to 1 parameter';
  110. SParserExpectedLBracketColon = 'Expected "(" or ":"';
  111. SParserExpectedSemiColonEnd = 'Expected ";" or "End"';
  112. SParserExpectedConstVarID = 'Expected "const", "var" or identifier';
  113. SParserExpectedNested = 'Expected nested keyword';
  114. SParserExpectedColonID = 'Expected ":" or identifier';
  115. SParserSyntaxError = 'Syntax error';
  116. SParserTypeSyntaxError = 'Syntax error in type';
  117. SParserArrayTypeSyntaxError = 'Syntax error in array type';
  118. SParserExpectedIdentifier = 'Identifier expected';
  119. SParserNotAProcToken = 'Not a procedure or function token';
  120. SRangeExpressionExpected = 'Range expression expected';
  121. SParserExpectCase = 'Case label expression expected';
  122. SParserGenericFunctionNeedsGenericKeyword = 'Generic function needs keyword generic';
  123. SLogStartImplementation = 'Start parsing implementation section.';
  124. SLogStartInterface = 'Start parsing interface section';
  125. SParserNoConstructorAllowed = 'Constructors or Destructors are not allowed in Interfaces or Records';
  126. SParserNoFieldsAllowedInX = 'Fields are not allowed in %s';
  127. SParserInvalidRecordVisibility = 'Records can only have public and (strict) private as visibility specifiers';
  128. SErrRecordConstantsNotAllowed = 'Record constants not allowed at this location.';
  129. SErrRecordVariablesNotAllowed = 'Record variables not allowed at this location.';
  130. SErrRecordMethodsNotAllowed = 'Record methods not allowed at this location.';
  131. SErrRecordPropertiesNotAllowed = 'Record properties not allowed at this location.';
  132. SErrRecordTypesNotAllowed = 'Record types not allowed at this location.';
  133. SParserTypeNotAllowedHere = 'Type "%s" not allowed here';
  134. SParserNotAnOperand = 'Not an operand: (%d : %s)';
  135. SParserArrayPropertiesCannotHaveDefaultValue = 'Array properties cannot have default value';
  136. SParserDefaultPropertyMustBeArray = 'The default property must be an array property';
  137. SParserUnknownProcedureType = 'Unknown procedure type "%d"';
  138. SParserGenericArray1Element = 'Generic arrays can have only 1 template element';
  139. SParserTypeParamsNotAllowedOnType = 'Type parameters not allowed on this type';
  140. SParserDuplicateIdentifier = 'Duplicate identifier "%s"';
  141. SParserDefaultParameterRequiredFor = 'Default parameter required for "%s"';
  142. SParserOnlyOneVariableCanBeInitialized = 'Only one variable can be initialized';
  143. SParserExpectedTypeButGot = 'Expected type, but got %s';
  144. SParserPropertyArgumentsCanNotHaveDefaultValues = 'Property arguments can not have default values';
  145. SParserExpectedExternalClassName = 'Expected external class name';
  146. SParserNoConstRangeAllowed = 'Const ranges are not allowed';
  147. SParserResourcestringsMustBeGlobal = 'Resourcestrings can be only static or global';
  148. SParserOnlyOneVariableCanBeAbsolute = 'Only one variable can be absolute';
  149. SParserXNotAllowedInY = '%s is not allowed in %s';
  150. SErrFileSystemNotSupported = 'No support for filesystems enabled';
  151. type
  152. TPasScopeType = (
  153. stModule, // e.g. unit, program, library
  154. stUsesClause,
  155. stTypeSection,
  156. stTypeDef, // e.g. a TPasType
  157. stResourceString, // e.g. TPasResString
  158. stProcedure, // also method, procedure, constructor, destructor, ...
  159. stProcedureHeader,
  160. stWithExpr, // calls BeginScope after parsing every WITH-expression
  161. stExceptOnExpr,
  162. stExceptOnStatement,
  163. stForLoopHeader,
  164. stDeclaration, // e.g. a TPasProperty, TPasVariable, TPasArgument, ...
  165. stAncestors, // the list of ancestors and interfaces of a class
  166. stInitialFinalization
  167. );
  168. TPasScopeTypes = set of TPasScopeType;
  169. TPasParserLogHandler = Procedure (Sender : TObject; Const Msg : String) of object;
  170. TPParserLogEvent = (pleInterface,pleImplementation);
  171. TPParserLogEvents = set of TPParserLogEvent;
  172. TPasParser = Class;
  173. { TPasTreeContainer }
  174. TPasTreeContainer = class
  175. private
  176. FCurrentParser: TPasParser;
  177. FNeedComments: Boolean;
  178. FOnLog: TPasParserLogHandler;
  179. FPParserLogEvents: TPParserLogEvents;
  180. FScannerLogEvents: TPScannerLogEvents;
  181. protected
  182. FPackage: TPasPackage;
  183. FInterfaceOnly : Boolean;
  184. procedure SetCurrentParser(AValue: TPasParser); virtual;
  185. public
  186. function CreateElement(AClass: TPTreeElement; const AName: String;
  187. AParent: TPasElement; const ASourceFilename: String;
  188. ASourceLinenumber: Integer): TPasElement;overload;
  189. function CreateElement(AClass: TPTreeElement; const AName: String;
  190. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  191. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;overload;
  192. virtual; abstract;
  193. function CreateElement(AClass: TPTreeElement; const AName: String;
  194. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  195. const ASrcPos: TPasSourcePos; TypeParams: TFPList = nil): TPasElement; overload;
  196. virtual;
  197. function CreateFunctionType(const AName, AResultName: String; AParent: TPasElement;
  198. UseParentAsResultParent: Boolean; const ASrcPos: TPasSourcePos; TypeParams: TFPList = nil): TPasFunctionType;
  199. function FindElement(const AName: String): TPasElement; virtual; abstract;
  200. function FindElementFor(const AName: String; AParent: TPasElement; TypeParamCount: integer): TPasElement; virtual;
  201. procedure BeginScope(ScopeType: TPasScopeType; El: TPasElement); virtual;
  202. procedure FinishScope(ScopeType: TPasScopeType; El: TPasElement); virtual;
  203. procedure FinishTypeAlias(var aType: TPasType); virtual;
  204. function FindModule(const AName: String): TPasModule; virtual;
  205. function FindModule(const AName: String; NameExpr, InFileExpr: TPasExpr): TPasModule; virtual;
  206. function CheckPendingUsedInterface(Section: TPasSection): boolean; virtual; // true if changed
  207. function NeedArrayValues(El: TPasElement): boolean; virtual;
  208. function GetDefaultClassVisibility(AClass: TPasClassType): TPasMemberVisibility; virtual;
  209. procedure ModeChanged(Sender: TObject; NewMode: TModeSwitch;
  210. Before: boolean; var Handled: boolean); virtual;
  211. property Package: TPasPackage read FPackage;
  212. property InterfaceOnly : Boolean Read FInterfaceOnly Write FInterFaceOnly;
  213. property ScannerLogEvents : TPScannerLogEvents Read FScannerLogEvents Write FScannerLogEvents;
  214. property ParserLogEvents : TPParserLogEvents Read FPParserLogEvents Write FPParserLogEvents;
  215. property OnLog : TPasParserLogHandler Read FOnLog Write FOnLog;
  216. property CurrentParser : TPasParser Read FCurrentParser Write SetCurrentParser;
  217. property NeedComments : Boolean Read FNeedComments Write FNeedComments;
  218. end;
  219. EParserError = class(Exception)
  220. private
  221. FFilename: String;
  222. FRow, FColumn: Integer;
  223. public
  224. constructor Create(const AReason, AFilename: String;
  225. ARow, AColumn: Integer); reintroduce;
  226. property Filename: String read FFilename;
  227. property Row: Integer read FRow;
  228. property Column: Integer read FColumn;
  229. end;
  230. TExprKind = (ek_Normal, ek_PropertyIndex);
  231. TIndentAction = (iaNone,iaIndent,iaUndent);
  232. { TPasParser }
  233. TPasParser = class
  234. private
  235. const FTokenRingSize = 32;
  236. type
  237. TTokenRec = record
  238. Token: TToken;
  239. AsString: String;
  240. Comments: TStrings;
  241. SourcePos: TPasSourcePos;
  242. TokenPos: TPasSourcePos;
  243. end;
  244. PTokenRec = ^TTokenRec;
  245. private
  246. FCurModule: TPasModule;
  247. FFileResolver: TBaseFileResolver;
  248. FImplicitUses: TStrings;
  249. FLastMsg: string;
  250. FLastMsgArgs: TMessageArgs;
  251. FLastMsgNumber: integer;
  252. FLastMsgPattern: string;
  253. FLastMsgType: TMessageType;
  254. FLogEvents: TPParserLogEvents;
  255. FOnLog: TPasParserLogHandler;
  256. FOptions: TPOptions;
  257. FScanner: TPascalScanner;
  258. FEngine: TPasTreeContainer;
  259. FCurToken: TToken;
  260. FCurTokenString: String;
  261. FSavedComments : String;
  262. // UngetToken support:
  263. FTokenRing: array[0..FTokenRingSize-1] of TTokenRec;
  264. FTokenRingCur: Integer; // index of current token in FTokenBuffer
  265. FTokenRingStart: Integer; // first valid ring index in FTokenBuffer, if FTokenRingStart=FTokenRingEnd the ring is empty
  266. FTokenRingEnd: Integer; // first invalid ring index in FTokenBuffer
  267. {$ifdef VerbosePasParser}
  268. FDumpIndent : String;
  269. procedure DumpCurToken(Const Msg : String; IndentAction : TIndentAction = iaNone);
  270. {$endif}
  271. function CheckOverloadList(AList: TFPList; AName: String; out OldMember: TPasElement): TPasOverloadedProc;
  272. function DoCheckHint(Element: TPasElement): Boolean;
  273. function GetCurrentModeSwitches: TModeSwitches;
  274. Procedure SetCurrentModeSwitches(AValue: TModeSwitches);
  275. function GetVariableModifiers(Parent: TPasElement;
  276. Out VarMods: TVariableModifiers; Out LibName, ExportName: TPasExpr;
  277. const AllowedMods: TVariableModifiers): string;
  278. function GetVariableValueAndLocation(Parent : TPasElement; Out Value: TPasExpr; Out AbsoluteExpr: TPasExpr; Out Location: String): Boolean;
  279. procedure HandleProcedureModifier(Parent: TPasElement; pm : TProcedureModifier);
  280. procedure HandleProcedureTypeModifier(ProcType: TPasProcedureType; ptm : TProcTypeModifier);
  281. procedure ParseMembersLocalConsts(AType: TPasMembersType; AVisibility: TPasMemberVisibility);
  282. procedure ParseMembersLocalTypes(AType: TPasMembersType; AVisibility: TPasMemberVisibility);
  283. procedure ParseVarList(Parent: TPasElement; VarList: TFPList; AVisibility: TPasMemberVisibility; Full: Boolean);
  284. procedure SetOptions(AValue: TPOptions);
  285. procedure OnScannerModeChanged(Sender: TObject; NewMode: TModeSwitch;
  286. Before: boolean; var Handled: boolean);
  287. protected
  288. Function SaveComments : String;
  289. Function SaveComments(Const AValue : String) : String;
  290. function LogEvent(E : TPParserLogEvent) : Boolean; inline;
  291. Procedure DoLog(MsgType: TMessageType; MsgNumber: integer; Const Msg : String; SkipSourceInfo : Boolean = False);overload;
  292. Procedure DoLog(MsgType: TMessageType; MsgNumber: integer; Const Fmt : String; Args : Array of {$ifdef pas2js}jsvalue{$else}const{$endif};SkipSourceInfo : Boolean = False);overload;
  293. function GetProcTypeFromToken(tk: TToken; IsClass: Boolean=False ): TProcType;
  294. procedure ParseAsmBlock(AsmBlock: TPasImplAsmStatement); virtual;
  295. procedure ParseRecordMembers(ARec: TPasRecordType; AEndToken: TToken; AllowMethods : Boolean);
  296. procedure ParseRecordVariantParts(ARec: TPasRecordType; AEndToken: TToken);
  297. function GetProcedureClass(ProcType : TProcType): TPTreeElement;
  298. procedure ParseClassFields(AType: TPasClassType; const AVisibility: TPasMemberVisibility; IsClassField : Boolean);
  299. procedure ParseClassMembers(AType: TPasClassType);
  300. procedure ProcessMethod(AType: TPasClassType; IsClass : Boolean; AVisibility : TPasMemberVisibility; MustBeGeneric: boolean);
  301. procedure ReadGenericArguments(List: TFPList; Parent: TPasElement);
  302. procedure ReadSpecializeArguments(Parent: TPasElement; Params: TFPList);
  303. function ReadDottedIdentifier(Parent: TPasElement; out Expr: TPasExpr; NeedAsString: boolean): String;
  304. function CheckProcedureArgs(Parent: TPasElement;
  305. Args: TFPList; // list of TPasArgument
  306. ProcType: TProcType): boolean;
  307. function CheckVisibility(S: String; var AVisibility: TPasMemberVisibility): Boolean;
  308. procedure ParseExc(MsgNumber: integer; const Msg: String);
  309. procedure ParseExc(MsgNumber: integer; const Fmt: String; Args : Array of {$ifdef pas2js}jsvalue{$else}const{$endif});
  310. procedure ParseExcExpectedIdentifier;
  311. procedure ParseExcSyntaxError;
  312. procedure ParseExcTokenError(const Arg: string);
  313. procedure ParseExcTypeParamsNotAllowed;
  314. procedure ParseExcExpectedAorB(const A, B: string);
  315. function OpLevel(t: TToken): Integer;
  316. Function TokenToExprOp (AToken : TToken) : TExprOpCode;
  317. function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement): TPasElement;overload;
  318. function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; const ASrcPos: TPasSourcePos): TPasElement;overload;
  319. function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility): TPasElement;overload;
  320. function CreateElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility; const ASrcPos: TPasSourcePos; TypeParams: TFPList = nil): TPasElement;overload;
  321. function CreatePrimitiveExpr(AParent: TPasElement; AKind: TPasExprKind; const AValue: String): TPrimitiveExpr;
  322. function CreateBoolConstExpr(AParent: TPasElement; AKind: TPasExprKind; const ABoolValue : Boolean): TBoolConstExpr;
  323. function CreateBinaryExpr(AParent : TPasElement; xleft, xright: TPasExpr; AOpCode: TExprOpCode): TBinaryExpr; overload;
  324. function CreateBinaryExpr(AParent : TPasElement; xleft, xright: TPasExpr; AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos): TBinaryExpr; overload;
  325. procedure AddToBinaryExprChain(var ChainFirst: TPasExpr;
  326. Element: TPasExpr; AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos);
  327. {$IFDEF VerbosePasParser}
  328. procedure WriteBinaryExprChain(Prefix: string; First, Last: TPasExpr);
  329. {$ENDIF}
  330. function CreateUnaryExpr(AParent : TPasElement; AOperand: TPasExpr; AOpCode: TExprOpCode): TUnaryExpr; overload;
  331. function CreateUnaryExpr(AParent : TPasElement; AOperand: TPasExpr; AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos): TUnaryExpr; overload;
  332. function CreateArrayValues(AParent : TPasElement): TArrayValues;
  333. function CreateFunctionType(const AName, AResultName: String; AParent: TPasElement;
  334. UseParentAsResultParent: Boolean; const NamePos: TPasSourcePos; TypeParams: TFPList = nil): TPasFunctionType;
  335. function CreateInheritedExpr(AParent : TPasElement): TInheritedExpr;
  336. function CreateSelfExpr(AParent : TPasElement): TSelfExpr;
  337. function CreateNilExpr(AParent : TPasElement): TNilExpr;
  338. function CreateRecordValues(AParent : TPasElement): TRecordValues;
  339. Function IsCurTokenHint(out AHint : TPasMemberHint) : Boolean; overload;
  340. Function IsCurTokenHint: Boolean; overload;
  341. Function TokenIsCallingConvention(const S: String; out CC : TCallingConvention) : Boolean; virtual;
  342. Function TokenIsProcedureModifier(Parent: TPasElement; const S: String; Out PM : TProcedureModifier): Boolean; virtual;
  343. Function TokenIsAnonymousProcedureModifier(Parent: TPasElement; S: String; Out PM: TProcedureModifier): Boolean; virtual;
  344. Function TokenIsProcedureTypeModifier(Parent : TPasElement; const S : String; Out PTM : TProcTypeModifier) : Boolean; virtual;
  345. Function CheckHint(Element : TPasElement; ExpectSemiColon : Boolean) : TPasMemberHints;
  346. function IsAnonymousProcAllowed(El: TPasElement): boolean; virtual;
  347. function ParseParams(AParent : TPasElement; ParamsKind: TPasExprKind; AllowFormatting : Boolean = False): TParamsExpr;
  348. function ParseExprOperand(AParent : TPasElement): TPasExpr;
  349. function ParseExpIdent(AParent : TPasElement): TPasExpr; deprecated 'use ParseExprOperand instead'; // since fpc 3.3.1
  350. procedure DoParseClassType(AType: TPasClassType);
  351. procedure DoParseClassExternalHeader(AObjKind: TPasObjKind;
  352. out AExternalNameSpace, AExternalName: string);
  353. procedure DoParseArrayType(ArrType: TPasArrayType);
  354. function DoParseExpression(AParent: TPaselement;InitExpr: TPasExpr=nil; AllowEqual : Boolean = True): TPasExpr;
  355. function DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
  356. function CheckPackMode: TPackMode;
  357. function AddUseUnit(ASection: TPasSection; const NamePos: TPasSourcePos;
  358. AUnitName : string; NameExpr: TPasExpr; InFileExpr: TPrimitiveExpr): TPasUsesUnit;
  359. procedure CheckImplicitUsedUnits(ASection: TPasSection);
  360. procedure FinishedModule; virtual;
  361. // Overload handling
  362. procedure AddProcOrFunction(Decs: TPasDeclarations; AProc: TPasProcedure);
  363. function CheckIfOverloaded(AParent: TPasElement; const AName: String): TPasElement;
  364. public
  365. constructor Create(AScanner: TPascalScanner; AFileResolver: TBaseFileResolver; AEngine: TPasTreeContainer);
  366. Destructor Destroy; override;
  367. procedure SetLastMsg(MsgType: TMessageType; MsgNumber: integer; Const Fmt : String; Args : Array of {$ifdef pas2js}jsvalue{$else}const{$endif});
  368. // General parsing routines
  369. function CurTokenName: String;
  370. function CurTokenText: String;
  371. Function CurComments : TStrings;
  372. function CurTokenPos: TPasSourcePos;
  373. function CurSourcePos: TPasSourcePos;
  374. function HasToken: boolean;
  375. Function SavedComments : String;
  376. procedure NextToken; // read next non whitespace, non space
  377. procedure ChangeToken(tk: TToken);
  378. procedure UngetToken;
  379. procedure CheckToken(tk: TToken);
  380. procedure CheckTokens(tk: TTokens);
  381. procedure ExpectToken(tk: TToken);
  382. procedure ExpectTokens(tk: TTokens);
  383. function GetPrevToken: TToken;
  384. function ExpectIdentifier: String;
  385. Function CurTokenIsIdentifier(Const S : String) : Boolean;
  386. // Expression parsing
  387. function isEndOfExp(AllowEqual : Boolean = False; CheckHints : Boolean = True): Boolean;
  388. function ExprToText(Expr: TPasExpr): String;
  389. function ArrayExprToText(Expr: TPasExprArray): String;
  390. // Type declarations
  391. function ResolveTypeReference(Name: string; Parent: TPasElement; ParamCnt: integer = 0): TPasType;
  392. function ParseComplexType(Parent : TPasElement = Nil): TPasType;
  393. function ParseTypeDecl(Parent: TPasElement): TPasType;
  394. function ParseGenericTypeDecl(Parent: TPasElement; AddToParent: boolean): TPasGenericType;
  395. function ParseType(Parent: TPasElement; const NamePos: TPasSourcePos; const TypeName: String = ''; Full: Boolean = false): TPasType;
  396. function ParseReferenceToProcedureType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasProcedureType;
  397. function ParseProcedureType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String; const PT: TProcType): TPasProcedureType;
  398. function ParseStringType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasAliasType;
  399. function ParseSimpleType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String; IsFull : Boolean = False): TPasType;
  400. function ParseAliasType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasType;
  401. function ParseTypeReference(Parent: TPasElement; NeedExpr: boolean; out Expr: TPasExpr): TPasType;
  402. function ParseSpecializeType(Parent: TPasElement; const TypeName, GenName: string; var GenNameExpr: TPasExpr): TPasSpecializeType;
  403. function ParsePointerType(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String): TPasPointerType;
  404. Function ParseArrayType(Parent : TPasElement; Const NamePos: TPasSourcePos; Const TypeName : String; PackMode : TPackMode) : TPasArrayType;
  405. Function ParseFileType(Parent : TPasElement; Const NamePos: TPasSourcePos; Const TypeName : String) : TPasFileType;
  406. Function ParseRecordDecl(Parent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName : string; const Packmode : TPackMode = pmNone) : TPasRecordType;
  407. function ParseEnumType(Parent: TPasElement; Const NamePos: TPasSourcePos; const TypeName: String): TPasEnumType;
  408. function ParseSetType(Parent: TPasElement; Const NamePos: TPasSourcePos; const TypeName: String; AIsPacked : Boolean = False): TPasSetType;
  409. Function ParseClassDecl(Parent: TPasElement; Const NamePos: TPasSourcePos; Const AClassName: String; AObjKind: TPasObjKind; PackMode : TPackMode= pmNone): TPasType;
  410. Function ParseProperty(Parent : TPasElement; Const AName : String; AVisibility : TPasMemberVisibility; IsClassField: boolean) : TPasProperty;
  411. function ParseRangeType(AParent: TPasElement; Const NamePos: TPasSourcePos; Const TypeName: String; Full: Boolean = True): TPasRangeType;
  412. procedure ParseExportDecl(Parent: TPasElement; List: TFPList);
  413. // Constant declarations
  414. function ParseConstDecl(Parent: TPasElement): TPasConst;
  415. function ParseResourcestringDecl(Parent: TPasElement): TPasResString;
  416. function ParseAttributes(Parent: TPasElement; Add: boolean): TPasAttributes;
  417. // Variable handling. This includes parts of records
  418. procedure ParseVarDecl(Parent: TPasElement; List: TFPList);
  419. procedure ParseInlineVarDecl(Parent: TPasElement; List: TFPList; AVisibility : TPasMemberVisibility = visDefault; ClosingBrace: Boolean = False);
  420. // Main scope parsing
  421. procedure ParseMain(var Module: TPasModule);
  422. procedure ParseUnit(var Module: TPasModule);
  423. function GetLastSection: TPasSection; virtual;
  424. function CanParseContinue(out Section: TPasSection): boolean; virtual;
  425. procedure ParseContinue; virtual;
  426. procedure ParseProgram(var Module: TPasModule; SkipHeader : Boolean = False);
  427. procedure ParseLibrary(var Module: TPasModule);
  428. procedure ParseOptionalUsesList(ASection: TPasSection);
  429. procedure ParseUsesList(ASection: TPasSection);
  430. procedure ParseInterface;
  431. procedure ParseImplementation;
  432. procedure ParseInitialization;
  433. procedure ParseFinalization;
  434. procedure ParseDeclarations(Declarations: TPasDeclarations);
  435. procedure ParseStatement(Parent: TPasImplBlock; out NewImplElement: TPasImplElement);
  436. procedure ParseLabels(AParent: TPasElement);
  437. procedure ParseProcBeginBlock(Parent: TProcedureBody);
  438. procedure ParseProcAsmBlock(Parent: TProcedureBody);
  439. // Function/Procedure declaration
  440. function ParseProcedureOrFunctionDecl(Parent: TPasElement;
  441. ProcType: TProcType; MustBeGeneric: boolean;
  442. AVisibility: TPasMemberVisibility = VisDefault): TPasProcedure;
  443. procedure ParseArgList(Parent: TPasElement;
  444. Args: TFPList; // list of TPasArgument
  445. EndToken: TToken);
  446. procedure ParseProcedureOrFunction(Parent: TPasElement; Element: TPasProcedureType; ProcType: TProcType; OfObjectPossible: Boolean);
  447. procedure ParseProcedureBody(Parent: TPasElement);
  448. function ParseMethodResolution(Parent: TPasElement): TPasMethodResolution;
  449. // Properties for external access
  450. property FileResolver: TBaseFileResolver read FFileResolver;
  451. property Scanner: TPascalScanner read FScanner;
  452. property Engine: TPasTreeContainer read FEngine;
  453. property CurToken: TToken read FCurToken;
  454. property CurTokenString: String read FCurTokenString;
  455. property Options : TPOptions Read FOptions Write SetOptions;
  456. property CurrentModeswitches : TModeSwitches Read GetCurrentModeSwitches Write SetCurrentModeSwitches;
  457. property CurModule : TPasModule Read FCurModule;
  458. property LogEvents : TPParserLogEvents Read FLogEvents Write FLogEvents;
  459. property OnLog : TPasParserLogHandler Read FOnLog Write FOnLog;
  460. property ImplicitUses: TStrings read FImplicitUses;
  461. property LastMsg: string read FLastMsg write FLastMsg;
  462. property LastMsgNumber: integer read FLastMsgNumber write FLastMsgNumber;
  463. property LastMsgType: TMessageType read FLastMsgType write FLastMsgType;
  464. property LastMsgPattern: string read FLastMsgPattern write FLastMsgPattern;
  465. property LastMsgArgs: TMessageArgs read FLastMsgArgs write FLastMsgArgs;
  466. end;
  467. Type
  468. TParseSourceOption = (
  469. {$ifdef HasStreams}
  470. poUseStreams,
  471. {$endif}
  472. poSkipDefaultDefs);
  473. TParseSourceOptions = set of TParseSourceOption;
  474. Var
  475. DefaultFileResolverClass : TBaseFileResolverClass = Nil;
  476. {$ifdef HasStreams}
  477. function ParseSource(AEngine: TPasTreeContainer;
  478. const FPCCommandLine, OSTarget, CPUTarget: String;
  479. UseStreams : Boolean): TPasModule; deprecated 'use version with options';
  480. {$endif}
  481. function ParseSource(AEngine: TPasTreeContainer;
  482. const FPCCommandLine, OSTarget, CPUTarget: String): TPasModule; deprecated 'use version with split command line';
  483. function ParseSource(AEngine: TPasTreeContainer;
  484. const FPCCommandLine, OSTarget, CPUTarget: String;
  485. Options : TParseSourceOptions): TPasModule; deprecated 'use version with split command line';
  486. function ParseSource(AEngine: TPasTreeContainer;
  487. const FPCCommandLine : Array of String;
  488. OSTarget, CPUTarget: String;
  489. Options : TParseSourceOptions): TPasModule;
  490. Function IsHintToken(T : String; Out AHint : TPasMemberHint) : boolean;
  491. Function IsProcModifier(S : String; Out PM : TProcedureModifier) : Boolean;
  492. Function IsCallingConvention(S : String; out CC : TCallingConvention) : Boolean;
  493. Function TokenToAssignKind( tk : TToken) : TAssignKind;
  494. implementation
  495. {$IF FPC_FULLVERSION>=30301}
  496. uses strutils;
  497. {$ENDIF}
  498. const
  499. WhitespaceTokensToIgnore = [tkWhitespace, tkComment, tkLineEnding, tkTab];
  500. type
  501. TDeclType = (declNone, declConst, declResourcestring, declType,
  502. declVar, declThreadvar, declProperty, declExports);
  503. {$IF FPC_FULLVERSION<30301}
  504. Function SplitCommandLine(S: String) : TStringDynArray;
  505. Function GetNextWord : String;
  506. Const
  507. WhiteSpace = [' ',#9,#10,#13];
  508. Literals = ['"',''''];
  509. Var
  510. Wstart,wend : Integer;
  511. InLiteral : Boolean;
  512. LastLiteral : Char;
  513. Procedure AppendToResult;
  514. begin
  515. Result:=Result+Copy(S,WStart,WEnd-WStart);
  516. WStart:=Wend+1;
  517. end;
  518. begin
  519. Result:='';
  520. WStart:=1;
  521. While (WStart<=Length(S)) and charinset(S[WStart],WhiteSpace) do
  522. Inc(WStart);
  523. WEnd:=WStart;
  524. InLiteral:=False;
  525. LastLiteral:=#0;
  526. While (Wend<=Length(S)) and (Not charinset(S[Wend],WhiteSpace) or InLiteral) do
  527. begin
  528. if charinset(S[Wend],Literals) then
  529. If InLiteral then
  530. begin
  531. InLiteral:=Not (S[Wend]=LastLiteral);
  532. if not InLiteral then
  533. AppendToResult;
  534. end
  535. else
  536. begin
  537. InLiteral:=True;
  538. LastLiteral:=S[Wend];
  539. AppendToResult;
  540. end;
  541. inc(wend);
  542. end;
  543. AppendToResult;
  544. While (WEnd<=Length(S)) and (S[Wend] in WhiteSpace) do
  545. inc(Wend);
  546. Delete(S,1,WEnd-1);
  547. end;
  548. Var
  549. W : String;
  550. len : Integer;
  551. begin
  552. Len:=0;
  553. Result:=Default(TStringDynArray);
  554. SetLength(Result,(Length(S) div 2)+1);
  555. While Length(S)>0 do
  556. begin
  557. W:=GetNextWord;
  558. If (W<>'') then
  559. begin
  560. Result[Len]:=W;
  561. Inc(Len);
  562. end;
  563. end;
  564. SetLength(Result,Len);
  565. end;
  566. {$ENDIF}
  567. Function IsHintToken(T : String; Out AHint : TPasMemberHint) : boolean;
  568. Const
  569. MemberHintTokens : Array[TPasMemberHint] of string =
  570. ('deprecated','library','platform','experimental','unimplemented');
  571. Var
  572. I : TPasMemberHint;
  573. begin
  574. t:=LowerCase(t);
  575. Result:=False;
  576. For I:=Low(TPasMemberHint) to High(TPasMemberHint) do
  577. begin
  578. result:=(t=MemberHintTokens[i]);
  579. if Result then
  580. begin
  581. aHint:=I;
  582. exit;
  583. end;
  584. end;
  585. end;
  586. Function IsCallingConvention(S : String; out CC : TCallingConvention) : Boolean;
  587. Var
  588. CCNames : Array[TCallingConvention] of String
  589. = ('','register','pascal','cdecl','stdcall','oldfpccall','safecall','syscall');
  590. Var
  591. C : TCallingConvention;
  592. begin
  593. S:=Lowercase(s);
  594. Result:=False;
  595. for C:=Low(TCallingConvention) to High(TCallingConvention) do
  596. begin
  597. Result:=(CCNames[c]<>'') and (s=CCnames[c]);
  598. If Result then
  599. begin
  600. CC:=C;
  601. exit;
  602. end;
  603. end;
  604. end;
  605. Function IsProcModifier(S : String; Out PM : TProcedureModifier) : Boolean;
  606. Var
  607. P : TProcedureModifier;
  608. begin
  609. S:=LowerCase(S);
  610. Result:=False;
  611. For P:=Low(TProcedureModifier) to High(TProcedureModifier) do
  612. begin
  613. Result:=s=ModifierNames[P];
  614. If Result then
  615. begin
  616. PM:=P;
  617. exit;
  618. end;
  619. end;
  620. end;
  621. Function TokenToAssignKind( tk : TToken) : TAssignKind;
  622. begin
  623. case tk of
  624. tkAssign : Result:=akDefault;
  625. tkAssignPlus : Result:=akAdd;
  626. tkAssignMinus : Result:=akMinus;
  627. tkAssignMul : Result:=akMul;
  628. tkAssignDivision : Result:=akDivision;
  629. else
  630. Raise Exception.CreateFmt('Not an assignment token : %s',[TokenInfos[tk]]);
  631. end;
  632. end;
  633. function ParseSource(AEngine: TPasTreeContainer;
  634. const FPCCommandLine, OSTarget, CPUTarget: String): TPasModule;
  635. var
  636. FPCParams: TStringDynArray;
  637. begin
  638. FPCParams:=SplitCommandLine(FPCCommandLine);
  639. Result:=ParseSource(AEngine, FPCParams, OSTarget, CPUTarget,[]);
  640. end;
  641. {$ifdef HasStreams}
  642. function ParseSource(AEngine: TPasTreeContainer;
  643. const FPCCommandLine, OSTarget, CPUTarget: String; UseStreams : Boolean): TPasModule;
  644. var
  645. FPCParams: TStringDynArray;
  646. begin
  647. FPCParams:=SplitCommandLine(FPCCommandLine);
  648. if UseStreams then
  649. Result:=ParseSource(AEngine,FPCParams, OSTarget, CPUTarget,[poUseStreams])
  650. else
  651. Result:=ParseSource(AEngine,FPCParams, OSTarget, CPUTarget,[]);
  652. end;
  653. {$endif}
  654. function ParseSource(AEngine: TPasTreeContainer;
  655. const FPCCommandLine, OSTarget, CPUTarget: String;
  656. Options : TParseSourceOptions): TPasModule;
  657. Var
  658. Args : TStringArray;
  659. begin
  660. Args:=SplitCommandLine(FPCCommandLine);
  661. Result:=ParseSource(aEngine,Args,OSTarget,CPUTarget,Options);
  662. end;
  663. function ParseSource(AEngine: TPasTreeContainer;
  664. const FPCCommandLine : Array of String;
  665. OSTarget, CPUTarget: String;
  666. Options : TParseSourceOptions): TPasModule;
  667. var
  668. FileResolver: TBaseFileResolver;
  669. Parser: TPasParser;
  670. Filename: String;
  671. Scanner: TPascalScanner;
  672. procedure ProcessCmdLinePart(S : String);
  673. var
  674. l,Len: Integer;
  675. begin
  676. if (S='') then
  677. exit;
  678. Len:=Length(S);
  679. if (s[1] = '-') and (len>1) then
  680. begin
  681. case s[2] of
  682. 'd': // -d define
  683. Scanner.AddDefine(UpperCase(Copy(s, 3, Len)));
  684. 'u': // -u undefine
  685. Scanner.RemoveDefine(UpperCase(Copy(s, 3, Len)));
  686. 'F': // -F
  687. if (len>2) and (s[3] = 'i') then // -Fi include path
  688. FileResolver.AddIncludePath(Copy(s, 4, Len));
  689. 'I': // -I include path
  690. FileResolver.AddIncludePath(Copy(s, 3, Len));
  691. 'S': // -S mode
  692. if (len>2) then
  693. begin
  694. l:=3;
  695. While L<=Len do
  696. begin
  697. case S[l] of
  698. 'c' : Scanner.Options:=Scanner.Options+[po_cassignments];
  699. 'd' : Scanner.SetCompilerMode('DELPHI');
  700. '2' : Scanner.SetCompilerMode('OBJFPC');
  701. 'h' : ; // do nothing
  702. end;
  703. inc(l);
  704. end;
  705. end;
  706. 'M' :
  707. begin
  708. delete(S,1,2);
  709. Scanner.SetCompilerMode(S);
  710. end;
  711. end;
  712. end else
  713. if Filename <> '' then
  714. raise ENotSupportedException.Create(SErrMultipleSourceFiles)
  715. else
  716. Filename := s;
  717. end;
  718. var
  719. S: String;
  720. begin
  721. if DefaultFileResolverClass=Nil then
  722. raise ENotImplemented.Create(SErrFileSystemNotSupported);
  723. Result := nil;
  724. FileResolver := nil;
  725. Scanner := nil;
  726. Parser := nil;
  727. try
  728. FileResolver := DefaultFileResolverClass.Create;
  729. {$ifdef HasStreams}
  730. if FileResolver is TFileResolver then
  731. TFileResolver(FileResolver).UseStreams:=poUseStreams in Options;
  732. {$endif}
  733. Scanner := TPascalScanner.Create(FileResolver);
  734. Scanner.LogEvents:=AEngine.ScannerLogEvents;
  735. Scanner.OnLog:=AEngine.Onlog;
  736. if not (poSkipDefaultDefs in Options) then
  737. begin
  738. Scanner.AddDefine('FPK');
  739. Scanner.AddDefine('FPC');
  740. // TargetOS
  741. s := UpperCase(OSTarget);
  742. Scanner.AddDefine(s);
  743. Case s of
  744. 'LINUX' : Scanner.AddDefine('UNIX');
  745. 'FREEBSD' :
  746. begin
  747. Scanner.AddDefine('BSD');
  748. Scanner.AddDefine('UNIX');
  749. end;
  750. 'NETBSD' :
  751. begin
  752. Scanner.AddDefine('BSD');
  753. Scanner.AddDefine('UNIX');
  754. end;
  755. 'SUNOS' :
  756. begin
  757. Scanner.AddDefine('SOLARIS');
  758. Scanner.AddDefine('UNIX');
  759. end;
  760. 'GO32V2' : Scanner.AddDefine('DPMI');
  761. 'BEOS' : Scanner.AddDefine('UNIX');
  762. 'QNX' : Scanner.AddDefine('UNIX');
  763. 'AROS' : Scanner.AddDefine('HASAMIGA');
  764. 'MORPHOS' : Scanner.AddDefine('HASAMIGA');
  765. 'AMIGA' : Scanner.AddDefine('HASAMIGA');
  766. end;
  767. // TargetCPU
  768. s := UpperCase(CPUTarget);
  769. Scanner.AddDefine('CPU'+s);
  770. if (s='X86_64') then
  771. Scanner.AddDefine('CPU64')
  772. else
  773. Scanner.AddDefine('CPU32');
  774. end;
  775. Parser := TPasParser.Create(Scanner, FileResolver, AEngine);
  776. if (poSkipDefaultDefs in Options) then
  777. Parser.ImplicitUses.Clear;
  778. Filename := '';
  779. Parser.LogEvents:=AEngine.ParserLogEvents;
  780. Parser.OnLog:=AEngine.Onlog;
  781. For S in FPCCommandLine do
  782. ProcessCmdLinePart(S);
  783. if Filename = '' then
  784. raise Exception.Create(SErrNoSourceGiven);
  785. {$IFDEF HASFS}
  786. FileResolver.AddIncludePath(ExtractFilePath(FileName));
  787. {$ENDIF}
  788. Scanner.OpenFile(Filename);
  789. Parser.ParseMain(Result);
  790. finally
  791. Parser.Free;
  792. Scanner.Free;
  793. FileResolver.Free;
  794. end;
  795. end;
  796. { ---------------------------------------------------------------------
  797. TPasTreeContainer
  798. ---------------------------------------------------------------------}
  799. procedure TPasTreeContainer.SetCurrentParser(AValue: TPasParser);
  800. begin
  801. if FCurrentParser=AValue then Exit;
  802. FCurrentParser:=AValue;
  803. end;
  804. function TPasTreeContainer.CreateElement(AClass: TPTreeElement;
  805. const AName: String; AParent: TPasElement; const ASourceFilename: String;
  806. ASourceLinenumber: Integer): TPasElement;
  807. begin
  808. Result := CreateElement(AClass, AName, AParent, visDefault, ASourceFilename,
  809. ASourceLinenumber);
  810. end;
  811. function TPasTreeContainer.CreateElement(AClass: TPTreeElement;
  812. const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility;
  813. const ASrcPos: TPasSourcePos; TypeParams: TFPList): TPasElement;
  814. begin
  815. Result := CreateElement(AClass, AName, AParent, AVisibility, ASrcPos.FileName,
  816. ASrcPos.Row);
  817. if TypeParams=nil then ;
  818. end;
  819. function TPasTreeContainer.CreateFunctionType(const AName, AResultName: String;
  820. AParent: TPasElement; UseParentAsResultParent: Boolean;
  821. const ASrcPos: TPasSourcePos; TypeParams: TFPList): TPasFunctionType;
  822. var
  823. ResultParent: TPasElement;
  824. begin
  825. Result := TPasFunctionType(CreateElement(TPasFunctionType, AName, AParent,
  826. visDefault, ASrcPos, TypeParams));
  827. if UseParentAsResultParent then
  828. ResultParent := AParent
  829. else
  830. ResultParent := Result;
  831. TPasFunctionType(Result).ResultEl :=
  832. TPasResultElement(CreateElement(TPasResultElement, AResultName, ResultParent,
  833. visDefault, ASrcPos, TypeParams));
  834. end;
  835. function TPasTreeContainer.FindElementFor(const AName: String;
  836. AParent: TPasElement; TypeParamCount: integer): TPasElement;
  837. begin
  838. Result:=FindElement(AName);
  839. if AParent=nil then ;
  840. if TypeParamCount=0 then ;
  841. end;
  842. procedure TPasTreeContainer.BeginScope(ScopeType: TPasScopeType; El: TPasElement
  843. );
  844. begin
  845. if ScopeType=stModule then ; // avoid compiler warning
  846. if El=nil then ;
  847. end;
  848. procedure TPasTreeContainer.FinishScope(ScopeType: TPasScopeType;
  849. El: TPasElement);
  850. begin
  851. if ScopeType=stModule then ; // avoid compiler warning
  852. if Assigned(El) and (CurrentParser<>nil) then
  853. El.SourceEndLinenumber := CurrentParser.CurSourcePos.Row;
  854. end;
  855. procedure TPasTreeContainer.FinishTypeAlias(var aType: TPasType);
  856. begin
  857. if aType=nil then ;
  858. end;
  859. function TPasTreeContainer.FindModule(const AName: String): TPasModule;
  860. begin
  861. if AName='' then ; // avoid compiler warning
  862. Result := nil;
  863. end;
  864. function TPasTreeContainer.FindModule(const AName: String; NameExpr,
  865. InFileExpr: TPasExpr): TPasModule;
  866. begin
  867. Result:=FindModule(AName);
  868. if NameExpr=nil then ;
  869. if InFileExpr=nil then ;
  870. end;
  871. function TPasTreeContainer.CheckPendingUsedInterface(Section: TPasSection
  872. ): boolean;
  873. begin
  874. if Section=nil then ; // avoid compiler warning
  875. Result:=false;
  876. end;
  877. function TPasTreeContainer.NeedArrayValues(El: TPasElement): boolean;
  878. begin
  879. Result:=false;
  880. if El=nil then ; // avoid compiler warning
  881. end;
  882. function TPasTreeContainer.GetDefaultClassVisibility(AClass: TPasClassType
  883. ): TPasMemberVisibility;
  884. begin
  885. Result:=visDefault;
  886. if AClass=nil then ; // avoid compiler warning
  887. end;
  888. procedure TPasTreeContainer.ModeChanged(Sender: TObject; NewMode: TModeSwitch;
  889. Before: boolean; var Handled: boolean);
  890. begin
  891. if Sender=nil then ;
  892. if NewMode=msDelphi then ;
  893. if Before then ;
  894. if Handled then ;
  895. end;
  896. { ---------------------------------------------------------------------
  897. EParserError
  898. ---------------------------------------------------------------------}
  899. constructor EParserError.Create(const AReason, AFilename: String;
  900. ARow, AColumn: Integer);
  901. begin
  902. inherited Create(AReason);
  903. FFilename := AFilename;
  904. FRow := ARow;
  905. FColumn := AColumn;
  906. end;
  907. { ---------------------------------------------------------------------
  908. TPasParser
  909. ---------------------------------------------------------------------}
  910. procedure TPasParser.ParseExc(MsgNumber: integer; const Msg: String);
  911. begin
  912. ParseExc(MsgNumber,Msg,[]);
  913. end;
  914. procedure TPasParser.ParseExc(MsgNumber: integer; const Fmt: String;
  915. Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif});
  916. var
  917. p: TPasSourcePos;
  918. begin
  919. {$IFDEF VerbosePasParser}
  920. writeln('TPasParser.ParseExc Token="',CurTokenText,'"');
  921. //writeln('TPasParser.ParseExc ',Scanner.CurColumn,' ',Scanner.CurSourcePos.Column,' ',Scanner.CurTokenPos.Column,' ',Scanner.CurSourceFile.Filename);
  922. {$ENDIF}
  923. SetLastMsg(mtError,MsgNumber,Fmt,Args);
  924. p:=Scanner.CurTokenPos;
  925. if p.FileName='' then
  926. p:=Scanner.CurSourcePos;
  927. if p.Row=0 then
  928. begin
  929. p.Row:=1;
  930. p.Column:=1;
  931. end;
  932. raise EParserError.Create(SafeFormat(SParserErrorAtToken,
  933. [FLastMsg, CurTokenName, p.FileName, p.Row, p.Column])
  934. {$ifdef addlocation}+' ('+IntToStr(p.Row)+' '+IntToStr(p.Column)+')'{$endif},
  935. p.FileName, p.Row, p.Column);
  936. end;
  937. procedure TPasParser.ParseExcExpectedIdentifier;
  938. begin
  939. ParseExc(nParserExpectedIdentifier,SParserExpectedIdentifier);
  940. end;
  941. procedure TPasParser.ParseExcSyntaxError;
  942. begin
  943. ParseExc(nParserSyntaxError,SParserSyntaxError);
  944. end;
  945. procedure TPasParser.ParseExcTokenError(const Arg: string);
  946. begin
  947. ParseExc(nParserExpectTokenError,SParserExpectTokenError,[Arg]);
  948. end;
  949. procedure TPasParser.ParseExcTypeParamsNotAllowed;
  950. begin
  951. ParseExc(nParserTypeParamsNotAllowedOnType,sParserTypeParamsNotAllowedOnType,[]);
  952. end;
  953. procedure TPasParser.ParseExcExpectedAorB(const A, B: string);
  954. begin
  955. ParseExc(nParserExpectToken2Error,SParserExpectToken2Error,[A,B]);
  956. end;
  957. constructor TPasParser.Create(AScanner: TPascalScanner;
  958. AFileResolver: TBaseFileResolver; AEngine: TPasTreeContainer);
  959. begin
  960. inherited Create;
  961. FScanner := AScanner;
  962. if FScanner.OnModeChanged=nil then
  963. FScanner.OnModeChanged:=@OnScannerModeChanged;
  964. FFileResolver := AFileResolver;
  965. FTokenRingCur:=High(FTokenRing);
  966. FEngine := AEngine;
  967. if Assigned(FEngine) then
  968. begin
  969. FEngine.CurrentParser:=Self;
  970. If FEngine.NeedComments then
  971. FScanner.SkipComments:=Not FEngine.NeedComments;
  972. end;
  973. FImplicitUses := TStringList.Create;
  974. FImplicitUses.Add('System'); // system always implicitely first.
  975. end;
  976. destructor TPasParser.Destroy;
  977. var
  978. i: Integer;
  979. begin
  980. if FScanner.OnModeChanged=@OnScannerModeChanged then
  981. FScanner.OnModeChanged:=nil;
  982. if Assigned(FEngine) then
  983. begin
  984. FEngine.CurrentParser:=Nil;
  985. FEngine:=nil;
  986. end;
  987. FreeAndNil(FImplicitUses);
  988. for i:=low(FTokenRing) to high(FTokenRing) do
  989. FreeAndNil(FTokenRing[i].Comments);
  990. inherited Destroy;
  991. end;
  992. function TPasParser.CurTokenName: String;
  993. begin
  994. if CurToken = tkIdentifier then
  995. Result := 'Identifier ' + FCurTokenString
  996. else
  997. Result := TokenInfos[CurToken];
  998. end;
  999. function TPasParser.CurTokenText: String;
  1000. begin
  1001. case CurToken of
  1002. tkIdentifier, tkString, tkNumber, tkChar:
  1003. Result := FCurTokenString;
  1004. else
  1005. Result := TokenInfos[CurToken];
  1006. end;
  1007. end;
  1008. function TPasParser.CurComments: TStrings;
  1009. begin
  1010. if FTokenRingStart=FTokenRingEnd then
  1011. Result:=nil
  1012. else
  1013. Result:=FTokenRing[FTokenRingCur].Comments;
  1014. end;
  1015. function TPasParser.CurTokenPos: TPasSourcePos;
  1016. begin
  1017. if HasToken then
  1018. Result:=FTokenRing[FTokenRingCur].TokenPos
  1019. else if Scanner<>nil then
  1020. Result:=Scanner.CurTokenPos
  1021. else
  1022. Result:=Default(TPasSourcePos);
  1023. end;
  1024. function TPasParser.CurSourcePos: TPasSourcePos;
  1025. begin
  1026. if HasToken then
  1027. Result:=FTokenRing[FTokenRingCur].SourcePos
  1028. else if Scanner<>nil then
  1029. Result:=Scanner.CurSourcePos
  1030. else
  1031. Result:=Default(TPasSourcePos);
  1032. end;
  1033. function TPasParser.HasToken: boolean;
  1034. begin
  1035. if FTokenRingStart<FTokenRingEnd then
  1036. Result:=(FTokenRingCur>=FTokenRingStart) and (FTokenRingCur<FTokenRingEnd)
  1037. else
  1038. Result:=(FTokenRingCur>=FTokenRingStart) or (FTokenRingCur<FTokenRingEnd);
  1039. end;
  1040. function TPasParser.SavedComments: String;
  1041. begin
  1042. Result:=FSavedComments;
  1043. end;
  1044. procedure TPasParser.NextToken;
  1045. Var
  1046. P: PTokenRec;
  1047. begin
  1048. FTokenRingCur:=(FTokenRingCur+1) mod FTokenRingSize;
  1049. P:=@FTokenRing[FTokenRingCur];
  1050. if FTokenRingCur <> FTokenRingEnd then
  1051. begin
  1052. // Get token from buffer
  1053. //writeln('TPasParser.NextToken REUSE Start=',FTokenRingStart,' Cur=',FTokenRingCur,' End=',FTokenRingEnd,' Cur=',CurTokenString);
  1054. FCurToken := Scanner.CheckToken(P^.Token,P^.AsString);
  1055. FCurTokenString := P^.AsString;
  1056. end
  1057. else
  1058. begin
  1059. // Fetch new token
  1060. //writeln('TPasParser.NextToken FETCH Start=',FTokenRingStart,' Cur=',FTokenRingCur,' End=',FTokenRingEnd,' Cur=',CurTokenString);
  1061. FTokenRingEnd:=(FTokenRingEnd+1) mod FTokenRingSize;
  1062. if FTokenRingStart=FTokenRingEnd then
  1063. FTokenRingStart:=(FTokenRingStart+1) mod FTokenRingSize;
  1064. try
  1065. if p^.Comments=nil then
  1066. p^.Comments:=TStringList.Create
  1067. else
  1068. p^.Comments.Clear;
  1069. repeat
  1070. FCurToken := Scanner.FetchToken;
  1071. if FCurToken=tkComment then
  1072. p^.Comments.Add(Scanner.CurTokenString);
  1073. until not (FCurToken in WhitespaceTokensToIgnore);
  1074. except
  1075. on e: EScannerError do
  1076. begin
  1077. if po_KeepScannerError in Options then
  1078. raise
  1079. else
  1080. begin
  1081. FLastMsgType := mtError;
  1082. FLastMsgNumber := Scanner.LastMsgNumber;
  1083. FLastMsgPattern := Scanner.LastMsgPattern;
  1084. FLastMsg := Scanner.LastMsg;
  1085. FLastMsgArgs := Scanner.LastMsgArgs;
  1086. raise EParserError.Create(e.Message,
  1087. Scanner.CurFilename, Scanner.CurRow, Scanner.CurColumn);
  1088. end;
  1089. end;
  1090. end;
  1091. p^.Token:=FCurToken;
  1092. FCurTokenString := Scanner.CurTokenString;
  1093. p^.AsString:=FCurTokenString;
  1094. p^.SourcePos:=Scanner.CurSourcePos;
  1095. p^.TokenPos:=Scanner.CurTokenPos;
  1096. end;
  1097. //writeln('TPasParser.NextToken END Start=',FTokenRingStart,' Cur=',FTokenRingCur,' End=',FTokenRingEnd,' Cur=',CurTokenString);
  1098. end;
  1099. procedure TPasParser.ChangeToken(tk: TToken);
  1100. var
  1101. Cur, Last: PTokenRec;
  1102. IsLast: Boolean;
  1103. begin
  1104. //writeln('TPasParser.ChangeToken FTokenBufferSize=',FTokenRingStart,' FTokenBufferIndex=',FTokenRingCur);
  1105. IsLast:=((FTokenRingCur+1) mod FTokenRingSize)=FTokenRingEnd;
  1106. if (CurToken=tkshr) and (tk=tkGreaterThan) and IsLast then
  1107. begin
  1108. // change last token '>>' into two '>'
  1109. Cur:=@FTokenRing[FTokenRingCur];
  1110. Cur^.Token:=tkGreaterThan;
  1111. Cur^.AsString:='>';
  1112. Last:=@FTokenRing[FTokenRingEnd];
  1113. Last^.Token:=tkGreaterThan;
  1114. Last^.AsString:='>';
  1115. if Last^.Comments<>nil then
  1116. Last^.Comments.Clear;
  1117. Last^.SourcePos:=Cur^.SourcePos;
  1118. dec(Cur^.SourcePos.Column);
  1119. Last^.TokenPos:=Cur^.TokenPos;
  1120. inc(Last^.TokenPos.Column);
  1121. FTokenRingEnd:=(FTokenRingEnd+1) mod FTokenRingSize;
  1122. if FTokenRingStart=FTokenRingEnd then
  1123. FTokenRingStart:=(FTokenRingStart+1) mod FTokenRingSize;
  1124. FCurToken:=tkGreaterThan;
  1125. FCurTokenString:='>';
  1126. end
  1127. else
  1128. CheckToken(tk);
  1129. end;
  1130. procedure TPasParser.UngetToken;
  1131. var
  1132. P: PTokenRec;
  1133. begin
  1134. //writeln('TPasParser.UngetToken START Start=',FTokenRingStart,' Cur=',FTokenRingCur,' End=',FTokenRingEnd,' Cur=',CurTokenString);
  1135. if FTokenRingStart = FTokenRingEnd then
  1136. ParseExc(nParserUngetTokenError,SParserUngetTokenError);
  1137. if FTokenRingCur>0 then
  1138. dec(FTokenRingCur)
  1139. else
  1140. FTokenRingCur:=High(FTokenRing);
  1141. P:=@FTokenRing[FTokenRingCur];
  1142. FCurToken := P^.Token;
  1143. FCurTokenString := P^.AsString;
  1144. //writeln('TPasParser.UngetToken END Start=',FTokenRingStart,' Cur=',FTokenRingCur,' End=',FTokenRingEnd,' Cur=',CurTokenString);
  1145. end;
  1146. procedure TPasParser.CheckToken(tk: TToken);
  1147. begin
  1148. if (CurToken<>tk) then
  1149. begin
  1150. {$IFDEF VerbosePasParser}
  1151. writeln('TPasParser.ParseExcTokenError String="',CurTokenString,'" Text="',CurTokenText,'" CurToken=',CurToken,' tk=',tk);
  1152. {$ENDIF}
  1153. ParseExcTokenError(TokenInfos[tk]);
  1154. end;
  1155. end;
  1156. procedure TPasParser.CheckTokens(tk: TTokens);
  1157. Var
  1158. S : String;
  1159. T : TToken;
  1160. begin
  1161. if not (CurToken in tk) then
  1162. begin
  1163. {$IFDEF VerbosePasParser}
  1164. writeln('TPasParser.ParseExcTokenError String="',CurTokenString,'" Text="',CurTokenText,'" CurToken=',CurToken);
  1165. {$ENDIF}
  1166. S:='';
  1167. For T in TToken do
  1168. if t in tk then
  1169. begin
  1170. if (S<>'') then
  1171. S:=S+' or ';
  1172. S:=S+TokenInfos[t];
  1173. end;
  1174. ParseExcTokenError(S);
  1175. end;
  1176. end;
  1177. procedure TPasParser.ExpectToken(tk: TToken);
  1178. begin
  1179. NextToken;
  1180. CheckToken(tk);
  1181. end;
  1182. procedure TPasParser.ExpectTokens(tk: TTokens);
  1183. begin
  1184. NextToken;
  1185. CheckTokens(tk);
  1186. end;
  1187. function TPasParser.GetPrevToken: TToken;
  1188. var
  1189. i: Integer;
  1190. P: PTokenRec;
  1191. begin
  1192. if FTokenRingStart = FTokenRingEnd then
  1193. Result:=tkEOF;
  1194. i:=FTokenRingCur;
  1195. if i>0 then
  1196. dec(i)
  1197. else
  1198. i:=High(FTokenRing);
  1199. P:=@FTokenRing[i];
  1200. Result := P^.Token;
  1201. end;
  1202. function TPasParser.ExpectIdentifier: String;
  1203. begin
  1204. ExpectToken(tkIdentifier);
  1205. Result := CurTokenString;
  1206. end;
  1207. function TPasParser.CurTokenIsIdentifier(const S: String): Boolean;
  1208. begin
  1209. Result:=(Curtoken=tkIdentifier) and (CompareText(S,CurtokenText)=0);
  1210. end;
  1211. function TPasParser.IsCurTokenHint(out AHint: TPasMemberHint): Boolean;
  1212. begin
  1213. Result:=CurToken=tklibrary;
  1214. if Result then
  1215. AHint:=hLibrary
  1216. else if (CurToken=tkIdentifier) then
  1217. Result:=IsHintToken(CurTokenString,ahint);
  1218. end;
  1219. function TPasParser.IsCurTokenHint: Boolean;
  1220. var
  1221. dummy : TPasMemberHint;
  1222. begin
  1223. Result:=IsCurTokenHint(dummy);
  1224. end;
  1225. function TPasParser.TokenIsCallingConvention(const S: String; out
  1226. CC: TCallingConvention): Boolean;
  1227. begin
  1228. Result:=IsCallingConvention(S,CC);
  1229. end;
  1230. function TPasParser.TokenIsProcedureModifier(Parent: TPasElement;
  1231. const S: String; out PM: TProcedureModifier): Boolean;
  1232. begin
  1233. Result:=IsProcModifier(S,PM);
  1234. if not Result then exit;
  1235. While (Parent<>Nil) do
  1236. begin
  1237. if Parent is TPasClassType then
  1238. begin
  1239. if PM in [pmPublic,pmForward] then exit(false);
  1240. case TPasClassType(Parent).ObjKind of
  1241. okInterface,okDispInterface:
  1242. if not (PM in [pmOverload, pmMessage,
  1243. pmDispId,pmNoReturn,pmFar,pmFinal]) then exit(false);
  1244. end;
  1245. exit;
  1246. end
  1247. else if Parent is TPasRecordType then
  1248. begin
  1249. if not (PM in [pmOverload,
  1250. pmInline, pmAssembler,
  1251. pmExternal,
  1252. pmNoReturn, pmFar, pmFinal]) then exit(false);
  1253. exit;
  1254. end;
  1255. Parent:=Parent.Parent;
  1256. end;
  1257. end;
  1258. function TPasParser.TokenIsAnonymousProcedureModifier(Parent: TPasElement;
  1259. S: String; out PM: TProcedureModifier): Boolean;
  1260. begin
  1261. Result:=IsProcModifier(S,PM);
  1262. if not Result then exit;
  1263. Result:=PM in [pmAssembler];
  1264. if Parent=nil then ;
  1265. end;
  1266. function TPasParser.TokenIsProcedureTypeModifier(Parent: TPasElement;
  1267. const S: String; out PTM: TProcTypeModifier): Boolean;
  1268. begin
  1269. if CompareText(S,ProcTypeModifiers[ptmVarargs])=0 then
  1270. begin
  1271. Result:=true;
  1272. PTM:=ptmVarargs;
  1273. end
  1274. else if CompareText(S,ProcTypeModifiers[ptmStatic])=0 then
  1275. begin
  1276. Result:=true;
  1277. PTM:=ptmStatic;
  1278. end
  1279. else
  1280. Result:=false;
  1281. if Parent=nil then;
  1282. end;
  1283. function TPasParser.CheckHint(Element: TPasElement; ExpectSemiColon: Boolean
  1284. ): TPasMemberHints;
  1285. Var
  1286. Found : Boolean;
  1287. h : TPasMemberHint;
  1288. begin
  1289. Result:=[];
  1290. Repeat
  1291. NextToken;
  1292. Found:=IsCurTokenHint(h);
  1293. If Found then
  1294. begin
  1295. Include(Result,h);
  1296. if (h=hDeprecated) then
  1297. begin
  1298. NextToken;
  1299. if (Curtoken<>tkString) then
  1300. UnGetToken
  1301. else if assigned(Element) then
  1302. Element.HintMessage:=CurTokenString;
  1303. end;
  1304. end;
  1305. Until Not Found;
  1306. UngetToken;
  1307. If Assigned(Element) then
  1308. Element.Hints:=Result;
  1309. if ExpectSemiColon then
  1310. ExpectToken(tkSemiColon);
  1311. end;
  1312. function TPasParser.IsAnonymousProcAllowed(El: TPasElement): boolean;
  1313. begin
  1314. while El is TPasExpr do
  1315. El:=El.Parent;
  1316. Result:=El is TPasImplBlock; // only in statements
  1317. end;
  1318. function TPasParser.CheckPackMode: TPackMode;
  1319. begin
  1320. NextToken;
  1321. Case CurToken of
  1322. tkPacked : Result:=pmPacked;
  1323. tkbitpacked : Result:=pmBitPacked;
  1324. else
  1325. result:=pmNone;
  1326. end;
  1327. if (Result<>pmNone) then
  1328. begin
  1329. NextToken;
  1330. if Not (CurToken in [tkArray, tkRecord, tkObject, tkClass, tkSet]) then
  1331. ParseExcTokenError('SET, ARRAY, RECORD, OBJECT or CLASS');
  1332. end;
  1333. end;
  1334. Function IsSimpleTypeToken(Var AName : String) : Boolean;
  1335. Const
  1336. SimpleTypeCount = 15;
  1337. SimpleTypeNames : Array[1..SimpleTypeCount] of string =
  1338. ('byte','boolean','char','integer','int64','longint','longword','double',
  1339. 'shortint','smallint','string','word','qword','cardinal','widechar');
  1340. SimpleTypeCaseNames : Array[1..SimpleTypeCount] of string =
  1341. ('Byte','Boolean','Char','Integer','Int64','LongInt','LongWord','Double',
  1342. 'ShortInt','SmallInt','String','Word','QWord','Cardinal','WideChar');
  1343. Var
  1344. S : String;
  1345. I : Integer;
  1346. begin
  1347. S:=LowerCase(AName);
  1348. I:=SimpleTypeCount;
  1349. While (I>0) and (s<>SimpleTypeNames[i]) do
  1350. Dec(I);
  1351. Result:=(I>0);
  1352. if Result Then
  1353. AName:=SimpleTypeCaseNames[I];
  1354. end;
  1355. function TPasParser.ParseStringType(Parent: TPasElement;
  1356. const NamePos: TPasSourcePos; const TypeName: String): TPasAliasType;
  1357. Var
  1358. LengthAsText : String;
  1359. ok: Boolean;
  1360. Params: TParamsExpr;
  1361. LengthExpr: TPasExpr;
  1362. begin
  1363. Result := TPasAliasType(CreateElement(TPasAliasType, TypeName, Parent, NamePos));
  1364. ok:=false;
  1365. try
  1366. If (Result.Name='') then
  1367. Result.Name:='string';
  1368. Result.Expr:=CreatePrimitiveExpr(Result,pekIdent,TypeName);
  1369. NextToken;
  1370. LengthAsText:='';
  1371. if CurToken=tkSquaredBraceOpen then
  1372. begin
  1373. Params:=TParamsExpr(CreateElement(TParamsExpr,'',Result));
  1374. Params.Value:=Result.Expr;
  1375. Result.Expr:=Params;
  1376. LengthAsText:='';
  1377. NextToken;
  1378. LengthExpr:=DoParseExpression(Result,nil,false);
  1379. Params.AddParam(LengthExpr);
  1380. CheckToken(tkSquaredBraceClose);
  1381. LengthAsText:=ExprToText(LengthExpr);
  1382. end
  1383. else
  1384. UngetToken;
  1385. Result.DestType:=TPasStringType(CreateElement(TPasStringType,'string',Result));
  1386. TPasStringType(Result.DestType).LengthExpr:=LengthAsText;
  1387. ok:=true;
  1388. finally
  1389. if not ok then
  1390. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  1391. end;
  1392. end;
  1393. function TPasParser.ParseSimpleType(Parent: TPasElement;
  1394. const NamePos: TPasSourcePos; const TypeName: String; IsFull: Boolean
  1395. ): TPasType;
  1396. Type
  1397. TSimpleTypeKind = (stkAlias,stkString,stkRange);
  1398. Var
  1399. Ref: TPasType;
  1400. K : TSimpleTypeKind;
  1401. Name : String;
  1402. Expr: TPasExpr;
  1403. ok, MustBeSpecialize: Boolean;
  1404. begin
  1405. Result:=nil;
  1406. if CurToken=tkspecialize then
  1407. begin
  1408. MustBeSpecialize:=true;
  1409. ExpectIdentifier;
  1410. end
  1411. else
  1412. MustBeSpecialize:=false;
  1413. Name := CurTokenString;
  1414. Expr:=nil;
  1415. Ref:=nil;
  1416. ok:=false;
  1417. try
  1418. if IsFull then
  1419. Name:=ReadDottedIdentifier(Parent,Expr,true)
  1420. else
  1421. begin
  1422. NextToken;
  1423. while CurToken=tkDot do
  1424. begin
  1425. ExpectIdentifier;
  1426. Name := Name+'.'+CurTokenString;
  1427. NextToken;
  1428. end;
  1429. end;
  1430. if MustBeSpecialize and (CurToken<>tkLessThan) then
  1431. ParseExcTokenError('<');
  1432. // Current token is first token after identifier.
  1433. if IsFull and (CurToken=tkSemicolon) or isCurTokenHint then // Type A = B;
  1434. begin
  1435. K:=stkAlias;
  1436. UnGetToken;
  1437. end
  1438. else if IsFull and (CurToken=tkSquaredBraceOpen) then
  1439. begin
  1440. if LowerCase(Name)='string' then // Type A = String[12]; shortstring
  1441. K:=stkString
  1442. else
  1443. ParseExcSyntaxError;
  1444. UnGetToken;
  1445. end
  1446. else if (CurToken = tkLessThan)
  1447. and (MustBeSpecialize or (msDelphi in CurrentModeswitches)) then // A = B<t>;
  1448. begin
  1449. Result:=ParseSpecializeType(Parent,TypeName,Name,Expr);
  1450. ok:=true;
  1451. exit;
  1452. end
  1453. else if (CurToken in [tkBraceOpen,tkDotDot]) then // A: B..C;
  1454. begin
  1455. K:=stkRange;
  1456. UnGetToken;
  1457. end
  1458. else
  1459. begin
  1460. if IsFull then
  1461. ParseExcTokenError(';');
  1462. K:=stkAlias;
  1463. if (not (po_resolvestandardtypes in Options)) and (LowerCase(Name)='string') then
  1464. K:=stkString;
  1465. UnGetToken;
  1466. end;
  1467. Case K of
  1468. stkString:
  1469. begin
  1470. ReleaseAndNil(TPasElement(Expr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
  1471. Result:=ParseStringType(Parent,NamePos,TypeName);
  1472. end;
  1473. stkRange:
  1474. begin
  1475. ReleaseAndNil(TPasElement(Expr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
  1476. UnGetToken; // move to '='
  1477. Result:=ParseRangeType(Parent,NamePos,TypeName,False);
  1478. end;
  1479. stkAlias:
  1480. begin
  1481. Ref:=ResolveTypeReference(Name,Parent);
  1482. if IsFull then
  1483. begin
  1484. Result := TPasAliasType(CreateElement(TPasAliasType, TypeName, Parent, NamePos));
  1485. TPasAliasType(Result).DestType:=Ref;
  1486. Ref:=nil;
  1487. TPasAliasType(Result).Expr:=Expr;
  1488. Expr.Parent:=Result;
  1489. Expr:=nil;
  1490. if TypeName<>'' then
  1491. Engine.FinishScope(stTypeDef,Result);
  1492. end
  1493. else
  1494. Result:=Ref;
  1495. end;
  1496. end;
  1497. ok:=true;
  1498. finally
  1499. if not ok then
  1500. begin
  1501. if Result<>nil then
  1502. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  1503. if Expr<>nil then
  1504. Expr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  1505. if Ref<>nil then
  1506. Ref.Release{$IFDEF CheckPasTreeRefCount}('ResolveTypeReference'){$ENDIF};
  1507. end
  1508. end;
  1509. end;
  1510. // On entry, we're on the TYPE token
  1511. function TPasParser.ParseAliasType(Parent: TPasElement;
  1512. const NamePos: TPasSourcePos; const TypeName: String): TPasType;
  1513. var
  1514. ok: Boolean;
  1515. begin
  1516. Result := TPasTypeAliasType(CreateElement(TPasTypeAliasType, TypeName, Parent, NamePos));
  1517. ok:=false;
  1518. try
  1519. TPasTypeAliasType(Result).DestType := ParseType(Result,NamePos,'');
  1520. Engine.FinishTypeAlias(Result);
  1521. Engine.FinishScope(stTypeDef,Result);
  1522. ok:=true;
  1523. finally
  1524. if not ok then
  1525. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  1526. end;
  1527. end;
  1528. function TPasParser.ParseTypeReference(Parent: TPasElement; NeedExpr: boolean;
  1529. out Expr: TPasExpr): TPasType;
  1530. // returns either
  1531. // a) TPasSpecializeType, Expr=nil
  1532. // b) TPasUnresolvedTypeRef, Expr<>nil
  1533. // c) TPasType, Expr<>nil
  1534. // After parsing CurToken is behind last reference token, e.g. ;
  1535. var
  1536. Name: String;
  1537. IsSpecialize, ok: Boolean;
  1538. begin
  1539. Result:=nil;
  1540. Expr:=nil;
  1541. ok:=false;
  1542. try
  1543. if CurToken=tkspecialize then
  1544. begin
  1545. IsSpecialize:=true;
  1546. NextToken;
  1547. end
  1548. else
  1549. IsSpecialize:=false;
  1550. // read dotted identifier
  1551. CheckToken(tkIdentifier);
  1552. Name:=ReadDottedIdentifier(Parent,Expr,true);
  1553. if CurToken=tkLessThan then
  1554. begin
  1555. // specialize
  1556. if IsSpecialize or (msDelphi in CurrentModeswitches) then
  1557. begin
  1558. Result:=ParseSpecializeType(Parent,'',Name,Expr);
  1559. NextToken;
  1560. end
  1561. else
  1562. CheckToken(tkend);
  1563. end
  1564. else if IsSpecialize then
  1565. CheckToken(tkLessThan)
  1566. else
  1567. begin
  1568. // simple type reference
  1569. Result:=ResolveTypeReference(Name,Parent);
  1570. end;
  1571. ok:=true;
  1572. finally
  1573. if not ok then
  1574. begin
  1575. if Result<>nil then
  1576. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  1577. ReleaseAndNil(TPasElement(Expr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
  1578. end
  1579. else if (not NeedExpr) and (Expr<>nil) then
  1580. ReleaseAndNil(TPasElement(Expr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
  1581. end;
  1582. end;
  1583. function TPasParser.ParseSpecializeType(Parent: TPasElement; const TypeName,
  1584. GenName: string; var GenNameExpr: TPasExpr): TPasSpecializeType;
  1585. // after parsing CurToken is at >
  1586. var
  1587. ST: TPasSpecializeType;
  1588. begin
  1589. Result:=nil;
  1590. if CurToken<>tkLessThan then
  1591. ParseExcTokenError('[20190801112729]');
  1592. ST:=TPasSpecializeType(CreateElement(TPasSpecializeType,TypeName,Parent));
  1593. try
  1594. if GenNameExpr<>nil then
  1595. begin
  1596. ST.Expr:=GenNameExpr;
  1597. GenNameExpr.Parent:=ST;
  1598. GenNameExpr:=nil; // ownership transferred to ST
  1599. end;
  1600. // read nested specialize arguments
  1601. ReadSpecializeArguments(ST,ST.Params);
  1602. // Important: resolve type reference AFTER args, because arg count is needed
  1603. ST.DestType:=ResolveTypeReference(GenName,ST,ST.Params.Count);
  1604. if CurToken<>tkGreaterThan then
  1605. ParseExcTokenError('[20190801113005]');
  1606. // ToDo: cascaded specialize A<B>.C<D>
  1607. Engine.FinishScope(stTypeDef,ST);
  1608. Result:=ST;
  1609. finally
  1610. if Result=nil then
  1611. ST.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  1612. end;
  1613. end;
  1614. function TPasParser.ParsePointerType(Parent: TPasElement;
  1615. const NamePos: TPasSourcePos; const TypeName: String): TPasPointerType;
  1616. var
  1617. ok: Boolean;
  1618. Name: String;
  1619. begin
  1620. Result := TPasPointerType(CreateElement(TPasPointerType, TypeName, Parent, NamePos));
  1621. ok:=false;
  1622. Try
  1623. // only allowed: ^dottedidentifer
  1624. // forbidden: ^^identifier, ^array of word, ^A<B>
  1625. ExpectIdentifier;
  1626. Name:=CurTokenString;
  1627. repeat
  1628. NextToken;
  1629. if CurToken=tkDot then
  1630. begin
  1631. ExpectIdentifier;
  1632. Name := Name+'.'+CurTokenString;
  1633. end
  1634. else
  1635. break;
  1636. until false;
  1637. UngetToken;
  1638. Result.DestType:=ResolveTypeReference(Name,Result);
  1639. Engine.FinishScope(stTypeDef,Result);
  1640. ok:=true;
  1641. finally
  1642. if not ok then
  1643. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  1644. end;
  1645. end;
  1646. function TPasParser.ParseEnumType(Parent: TPasElement;
  1647. const NamePos: TPasSourcePos; const TypeName: String): TPasEnumType;
  1648. Var
  1649. EnumValue: TPasEnumValue;
  1650. ok: Boolean;
  1651. begin
  1652. Result := TPasEnumType(CreateElement(TPasEnumType, TypeName, Parent, NamePos));
  1653. ok:=false;
  1654. try
  1655. while True do
  1656. begin
  1657. NextToken;
  1658. SaveComments;
  1659. EnumValue := TPasEnumValue(CreateElement(TPasEnumValue, CurTokenString, Result));
  1660. Result.Values.Add(EnumValue);
  1661. NextToken;
  1662. if CurToken = tkBraceClose then
  1663. break
  1664. else if CurToken in [tkEqual,tkAssign] then
  1665. begin
  1666. NextToken;
  1667. EnumValue.Value:=DoParseExpression(Result);
  1668. // UngetToken;
  1669. if CurToken = tkBraceClose then
  1670. Break
  1671. else if not (CurToken=tkComma) then
  1672. ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
  1673. end
  1674. else if not (CurToken=tkComma) then
  1675. ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket)
  1676. end;
  1677. Engine.FinishScope(stTypeDef,Result);
  1678. ok:=true;
  1679. finally
  1680. if not ok then
  1681. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  1682. end;
  1683. end;
  1684. function TPasParser.ParseSetType(Parent: TPasElement;
  1685. const NamePos: TPasSourcePos; const TypeName: String; AIsPacked : Boolean = False): TPasSetType;
  1686. var
  1687. ok: Boolean;
  1688. begin
  1689. Result := TPasSetType(CreateElement(TPasSetType, TypeName, Parent, NamePos));
  1690. Result.IsPacked:=AIsPacked;
  1691. ok:=false;
  1692. try
  1693. ExpectToken(tkOf);
  1694. Result.EnumType := ParseType(Result,CurSourcePos);
  1695. Engine.FinishScope(stTypeDef,Result);
  1696. ok:=true;
  1697. finally
  1698. if not ok then
  1699. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  1700. end;
  1701. end;
  1702. function TPasParser.ParseType(Parent: TPasElement;
  1703. const NamePos: TPasSourcePos; const TypeName: String; Full: Boolean
  1704. ): TPasType;
  1705. Const
  1706. // These types are allowed only when full type declarations
  1707. FullTypeTokens = [tkGeneric,{tkSpecialize,}tkClass,tkInterface,tkDispInterface,tkType];
  1708. // Parsing of these types already takes care of hints
  1709. NoHintTokens = [tkProcedure,tkFunction];
  1710. var
  1711. PM: TPackMode;
  1712. CH, isHelper, ok: Boolean;
  1713. begin
  1714. Result := nil;
  1715. // NextToken and check pack mode
  1716. Pm:=CheckPackMode;
  1717. if Full then
  1718. CH:=Not (CurToken in NoHintTokens)
  1719. else
  1720. begin
  1721. CH:=False;
  1722. if (CurToken in FullTypeTokens) then
  1723. ParseExc(nParserTypeNotAllowedHere,SParserTypeNotAllowedHere,[CurtokenText]);
  1724. end;
  1725. ok:=false;
  1726. Try
  1727. case CurToken of
  1728. // types only allowed when full
  1729. tkObject: Result := ParseClassDecl(Parent, NamePos, TypeName, okObject,PM);
  1730. tkDispInterface:
  1731. Result := ParseClassDecl(Parent, NamePos, TypeName, okDispInterface,PM);
  1732. tkInterface:
  1733. Result := ParseClassDecl(Parent, NamePos, TypeName, okInterface,PM);
  1734. tkSpecialize:
  1735. Result:=ParseSimpleType(Parent,CurSourcePos,TypeName);
  1736. tkClass:
  1737. begin
  1738. isHelper:=false;
  1739. NextToken;
  1740. if CurTokenIsIdentifier('Helper') then
  1741. begin
  1742. // class helper: atype end;
  1743. // class helper for atype end;
  1744. NextToken;
  1745. isHelper:=CurToken in [tkfor,tkBraceOpen];
  1746. UnGetToken;
  1747. end;
  1748. UngetToken;
  1749. if isHelper then
  1750. Result:=ParseClassDecl(Parent,NamePos,TypeName,okClassHelper, PM)
  1751. else
  1752. Result:=ParseClassDecl(Parent, NamePos, TypeName, okClass, PM);
  1753. end;
  1754. tkType:
  1755. begin
  1756. isHelper:=false;
  1757. if msTypeHelpers in Scanner.CurrentModeSwitches then
  1758. begin
  1759. NextToken;
  1760. if CurTokenIsIdentifier('helper') then
  1761. begin
  1762. // atype = type helper;
  1763. // atype = type helper for atype end;
  1764. NextToken;
  1765. isHelper:=CurToken in [tkfor,tkBraceOpen];
  1766. UnGetToken;
  1767. end;
  1768. UnGetToken;
  1769. end;
  1770. if isHelper then
  1771. Result:=ParseClassDecl(Parent,NamePos,TypeName,okTypeHelper,PM)
  1772. else
  1773. Result:=ParseAliasType(Parent,NamePos,TypeName);
  1774. end;
  1775. // Always allowed
  1776. tkIdentifier:
  1777. begin
  1778. // Bug 31709: PReference = ^Reference;
  1779. // Checked in Delphi: ^Reference to procedure; is not allowed !!
  1780. if CurTokenIsIdentifier('reference') and Not (Parent is TPasPointerType) then
  1781. begin
  1782. CH:=False;
  1783. Result:=ParseReferencetoProcedureType(Parent,NamePos,TypeName)
  1784. end
  1785. else
  1786. Result:=ParseSimpleType(Parent,NamePos,TypeName,Full);
  1787. end;
  1788. tkCaret: Result:=ParsePointerType(Parent,NamePos,TypeName);
  1789. tkFile: Result:=ParseFileType(Parent,NamePos,TypeName);
  1790. tkArray: Result:=ParseArrayType(Parent,NamePos,TypeName,pm);
  1791. tkBraceOpen: Result:=ParseEnumType(Parent,NamePos,TypeName);
  1792. tkSet: Result:=ParseSetType(Parent,NamePos,TypeName,pm=pmPacked);
  1793. tkProcedure: Result:=ParseProcedureType(Parent,NamePos,TypeName,ptProcedure);
  1794. tkFunction: Result:=ParseProcedureType(Parent,NamePos,TypeName,ptFunction);
  1795. tkRecord:
  1796. begin
  1797. NextToken;
  1798. isHelper:=false;
  1799. if CurTokenIsIdentifier('Helper') then
  1800. begin
  1801. // record helper: atype end;
  1802. // record helper for atype end;
  1803. NextToken;
  1804. isHelper:=CurToken in [tkfor,tkBraceOpen];
  1805. UnGetToken;
  1806. end;
  1807. UngetToken;
  1808. if isHelper then
  1809. Result:=ParseClassDecl(Parent,NamePos,TypeName,okRecordHelper,PM)
  1810. else
  1811. Result:=ParseRecordDecl(Parent,NamePos,TypeName,PM);
  1812. end;
  1813. tkNumber,tkMinus,tkChar:
  1814. begin
  1815. UngetToken;
  1816. Result:=ParseRangeType(Parent,NamePos,TypeName,Full);
  1817. end;
  1818. else
  1819. ParseExcExpectedIdentifier;
  1820. end;
  1821. if CH then
  1822. CheckHint(Result,True);
  1823. ok:=true;
  1824. finally
  1825. if not ok then
  1826. if Result<>nil then
  1827. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  1828. end;
  1829. end;
  1830. function TPasParser.ParseReferenceToProcedureType(Parent: TPasElement; const NamePos: TPasSourcePos; const TypeName: String
  1831. ): TPasProcedureType;
  1832. begin
  1833. if not CurTokenIsIdentifier('reference') then
  1834. ParseExcTokenError('reference');
  1835. ExpectToken(tkTo);
  1836. NextToken;
  1837. Case CurToken of
  1838. tkprocedure : Result:=ParseProcedureType(Parent,NamePos,TypeName,ptProcedure);
  1839. tkfunction : Result:=ParseProcedureType(Parent,NamePos,TypeName,ptFunction);
  1840. else
  1841. ParseExcTokenError('procedure or function');
  1842. end;
  1843. Result.IsReferenceTo:=True;
  1844. end;
  1845. function TPasParser.ParseComplexType(Parent : TPasElement = Nil): TPasType;
  1846. begin
  1847. NextToken;
  1848. case CurToken of
  1849. tkProcedure:
  1850. begin
  1851. Result := TPasProcedureType(CreateElement(TPasProcedureType, '', Parent));
  1852. ParseProcedureOrFunction(Result, TPasProcedureType(Result), ptProcedure, True);
  1853. if CurToken = tkSemicolon then
  1854. UngetToken; // Unget semicolon
  1855. end;
  1856. tkFunction:
  1857. begin
  1858. Result := CreateFunctionType('', 'Result', Parent, False, CurSourcePos);
  1859. ParseProcedureOrFunction(Result, TPasFunctionType(Result), ptFunction, True);
  1860. if CurToken = tkSemicolon then
  1861. UngetToken; // Unget semicolon
  1862. end;
  1863. else
  1864. UngetToken;
  1865. Result := ParseType(Parent,CurSourcePos);
  1866. end;
  1867. end;
  1868. function TPasParser.ParseArrayType(Parent: TPasElement;
  1869. const NamePos: TPasSourcePos; const TypeName: String; PackMode: TPackMode
  1870. ): TPasArrayType;
  1871. Var
  1872. ok: Boolean;
  1873. begin
  1874. Result := TPasArrayType(CreateElement(TPasArrayType, TypeName, Parent, NamePos));
  1875. ok:=false;
  1876. try
  1877. Result.PackMode:=PackMode;
  1878. DoParseArrayType(Result);
  1879. Engine.FinishScope(stTypeDef,Result);
  1880. ok:=true;
  1881. finally
  1882. if not ok then
  1883. begin
  1884. Result.Parent:=nil;
  1885. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  1886. end;
  1887. end;
  1888. end;
  1889. function TPasParser.ParseFileType(Parent: TPasElement;
  1890. const NamePos: TPasSourcePos; const TypeName: String): TPasFileType;
  1891. begin
  1892. Result:=TPasFileType(CreateElement(TPasFileType, TypeName, Parent, NamePos));
  1893. NextToken;
  1894. If CurToken=tkOf then
  1895. Result.ElType := ParseType(Result,CurSourcePos)
  1896. else
  1897. UngetToken;
  1898. end;
  1899. function TPasParser.isEndOfExp(AllowEqual : Boolean = False; CheckHints : Boolean = True):Boolean;
  1900. const
  1901. EndExprToken = [
  1902. tkEOF, tkBraceClose, tkSquaredBraceClose, tkSemicolon, tkComma, tkColon,
  1903. tkdo, tkdownto, tkelse, tkend, tkof, tkthen, tkto
  1904. ];
  1905. begin
  1906. Result:=(CurToken in EndExprToken) or (CheckHints and IsCurTokenHint);
  1907. if Not (Result or AllowEqual) then
  1908. Result:=(Curtoken=tkEqual);
  1909. end;
  1910. function TPasParser.ExprToText(Expr: TPasExpr): String;
  1911. var
  1912. C: TClass;
  1913. begin
  1914. C:=Expr.ClassType;
  1915. if C=TPrimitiveExpr then
  1916. Result:=TPrimitiveExpr(Expr).Value
  1917. else if C=TSelfExpr then
  1918. Result:='self'
  1919. else if C=TBoolConstExpr then
  1920. Result:=BoolToStr(TBoolConstExpr(Expr).Value,'true','false')
  1921. else if C=TNilExpr then
  1922. Result:='nil'
  1923. else if C=TInheritedExpr then
  1924. Result:='inherited'
  1925. else if C=TUnaryExpr then
  1926. Result:=OpcodeStrings[TUnaryExpr(Expr).OpCode]+ExprToText(TUnaryExpr(Expr).Operand)
  1927. else if C=TBinaryExpr then
  1928. begin
  1929. Result:=ExprToText(TBinaryExpr(Expr).left);
  1930. if OpcodeStrings[TBinaryExpr(Expr).OpCode]<>'' then
  1931. Result:=Result+OpcodeStrings[TBinaryExpr(Expr).OpCode]
  1932. else
  1933. Result:=Result+' ';
  1934. Result:=Result+ExprToText(TBinaryExpr(Expr).right)
  1935. end
  1936. else if C=TParamsExpr then
  1937. begin
  1938. case TParamsExpr(Expr).Kind of
  1939. pekArrayParams: Result:=ExprToText(TParamsExpr(Expr).Value)
  1940. +'['+ArrayExprToText(TParamsExpr(Expr).Params)+']';
  1941. pekFuncParams: Result:=ExprToText(TParamsExpr(Expr).Value)
  1942. +'('+ArrayExprToText(TParamsExpr(Expr).Params)+')';
  1943. pekSet: Result:='['+ArrayExprToText(TParamsExpr(Expr).Params)+']';
  1944. else ParseExc(nErrUnknownOperatorType,SErrUnknownOperatorType,[ExprKindNames[TParamsExpr(Expr).Kind]]);
  1945. end;
  1946. end
  1947. else
  1948. ParseExc(nErrUnknownOperatorType,SErrUnknownOperatorType,['TPasParser.ExprToText: '+Expr.ClassName]);
  1949. end;
  1950. function TPasParser.ArrayExprToText(Expr: TPasExprArray): String;
  1951. var
  1952. i: Integer;
  1953. begin
  1954. Result:='';
  1955. for i:=0 to length(Expr)-1 do
  1956. begin
  1957. if i>0 then
  1958. Result:=Result+',';
  1959. Result:=Result+ExprToText(Expr[i]);
  1960. end;
  1961. end;
  1962. function TPasParser.ResolveTypeReference(Name: string; Parent: TPasElement;
  1963. ParamCnt: integer): TPasType;
  1964. var
  1965. SS: Boolean;
  1966. Ref: TPasElement;
  1967. begin
  1968. Ref:=Nil;
  1969. SS:=(not (po_ResolveStandardTypes in FOptions)) and isSimpleTypeToken(Name);
  1970. if not SS then
  1971. begin
  1972. Ref:=Engine.FindElementFor(Name,Parent,ParamCnt);
  1973. if Ref=nil then
  1974. begin
  1975. {$IFDEF VerbosePasResolver}
  1976. {AllowWriteln}
  1977. if po_resolvestandardtypes in FOptions then
  1978. begin
  1979. writeln('ERROR: TPasParser.ResolveTypeReference: resolver failed to raise an error');
  1980. ParseExcExpectedIdentifier;
  1981. end;
  1982. {AllowWriteln-}
  1983. {$ENDIF}
  1984. end
  1985. else if not (Ref is TPasType) then
  1986. ParseExc(nParserExpectedTypeButGot,SParserExpectedTypeButGot,[Ref.ElementTypeName]);
  1987. end;
  1988. if (Ref=Nil) then
  1989. Result:=TPasUnresolvedTypeRef(CreateElement(TPasUnresolvedTypeRef,Name,Parent))
  1990. else
  1991. begin
  1992. Ref.AddRef{$IFDEF CheckPasTreeRefCount}('ResolveTypeReference'){$ENDIF};
  1993. Result:=TPasType(Ref);
  1994. end;
  1995. end;
  1996. function TPasParser.ParseParams(AParent: TPasElement; ParamsKind: TPasExprKind;
  1997. AllowFormatting: Boolean = False): TParamsExpr;
  1998. var
  1999. Params : TParamsExpr;
  2000. Expr : TPasExpr;
  2001. PClose : TToken;
  2002. begin
  2003. Result:=nil;
  2004. if ParamsKind in [pekArrayParams, pekSet] then
  2005. begin
  2006. if CurToken<>tkSquaredBraceOpen then
  2007. ParseExc(nParserExpectTokenError,SParserExpectTokenError,['[']);
  2008. PClose:=tkSquaredBraceClose;
  2009. end
  2010. else
  2011. begin
  2012. if CurToken<>tkBraceOpen then
  2013. ParseExc(nParserExpectTokenError,SParserExpectTokenError,['(']);
  2014. PClose:=tkBraceClose;
  2015. end;
  2016. Params:=TParamsExpr(CreateElement(TParamsExpr,'',AParent,CurTokenPos));
  2017. try
  2018. Params.Kind:=ParamsKind;
  2019. NextToken;
  2020. if not isEndOfExp(false,false) then
  2021. begin
  2022. repeat
  2023. Expr:=DoParseExpression(Params);
  2024. if not Assigned(Expr) then
  2025. ParseExcSyntaxError;
  2026. Params.AddParam(Expr);
  2027. if (CurToken=tkColon) then
  2028. if Not AllowFormatting then
  2029. ParseExc(nParserExpectTokenError,SParserExpectTokenError,[','])
  2030. else
  2031. begin
  2032. NextToken;
  2033. Expr.format1:=DoParseExpression(Expr);
  2034. if (CurToken=tkColon) then
  2035. begin
  2036. NextToken;
  2037. Expr.format2:=DoParseExpression(Expr);
  2038. end;
  2039. end;
  2040. if not (CurToken in [tkComma, PClose]) then
  2041. ParseExc(nParserExpectTokenError,SParserExpectTokenError,[',']);
  2042. if CurToken = tkComma then
  2043. begin
  2044. NextToken;
  2045. if CurToken = PClose then
  2046. begin
  2047. //ErrorExpected(parser, 'identifier');
  2048. ParseExcSyntaxError;
  2049. end;
  2050. end;
  2051. until CurToken=PClose;
  2052. end;
  2053. NextToken;
  2054. Result:=Params;
  2055. finally
  2056. if Result=nil then
  2057. Params.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  2058. end;
  2059. end;
  2060. function TPasParser.TokenToExprOp(AToken: TToken): TExprOpCode;
  2061. begin
  2062. Case AToken of
  2063. tkMul : Result:=eopMultiply;
  2064. tkPlus : Result:=eopAdd;
  2065. tkMinus : Result:=eopSubtract;
  2066. tkDivision : Result:=eopDivide;
  2067. tkLessThan : Result:=eopLessThan;
  2068. tkEqual : Result:=eopEqual;
  2069. tkGreaterThan : Result:=eopGreaterThan;
  2070. tkAt : Result:=eopAddress;
  2071. tkAtAt : Result:=eopMemAddress;
  2072. tkNotEqual : Result:=eopNotEqual;
  2073. tkLessEqualThan : Result:=eopLessthanEqual;
  2074. tkGreaterEqualThan : Result:=eopGreaterThanEqual;
  2075. tkPower : Result:=eopPower;
  2076. tkSymmetricalDifference : Result:=eopSymmetricalDifference;
  2077. tkIs : Result:=eopIs;
  2078. tkAs : Result:=eopAs;
  2079. tkSHR : Result:=eopSHR;
  2080. tkSHL : Result:=eopSHL;
  2081. tkAnd : Result:=eopAnd;
  2082. tkOr : Result:=eopOR;
  2083. tkXor : Result:=eopXOR;
  2084. tkMod : Result:=eopMod;
  2085. tkDiv : Result:=eopDiv;
  2086. tkNot : Result:=eopNot;
  2087. tkIn : Result:=eopIn;
  2088. tkDot : Result:=eopSubIdent;
  2089. tkCaret : Result:=eopDeref;
  2090. else
  2091. ParseExc(nParserNotAnOperand,SParserNotAnOperand,[AToken,TokenInfos[AToken]]);
  2092. end;
  2093. end;
  2094. function TPasParser.ParseExprOperand(AParent: TPasElement): TPasExpr;
  2095. type
  2096. TAllow = (aCannot, aCan, aMust);
  2097. Function IsWriteOrStr(P : TPasExpr) : boolean;
  2098. Var
  2099. N : String;
  2100. begin
  2101. Result:=P is TPrimitiveExpr;
  2102. if Result then
  2103. begin
  2104. N:=LowerCase(TPrimitiveExpr(P).Value);
  2105. // We should actually resolve this to system.NNN
  2106. Result:=(N='write') or (N='str') or (N='writeln') or (N='writestr');
  2107. end;
  2108. end;
  2109. function IsSpecialize: boolean;
  2110. var
  2111. LookAhead, i: Integer;
  2112. function Next: boolean;
  2113. begin
  2114. if LookAhead=FTokenRingSize then exit(false);
  2115. NextToken;
  2116. inc(LookAhead);
  2117. Result:=true;
  2118. end;
  2119. begin
  2120. Result:=false;
  2121. LookAhead:=0;
  2122. CheckToken(tkLessThan);
  2123. try
  2124. Next;
  2125. if not (CurToken in [tkIdentifier,tkself]) then exit;
  2126. while Next do
  2127. case CurToken of
  2128. tkDot:
  2129. begin
  2130. if not Next then exit;
  2131. if not (CurToken in [tkIdentifier,tkself,tktrue,tkfalse]) then exit;
  2132. end;
  2133. tkComma:
  2134. begin
  2135. if not Next then exit;
  2136. if not (CurToken in [tkIdentifier,tkself]) then exit;
  2137. end;
  2138. tkLessThan:
  2139. begin
  2140. // e.g. A<B<
  2141. // not a valid comparison, could be a specialization -> good enough
  2142. exit(true);
  2143. end;
  2144. tkGreaterThan:
  2145. begin
  2146. // e.g. A<B>
  2147. exit(true);
  2148. end;
  2149. else
  2150. exit;
  2151. end;
  2152. finally
  2153. for i:=1 to LookAhead do
  2154. UngetToken;
  2155. end;
  2156. end;
  2157. var
  2158. Last, Func, Expr: TPasExpr;
  2159. Params: TParamsExpr;
  2160. Bin: TBinaryExpr;
  2161. ok: Boolean;
  2162. CanSpecialize: TAllow;
  2163. aName: String;
  2164. ISE: TInlineSpecializeExpr;
  2165. SrcPos, ScrPos: TPasSourcePos;
  2166. ProcType: TProcType;
  2167. ProcExpr: TProcedureExpr;
  2168. begin
  2169. Result:=nil;
  2170. CanSpecialize:=aCannot;
  2171. aName:='';
  2172. case CurToken of
  2173. tkString: Last:=CreatePrimitiveExpr(AParent,pekString,CurTokenString);
  2174. tkChar: Last:=CreatePrimitiveExpr(AParent,pekString,CurTokenText);
  2175. tkNumber: Last:=CreatePrimitiveExpr(AParent,pekNumber,CurTokenString);
  2176. tkIdentifier:
  2177. begin
  2178. if msDelphi in CurrentModeswitches then
  2179. CanSpecialize:=aCan
  2180. else
  2181. CanSpecialize:=aCannot;
  2182. aName:=CurTokenText;
  2183. if (CompareText(aName,'self')=0) and not (tkself in Scanner.NonTokens) then
  2184. Last:=CreateSelfExpr(AParent)
  2185. else
  2186. Last:=CreatePrimitiveExpr(AParent,pekIdent,aName);
  2187. end;
  2188. tkspecialize:
  2189. begin
  2190. CanSpecialize:=aMust;
  2191. ExpectToken(tkIdentifier);
  2192. aName:=CurTokenText;
  2193. Last:=CreatePrimitiveExpr(AParent,pekIdent,aName);
  2194. end;
  2195. tkfalse, tktrue: Last:=CreateBoolConstExpr(AParent,pekBoolConst, CurToken=tktrue);
  2196. tknil: Last:=CreateNilExpr(AParent);
  2197. tkSquaredBraceOpen:
  2198. begin
  2199. Last:=ParseParams(AParent,pekSet);
  2200. UngetToken;
  2201. end;
  2202. tkinherited:
  2203. begin
  2204. //inherited; inherited function
  2205. Last:=CreateInheritedExpr(AParent);
  2206. NextToken;
  2207. if (CurToken=tkIdentifier) then
  2208. begin
  2209. SrcPos:=CurTokenPos;
  2210. Bin:=CreateBinaryExpr(AParent,Last,ParseExprOperand(AParent),eopNone,SrcPos);
  2211. if not Assigned(Bin.right) then
  2212. begin
  2213. Bin.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  2214. ParseExcExpectedIdentifier;
  2215. end;
  2216. Result:=Bin;
  2217. exit;
  2218. end;
  2219. UngetToken;
  2220. end;
  2221. tkself:
  2222. begin
  2223. CanSpecialize:=aCan;
  2224. aName:=CurTokenText;
  2225. Last:=CreateSelfExpr(AParent);
  2226. end;
  2227. tkprocedure,tkfunction:
  2228. begin
  2229. if not IsAnonymousProcAllowed(AParent) then
  2230. ParseExcExpectedIdentifier;
  2231. if CurToken=tkprocedure then
  2232. ProcType:=ptAnonymousProcedure
  2233. else
  2234. ProcType:=ptAnonymousFunction;
  2235. try
  2236. ProcExpr:=TProcedureExpr(CreateElement(TProcedureExpr,'',AParent,visPublic));
  2237. ProcExpr.Proc:=TPasAnonymousProcedure(ParseProcedureOrFunctionDecl(ProcExpr,ProcType,false));
  2238. Engine.FinishScope(stProcedure,ProcExpr.Proc);
  2239. Result:=ProcExpr;
  2240. finally
  2241. if Result=nil then
  2242. ProcExpr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  2243. end;
  2244. exit; // do not allow postfix operators . ^. [] ()
  2245. end;
  2246. tkCaret:
  2247. begin
  2248. // Why is this still needed?
  2249. // ^A..^_ characters
  2250. NextToken;
  2251. if not (length(CurTokenText)=1) or not (CurTokenText[1] in ['A'..'_']) then
  2252. begin
  2253. UngetToken;
  2254. ParseExcExpectedIdentifier;
  2255. end;
  2256. Last:=CreatePrimitiveExpr(AParent,pekString, '^'+CurTokenText);
  2257. end;
  2258. tkBraceOpen:
  2259. begin
  2260. NextToken;
  2261. Last:=DoParseExpression(AParent);
  2262. if not Assigned(Last) then
  2263. ParseExcSyntaxError;
  2264. if (CurToken<>tkBraceClose) then
  2265. begin
  2266. Last.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  2267. CheckToken(tkBraceClose);
  2268. end;
  2269. end
  2270. else
  2271. ParseExcExpectedIdentifier;
  2272. end;
  2273. Result:=Last;
  2274. ok:=false;
  2275. ISE:=nil;
  2276. try
  2277. NextToken;
  2278. Func:=Last;
  2279. repeat
  2280. case CurToken of
  2281. tkDot:
  2282. begin
  2283. ScrPos:=CurTokenPos;
  2284. NextToken;
  2285. if CurToken=tkspecialize then
  2286. begin
  2287. if CanSpecialize=aMust then
  2288. CheckToken(tkLessThan);
  2289. CanSpecialize:=aMust;
  2290. NextToken;
  2291. end;
  2292. if CurToken in [tkIdentifier,tktrue,tkfalse,tkself] then // true and false are sub identifiers as well
  2293. begin
  2294. aName:=aName+'.'+CurTokenString;
  2295. Expr:=CreatePrimitiveExpr(AParent,pekIdent,CurTokenString);
  2296. AddToBinaryExprChain(Result,Expr,eopSubIdent,ScrPos);
  2297. Func:=Expr;
  2298. NextToken;
  2299. end
  2300. else
  2301. begin
  2302. UngetToken;
  2303. ParseExcExpectedIdentifier;
  2304. end;
  2305. end;
  2306. tkBraceOpen,tkSquaredBraceOpen:
  2307. begin
  2308. if CurToken=tkBraceOpen then
  2309. Params:=ParseParams(AParent,pekFuncParams,IsWriteOrStr(Func))
  2310. else
  2311. Params:=ParseParams(AParent,pekArrayParams);
  2312. if not Assigned(Params) then Exit;
  2313. Params.Value:=Result;
  2314. Result.Parent:=Params;
  2315. Result:=Params;
  2316. CanSpecialize:=aCannot;
  2317. Func:=nil;
  2318. end;
  2319. tkCaret:
  2320. begin
  2321. Result:=CreateUnaryExpr(AParent,Result,TokenToExprOp(CurToken));
  2322. NextToken;
  2323. CanSpecialize:=aCannot;
  2324. Func:=nil;
  2325. end;
  2326. tkLessThan:
  2327. begin
  2328. SrcPos:=CurTokenPos;
  2329. if CanSpecialize=aCannot then
  2330. break
  2331. else if (CanSpecialize=aCan) and not IsSpecialize then
  2332. break
  2333. else
  2334. begin
  2335. // an inline specialization (e.g. A<B,C> or something.A<B>)
  2336. // check expression in front is an identifier
  2337. Expr:=Result;
  2338. if Expr.Kind=pekBinary then
  2339. begin
  2340. if Expr.OpCode<>eopSubIdent then
  2341. ParseExcSyntaxError;
  2342. Expr:=TBinaryExpr(Expr).right;
  2343. end;
  2344. if Expr.Kind<>pekIdent then
  2345. ParseExcSyntaxError;
  2346. // read specialized params
  2347. ISE:=TInlineSpecializeExpr(CreateElement(TInlineSpecializeExpr,'',AParent,SrcPos));
  2348. ReadSpecializeArguments(ISE,ISE.Params);
  2349. // A<B> or something.A<B>
  2350. ISE.NameExpr:=Result;
  2351. Result.Parent:=ISE;
  2352. Result:=ISE;
  2353. ISE:=nil;
  2354. CanSpecialize:=aCannot;
  2355. NextToken;
  2356. end;
  2357. Func:=nil;
  2358. end
  2359. else
  2360. break;
  2361. end;
  2362. until false;
  2363. ok:=true;
  2364. finally
  2365. if not ok then
  2366. begin
  2367. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  2368. ISE.Free;
  2369. end;
  2370. end;
  2371. end;
  2372. function TPasParser.ParseExpIdent(AParent: TPasElement): TPasExpr;
  2373. begin
  2374. Result:=ParseExprOperand(AParent);
  2375. end;
  2376. function TPasParser.OpLevel(t: TToken): Integer;
  2377. begin
  2378. case t of
  2379. // tkDot:
  2380. // Result:=5;
  2381. tknot,tkAt,tkAtAt:
  2382. Result:=4;
  2383. tkMul, tkDivision, tkdiv, tkmod, tkand, tkShl,tkShr, tkas, tkPower, tkis:
  2384. // Note that "is" has same precedence as "and" in Delphi and fpc, even though
  2385. // some docs say otherwise. e.g. "Obj is TObj and aBool"
  2386. Result:=3;
  2387. tkPlus, tkMinus, tkor, tkxor:
  2388. Result:=2;
  2389. tkEqual, tkNotEqual, tkLessThan, tkLessEqualThan, tkGreaterThan, tkGreaterEqualThan, tkin:
  2390. Result:=1;
  2391. else
  2392. Result:=0;
  2393. end;
  2394. end;
  2395. function TPasParser.DoParseExpression(AParent: TPaselement; InitExpr: TPasExpr;
  2396. AllowEqual: Boolean): TPasExpr;
  2397. type
  2398. TOpStackItem = record
  2399. Token: TToken;
  2400. SrcPos: TPasSourcePos;
  2401. end;
  2402. var
  2403. ExpStack : TFPList; // list of TPasExpr
  2404. OpStack : array of TOpStackItem;
  2405. OpStackTop: integer;
  2406. PrefixCnt : Integer;
  2407. x : TPasExpr;
  2408. i : Integer;
  2409. TempOp : TToken;
  2410. NotBinary : Boolean;
  2411. const
  2412. PrefixSym = [tkPlus, tkMinus, tknot, tkAt, tkAtAt]; // + - not @ @@
  2413. BinaryOP = [tkMul, tkDivision, tkdiv, tkmod, tkDotDot,
  2414. tkand, tkShl,tkShr, tkas, tkPower,
  2415. tkPlus, tkMinus, tkor, tkxor, tkSymmetricalDifference,
  2416. tkEqual, tkNotEqual, tkLessThan, tkLessEqualThan,
  2417. tkGreaterThan, tkGreaterEqualThan, tkin, tkis];
  2418. function PopExp: TPasExpr; inline;
  2419. begin
  2420. if ExpStack.Count>0 then begin
  2421. Result:=TPasExpr(ExpStack[ExpStack.Count-1]);
  2422. ExpStack.Delete(ExpStack.Count-1);
  2423. end else
  2424. Result:=nil;
  2425. end;
  2426. procedure PushOper(Token: TToken);
  2427. begin
  2428. inc(OpStackTop);
  2429. if OpStackTop=length(OpStack) then
  2430. SetLength(OpStack,length(OpStack)*2+4);
  2431. OpStack[OpStackTop].Token:=Token;
  2432. OpStack[OpStackTop].SrcPos:=CurTokenPos;
  2433. end;
  2434. function PeekOper: TToken; inline;
  2435. begin
  2436. if OpStackTop>=0 then Result:=OpStack[OpStackTop].Token
  2437. else Result:=tkEOF;
  2438. end;
  2439. function PopOper(out SrcPos: TPasSourcePos): TToken;
  2440. begin
  2441. Result:=PeekOper;
  2442. if Result=tkEOF then
  2443. SrcPos:=DefPasSourcePos
  2444. else
  2445. begin
  2446. SrcPos:=OpStack[OpStackTop].SrcPos;
  2447. dec(OpStackTop);
  2448. end;
  2449. end;
  2450. procedure PopAndPushOperator;
  2451. var
  2452. t : TToken;
  2453. xright : TPasExpr;
  2454. xleft : TPasExpr;
  2455. bin : TBinaryExpr;
  2456. SrcPos: TPasSourcePos;
  2457. begin
  2458. t:=PopOper(SrcPos);
  2459. xright:=PopExp;
  2460. xleft:=PopExp;
  2461. if t=tkDotDot then
  2462. begin
  2463. bin:=CreateBinaryExpr(AParent,xleft,xright,eopNone,SrcPos);
  2464. bin.Kind:=pekRange;
  2465. end
  2466. else
  2467. bin:=CreateBinaryExpr(AParent,xleft,xright,TokenToExprOp(t),SrcPos);
  2468. ExpStack.Add(bin);
  2469. end;
  2470. Var
  2471. AllowedBinaryOps : Set of TToken;
  2472. SrcPos: TPasSourcePos;
  2473. begin
  2474. AllowedBinaryOps:=BinaryOP;
  2475. if Not AllowEqual then
  2476. Exclude(AllowedBinaryOps,tkEqual);
  2477. {$ifdef VerbosePasParser}
  2478. //DumpCurToken('Entry',iaIndent);
  2479. {$endif}
  2480. Result:=nil;
  2481. ExpStack := TFPList.Create;
  2482. SetLength(OpStack,4);
  2483. OpStackTop:=-1;
  2484. try
  2485. repeat
  2486. NotBinary:=True;
  2487. PrefixCnt:=0;
  2488. if not Assigned(InitExpr) then
  2489. begin
  2490. // parse prefix operators
  2491. while CurToken in PrefixSym do
  2492. begin
  2493. PushOper(CurToken);
  2494. inc(PrefixCnt);
  2495. NextToken;
  2496. end;
  2497. // parse operand
  2498. x:=ParseExprOperand(AParent);
  2499. if not Assigned(x) then
  2500. ParseExcSyntaxError;
  2501. ExpStack.Add(x);
  2502. // apply prefixes
  2503. for i:=1 to PrefixCnt do
  2504. begin
  2505. TempOp:=PopOper(SrcPos);
  2506. x:=PopExp;
  2507. if (TempOp=tkMinus) and (x.Kind=pekRange) then
  2508. begin
  2509. TBinaryExpr(x).Left:=CreateUnaryExpr(x, TBinaryExpr(x).left,
  2510. eopSubtract, SrcPos);
  2511. ExpStack.Add(x);
  2512. end
  2513. else
  2514. ExpStack.Add(CreateUnaryExpr(AParent, x, TokenToExprOp(TempOp), SrcPos));
  2515. end;
  2516. end
  2517. else
  2518. begin
  2519. // the first part of the expression has been parsed externally.
  2520. // this is used by Constant Expression parser (CEP) parsing only,
  2521. // whenever it makes a false assuming on constant expression type.
  2522. // i.e: SI_PAD_SIZE = ((128/sizeof(longint)) - 3);
  2523. //
  2524. // CEP assumes that it's array or record, because the expression
  2525. // starts with "(". After the first part is parsed, the CEP meets "-"
  2526. // that assures, it's not an array expression. The CEP should give the
  2527. // first part back to the expression parser, to get the correct
  2528. // token tree according to the operations priority.
  2529. //
  2530. // quite ugly. type information is required for CEP to work clean
  2531. ExpStack.Add(InitExpr);
  2532. InitExpr:=nil;
  2533. end;
  2534. if (CurToken in AllowedBinaryOPs) then
  2535. begin
  2536. // process operators of higher precedence than next operator
  2537. NotBinary:=False;
  2538. TempOp:=PeekOper;
  2539. while (OpStackTop>=0) and (OpLevel(TempOp)>=OpLevel(CurToken)) do begin
  2540. PopAndPushOperator;
  2541. TempOp:=PeekOper;
  2542. end;
  2543. PushOper(CurToken);
  2544. NextToken;
  2545. end;
  2546. //Writeln('Bin ',NotBinary ,' or EOE ',isEndOfExp, ' Ex ',Assigned(x),' stack ',ExpStack.Count);
  2547. until NotBinary or isEndOfExp(AllowEqual, NotBinary);
  2548. if not NotBinary then ParseExcExpectedIdentifier;
  2549. while OpStackTop>=0 do PopAndPushOperator;
  2550. // only 1 expression should be left on the OpStack
  2551. if ExpStack.Count<>1 then
  2552. ParseExcSyntaxError;
  2553. Result:=TPasExpr(ExpStack[0]);
  2554. Result.Parent:=AParent;
  2555. finally
  2556. {$ifdef VerbosePasParser}
  2557. if Not Assigned(Result) then
  2558. DumpCurToken('Exiting (no result)',iaUndent)
  2559. else
  2560. DumpCurtoken('Exiting (Result: "'+Result.GetDeclaration(true)+'") ',iaUndent);
  2561. {$endif}
  2562. if not Assigned(Result) then begin
  2563. // expression error!
  2564. for i:=0 to ExpStack.Count-1 do
  2565. TPasExpr(ExpStack[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  2566. end;
  2567. SetLength(OpStack,0);
  2568. ExpStack.Free;
  2569. end;
  2570. end;
  2571. function GetExprIdent(p: TPasExpr): String;
  2572. begin
  2573. Result:='';
  2574. if not Assigned(p) then exit;
  2575. if (p.ClassType=TPrimitiveExpr) and (p.Kind=pekIdent) then
  2576. Result:=TPrimitiveExpr(p).Value
  2577. else if (p.ClassType=TSelfExpr) then
  2578. Result:='Self';
  2579. end;
  2580. function TPasParser.DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
  2581. // sets CurToken to token behind expression
  2582. function lastfield:boolean;
  2583. begin
  2584. Result:=CurToken<>tkSemicolon;
  2585. if not Result then
  2586. begin
  2587. NextToken;
  2588. if CurToken=tkBraceClose then
  2589. Result:=true
  2590. else
  2591. UngetToken;
  2592. end;
  2593. end;
  2594. procedure ReadArrayValues(x : TPasExpr);
  2595. var
  2596. a: TArrayValues;
  2597. begin
  2598. Result:=nil;
  2599. a:=nil;
  2600. try
  2601. a:=CreateArrayValues(AParent);
  2602. if x<>nil then
  2603. begin
  2604. a.AddValues(x);
  2605. x:=nil;
  2606. end;
  2607. repeat
  2608. NextToken;
  2609. a.AddValues(DoParseConstValueExpression(a));
  2610. until CurToken<>tkComma;
  2611. Result:=a;
  2612. finally
  2613. if Result=nil then
  2614. begin
  2615. a.Free;
  2616. x.Free;
  2617. end;
  2618. end;
  2619. end;
  2620. var
  2621. x , v: TPasExpr;
  2622. n : String;
  2623. r : TRecordValues;
  2624. begin
  2625. if CurToken <> tkBraceOpen then
  2626. Result:=DoParseExpression(AParent)
  2627. else begin
  2628. Result:=nil;
  2629. if Engine.NeedArrayValues(AParent) then
  2630. ReadArrayValues(nil)
  2631. else
  2632. begin
  2633. NextToken;
  2634. x:=DoParseConstValueExpression(AParent);
  2635. case CurToken of
  2636. tkComma: // array of values (a,b,c);
  2637. ReadArrayValues(x);
  2638. tkColon: // record field (a:xxx;b:yyy;c:zzz);
  2639. begin
  2640. if not (x is TPrimitiveExpr) then
  2641. CheckToken(tkBraceClose);
  2642. r:=nil;
  2643. try
  2644. n:=GetExprIdent(x);
  2645. r:=CreateRecordValues(AParent);
  2646. NextToken;
  2647. v:=DoParseConstValueExpression(r);
  2648. r.AddField(TPrimitiveExpr(x), v);
  2649. x:=nil;
  2650. if not lastfield then
  2651. repeat
  2652. n:=ExpectIdentifier;
  2653. x:=CreatePrimitiveExpr(r,pekIdent,n);
  2654. ExpectToken(tkColon);
  2655. NextToken;
  2656. v:=DoParseConstValueExpression(AParent);
  2657. r.AddField(TPrimitiveExpr(x), v);
  2658. x:=nil;
  2659. until lastfield; // CurToken<>tkSemicolon;
  2660. Result:=r;
  2661. finally
  2662. if Result=nil then
  2663. begin
  2664. r.Free;
  2665. x.Free;
  2666. end;
  2667. end;
  2668. end;
  2669. else
  2670. // Binary expression! ((128 div sizeof(longint)) - 3);
  2671. Result:=DoParseExpression(AParent,x);
  2672. if CurToken<>tkBraceClose then
  2673. begin
  2674. ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
  2675. ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
  2676. end;
  2677. NextToken;
  2678. if CurToken <> tkSemicolon then // the continue of expression
  2679. Result:=DoParseExpression(AParent,Result);
  2680. Exit;
  2681. end;
  2682. end;
  2683. if CurToken<>tkBraceClose then
  2684. begin
  2685. ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
  2686. ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
  2687. end;
  2688. NextToken;
  2689. end;
  2690. end;
  2691. function TPasParser.CheckOverloadList(AList: TFPList; AName: String; out
  2692. OldMember: TPasElement): TPasOverloadedProc;
  2693. Var
  2694. I : Integer;
  2695. begin
  2696. Result:=Nil;
  2697. I:=0;
  2698. While (Result=Nil) and (I<AList.Count) do
  2699. begin
  2700. OldMember:=TPasElement(AList[i]);
  2701. if CompareText(OldMember.Name, AName) = 0 then
  2702. begin
  2703. if OldMember is TPasOverloadedProc then
  2704. Result:=TPasOverloadedProc(OldMember)
  2705. else
  2706. begin
  2707. Result:=TPasOverloadedProc(CreateElement(TPasOverloadedProc, AName, OldMember.Parent));
  2708. OldMember.Parent:=Result;
  2709. Result.Visibility:=OldMember.Visibility;
  2710. Result.Overloads.Add(OldMember);
  2711. Result.SourceFilename:=OldMember.SourceFilename;
  2712. Result.SourceLinenumber:=OldMember.SourceLinenumber;
  2713. Result.DocComment:=Oldmember.DocComment;
  2714. AList[i] := Result;
  2715. end;
  2716. end;
  2717. Inc(I);
  2718. end;
  2719. If Result=Nil then
  2720. OldMember:=Nil;
  2721. end;
  2722. procedure TPasParser.AddProcOrFunction(Decs: TPasDeclarations;
  2723. AProc: TPasProcedure);
  2724. var
  2725. I : Integer;
  2726. OldMember: TPasElement;
  2727. OverloadedProc: TPasOverloadedProc;
  2728. begin
  2729. With Decs do
  2730. begin
  2731. if not (po_nooverloadedprocs in Options) then
  2732. OverloadedProc:=CheckOverloadList(Functions,AProc.Name,OldMember)
  2733. else
  2734. OverloadedProc:=nil;
  2735. If (OverloadedProc<>Nil) then
  2736. begin
  2737. OverLoadedProc.Overloads.Add(AProc);
  2738. if (OldMember<>OverloadedProc) then
  2739. begin
  2740. I:=Declarations.IndexOf(OldMember);
  2741. If I<>-1 then
  2742. Declarations[i]:=OverloadedProc;
  2743. end;
  2744. end
  2745. else
  2746. begin
  2747. Declarations.Add(AProc);
  2748. Functions.Add(AProc);
  2749. end;
  2750. end;
  2751. Engine.FinishScope(stProcedure,AProc);
  2752. end;
  2753. // Return the parent of a function declaration. This is AParent,
  2754. // except when AParent is a class/record and the function is overloaded.
  2755. // Then the parent is the overload object.
  2756. function TPasParser.CheckIfOverloaded(AParent: TPasElement; const AName: String): TPasElement;
  2757. var
  2758. Member: TPasElement;
  2759. OverloadedProc: TPasOverloadedProc;
  2760. begin
  2761. Result:=AParent;
  2762. If (not (po_nooverloadedprocs in Options)) and (AParent is TPasMembersType) then
  2763. begin
  2764. OverloadedProc:=CheckOverLoadList(TPasMembersType(AParent).Members,AName,Member);
  2765. If (OverloadedProc<>Nil) then
  2766. Result:=OverloadedProc;
  2767. end;
  2768. end;
  2769. procedure TPasParser.ParseMain(var Module: TPasModule);
  2770. begin
  2771. Module:=nil;
  2772. NextToken;
  2773. SaveComments;
  2774. case CurToken of
  2775. tkUnit:
  2776. ParseUnit(Module);
  2777. tkProgram:
  2778. ParseProgram(Module);
  2779. tkLibrary:
  2780. ParseLibrary(Module);
  2781. tkEOF:
  2782. CheckToken(tkprogram);
  2783. else
  2784. UngetToken;
  2785. ParseProgram(Module,True);
  2786. end;
  2787. end;
  2788. // Starts after the "unit" token
  2789. procedure TPasParser.ParseUnit(var Module: TPasModule);
  2790. var
  2791. AUnitName: String;
  2792. StartPos: TPasSourcePos;
  2793. HasFinished: Boolean;
  2794. begin
  2795. StartPos:=CurTokenPos;
  2796. Module := nil;
  2797. AUnitName := ExpectIdentifier;
  2798. NextToken;
  2799. while CurToken = tkDot do
  2800. begin
  2801. ExpectIdentifier;
  2802. AUnitName := AUnitName + '.' + CurTokenString;
  2803. NextToken;
  2804. end;
  2805. UngetToken;
  2806. Module := TPasModule(CreateElement(TPasModule, AUnitName, Engine.Package, StartPos));
  2807. FCurModule:=Module;
  2808. HasFinished:=true;
  2809. try
  2810. if Assigned(Engine.Package) then
  2811. begin
  2812. Module.PackageName := Engine.Package.Name;
  2813. Engine.Package.Modules.Add(Module);
  2814. Module.AddRef{$IFDEF CheckPasTreeRefCount}('TPasPackage.Modules'){$ENDIF};
  2815. end;
  2816. CheckHint(Module,True);
  2817. ExpectToken(tkInterface);
  2818. if po_StopOnUnitInterface in Options then
  2819. begin
  2820. HasFinished:=false;
  2821. {$IFDEF VerbosePasResolver}
  2822. writeln('TPasParser.ParseUnit pause parsing after unit name ',CurModule.Name);
  2823. {$ENDIF}
  2824. exit;
  2825. end;
  2826. ParseInterface;
  2827. if (Module.InterfaceSection<>nil)
  2828. and (Module.InterfaceSection.PendingUsedIntf<>nil) then
  2829. begin
  2830. HasFinished:=false;
  2831. {$IFDEF VerbosePasResolver}
  2832. writeln('TPasParser.ParseUnit pause parsing after interface uses list ',CurModule.Name);
  2833. {$ENDIF}
  2834. end;
  2835. if (Module.ImplementationSection<>nil)
  2836. and (Module.ImplementationSection.PendingUsedIntf<>nil) then
  2837. begin
  2838. HasFinished:=false;
  2839. {$IFDEF VerbosePasResolver}
  2840. writeln('TPasParser.ParseUnit pause parsing after implementation uses list ',CurModule.Name);
  2841. {$ENDIF}
  2842. end;
  2843. if HasFinished then
  2844. FinishedModule;
  2845. finally
  2846. if HasFinished then
  2847. FCurModule:=nil; // clear module if there is an error or finished parsing
  2848. end;
  2849. end;
  2850. function TPasParser.GetLastSection: TPasSection;
  2851. begin
  2852. Result:=nil;
  2853. if FCurModule=nil then
  2854. exit; // parse completed
  2855. if CurModule is TPasProgram then
  2856. Result:=TPasProgram(CurModule).ProgramSection
  2857. else if CurModule is TPasLibrary then
  2858. Result:=TPasLibrary(CurModule).LibrarySection
  2859. else if (CurModule.ClassType=TPasModule) or (CurModule is TPasUnitModule) then
  2860. begin
  2861. if CurModule.ImplementationSection<>nil then
  2862. Result:=CurModule.ImplementationSection
  2863. else
  2864. Result:=CurModule.InterfaceSection; // might be nil
  2865. end;
  2866. end;
  2867. function TPasParser.CanParseContinue(out Section: TPasSection): boolean;
  2868. begin
  2869. Result:=false;
  2870. Section:=nil;
  2871. if FCurModule=nil then
  2872. exit; // parse completed
  2873. if (LastMsg<>'') and (LastMsgType<=mtError) then
  2874. begin
  2875. {$IF defined(VerbosePasResolver) or defined(VerboseUnitQueue)}
  2876. writeln('TPasParser.CanParseContinue ',CurModule.Name,' LastMsg="',LastMsgType,':',LastMsg,'"');
  2877. {$ENDIF}
  2878. exit;
  2879. end;
  2880. if (Scanner.LastMsg<>'') and (Scanner.LastMsgType<=mtError) then
  2881. begin
  2882. {$IF defined(VerbosePasResolver) or defined(VerboseUnitQueue)}
  2883. writeln('TPasParser.CanParseContinue ',CurModule.Name,' Scanner.LastMsg="',Scanner.LastMsgType,':',Scanner.LastMsg,'"');
  2884. {$ENDIF}
  2885. exit;
  2886. end;
  2887. Section:=GetLastSection;
  2888. if Section=nil then
  2889. if (po_StopOnUnitInterface in Options)
  2890. and ((CurModule is TPasUnitModule) or (CurModule.ClassType=TPasModule))
  2891. and (CurModule.InterfaceSection=nil) then
  2892. exit(true)
  2893. else
  2894. begin
  2895. {$IFDEF VerboseUnitQueue}
  2896. writeln('TPasParser.CanParseContinue ',CurModule.Name,' no LastSection');
  2897. {$ENDIF}
  2898. exit(false);
  2899. end;
  2900. Result:=Section.PendingUsedIntf=nil;
  2901. {$IFDEF VerboseUnitQueue}
  2902. writeln('TPasParser.CanParseContinue ',CurModule.Name,' Result=',Result,' ',Section.ElementTypeName);
  2903. {$ENDIF}
  2904. end;
  2905. procedure TPasParser.ParseContinue;
  2906. // continue parsing after stopped due to pending uses
  2907. var
  2908. Section: TPasSection;
  2909. HasFinished: Boolean;
  2910. begin
  2911. if CurModule=nil then
  2912. ParseExcTokenError('TPasParser.ParseContinue missing module');
  2913. {$IFDEF VerbosePasParser}
  2914. writeln('TPasParser.ParseContinue ',CurModule.Name);
  2915. {$ENDIF}
  2916. if not CanParseContinue(Section) then
  2917. ParseExcTokenError('TPasParser.ParseContinue missing section');
  2918. HasFinished:=true;
  2919. try
  2920. if Section=nil then
  2921. begin
  2922. // continue after unit name
  2923. ParseInterface;
  2924. end
  2925. else
  2926. begin
  2927. // continue after uses clause
  2928. Engine.FinishScope(stUsesClause,Section);
  2929. ParseDeclarations(Section);
  2930. end;
  2931. Section:=GetLastSection;
  2932. if Section=nil then
  2933. ParseExc(nErrNoSourceGiven,'[20180306112327]');
  2934. if Section.PendingUsedIntf<>nil then
  2935. HasFinished:=false;
  2936. if HasFinished then
  2937. FinishedModule;
  2938. finally
  2939. if HasFinished then
  2940. FCurModule:=nil; // clear module if there is an error or finished parsing
  2941. end;
  2942. end;
  2943. // Starts after the "program" token
  2944. procedure TPasParser.ParseProgram(var Module: TPasModule; SkipHeader : Boolean = False);
  2945. Var
  2946. PP : TPasProgram;
  2947. Section : TProgramSection;
  2948. N : String;
  2949. StartPos: TPasSourcePos;
  2950. HasFinished: Boolean;
  2951. {$IFDEF VerbosePasResolver}
  2952. aSection: TPasSection;
  2953. {$ENDIF}
  2954. begin
  2955. StartPos:=CurTokenPos;
  2956. if SkipHeader then
  2957. N:=ChangeFileExt(Scanner.CurFilename,'')
  2958. else
  2959. begin
  2960. N:=ExpectIdentifier;
  2961. NextToken;
  2962. while CurToken = tkDot do
  2963. begin
  2964. ExpectIdentifier;
  2965. N := N + '.' + CurTokenString;
  2966. NextToken;
  2967. end;
  2968. UngetToken;
  2969. end;
  2970. Module := nil;
  2971. PP:=TPasProgram(CreateElement(TPasProgram, N, Engine.Package, StartPos));
  2972. Module :=PP;
  2973. HasFinished:=true;
  2974. FCurModule:=Module;
  2975. try
  2976. if Assigned(Engine.Package) then
  2977. begin
  2978. Module.PackageName := Engine.Package.Name;
  2979. Engine.Package.Modules.Add(Module);
  2980. end;
  2981. if not SkipHeader then
  2982. begin
  2983. NextToken;
  2984. If (CurToken=tkBraceOpen) then
  2985. begin
  2986. PP.InputFile:=ExpectIdentifier;
  2987. NextToken;
  2988. if Not (CurToken in [tkBraceClose,tkComma]) then
  2989. ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
  2990. If (CurToken=tkComma) then
  2991. PP.OutPutFile:=ExpectIdentifier;
  2992. ExpectToken(tkBraceClose);
  2993. NextToken;
  2994. end;
  2995. if (CurToken<>tkSemicolon) then
  2996. ParseExcTokenError(';');
  2997. end;
  2998. Section := TProgramSection(CreateElement(TProgramSection, '', CurModule));
  2999. PP.ProgramSection := Section;
  3000. ParseOptionalUsesList(Section);
  3001. HasFinished:=Section.PendingUsedIntf=nil;
  3002. if not HasFinished then
  3003. begin
  3004. {$IFDEF VerbosePasResolver}
  3005. {AllowWriteln}
  3006. writeln('TPasParser.ParseProgram pause parsing after uses list of "',CurModule.Name,'"');
  3007. if CanParseContinue(aSection) then
  3008. begin
  3009. writeln('TPasParser.ParseProgram Section=',Section.ClassName,' Section.PendingUsedIntf=',Section.PendingUsedIntf<>nil);
  3010. if aSection<>nil then
  3011. writeln('TPasParser.ParseProgram aSection=',aSection.ClassName,' ',Section=aSection);
  3012. ParseExc(nErrNoSourceGiven,'[20180305172432] ');
  3013. end;
  3014. {AllowWriteln-}
  3015. {$ENDIF}
  3016. exit;
  3017. end;
  3018. ParseDeclarations(Section);
  3019. FinishedModule;
  3020. finally
  3021. if HasFinished then
  3022. FCurModule:=nil; // clear module if there is an error or finished parsing
  3023. end;
  3024. end;
  3025. // Starts after the "library" token
  3026. procedure TPasParser.ParseLibrary(var Module: TPasModule);
  3027. Var
  3028. PP : TPasLibrary;
  3029. Section : TLibrarySection;
  3030. N: String;
  3031. StartPos: TPasSourcePos;
  3032. HasFinished: Boolean;
  3033. begin
  3034. StartPos:=CurTokenPos;
  3035. N:=ExpectIdentifier;
  3036. NextToken;
  3037. while CurToken = tkDot do
  3038. begin
  3039. ExpectIdentifier;
  3040. N := N + '.' + CurTokenString;
  3041. NextToken;
  3042. end;
  3043. UngetToken;
  3044. Module := nil;
  3045. PP:=TPasLibrary(CreateElement(TPasLibrary, N, Engine.Package, StartPos));
  3046. Module :=PP;
  3047. HasFinished:=true;
  3048. FCurModule:=Module;
  3049. try
  3050. if Assigned(Engine.Package) then
  3051. begin
  3052. Module.PackageName := Engine.Package.Name;
  3053. Engine.Package.Modules.Add(Module);
  3054. end;
  3055. NextToken;
  3056. if (CurToken<>tkSemicolon) then
  3057. ParseExcTokenError(';');
  3058. Section := TLibrarySection(CreateElement(TLibrarySection, '', CurModule));
  3059. PP.LibrarySection := Section;
  3060. ParseOptionalUsesList(Section);
  3061. HasFinished:=Section.PendingUsedIntf=nil;
  3062. if not HasFinished then
  3063. exit;
  3064. ParseDeclarations(Section);
  3065. FinishedModule;
  3066. finally
  3067. if HasFinished then
  3068. FCurModule:=nil; // clear module if there is an error or finished parsing
  3069. end;
  3070. end;
  3071. procedure TPasParser.ParseOptionalUsesList(ASection: TPasSection);
  3072. // checks if next token is Uses keyword and reads the uses list
  3073. begin
  3074. NextToken;
  3075. CheckImplicitUsedUnits(ASection);
  3076. if CurToken=tkuses then
  3077. ParseUsesList(ASection)
  3078. else
  3079. UngetToken;
  3080. Engine.CheckPendingUsedInterface(ASection);
  3081. if ASection.PendingUsedIntf<>nil then
  3082. exit;
  3083. Engine.FinishScope(stUsesClause,ASection);
  3084. end;
  3085. // Starts after the "interface" token
  3086. procedure TPasParser.ParseInterface;
  3087. var
  3088. Section: TInterfaceSection;
  3089. begin
  3090. If LogEvent(pleInterface) then
  3091. DoLog(mtInfo,nLogStartInterface,SLogStartInterface);
  3092. Section := TInterfaceSection(CreateElement(TInterfaceSection, '', CurModule));
  3093. CurModule.InterfaceSection := Section;
  3094. ParseOptionalUsesList(Section);
  3095. if Section.PendingUsedIntf<>nil then
  3096. exit;
  3097. ParseDeclarations(Section); // this also parses the Implementation section
  3098. end;
  3099. // Starts after the "implementation" token
  3100. procedure TPasParser.ParseImplementation;
  3101. var
  3102. Section: TImplementationSection;
  3103. begin
  3104. Section := TImplementationSection(CreateElement(TImplementationSection, '', CurModule));
  3105. CurModule.ImplementationSection := Section;
  3106. ParseOptionalUsesList(Section);
  3107. if Section.PendingUsedIntf<>nil then
  3108. exit;
  3109. ParseDeclarations(Section);
  3110. end;
  3111. procedure TPasParser.ParseInitialization;
  3112. var
  3113. Section: TInitializationSection;
  3114. SubBlock: TPasImplElement;
  3115. begin
  3116. Section := TInitializationSection(CreateElement(TInitializationSection, '', CurModule,CurTokenPos));
  3117. CurModule.InitializationSection := Section;
  3118. repeat
  3119. NextToken;
  3120. if (CurToken=tkend) then
  3121. begin
  3122. ExpectToken(tkDot);
  3123. Engine.FinishScope(stInitialFinalization,Section);
  3124. exit;
  3125. end
  3126. else if (CurToken=tkfinalization) then
  3127. begin
  3128. Engine.FinishScope(stInitialFinalization,Section);
  3129. ParseFinalization;
  3130. exit;
  3131. end
  3132. else if CurToken<>tkSemiColon then
  3133. begin
  3134. UngetToken;
  3135. ParseStatement(Section,SubBlock);
  3136. if SubBlock=nil then
  3137. ExpectToken(tkend);
  3138. end;
  3139. until false;
  3140. end;
  3141. procedure TPasParser.ParseFinalization;
  3142. var
  3143. Section: TFinalizationSection;
  3144. SubBlock: TPasImplElement;
  3145. begin
  3146. Section := TFinalizationSection(CreateElement(TFinalizationSection, '', CurModule));
  3147. CurModule.FinalizationSection := Section;
  3148. repeat
  3149. NextToken;
  3150. if (CurToken=tkend) then
  3151. begin
  3152. ExpectToken(tkDot);
  3153. Engine.FinishScope(stInitialFinalization,Section);
  3154. exit;
  3155. end
  3156. else if CurToken<>tkSemiColon then
  3157. begin
  3158. UngetToken;
  3159. ParseStatement(Section,SubBlock);
  3160. if SubBlock=nil then
  3161. ExpectToken(tkend);
  3162. end;
  3163. until false;
  3164. end;
  3165. function TPasParser.GetProcTypeFromToken(tk: TToken; IsClass: Boolean
  3166. ): TProcType;
  3167. begin
  3168. Case tk of
  3169. tkProcedure :
  3170. if IsClass then
  3171. Result:=ptClassProcedure
  3172. else
  3173. Result:=ptProcedure;
  3174. tkFunction:
  3175. if IsClass then
  3176. Result:=ptClassFunction
  3177. else
  3178. Result:=ptFunction;
  3179. tkConstructor:
  3180. if IsClass then
  3181. Result:=ptClassConstructor
  3182. else
  3183. Result:=ptConstructor;
  3184. tkDestructor:
  3185. if IsClass then
  3186. Result:=ptClassDestructor
  3187. else
  3188. Result:=ptDestructor;
  3189. tkOperator:
  3190. if IsClass then
  3191. Result:=ptClassOperator
  3192. else
  3193. Result:=ptOperator;
  3194. else
  3195. ParseExc(nParserNotAProcToken,SParserNotAProcToken);
  3196. end;
  3197. end;
  3198. procedure TPasParser.ParseDeclarations(Declarations: TPasDeclarations);
  3199. var
  3200. HadTypeSection: boolean;
  3201. CurBlock: TDeclType;
  3202. procedure SetBlock(NewBlock: TDeclType);
  3203. begin
  3204. if CurBlock=NewBlock then exit;
  3205. if CurBlock=declType then
  3206. begin
  3207. if msDelphi in CurrentModeswitches then
  3208. // Delphi allows forward types only inside a type section
  3209. Engine.FinishScope(stTypeSection,Declarations);
  3210. end;
  3211. if NewBlock=declType then
  3212. HadTypeSection:=true
  3213. else if (NewBlock=declNone) and HadTypeSection then
  3214. begin
  3215. HadTypeSection:=false;
  3216. if not (msDelphi in CurrentModeswitches) then
  3217. // ObjFPC allows forward types inside a whole section
  3218. Engine.FinishScope(stTypeSection,Declarations);
  3219. end;
  3220. CurBlock:=NewBlock;
  3221. Scanner.SetForceCaret(NewBlock=declType);
  3222. end;
  3223. var
  3224. ConstEl: TPasConst;
  3225. ResStrEl: TPasResString;
  3226. TypeEl: TPasType;
  3227. ClassEl: TPasClassType;
  3228. List: TFPList;
  3229. i,j: Integer;
  3230. ExpEl: TPasExportSymbol;
  3231. PropEl : TPasProperty;
  3232. PT : TProcType;
  3233. ok, MustBeGeneric: Boolean;
  3234. Proc: TPasProcedure;
  3235. CurEl: TPasElement;
  3236. begin
  3237. CurBlock := declNone;
  3238. HadTypeSection:=false;
  3239. while True do
  3240. begin
  3241. if CurBlock in [DeclNone,declConst,declType] then
  3242. Scanner.SetTokenOption(toOperatorToken)
  3243. else
  3244. Scanner.UnSetTokenOption(toOperatorToken);
  3245. NextToken;
  3246. Scanner.SkipGlobalSwitches:=true;
  3247. // writeln('TPasParser.ParseDeclarations Token=',CurTokenString,' ',CurToken, ' ',scanner.CurFilename);
  3248. case CurToken of
  3249. tkend:
  3250. begin
  3251. If (CurModule is TPasProgram) and (CurModule.InitializationSection=Nil) then
  3252. ParseExcTokenError('begin');
  3253. ExpectToken(tkDot);
  3254. break;
  3255. end;
  3256. tkimplementation:
  3257. if (Declarations is TInterfaceSection) then
  3258. begin
  3259. If Not Engine.InterfaceOnly then
  3260. begin
  3261. If LogEvent(pleImplementation) then
  3262. DoLog(mtInfo,nLogStartImplementation,SLogStartImplementation);
  3263. SetBlock(declNone);
  3264. ParseImplementation;
  3265. end;
  3266. break;
  3267. end
  3268. else
  3269. ParseExcSyntaxError;
  3270. tkinitialization:
  3271. if (Declarations is TInterfaceSection)
  3272. or ((Declarations is TImplementationSection) and not (Declarations is TProgramSection)) then
  3273. begin
  3274. SetBlock(declNone);
  3275. ParseInitialization;
  3276. break;
  3277. end
  3278. else
  3279. ParseExcSyntaxError;
  3280. tkfinalization:
  3281. if (Declarations is TInterfaceSection)
  3282. or ((Declarations is TImplementationSection) and not (Declarations is TProgramSection)) then
  3283. begin
  3284. SetBlock(declNone);
  3285. ParseFinalization;
  3286. break;
  3287. end;
  3288. tkUses:
  3289. if Declarations.ClassType=TInterfaceSection then
  3290. ParseExcTokenError(TokenInfos[tkimplementation])
  3291. else if Declarations is TPasSection then
  3292. ParseExcTokenError(TokenInfos[tkend])
  3293. else
  3294. ParseExcSyntaxError;
  3295. tkConst:
  3296. SetBlock(declConst);
  3297. tkexports:
  3298. SetBlock(declExports);
  3299. tkResourcestring:
  3300. if Declarations is TPasSection then
  3301. SetBlock(declResourcestring)
  3302. else
  3303. begin
  3304. {$IFDEF VerbosePasParser}
  3305. writeln('TPasParser.ParseDeclarations ',Declarations.Parent.ClassName);
  3306. {$ENDIF}
  3307. ParseExc(nParserResourcestringsMustBeGlobal,SParserResourcestringsMustBeGlobal);
  3308. end;
  3309. tkType:
  3310. SetBlock(declType);
  3311. tkVar:
  3312. SetBlock(declVar);
  3313. tkThreadVar:
  3314. SetBlock(declThreadVar);
  3315. tkProperty:
  3316. SetBlock(declProperty);
  3317. tkProcedure, tkFunction, tkConstructor, tkDestructor, tkOperator:
  3318. begin
  3319. MustBeGeneric:=(not (msDelphi in CurrentModeswitches)) and (GetPrevToken=tkgeneric);
  3320. SetBlock(declNone);
  3321. SaveComments;
  3322. pt:=GetProcTypeFromToken(CurToken);
  3323. AddProcOrFunction(Declarations, ParseProcedureOrFunctionDecl(Declarations, pt, MustBeGeneric));
  3324. end;
  3325. tkClass:
  3326. begin
  3327. MustBeGeneric:=(not (msDelphi in CurrentModeswitches)) and (GetPrevToken=tkgeneric);
  3328. SetBlock(declNone);
  3329. SaveComments;
  3330. NextToken;
  3331. CheckTokens([tkprocedure,tkFunction,tkConstructor,tkDestructor,tkoperator]);
  3332. pt:=GetProcTypeFromToken(CurToken,True);
  3333. AddProcOrFunction(Declarations,ParseProcedureOrFunctionDecl(Declarations, pt, MustBeGeneric));
  3334. end;
  3335. tkIdentifier:
  3336. begin
  3337. Scanner.UnSetTokenOption(toOperatorToken);
  3338. SaveComments;
  3339. case CurBlock of
  3340. declConst:
  3341. begin
  3342. ConstEl := ParseConstDecl(Declarations);
  3343. Declarations.Declarations.Add(ConstEl);
  3344. Declarations.Consts.Add(ConstEl);
  3345. Engine.FinishScope(stDeclaration,ConstEl);
  3346. end;
  3347. declResourcestring:
  3348. begin
  3349. ResStrEl := ParseResourcestringDecl(Declarations);
  3350. Declarations.Declarations.Add(ResStrEl);
  3351. Declarations.ResStrings.Add(ResStrEl);
  3352. Engine.FinishScope(stResourceString,ResStrEl);
  3353. end;
  3354. declType:
  3355. begin
  3356. TypeEl := ParseTypeDecl(Declarations);
  3357. // Scanner.SetForceCaret(OldForceCaret); // It may have been switched off
  3358. if Assigned(TypeEl) then // !!!
  3359. begin
  3360. Declarations.Declarations.Add(TypeEl);
  3361. {$IFDEF CheckPasTreeRefCount}if TypeEl.RefIds.IndexOf('CreateElement')>=0 then TypeEl.ChangeRefId('CreateElement','TPasDeclarations.Children');{$ENDIF}
  3362. if (TypeEl.ClassType = TPasClassType)
  3363. and (not (po_keepclassforward in Options)) then
  3364. begin
  3365. // Remove previous forward declarations, if necessary
  3366. for i := 0 to Declarations.Classes.Count - 1 do
  3367. begin
  3368. ClassEl := TPasClassType(Declarations.Classes[i]);
  3369. if CompareText(ClassEl.Name, TypeEl.Name) = 0 then
  3370. begin
  3371. Declarations.Classes.Delete(i);
  3372. for j := 0 to Declarations.Declarations.Count - 1 do
  3373. if CompareText(TypeEl.Name,
  3374. TPasElement(Declarations.Declarations[j]).Name) = 0 then
  3375. begin
  3376. Declarations.Declarations.Delete(j);
  3377. break;
  3378. end;
  3379. ClassEl.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  3380. break;
  3381. end;
  3382. end;
  3383. // Add the new class to the class list
  3384. Declarations.Classes.Add(TypeEl)
  3385. end else
  3386. Declarations.Types.Add(TypeEl);
  3387. end;
  3388. end;
  3389. declExports:
  3390. begin
  3391. List := TFPList.Create;
  3392. try
  3393. ok:=false;
  3394. try
  3395. ParseExportDecl(Declarations, List);
  3396. ok:=true;
  3397. finally
  3398. if not ok then
  3399. for i := 0 to List.Count - 1 do
  3400. TPasExportSymbol(List[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  3401. end;
  3402. for i := 0 to List.Count - 1 do
  3403. begin
  3404. ExpEl := TPasExportSymbol(List[i]);
  3405. Declarations.Declarations.Add(ExpEl);
  3406. {$IFDEF CheckPasTreeRefCount}ExpEl.ChangeRefId('CreateElement','TPasDeclarations.Children');{$ENDIF}
  3407. Declarations.ExportSymbols.Add(ExpEl);
  3408. end;
  3409. finally
  3410. List.Free;
  3411. end;
  3412. end;
  3413. declVar, declThreadVar:
  3414. begin
  3415. List := TFPList.Create;
  3416. try
  3417. ParseVarDecl(Declarations, List);
  3418. for i := 0 to List.Count - 1 do
  3419. begin
  3420. CurEl := TPasElement(List[i]);
  3421. Declarations.Declarations.Add(CurEl);
  3422. if CurEl.ClassType=TPasAttributes then
  3423. Declarations.Attributes.Add(CurEl)
  3424. else
  3425. Declarations.Variables.Add(TPasVariable(CurEl));
  3426. Engine.FinishScope(stDeclaration,CurEl);
  3427. end;
  3428. CheckToken(tkSemicolon);
  3429. finally
  3430. List.Free;
  3431. end;
  3432. end;
  3433. declProperty:
  3434. begin
  3435. PropEl:=ParseProperty(Declarations,CurtokenString,visDefault,false);
  3436. Declarations.Declarations.Add(PropEl);
  3437. {$IFDEF CheckPasTreeRefCount}PropEl.ChangeRefId('CreateElement','TPasDeclarations.Children');{$ENDIF}
  3438. Declarations.Properties.Add(PropEl);
  3439. Engine.FinishScope(stDeclaration,PropEl);
  3440. end;
  3441. else
  3442. ParseExcSyntaxError;
  3443. end;
  3444. end;
  3445. tkGeneric:
  3446. begin
  3447. NextToken;
  3448. if (CurToken in [tkprocedure,tkfunction]) then
  3449. begin
  3450. if msDelphi in CurrentModeswitches then
  3451. ParseExcSyntaxError; // inconsistency, tkGeneric should be in Scanner.NonTokens
  3452. SetBlock(declNone);
  3453. UngetToken;
  3454. end;
  3455. if CurBlock = declType then
  3456. begin
  3457. CheckToken(tkIdentifier);
  3458. ParseGenericTypeDecl(Declarations,true);
  3459. end
  3460. else if CurBlock = declNone then
  3461. begin
  3462. if msDelphi in CurrentModeswitches then
  3463. ParseExcSyntaxError; // inconsistency, tkGeneric should be in Scanner.NonTokens
  3464. SetBlock(declNone);
  3465. SaveComments;
  3466. NextToken;
  3467. case CurToken of
  3468. tkclass:
  3469. begin
  3470. // generic class ...
  3471. NextToken;
  3472. if not (CurToken in [tkprocedure,tkfunction]) then
  3473. ParseExcSyntaxError;
  3474. // generic class procedure ...
  3475. pt:=GetProcTypeFromToken(CurToken,true);
  3476. AddProcOrFunction(Declarations, ParseProcedureOrFunctionDecl(Declarations, pt, true));
  3477. end;
  3478. tkprocedure,tkfunction:
  3479. begin
  3480. // generic procedure ...
  3481. SetBlock(declNone);
  3482. SaveComments;
  3483. pt:=GetProcTypeFromToken(CurToken);
  3484. AddProcOrFunction(Declarations, ParseProcedureOrFunctionDecl(Declarations, pt, true));
  3485. end;
  3486. else
  3487. ParseExcSyntaxError;
  3488. end;
  3489. end
  3490. else
  3491. begin
  3492. ParseExcSyntaxError;
  3493. end;
  3494. end;
  3495. tkbegin:
  3496. begin
  3497. if Declarations is TProcedureBody then
  3498. begin
  3499. Proc:=Declarations.Parent as TPasProcedure;
  3500. if pmAssembler in Proc.Modifiers then
  3501. ParseExc(nParserExpectTokenError,SParserExpectTokenError,['asm']);
  3502. SetBlock(declNone);
  3503. ParseProcBeginBlock(TProcedureBody(Declarations));
  3504. break;
  3505. end
  3506. else if (Declarations is TInterfaceSection)
  3507. or (Declarations is TImplementationSection) then
  3508. begin
  3509. SetBlock(declNone);
  3510. ParseInitialization;
  3511. break;
  3512. end
  3513. else
  3514. ParseExcSyntaxError;
  3515. end;
  3516. tkasm:
  3517. begin
  3518. if Declarations is TProcedureBody then
  3519. begin
  3520. Proc:=Declarations.Parent as TPasProcedure;
  3521. // Assembler keyword is optional in Delphi mode (bug 31690)
  3522. if not ((pmAssembler in Proc.Modifiers) or (msDelphi in CurrentModeswitches)) then
  3523. ParseExc(nParserExpectTokenError,SParserExpectTokenError,['begin']);
  3524. SetBlock(declNone);
  3525. ParseProcAsmBlock(TProcedureBody(Declarations));
  3526. break;
  3527. end
  3528. else
  3529. ParseExcSyntaxError;
  3530. end;
  3531. tklabel:
  3532. begin
  3533. SetBlock(declNone);
  3534. if not (Declarations is TInterfaceSection) then
  3535. ParseLabels(Declarations);
  3536. end;
  3537. tkSquaredBraceOpen:
  3538. if msPrefixedAttributes in CurrentModeSwitches then
  3539. ParseAttributes(Declarations,true)
  3540. else
  3541. ParseExcSyntaxError;
  3542. else
  3543. ParseExcSyntaxError;
  3544. end;
  3545. end;
  3546. SetBlock(declNone);
  3547. end;
  3548. function TPasParser.AddUseUnit(ASection: TPasSection;
  3549. const NamePos: TPasSourcePos; AUnitName: string; NameExpr: TPasExpr;
  3550. InFileExpr: TPrimitiveExpr): TPasUsesUnit;
  3551. procedure CheckDuplicateInUsesList(UsesClause: TPasUsesClause);
  3552. var
  3553. i: Integer;
  3554. begin
  3555. if UsesClause=nil then exit;
  3556. for i:=0 to length(UsesClause)-1 do
  3557. if CompareText(AUnitName,UsesClause[i].Name)=0 then
  3558. ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
  3559. end;
  3560. procedure CheckDuplicateInUsesList(UnitRef: TPasElement; UsesClause: TPasUsesClause);
  3561. var
  3562. i: Integer;
  3563. begin
  3564. if UsesClause=nil then exit;
  3565. for i:=0 to length(UsesClause)-1 do
  3566. if UsesClause[i].Module=UnitRef then
  3567. ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
  3568. end;
  3569. var
  3570. UnitRef: TPasElement;
  3571. UsesUnit: TPasUsesUnit;
  3572. begin
  3573. Result:=nil;
  3574. UsesUnit:=nil;
  3575. UnitRef:=nil;
  3576. try
  3577. {$IFDEF VerbosePasParser}
  3578. writeln('TPasParser.AddUseUnit AUnitName=',AUnitName,' CurModule.Name=',CurModule.Name);
  3579. {$ENDIF}
  3580. if CompareText(AUnitName,CurModule.Name)=0 then
  3581. begin
  3582. if CompareText(AUnitName,'System')=0 then
  3583. exit; // for compatibility ignore implicit use of system in system
  3584. ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
  3585. end;
  3586. UnitRef := Engine.FindModule(AUnitName,NameExpr,InFileExpr);
  3587. if Assigned(UnitRef) then
  3588. begin
  3589. UnitRef.AddRef{$IFDEF CheckPasTreeRefCount}('TPasUsesUnit.Module'){$ENDIF};
  3590. CheckDuplicateInUsesList(UnitRef,ASection.UsesClause);
  3591. if ASection.ClassType=TImplementationSection then
  3592. CheckDuplicateInUsesList(UnitRef,CurModule.InterfaceSection.UsesClause);
  3593. end
  3594. else
  3595. begin
  3596. CheckDuplicateInUsesList(ASection.UsesClause);
  3597. if ASection.ClassType=TImplementationSection then
  3598. CheckDuplicateInUsesList(CurModule.InterfaceSection.UsesClause);
  3599. UnitRef := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef,
  3600. AUnitName, ASection, NamePos));
  3601. end;
  3602. UsesUnit:=TPasUsesUnit(CreateElement(TPasUsesUnit,AUnitName,ASection,NamePos));
  3603. Result:=ASection.AddUnitToUsesList(AUnitName,NameExpr,InFileExpr,UnitRef,UsesUnit);
  3604. if InFileExpr<>nil then
  3605. begin
  3606. if UnitRef is TPasModule then
  3607. begin
  3608. if TPasModule(UnitRef).Filename='' then
  3609. TPasModule(UnitRef).Filename:=InFileExpr.Value;
  3610. end
  3611. else if UnitRef is TPasUnresolvedUnitRef then
  3612. TPasUnresolvedUnitRef(UnitRef).FileName:=InFileExpr.Value;
  3613. end;
  3614. finally
  3615. if Result=nil then
  3616. begin
  3617. if UsesUnit<>nil then
  3618. UsesUnit.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  3619. if NameExpr<>nil then
  3620. NameExpr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  3621. if InFileExpr<>nil then
  3622. InFileExpr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  3623. if UnitRef<>nil then
  3624. UnitRef.Release{$IFDEF CheckPasTreeRefCount}('FindModule'){$ENDIF};
  3625. end;
  3626. end;
  3627. end;
  3628. procedure TPasParser.CheckImplicitUsedUnits(ASection: TPasSection);
  3629. var
  3630. i: Integer;
  3631. NamePos: TPasSourcePos;
  3632. begin
  3633. If not (ASection.ClassType=TImplementationSection) Then // interface,program,library,package
  3634. begin
  3635. // load implicit units, like 'System'
  3636. NamePos:=CurSourcePos;
  3637. for i:=0 to ImplicitUses.Count-1 do
  3638. AddUseUnit(ASection,NamePos,ImplicitUses[i],nil,nil);
  3639. end;
  3640. end;
  3641. procedure TPasParser.FinishedModule;
  3642. begin
  3643. if Scanner<>nil then
  3644. Scanner.FinishedModule;
  3645. Engine.FinishScope(stModule,CurModule);
  3646. end;
  3647. // Starts after the "uses" token
  3648. procedure TPasParser.ParseUsesList(ASection: TPasSection);
  3649. var
  3650. AUnitName, aName: String;
  3651. NameExpr: TPasExpr;
  3652. InFileExpr: TPrimitiveExpr;
  3653. FreeExpr: Boolean;
  3654. NamePos, SrcPos: TPasSourcePos;
  3655. aModule: TPasModule;
  3656. begin
  3657. Scanner.SkipGlobalSwitches:=true;
  3658. NameExpr:=nil;
  3659. InFileExpr:=nil;
  3660. FreeExpr:=true;
  3661. try
  3662. Repeat
  3663. FreeExpr:=true;
  3664. AUnitName := ExpectIdentifier;
  3665. NamePos:=CurSourcePos;
  3666. NameExpr:=CreatePrimitiveExpr(ASection,pekString,AUnitName);
  3667. NextToken;
  3668. while CurToken = tkDot do
  3669. begin
  3670. SrcPos:=CurTokenPos;
  3671. ExpectIdentifier;
  3672. aName:=CurTokenString;
  3673. AUnitName := AUnitName + '.' + aName;
  3674. AddToBinaryExprChain(NameExpr,
  3675. CreatePrimitiveExpr(ASection,pekString,aName),eopSubIdent,SrcPos);
  3676. NextToken;
  3677. end;
  3678. if (CurToken=tkin) then
  3679. begin
  3680. if (msDelphi in CurrentModeswitches) then
  3681. begin
  3682. aModule:=ASection.GetModule;
  3683. if (aModule<>nil)
  3684. and ((aModule.ClassType=TPasModule) or (aModule is TPasUnitModule)) then
  3685. CheckToken(tkSemicolon); // delphi does not allow in-filename in units
  3686. end;
  3687. ExpectToken(tkString);
  3688. InFileExpr:=CreatePrimitiveExpr(ASection,pekString,CurTokenString);
  3689. NextToken;
  3690. end;
  3691. FreeExpr:=false;
  3692. AddUseUnit(ASection,NamePos,AUnitName,NameExpr,InFileExpr);
  3693. InFileExpr:=nil;
  3694. NameExpr:=nil;
  3695. if Not (CurToken in [tkComma,tkSemicolon]) then
  3696. ParseExc(nParserExpectedCommaSemicolon,SParserExpectedCommaSemicolon);
  3697. Until (CurToken=tkSemicolon);
  3698. finally
  3699. if FreeExpr then
  3700. begin
  3701. ReleaseAndNil(TPasElement(NameExpr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
  3702. ReleaseAndNil(TPasElement(InFileExpr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
  3703. end;
  3704. end;
  3705. end;
  3706. // Starts after the variable name
  3707. function TPasParser.ParseConstDecl(Parent: TPasElement): TPasConst;
  3708. var
  3709. OldForceCaret,ok: Boolean;
  3710. begin
  3711. SaveComments;
  3712. Result := TPasConst(CreateElement(TPasConst, CurTokenString, Parent));
  3713. if Parent is TPasMembersType then
  3714. Include(Result.VarModifiers,vmClass);
  3715. ok:=false;
  3716. try
  3717. NextToken;
  3718. if CurToken = tkColon then
  3719. begin
  3720. if not (bsWriteableConst in Scanner.CurrentBoolSwitches) then
  3721. Result.IsConst:=true;
  3722. OldForceCaret:=Scanner.SetForceCaret(True);
  3723. try
  3724. Result.VarType := ParseType(Result,CurSourcePos);
  3725. {$IFDEF CheckPasTreeRefCount}if Result.VarType.RefIds.IndexOf('CreateElement')>=0 then Result.VarType.ChangeRefId('CreateElement','TPasVariable.VarType'){$ENDIF};
  3726. finally
  3727. Scanner.SetForceCaret(OldForceCaret);
  3728. end;
  3729. end
  3730. else
  3731. begin
  3732. UngetToken;
  3733. Result.IsConst:=true;
  3734. end;
  3735. NextToken;
  3736. if CurToken=tkEqual then
  3737. begin
  3738. NextToken;
  3739. Result.Expr:=DoParseConstValueExpression(Result);
  3740. if (Result.VarType=Nil) and (Result.Expr.Kind=pekRange) then
  3741. ParseExc(nParserNoConstRangeAllowed,SParserNoConstRangeAllowed);
  3742. end
  3743. else if (Result.VarType<>nil)
  3744. and (po_ExtConstWithoutExpr in Options) then
  3745. begin
  3746. if (Parent is TPasClassType)
  3747. and TPasClassType(Parent).IsExternal
  3748. and (TPasClassType(Parent).ObjKind=okClass) then
  3749. // typed const without expression is allowed in external class
  3750. Result.IsConst:=true
  3751. else if CurToken=tkSemicolon then
  3752. begin
  3753. NextToken;
  3754. if CurTokenIsIdentifier('external') then
  3755. begin
  3756. // typed external const without expression is allowed
  3757. Result.IsConst:=true;
  3758. Include(Result.VarModifiers,vmExternal);
  3759. NextToken;
  3760. if CurToken in [tkString,tkIdentifier] then
  3761. begin
  3762. // external LibraryName;
  3763. // external LibraryName name ExportName;
  3764. // external name ExportName;
  3765. if not CurTokenIsIdentifier('name') then
  3766. Result.LibraryName:=DoParseExpression(Result);
  3767. if not CurTokenIsIdentifier('name') then
  3768. ParseExcSyntaxError;
  3769. NextToken;
  3770. if not (CurToken in [tkChar,tkString,tkIdentifier]) then
  3771. ParseExcTokenError(TokenInfos[tkString]);
  3772. Result.ExportName:=DoParseExpression(Result);
  3773. Result.IsConst:=true; // external const is readonly
  3774. end
  3775. else if CurToken=tkSemicolon then
  3776. // external;
  3777. else
  3778. ParseExcSyntaxError;
  3779. end
  3780. else
  3781. begin
  3782. UngetToken;
  3783. CheckToken(tkEqual);
  3784. end;
  3785. end
  3786. else
  3787. CheckToken(tkEqual);
  3788. end
  3789. else
  3790. CheckToken(tkEqual);
  3791. UngetToken;
  3792. CheckHint(Result,not (Parent is TPasMembersType));
  3793. ok:=true;
  3794. finally
  3795. if not ok then
  3796. ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
  3797. end;
  3798. end;
  3799. // Starts after the variable name
  3800. function TPasParser.ParseResourcestringDecl(Parent: TPasElement): TPasResString;
  3801. var
  3802. ok: Boolean;
  3803. begin
  3804. SaveComments;
  3805. Result := TPasResString(CreateElement(TPasResString, CurTokenString, Parent));
  3806. ok:=false;
  3807. try
  3808. ExpectToken(tkEqual);
  3809. NextToken; // skip tkEqual
  3810. Result.Expr:=DoParseConstValueExpression(Result);
  3811. UngetToken;
  3812. CheckHint(Result,True);
  3813. ok:=true;
  3814. finally
  3815. if not ok then
  3816. ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
  3817. end;
  3818. end;
  3819. function TPasParser.ParseAttributes(Parent: TPasElement; Add: boolean
  3820. ): TPasAttributes;
  3821. // returns with CurToken at tkSquaredBraceClose
  3822. var
  3823. Expr, Arg: TPasExpr;
  3824. Attributes: TPasAttributes;
  3825. Params: TParamsExpr;
  3826. Decls: TPasDeclarations;
  3827. begin
  3828. Result:=nil;
  3829. Attributes:=TPasAttributes(CreateElement(TPasAttributes,'',Parent));
  3830. try
  3831. repeat
  3832. NextToken;
  3833. // [name,name(param,param,...),...]
  3834. Expr:=nil;
  3835. ReadDottedIdentifier(Attributes,Expr,false);
  3836. if CurToken=tkBraceOpen then
  3837. begin
  3838. Params:=TParamsExpr(CreateElement(TParamsExpr,'',Attributes));
  3839. Params.Kind:=pekFuncParams;
  3840. Attributes.AddCall(Params);
  3841. Params.Value:=Expr;
  3842. Expr.Parent:=Params;
  3843. Expr:=nil;
  3844. repeat
  3845. NextToken;
  3846. if CurToken=tkBraceClose then
  3847. break;
  3848. Arg:=DoParseConstValueExpression(Params);
  3849. Params.AddParam(Arg);
  3850. until CurToken<>tkComma;
  3851. CheckToken(tkBraceClose);
  3852. NextToken;
  3853. end
  3854. else
  3855. begin
  3856. Attributes.AddCall(Expr);
  3857. Expr:=nil;
  3858. end;
  3859. until CurToken<>tkComma;
  3860. CheckToken(tkSquaredBraceClose);
  3861. Result:=Attributes;
  3862. if Add then
  3863. begin
  3864. if Parent is TPasDeclarations then
  3865. begin
  3866. Decls:=TPasDeclarations(Parent);
  3867. Decls.Declarations.Add(Result);
  3868. Decls.Attributes.Add(Result);
  3869. end
  3870. else if Parent is TPasMembersType then
  3871. TPasMembersType(Parent).Members.Add(Result)
  3872. else
  3873. ParseExcTokenError('[20190922193803]');
  3874. Engine.FinishScope(stDeclaration,Result);
  3875. end;
  3876. finally
  3877. if Result=nil then
  3878. begin
  3879. Attributes.Free;
  3880. Expr.Free;
  3881. end;
  3882. end;
  3883. end;
  3884. {$warn 5043 off}
  3885. procedure TPasParser.ReadGenericArguments(List: TFPList; Parent: TPasElement);
  3886. Var
  3887. N : String;
  3888. T : TPasGenericTemplateType;
  3889. Expr: TPasExpr;
  3890. TypeEl: TPasType;
  3891. begin
  3892. ExpectToken(tkLessThan);
  3893. repeat
  3894. N:=ExpectIdentifier;
  3895. T:=TPasGenericTemplateType(CreateElement(TPasGenericTemplateType,N,Parent));
  3896. List.Add(T);
  3897. NextToken;
  3898. if Curtoken = tkColon then
  3899. repeat
  3900. NextToken;
  3901. // comma separated list of constraints: identifier, class, record, constructor
  3902. case CurToken of
  3903. tkclass,tkrecord,tkconstructor:
  3904. begin
  3905. if T.TypeConstraint='' then
  3906. T.TypeConstraint:=CurTokenString;
  3907. Expr:=CreatePrimitiveExpr(T,pekIdent,CurTokenText);
  3908. T.AddConstraint(Expr);
  3909. NextToken;
  3910. end;
  3911. tkIdentifier,tkspecialize:
  3912. begin
  3913. TypeEl:=ParseTypeReference(T,false,Expr);
  3914. if T.TypeConstraint='' then
  3915. T.TypeConstraint:=TypeEl.Name;
  3916. if (Expr<>nil) and (Expr.Parent=T) then
  3917. Expr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  3918. T.AddConstraint(TypeEl);
  3919. end;
  3920. else
  3921. CheckToken(tkIdentifier);
  3922. end;
  3923. until CurToken<>tkComma;
  3924. Engine.FinishScope(stTypeDef,T);
  3925. until not (CurToken in [tkSemicolon,tkComma]);
  3926. if CurToken<>tkGreaterThan then
  3927. ParseExcExpectedAorB(TokenInfos[tkComma], TokenInfos[tkGreaterThan]);
  3928. end;
  3929. {$warn 5043 on}
  3930. procedure TPasParser.ReadSpecializeArguments(Parent: TPasElement;
  3931. Params: TFPList);
  3932. // after parsing CurToken is on tkGreaterThan
  3933. Var
  3934. TypeEl: TPasType;
  3935. begin
  3936. //writeln('START TPasParser.ReadSpecializeArguments ',CurTokenText,' ',CurTokenString);
  3937. CheckToken(tkLessThan);
  3938. repeat
  3939. //writeln('ARG TPasParser.ReadSpecializeArguments ',CurTokenText,' ',CurTokenString);
  3940. TypeEl:=ParseType(Parent,CurTokenPos,'');
  3941. Params.Add(TypeEl);
  3942. NextToken;
  3943. if CurToken=tkComma then
  3944. continue
  3945. else if CurToken=tkshr then
  3946. begin
  3947. ChangeToken(tkGreaterThan);
  3948. break;
  3949. end
  3950. else if CurToken=tkGreaterThan then
  3951. break
  3952. else
  3953. ParseExcExpectedAorB(TokenInfos[tkComma], TokenInfos[tkGreaterThan]);
  3954. until false;
  3955. end;
  3956. function TPasParser.ReadDottedIdentifier(Parent: TPasElement; out
  3957. Expr: TPasExpr; NeedAsString: boolean): String;
  3958. var
  3959. SrcPos: TPasSourcePos;
  3960. begin
  3961. Expr:=nil;
  3962. if NeedAsString then
  3963. Result := CurTokenString
  3964. else
  3965. Result:='';
  3966. CheckToken(tkIdentifier);
  3967. Expr:=CreatePrimitiveExpr(Parent,pekIdent,CurTokenString);
  3968. NextToken;
  3969. while CurToken=tkDot do
  3970. begin
  3971. SrcPos:=CurTokenPos;
  3972. ExpectIdentifier;
  3973. if NeedAsString then
  3974. Result := Result+'.'+CurTokenString;
  3975. AddToBinaryExprChain(Expr,CreatePrimitiveExpr(Parent,pekIdent,CurTokenString),
  3976. eopSubIdent,SrcPos);
  3977. NextToken;
  3978. end;
  3979. end;
  3980. // Starts after the type name
  3981. function TPasParser.ParseRangeType(AParent: TPasElement;
  3982. const NamePos: TPasSourcePos; const TypeName: String; Full: Boolean
  3983. ): TPasRangeType;
  3984. Var
  3985. PE : TPasExpr;
  3986. ok: Boolean;
  3987. begin
  3988. Result := TPasRangeType(CreateElement(TPasRangeType, TypeName, AParent, NamePos));
  3989. ok:=false;
  3990. try
  3991. if Full then
  3992. begin
  3993. If not (CurToken=tkEqual) then
  3994. ParseExcTokenError(TokenInfos[tkEqual]);
  3995. end;
  3996. NextToken;
  3997. PE:=DoParseExpression(Result,Nil,False);
  3998. if not ((PE is TBinaryExpr) and (TBinaryExpr(PE).Kind=pekRange)) then
  3999. begin
  4000. PE.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  4001. ParseExc(nRangeExpressionExpected,SRangeExpressionExpected);
  4002. end;
  4003. Result.RangeExpr:=TBinaryExpr(PE);
  4004. UngetToken;
  4005. Engine.FinishScope(stTypeDef,Result);
  4006. ok:=true;
  4007. finally
  4008. if not ok then
  4009. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  4010. end;
  4011. end;
  4012. // Starts after Exports, on first identifier.
  4013. procedure TPasParser.ParseExportDecl(Parent: TPasElement; List: TFPList);
  4014. Var
  4015. E : TPasExportSymbol;
  4016. begin
  4017. Repeat
  4018. if List.Count<>0 then
  4019. ExpectIdentifier;
  4020. E:=TPasExportSymbol(CreateElement(TPasExportSymbol,CurtokenString,Parent));
  4021. List.Add(E);
  4022. NextToken;
  4023. if CurTokenIsIdentifier('INDEX') then
  4024. begin
  4025. NextToken;
  4026. E.Exportindex:=DoParseExpression(E,Nil)
  4027. end
  4028. else if CurTokenIsIdentifier('NAME') then
  4029. begin
  4030. NextToken;
  4031. E.ExportName:=DoParseExpression(E,Nil)
  4032. end;
  4033. if not (CurToken in [tkComma,tkSemicolon]) then
  4034. ParseExc(nParserExpectedCommaSemicolon,SParserExpectedCommaSemicolon);
  4035. until (CurToken=tkSemicolon);
  4036. end;
  4037. function TPasParser.ParseProcedureType(Parent: TPasElement;
  4038. const NamePos: TPasSourcePos; const TypeName: String; const PT: TProcType
  4039. ): TPasProcedureType;
  4040. var
  4041. ok: Boolean;
  4042. begin
  4043. if PT in [ptFunction,ptClassFunction] then
  4044. Result := CreateFunctionType(TypeName, 'Result', Parent, False, NamePos)
  4045. else
  4046. Result := TPasProcedureType(CreateElement(TPasProcedureType, TypeName, Parent, NamePos));
  4047. ok:=false;
  4048. try
  4049. ParseProcedureOrFunction(Result, TPasProcedureType(Result), PT, True);
  4050. ok:=true;
  4051. finally
  4052. if not ok then
  4053. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  4054. end;
  4055. end;
  4056. function TPasParser.ParseTypeDecl(Parent: TPasElement): TPasType;
  4057. var
  4058. TypeName: String;
  4059. NamePos: TPasSourcePos;
  4060. OldForceCaret , IsDelphiGenericType: Boolean;
  4061. begin
  4062. OldForceCaret:=Scanner.SetForceCaret(True);
  4063. try
  4064. IsDelphiGenericType:=false;
  4065. if (msDelphi in CurrentModeswitches) then
  4066. begin
  4067. NextToken;
  4068. IsDelphiGenericType:=CurToken=tkLessThan;
  4069. UngetToken;
  4070. end;
  4071. if IsDelphiGenericType then
  4072. Result:=ParseGenericTypeDecl(Parent,false)
  4073. else
  4074. begin
  4075. TypeName := CurTokenString;
  4076. NamePos:=CurSourcePos;
  4077. ExpectToken(tkEqual);
  4078. Result:=ParseType(Parent,NamePos,TypeName,True);
  4079. end;
  4080. finally
  4081. Scanner.SetForceCaret(OldForceCaret);
  4082. end;
  4083. end;
  4084. function TPasParser.ParseGenericTypeDecl(Parent: TPasElement;
  4085. AddToParent: boolean): TPasGenericType;
  4086. procedure InitGenericType(NewEl: TPasGenericType; GenericTemplateTypes: TFPList);
  4087. begin
  4088. ParseGenericTypeDecl:=NewEl;
  4089. if AddToParent then
  4090. begin
  4091. if Parent is TPasDeclarations then
  4092. begin
  4093. TPasDeclarations(Parent).Declarations.Add(NewEl);
  4094. {$IFDEF CheckPasTreeRefCount}NewEl.ChangeRefId('CreateElement','TPasDeclarations.Children');{$ENDIF}
  4095. end
  4096. else if Parent is TPasMembersType then
  4097. begin
  4098. TPasMembersType(Parent).Members.Add(NewEl);
  4099. {$IFDEF CheckPasTreeRefCount}NewEl.ChangeRefId('CreateElement','TPasMembersType.Members');{$ENDIF}
  4100. end;
  4101. end;
  4102. if GenericTemplateTypes.Count>0 then
  4103. begin
  4104. // Note: TPasResolver sets GenericTemplateTypes already in CreateElement
  4105. // This is for other tools like fpdoc.
  4106. NewEl.SetGenericTemplates(GenericTemplateTypes);
  4107. end;
  4108. end;
  4109. procedure ParseProcType(const TypeName: string;
  4110. const NamePos: TPasSourcePos; TypeParams: TFPList;
  4111. IsReferenceTo: boolean);
  4112. var
  4113. ProcTypeEl: TPasProcedureType;
  4114. ProcType: TProcType;
  4115. begin
  4116. case CurToken of
  4117. tkFunction:
  4118. begin
  4119. ProcTypeEl := CreateFunctionType(TypeName, 'Result', Parent, False,
  4120. NamePos, TypeParams);
  4121. ProcType:=ptFunction;
  4122. end;
  4123. tkprocedure:
  4124. begin
  4125. ProcTypeEl := TPasProcedureType(CreateElement(TPasProcedureType,
  4126. TypeName, Parent, visDefault, NamePos, TypeParams));
  4127. ProcType:=ptProcedure;
  4128. end;
  4129. else
  4130. ParseExcTokenError('procedure or function');
  4131. end;
  4132. ProcTypeEl.IsReferenceTo:=IsReferenceTo;
  4133. if AddToParent and (Parent is TPasDeclarations) then
  4134. TPasDeclarations(Parent).Functions.Add(ProcTypeEl);
  4135. InitGenericType(ProcTypeEl,TypeParams);
  4136. ParseProcedureOrFunction(ProcTypeEl, ProcTypeEl, ProcType, True);
  4137. end;
  4138. var
  4139. TypeName, AExternalNameSpace, AExternalName: String;
  4140. NamePos: TPasSourcePos;
  4141. TypeParams: TFPList;
  4142. ClassEl: TPasClassType;
  4143. RecordEl: TPasRecordType;
  4144. ArrEl: TPasArrayType;
  4145. i: Integer;
  4146. AObjKind: TPasObjKind;
  4147. begin
  4148. Result:=nil;
  4149. TypeName := CurTokenString;
  4150. NamePos := CurSourcePos;
  4151. TypeParams:=TFPList.Create;
  4152. try
  4153. ReadGenericArguments(TypeParams,Parent);
  4154. ExpectToken(tkEqual);
  4155. NextToken;
  4156. Case CurToken of
  4157. tkObject,
  4158. tkClass,
  4159. tkinterface:
  4160. begin
  4161. case CurToken of
  4162. tkobject: AObjKind:=okObject;
  4163. tkinterface: AObjKind:=okInterface;
  4164. else AObjKind:=okClass;
  4165. end;
  4166. NextToken;
  4167. if (AObjKind = okClass) and (CurToken = tkOf) then
  4168. ParseExcExpectedIdentifier;
  4169. DoParseClassExternalHeader(AObjKind,AExternalNameSpace,AExternalName);
  4170. ClassEl := TPasClassType(CreateElement(TPasClassType,
  4171. TypeName, Parent, visDefault, NamePos, TypeParams));
  4172. ClassEl.ObjKind:=AObjKind;
  4173. if AObjKind=okInterface then
  4174. if SameText(Scanner.CurrentValueSwitch[vsInterfaces],'CORBA') then
  4175. ClassEl.InterfaceType:=citCorba;
  4176. if AddToParent and (Parent is TPasDeclarations) then
  4177. TPasDeclarations(Parent).Classes.Add(ClassEl);
  4178. ClassEl.IsExternal:=(AExternalName<>'');
  4179. if AExternalName<>'' then
  4180. ClassEl.ExternalName:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalName,'''');
  4181. if AExternalNameSpace<>'' then
  4182. ClassEl.ExternalNameSpace:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalNameSpace,'''');
  4183. InitGenericType(ClassEl,TypeParams);
  4184. DoParseClassType(ClassEl);
  4185. CheckHint(ClassEl,True);
  4186. Engine.FinishScope(stTypeDef,ClassEl);
  4187. end;
  4188. tkRecord:
  4189. begin
  4190. RecordEl := TPasRecordType(CreateElement(TPasRecordType,
  4191. TypeName, Parent, visDefault, NamePos, TypeParams));
  4192. if AddToParent and (Parent is TPasDeclarations) then
  4193. TPasDeclarations(Parent).Classes.Add(RecordEl);
  4194. InitGenericType(RecordEl,TypeParams);
  4195. NextToken;
  4196. ParseRecordMembers(RecordEl,tkend,
  4197. (msAdvancedRecords in Scanner.CurrentModeSwitches)
  4198. and not (Parent is TProcedureBody)
  4199. and (RecordEl.Name<>''));
  4200. CheckHint(RecordEl,True);
  4201. Engine.FinishScope(stTypeDef,RecordEl);
  4202. end;
  4203. tkArray:
  4204. begin
  4205. ArrEl := TPasArrayType(CreateElement(TPasArrayType,
  4206. TypeName, Parent, visDefault, NamePos, TypeParams));
  4207. if AddToParent and (Parent is TPasDeclarations) then
  4208. TPasDeclarations(Parent).Types.Add(ArrEl);
  4209. InitGenericType(ArrEl,TypeParams);
  4210. DoParseArrayType(ArrEl);
  4211. CheckHint(ArrEl,True);
  4212. Engine.FinishScope(stTypeDef,ArrEl);
  4213. end;
  4214. tkprocedure,tkfunction:
  4215. ParseProcType(TypeName,NamePos,TypeParams,false);
  4216. tkIdentifier:
  4217. if CurTokenIsIdentifier('reference') then
  4218. begin
  4219. NextToken;
  4220. CheckToken(tkto);
  4221. NextToken;
  4222. ParseProcType(TypeName,NamePos,TypeParams,true);
  4223. end
  4224. else
  4225. ParseExcTypeParamsNotAllowed;
  4226. else
  4227. ParseExcTypeParamsNotAllowed;
  4228. end;
  4229. finally
  4230. for i:=0 to TypeParams.Count-1 do
  4231. TPasElement(TypeParams[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  4232. TypeParams.Free;
  4233. end;
  4234. end;
  4235. function TPasParser.GetVariableValueAndLocation(Parent: TPasElement; out
  4236. Value: TPasExpr; out AbsoluteExpr: TPasExpr; out Location: String): Boolean;
  4237. begin
  4238. Value:=Nil;
  4239. AbsoluteExpr:=Nil;
  4240. Location:='';
  4241. NextToken;
  4242. Result:=CurToken=tkEqual;
  4243. if Result then
  4244. begin
  4245. NextToken;
  4246. Value := DoParseConstValueExpression(Parent);
  4247. end;
  4248. if (CurToken=tkAbsolute) then
  4249. begin
  4250. Result:=True;
  4251. NextToken;
  4252. Location:=ReadDottedIdentifier(Parent,AbsoluteExpr,true);
  4253. UnGetToken;
  4254. end
  4255. else
  4256. UngetToken;
  4257. end;
  4258. function TPasParser.GetVariableModifiers(Parent: TPasElement; out
  4259. VarMods: TVariableModifiers; out LibName, ExportName: TPasExpr;
  4260. const AllowedMods: TVariableModifiers): string;
  4261. Var
  4262. S : String;
  4263. ExtMod: TVariableModifier;
  4264. begin
  4265. Result := '';
  4266. LibName := nil;
  4267. ExportName := nil;
  4268. VarMods := [];
  4269. NextToken;
  4270. If (vmCVar in AllowedMods) and CurTokenIsIdentifier('cvar') then
  4271. begin
  4272. Result:=';cvar';
  4273. Include(VarMods,vmcvar);
  4274. ExpectToken(tkSemicolon);
  4275. NextToken;
  4276. end;
  4277. s:=LowerCase(CurTokenText);
  4278. if (vmExternal in AllowedMods) and (s='external') then
  4279. ExtMod:=vmExternal
  4280. else if (vmPublic in AllowedMods) and (s='public') then
  4281. ExtMod:=vmPublic
  4282. else if (vmExport in AllowedMods) and (s='export') then
  4283. ExtMod:=vmExport
  4284. else
  4285. begin
  4286. UngetToken;
  4287. exit;
  4288. end;
  4289. Include(VarMods,ExtMod);
  4290. Result:=Result+';'+CurTokenText;
  4291. NextToken;
  4292. if not (CurToken in [tkString,tkIdentifier]) then
  4293. begin
  4294. if (CurToken=tkSemicolon) and (ExtMod in [vmExternal,vmPublic]) then
  4295. exit;
  4296. ParseExcSyntaxError;
  4297. end;
  4298. // export name exportname;
  4299. // public;
  4300. // public name exportname;
  4301. // external;
  4302. // external libname;
  4303. // external libname name exportname;
  4304. // external name exportname;
  4305. if (ExtMod=vmExternal) and (CurToken in [tkString,tkIdentifier])
  4306. and Not (CurTokenIsIdentifier('name')) then
  4307. begin
  4308. Result := Result + ' ' + CurTokenText;
  4309. LibName:=DoParseExpression(Parent);
  4310. end;
  4311. if not CurTokenIsIdentifier('name') then
  4312. ParseExcSyntaxError;
  4313. NextToken;
  4314. if not (CurToken in [tkChar,tkString,tkIdentifier]) then
  4315. ParseExcTokenError(TokenInfos[tkString]);
  4316. Result := Result + ' ' + CurTokenText;
  4317. ExportName:=DoParseExpression(Parent);
  4318. end;
  4319. // Full means that a full variable declaration is being parsed.
  4320. procedure TPasParser.ParseVarList(Parent: TPasElement; VarList: TFPList;
  4321. AVisibility: TPasMemberVisibility; Full : Boolean);
  4322. // on Exception the VarList is restored, no need to Release the new elements
  4323. var
  4324. i, OldListCount: Integer;
  4325. Value , aLibName, aExpName, AbsoluteExpr: TPasExpr;
  4326. VarType: TPasType;
  4327. VarEl: TPasVariable;
  4328. H : TPasMemberHints;
  4329. VarMods, AllowedVarMods: TVariableModifiers;
  4330. D,Mods,AbsoluteLocString: string;
  4331. OldForceCaret,ok,ExternalStruct: Boolean;
  4332. begin
  4333. Value:=Nil;
  4334. aLibName:=nil;
  4335. aExpName:=nil;
  4336. AbsoluteExpr:=nil;
  4337. AbsoluteLocString:='';
  4338. OldListCount:=VarList.Count;
  4339. ok:=false;
  4340. try
  4341. D:=SaveComments; // This means we support only one comment per 'list'.
  4342. VarEl:=nil;
  4343. while CurToken=tkSquaredBraceOpen do
  4344. begin
  4345. if msPrefixedAttributes in CurrentModeswitches then
  4346. begin
  4347. VarList.Add(ParseAttributes(Parent,false));
  4348. NextToken;
  4349. end
  4350. else
  4351. CheckToken(tkIdentifier);
  4352. end;
  4353. Repeat
  4354. // create the TPasVariable here, so that SourceLineNumber is correct
  4355. VarEl:=TPasVariable(CreateElement(TPasVariable,CurTokenString,Parent,
  4356. AVisibility,CurTokenPos));
  4357. VarList.Add(VarEl);
  4358. NextToken;
  4359. case CurToken of
  4360. tkColon: break;
  4361. tkComma: ExpectIdentifier;
  4362. else ParseExc(nParserExpectedCommaColon,SParserExpectedCommaColon);
  4363. end;
  4364. Until (CurToken=tkColon);
  4365. OldForceCaret:=Scanner.SetForceCaret(True);
  4366. try
  4367. VarType := ParseComplexType(VarEl);
  4368. {$IFDEF CheckPasTreeRefCount}if VarType.RefIds.IndexOf('CreateElement')>=0 then VarType.ChangeRefId('CreateElement','TPasVariable.VarType'){$ENDIF};
  4369. finally
  4370. Scanner.SetForceCaret(OldForceCaret);
  4371. end;
  4372. // read type
  4373. for i := OldListCount to VarList.Count - 1 do
  4374. begin
  4375. VarEl:=TPasVariable(VarList[i]);
  4376. // Writeln(VarEl.Name, AVisibility);
  4377. VarEl.VarType := VarType;
  4378. //VarType.Parent := VarEl; // this is wrong for references
  4379. if (i>OldListCount) then
  4380. VarType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasVariable.VarType'){$ENDIF};
  4381. end;
  4382. H:=CheckHint(Nil,False);
  4383. If Full then
  4384. GetVariableValueAndLocation(VarEl,Value,AbsoluteExpr,AbsoluteLocString);
  4385. if (VarList.Count>OldListCount+1) then
  4386. begin
  4387. // multiple variables
  4388. if Value<>nil then
  4389. ParseExc(nParserOnlyOneVariableCanBeInitialized,SParserOnlyOneVariableCanBeInitialized);
  4390. if AbsoluteExpr<>nil then
  4391. ParseExc(nParserOnlyOneVariableCanBeAbsolute,SParserOnlyOneVariableCanBeAbsolute);
  4392. end;
  4393. TPasVariable(VarList[OldListCount]).Expr:=Value;
  4394. Value:=nil;
  4395. // Note: external members are allowed for non external classes/records too
  4396. ExternalStruct:=(msExternalClass in CurrentModeSwitches)
  4397. and (Parent is TPasMembersType);
  4398. H:=H+CheckHint(Nil,False);
  4399. if Full or ExternalStruct then
  4400. begin
  4401. NextToken;
  4402. If Curtoken<>tkSemicolon then
  4403. UnGetToken;
  4404. VarEl:=TPasVariable(VarList[OldListCount]);
  4405. AllowedVarMods:=[];
  4406. if ExternalStruct then
  4407. AllowedVarMods:=[vmExternal]
  4408. else
  4409. AllowedVarMods:=[vmCVar,vmExternal,vmPublic,vmExport];
  4410. Mods:=GetVariableModifiers(VarEl,VarMods,aLibName,aExpName,AllowedVarMods);
  4411. if (Mods='') and (CurToken<>tkSemicolon) then
  4412. NextToken;
  4413. end
  4414. else
  4415. begin
  4416. NextToken;
  4417. VarMods:=[];
  4418. Mods:='';
  4419. end;
  4420. SaveComments(D);
  4421. // connect
  4422. for i := OldListCount to VarList.Count - 1 do
  4423. begin
  4424. VarEl:=TPasVariable(VarList[i]);
  4425. // Writeln(VarEl.Name, AVisibility);
  4426. // Procedure declaration eats the hints.
  4427. if Assigned(VarType) and (VarType is TPasProcedureType) then
  4428. VarEl.Hints:=VarType.Hints
  4429. else
  4430. VarEl.Hints:=H;
  4431. VarEl.Modifiers:=Mods;
  4432. VarEl.VarModifiers:=VarMods;
  4433. VarEl.{%H-}AbsoluteLocation:=AbsoluteLocString;
  4434. if AbsoluteExpr<>nil then
  4435. begin
  4436. VarEl.AbsoluteExpr:=AbsoluteExpr;
  4437. AbsoluteExpr:=nil;
  4438. end;
  4439. if aLibName<>nil then
  4440. begin
  4441. VarEl.LibraryName:=aLibName;
  4442. aLibName:=nil;
  4443. end;
  4444. if aExpName<>nil then
  4445. begin
  4446. VarEl.ExportName:=aExpName;
  4447. aExpName:=nil;
  4448. end;
  4449. end;
  4450. ok:=true;
  4451. finally
  4452. if not ok then
  4453. begin
  4454. if aLibName<>nil then aLibName.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  4455. if aExpName<>nil then aExpName.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  4456. if AbsoluteExpr<>nil then AbsoluteExpr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  4457. if Value<>nil then Value.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  4458. for i:=OldListCount to VarList.Count-1 do
  4459. TPasElement(VarList[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  4460. VarList.Count:=OldListCount;
  4461. end;
  4462. end;
  4463. end;
  4464. procedure TPasParser.SetOptions(AValue: TPOptions);
  4465. begin
  4466. if FOptions=AValue then Exit;
  4467. FOptions:=AValue;
  4468. If Assigned(FScanner) then
  4469. FScanner.Options:=AValue;
  4470. end;
  4471. procedure TPasParser.OnScannerModeChanged(Sender: TObject;
  4472. NewMode: TModeSwitch; Before: boolean; var Handled: boolean);
  4473. begin
  4474. Engine.ModeChanged(Self,NewMode,Before,Handled);
  4475. if Sender=nil then ;
  4476. end;
  4477. function TPasParser.SaveComments: String;
  4478. begin
  4479. if Engine.NeedComments then
  4480. FSavedComments:=CurComments.Text; // Expensive, so don't do unless needed.
  4481. Result:=FSavedComments;
  4482. end;
  4483. function TPasParser.SaveComments(const AValue: String): String;
  4484. begin
  4485. FSavedComments:=AValue;
  4486. Result:=FSavedComments;
  4487. end;
  4488. function TPasParser.LogEvent(E: TPParserLogEvent): Boolean;
  4489. begin
  4490. Result:=E in FLogEvents;
  4491. end;
  4492. procedure TPasParser.SetLastMsg(MsgType: TMessageType; MsgNumber: integer;
  4493. const Fmt: String; Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif});
  4494. begin
  4495. FLastMsgType := MsgType;
  4496. FLastMsgNumber := MsgNumber;
  4497. FLastMsgPattern := Fmt;
  4498. FLastMsg := SafeFormat(Fmt,Args);
  4499. CreateMsgArgs(FLastMsgArgs,Args);
  4500. end;
  4501. procedure TPasParser.DoLog(MsgType: TMessageType; MsgNumber: integer;
  4502. const Msg: String; SkipSourceInfo: Boolean);
  4503. begin
  4504. DoLog(MsgType,MsgNumber,Msg,[],SkipSourceInfo);
  4505. end;
  4506. procedure TPasParser.DoLog(MsgType: TMessageType; MsgNumber: integer;
  4507. const Fmt: String; Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif};
  4508. SkipSourceInfo: Boolean);
  4509. Var
  4510. Msg : String;
  4511. begin
  4512. if (Scanner<>nil) and Scanner.IgnoreMsgType(MsgType) then
  4513. exit;
  4514. SetLastMsg(MsgType,MsgNumber,Fmt,Args);
  4515. If Assigned(FOnLog) then
  4516. begin
  4517. Msg:=MessageTypeNames[MsgType]+': ';
  4518. if SkipSourceInfo or not assigned(scanner) then
  4519. Msg:=Msg+FLastMsg
  4520. else
  4521. Msg:=Msg+Format('%s(%d,%d) : %s',[Scanner.CurFilename,Scanner.CurRow,Scanner.CurColumn,FLastMsg]);
  4522. FOnLog(Self,Msg);
  4523. end;
  4524. end;
  4525. procedure TPasParser.ParseInlineVarDecl(Parent: TPasElement; List: TFPList;
  4526. AVisibility: TPasMemberVisibility = VisDefault; ClosingBrace: Boolean = False);
  4527. Var
  4528. tt : TTokens;
  4529. begin
  4530. ParseVarList(Parent,List,AVisibility,False);
  4531. tt:=[tkEnd,tkSemicolon];
  4532. if ClosingBrace then
  4533. Include(tt,tkBraceClose);
  4534. if not (CurToken in tt) then
  4535. ParseExc(nParserExpectedSemiColonEnd,SParserExpectedSemiColonEnd);
  4536. end;
  4537. // Starts after the variable name
  4538. procedure TPasParser.ParseVarDecl(Parent: TPasElement; List: TFPList);
  4539. begin
  4540. ParseVarList(Parent,List,visDefault,True);
  4541. end;
  4542. // Starts after the opening bracket token
  4543. procedure TPasParser.ParseArgList(Parent: TPasElement; Args: TFPList; EndToken: TToken);
  4544. var
  4545. IsUntyped, ok, LastHadDefaultValue: Boolean;
  4546. Name : String;
  4547. Value : TPasExpr;
  4548. i, OldArgCount: Integer;
  4549. Arg: TPasArgument;
  4550. Access: TArgumentAccess;
  4551. ArgType: TPasType;
  4552. begin
  4553. LastHadDefaultValue := false;
  4554. while True do
  4555. begin
  4556. OldArgCount:=Args.Count;
  4557. Access := argDefault;
  4558. IsUntyped := False;
  4559. ArgType := nil;
  4560. NextToken;
  4561. if CurToken = tkConst then
  4562. begin
  4563. Access := argConst;
  4564. Name := ExpectIdentifier;
  4565. end else if CurToken = tkConstRef then
  4566. begin
  4567. Access := argConstref;
  4568. Name := ExpectIdentifier;
  4569. end else if CurToken = tkVar then
  4570. begin
  4571. Access := ArgVar;
  4572. Name := ExpectIdentifier;
  4573. end else if (CurToken = tkIdentifier) and (UpperCase(CurTokenString) = 'OUT') then
  4574. begin
  4575. Access := ArgOut;
  4576. Name := ExpectIdentifier;
  4577. end else if CurToken = tkIdentifier then
  4578. Name := CurTokenString
  4579. else
  4580. ParseExc(nParserExpectedConstVarID,SParserExpectedConstVarID);
  4581. while True do
  4582. begin
  4583. Arg := TPasArgument(CreateElement(TPasArgument, Name, Parent));
  4584. Arg.Access := Access;
  4585. Args.Add(Arg);
  4586. NextToken;
  4587. if CurToken = tkColon then
  4588. break
  4589. else if ((CurToken = tkSemicolon) or (CurToken = tkBraceClose)) and
  4590. (Access <> argDefault) then
  4591. begin
  4592. // found an untyped const or var argument
  4593. UngetToken;
  4594. IsUntyped := True;
  4595. break
  4596. end
  4597. else if CurToken <> tkComma then
  4598. ParseExc(nParserExpectedCommaColon,SParserExpectedCommaColon);
  4599. NextToken;
  4600. if CurToken = tkIdentifier then
  4601. Name := CurTokenString
  4602. else
  4603. ParseExc(nParserExpectedConstVarID,SParserExpectedConstVarID);
  4604. end;
  4605. Value:=Nil;
  4606. if not IsUntyped then
  4607. begin
  4608. Arg := TPasArgument(Args[OldArgCount]);
  4609. ArgType := ParseType(Arg,CurSourcePos);
  4610. ok:=false;
  4611. try
  4612. NextToken;
  4613. if CurToken = tkEqual then
  4614. begin
  4615. if (Args.Count>OldArgCount+1) then
  4616. begin
  4617. ArgType.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  4618. ArgType:=nil;
  4619. ParseExc(nParserOnlyOneArgumentCanHaveDefault,SParserOnlyOneArgumentCanHaveDefault);
  4620. end;
  4621. if Parent is TPasProperty then
  4622. ParseExc(nParserPropertyArgumentsCanNotHaveDefaultValues,
  4623. SParserPropertyArgumentsCanNotHaveDefaultValues);
  4624. NextToken;
  4625. Value := DoParseExpression(Arg,Nil);
  4626. // After this, we're on ), which must be unget.
  4627. LastHadDefaultValue:=true;
  4628. end
  4629. else if LastHadDefaultValue then
  4630. ParseExc(nParserDefaultParameterRequiredFor,
  4631. SParserDefaultParameterRequiredFor,[TPasArgument(Args[OldArgCount]).Name]);
  4632. UngetToken;
  4633. ok:=true;
  4634. finally
  4635. if (not ok) and (ArgType<>nil) then
  4636. ArgType.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  4637. end;
  4638. end;
  4639. for i := OldArgCount to Args.Count - 1 do
  4640. begin
  4641. Arg := TPasArgument(Args[i]);
  4642. Arg.ArgType := ArgType;
  4643. if Assigned(ArgType) then
  4644. begin
  4645. if (i > OldArgCount) then
  4646. ArgType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
  4647. end;
  4648. Arg.ValueExpr := Value;
  4649. Value:=Nil; // Only the first gets a value. OK, since Var A,B : Integer = 1 is not allowed.
  4650. end;
  4651. for i := OldArgCount to Args.Count - 1 do
  4652. Engine.FinishScope(stDeclaration,TPasArgument(Args[i]));
  4653. NextToken;
  4654. if (CurToken = tkIdentifier) and (LowerCase(CurTokenString) = 'location') then
  4655. begin
  4656. NextToken; // remove 'location'
  4657. NextToken; // remove register
  4658. end;
  4659. if CurToken = EndToken then
  4660. break;
  4661. CheckToken(tkSemicolon);
  4662. end;
  4663. end;
  4664. function TPasParser.CheckProcedureArgs(Parent: TPasElement; Args: TFPList;
  4665. ProcType: TProcType): boolean;
  4666. begin
  4667. NextToken;
  4668. if CurToken=tkBraceOpen then
  4669. begin
  4670. Result:=true;
  4671. NextToken;
  4672. if (CurToken<>tkBraceClose) then
  4673. begin
  4674. UngetToken;
  4675. ParseArgList(Parent, Args, tkBraceClose);
  4676. end;
  4677. end
  4678. else
  4679. begin
  4680. Result:=false;
  4681. case ProcType of
  4682. ptOperator,ptClassOperator:
  4683. ParseExc(nParserExpectedLBracketColon,SParserExpectedLBracketColon);
  4684. ptAnonymousProcedure,ptAnonymousFunction:
  4685. case CurToken of
  4686. tkIdentifier, // e.g. procedure assembler
  4687. tkbegin,tkvar,tkconst,tktype,tkprocedure,tkfunction:
  4688. UngetToken;
  4689. tkColon:
  4690. if ProcType=ptAnonymousFunction then
  4691. UngetToken
  4692. else
  4693. ParseExcTokenError('begin');
  4694. else
  4695. ParseExcTokenError('begin');
  4696. end;
  4697. else
  4698. case CurToken of
  4699. tkSemicolon, // e.g. procedure;
  4700. tkColon, // e.g. function: id
  4701. tkof, // e.g. procedure of object
  4702. tkis, // e.g. procedure is nested
  4703. tkIdentifier: // e.g. procedure cdecl;
  4704. UngetToken;
  4705. else
  4706. ParseExcTokenError(';');
  4707. end;
  4708. end;
  4709. end;
  4710. end;
  4711. procedure TPasParser.HandleProcedureModifier(Parent: TPasElement; pm: TProcedureModifier);
  4712. // at end on last token of modifier, usually the semicolon
  4713. Var
  4714. P : TPasProcedure;
  4715. E : TPasExpr;
  4716. procedure AddModifier;
  4717. begin
  4718. if pm in P.Modifiers then
  4719. ParseExcSyntaxError;
  4720. P.AddModifier(pm);
  4721. end;
  4722. begin
  4723. P:=TPasProcedure(Parent);
  4724. if pm<>pmPublic then
  4725. AddModifier;
  4726. Case pm of
  4727. pmExternal:
  4728. begin
  4729. NextToken;
  4730. if CurToken in [tkString,tkIdentifier] then
  4731. begin
  4732. // external libname
  4733. // external libname name XYZ
  4734. // external name XYZ
  4735. if Not CurTokenIsIdentifier('NAME') then
  4736. begin
  4737. E:=DoParseExpression(Parent);
  4738. if Assigned(P) then
  4739. P.LibraryExpr:=E;
  4740. end;
  4741. if CurTokenIsIdentifier('NAME') then
  4742. begin
  4743. NextToken;
  4744. if not (CurToken in [tkChar,tkString,tkIdentifier]) then
  4745. ParseExcTokenError(TokenInfos[tkString]);
  4746. E:=DoParseExpression(Parent);
  4747. if Assigned(P) then
  4748. P.LibrarySymbolName:=E;
  4749. end;
  4750. if CurToken<>tkSemicolon then
  4751. UngetToken;
  4752. end
  4753. else
  4754. UngetToken;
  4755. end;
  4756. pmPublic:
  4757. begin
  4758. NextToken;
  4759. If not CurTokenIsIdentifier('name') then
  4760. begin
  4761. if P.Parent is TPasMembersType then
  4762. begin
  4763. // public section starts
  4764. UngetToken;
  4765. UngetToken;
  4766. exit;
  4767. end;
  4768. AddModifier;
  4769. CheckToken(tkSemicolon);
  4770. exit;
  4771. end
  4772. else
  4773. begin
  4774. AddModifier;
  4775. NextToken; // Should be "public name string".
  4776. if not (CurToken in [tkString,tkIdentifier]) then
  4777. ParseExcTokenError(TokenInfos[tkString]);
  4778. E:=DoParseExpression(Parent);
  4779. if Parent is TPasProcedure then
  4780. TPasProcedure(Parent).PublicName:=E;
  4781. CheckToken(tkSemicolon);
  4782. end;
  4783. end;
  4784. pmForward:
  4785. begin
  4786. if (Parent.Parent is TInterfaceSection) then
  4787. begin
  4788. ParseExc(nParserForwardNotInterface,SParserForwardNotInterface);
  4789. UngetToken;
  4790. end;
  4791. end;
  4792. pmMessage:
  4793. begin
  4794. NextToken;
  4795. E:=DoParseExpression(Parent);
  4796. TPasProcedure(Parent).MessageExpr:=E;
  4797. if E is TPrimitiveExpr then
  4798. begin
  4799. TPasProcedure(Parent).MessageName:=TPrimitiveExpr(E).Value;
  4800. case E.Kind of
  4801. pekNumber, pekUnary: TPasProcedure(Parent).Messagetype:=pmtInteger;
  4802. pekString: TPasProcedure(Parent).Messagetype:=pmtString;
  4803. end;
  4804. end;
  4805. if CurToken<>tkSemicolon then
  4806. UngetToken;
  4807. end;
  4808. pmDispID:
  4809. begin
  4810. NextToken;
  4811. TPasProcedure(Parent).DispIDExpr:=DoParseExpression(Parent);
  4812. if CurToken<>tkSemicolon then
  4813. UngetToken;
  4814. end;
  4815. end; // Case
  4816. end;
  4817. procedure TPasParser.HandleProcedureTypeModifier(ProcType: TPasProcedureType;
  4818. ptm: TProcTypeModifier);
  4819. begin
  4820. if ptm in ProcType.Modifiers then
  4821. ParseExcSyntaxError;
  4822. Include(ProcType.Modifiers,ptm);
  4823. end;
  4824. // Next token is expected to be a "(", ";" or for a function ":". The caller
  4825. // will get the token after the final ";" as next token.
  4826. function TPasParser.DoCheckHint(Element : TPasElement): Boolean;
  4827. var
  4828. ahint : TPasMemberHint;
  4829. begin
  4830. Result:= IsCurTokenHint(ahint);
  4831. if Result then // deprecated,platform,experimental,library, unimplemented etc
  4832. begin
  4833. Element.Hints:=Element.Hints+[ahint];
  4834. if aHint=hDeprecated then
  4835. begin
  4836. NextToken;
  4837. if (CurToken<>tkString) then
  4838. UngetToken
  4839. else
  4840. Element.HintMessage:=CurTokenString;
  4841. end;
  4842. end;
  4843. end;
  4844. procedure TPasParser.ParseProcedureOrFunction(Parent: TPasElement;
  4845. Element: TPasProcedureType; ProcType: TProcType; OfObjectPossible: Boolean);
  4846. Function FindInSection(AName : String;ASection : TPasSection) : Boolean;
  4847. Var
  4848. I : integer;
  4849. Cn,FN : String;
  4850. CT : TPasClassType;
  4851. begin
  4852. I:=ASection.Functions.Count-1;
  4853. While (I>=0) and (CompareText(TPasElement(ASection.Functions[I]).Name,AName)<>0) do
  4854. Dec(I);
  4855. Result:=I<>-1;
  4856. I:=Pos('.',AName);
  4857. if (Not Result) and (I>0) then
  4858. begin
  4859. CN:=Copy(AName,1,I-1);
  4860. FN:=AName;
  4861. Delete(FN,1,I);
  4862. I:=ASection.Classes.Count-1;
  4863. While Not Result and (I>=0) do
  4864. begin
  4865. CT:=TPasClassType(ASection.Classes[i]);
  4866. if CompareText(CT.Name,CN)=0 then
  4867. Result:=CT.FindMember(TPasFunction, FN)<>Nil;
  4868. Dec(I);
  4869. end;
  4870. end;
  4871. end;
  4872. procedure ConsumeSemi;
  4873. begin
  4874. NextToken;
  4875. if (CurToken <> tkSemicolon) and IsCurTokenHint then
  4876. UngetToken;
  4877. end;
  4878. Var
  4879. Tok : String;
  4880. CC : TCallingConvention;
  4881. PM : TProcedureModifier;
  4882. ResultEl: TPasResultElement;
  4883. OK: Boolean;
  4884. IsProcType: Boolean; // false = procedure, true = procedure type
  4885. IsAnonymous: Boolean;
  4886. PTM: TProcTypeModifier;
  4887. ModTokenCount: Integer;
  4888. LastToken: TToken;
  4889. begin
  4890. // Element must be non-nil. Removed all checks for not-nil.
  4891. // If it is nil, the following fails anyway.
  4892. CheckProcedureArgs(Element,Element.Args,ProcType);
  4893. IsProcType:=not (Parent is TPasProcedure);
  4894. IsAnonymous:=(not IsProcType) and (ProcType in [ptAnonymousProcedure,ptAnonymousFunction]);
  4895. case ProcType of
  4896. ptFunction,ptClassFunction,ptAnonymousFunction:
  4897. begin
  4898. NextToken;
  4899. if CurToken = tkColon then
  4900. begin
  4901. ResultEl:=TPasFunctionType(Element).ResultEl;
  4902. ResultEl.ResultType := ParseType(ResultEl,CurSourcePos);
  4903. end
  4904. // In Delphi mode, the signature in the implementation section can be
  4905. // without result as it was declared
  4906. // We actually check if the function exists in the interface section.
  4907. else if (not IsAnonymous)
  4908. and (msDelphi in CurrentModeswitches)
  4909. and (Assigned(CurModule.ImplementationSection)
  4910. or (CurModule is TPasProgram))
  4911. then
  4912. begin
  4913. if Assigned(CurModule.InterfaceSection) then
  4914. OK:=FindInSection(Parent.Name,CurModule.InterfaceSection)
  4915. else if (CurModule is TPasProgram) and Assigned(TPasProgram(CurModule).ProgramSection) then
  4916. OK:=FindInSection(Parent.Name,TPasProgram(CurModule).ProgramSection);
  4917. if Not OK then
  4918. CheckToken(tkColon)
  4919. else
  4920. begin
  4921. CheckToken(tkSemiColon);
  4922. UngetToken;
  4923. end;
  4924. end
  4925. else
  4926. begin
  4927. // Raise error
  4928. CheckToken(tkColon);
  4929. end;
  4930. end;
  4931. ptOperator,ptClassOperator:
  4932. begin
  4933. NextToken;
  4934. ResultEl:=TPasFunctionType(Element).ResultEl;
  4935. if (CurToken=tkIdentifier) then
  4936. begin
  4937. ResultEl.Name := CurTokenName;
  4938. ExpectToken(tkColon);
  4939. end
  4940. else
  4941. if (CurToken=tkColon) then
  4942. ResultEl.Name := 'Result'
  4943. else
  4944. ParseExc(nParserExpectedColonID,SParserExpectedColonID);
  4945. ResultEl.ResultType := ParseType(ResultEl,CurSourcePos);
  4946. end;
  4947. end;
  4948. if OfObjectPossible then
  4949. begin
  4950. NextToken;
  4951. if (CurToken = tkOf) then
  4952. begin
  4953. ExpectToken(tkObject);
  4954. Element.IsOfObject := True;
  4955. end
  4956. else if (CurToken = tkIs) then
  4957. begin
  4958. expectToken(tkIdentifier);
  4959. if (lowerCase(CurTokenString)<>'nested') then
  4960. ParseExc(nParserExpectedNested,SParserExpectedNested);
  4961. Element.IsNested:=True;
  4962. end
  4963. else
  4964. UnGetToken;
  4965. end;
  4966. ModTokenCount:=0;
  4967. //writeln('TPasParser.ParseProcedureOrFunction IsProcType=',IsProcType,' IsAnonymous=',IsAnonymous);
  4968. Repeat
  4969. inc(ModTokenCount);
  4970. //writeln('TPasParser.ParseProcedureOrFunction ',ModTokenCount,' ',CurToken,' ',CurTokenText);
  4971. LastToken:=CurToken;
  4972. NextToken;
  4973. if (CurToken = tkEqual) and IsProcType and (ModTokenCount<=3) then
  4974. begin
  4975. // for example: const p: procedure = nil;
  4976. UngetToken;
  4977. Engine.FinishScope(stProcedureHeader,Element);
  4978. exit;
  4979. end;
  4980. If CurToken=tkSemicolon then
  4981. begin
  4982. if IsAnonymous then
  4983. CheckToken(tkbegin); // begin expected, but ; found
  4984. if LastToken=tkSemicolon then
  4985. ParseExcSyntaxError;
  4986. continue;
  4987. end
  4988. else if TokenIsCallingConvention(CurTokenString,cc) then
  4989. begin
  4990. Element.CallingConvention:=Cc;
  4991. if cc = ccSysCall then
  4992. begin
  4993. // remove LibBase
  4994. NextToken;
  4995. if CurToken=tkSemiColon then
  4996. UngetToken
  4997. else
  4998. // remove legacy or basesysv on MorphOS syscalls
  4999. begin
  5000. if CurTokenIsIdentifier('legacy') or CurTokenIsIdentifier('BaseSysV') then
  5001. NextToken;
  5002. NextToken; // remove offset
  5003. end;
  5004. end;
  5005. if IsProcType then
  5006. begin
  5007. ExpectTokens([tkSemicolon,tkEqual]);
  5008. if CurToken=tkEqual then
  5009. UngetToken;
  5010. end
  5011. else if IsAnonymous then
  5012. else
  5013. ExpectTokens([tkSemicolon]);
  5014. end
  5015. else if IsAnonymous and TokenIsAnonymousProcedureModifier(Parent,CurTokenString,PM) then
  5016. HandleProcedureModifier(Parent,PM)
  5017. else if TokenIsProcedureTypeModifier(Parent,CurTokenString,PTM) then
  5018. HandleProcedureTypeModifier(Element,PTM)
  5019. else if (not IsProcType) and (not IsAnonymous)
  5020. and TokenIsProcedureModifier(Parent,CurTokenString,PM) then
  5021. HandleProcedureModifier(Parent,PM)
  5022. else if (CurToken=tklibrary) and not IsProcType and not IsAnonymous then
  5023. // library is a token and a directive.
  5024. begin
  5025. Tok:=UpperCase(CurTokenString);
  5026. NextToken;
  5027. If (tok<>'NAME') then
  5028. begin
  5029. if hLibrary in Element.Hints then
  5030. ParseExcSyntaxError;
  5031. Element.Hints:=Element.Hints+[hLibrary];
  5032. end
  5033. else
  5034. begin
  5035. NextToken; // Should be "export name astring".
  5036. ExpectToken(tkSemicolon);
  5037. end;
  5038. end
  5039. else if (not IsAnonymous) and DoCheckHint(Element) then
  5040. // deprecated,platform,experimental,library, unimplemented etc
  5041. ConsumeSemi
  5042. else if (CurToken=tkIdentifier) and (not IsAnonymous)
  5043. and (CompareText(CurTokenText,'alias')=0) then
  5044. begin
  5045. ExpectToken(tkColon);
  5046. ExpectToken(tkString);
  5047. if (Parent is TPasProcedure) then
  5048. (Parent as TPasProcedure).AliasName:=CurTokenText;
  5049. ExpectToken(tkSemicolon);
  5050. end
  5051. else if (CurToken = tkSquaredBraceOpen) then
  5052. begin
  5053. if msPrefixedAttributes in CurrentModeswitches then
  5054. begin
  5055. // [attribute]
  5056. UngetToken;
  5057. break;
  5058. end
  5059. else
  5060. begin
  5061. // ToDo: read FPC's [] modifiers, e.g. [public,alias:'']
  5062. repeat
  5063. NextToken;
  5064. if CurToken in [tkSquaredBraceOpen,tkSemicolon] then
  5065. CheckToken(tkSquaredBraceClose);
  5066. until CurToken = tkSquaredBraceClose;
  5067. ExpectToken(tkSemicolon);
  5068. end;
  5069. end
  5070. else
  5071. begin
  5072. // not a modifier/hint/calling convention
  5073. if LastToken=tkSemicolon then
  5074. begin
  5075. UngetToken;
  5076. if IsAnonymous then
  5077. ParseExcSyntaxError;
  5078. break;
  5079. end
  5080. else if IsAnonymous then
  5081. begin
  5082. UngetToken;
  5083. break;
  5084. end
  5085. else
  5086. begin
  5087. CheckToken(tkSemicolon);
  5088. continue;
  5089. end;
  5090. end;
  5091. // Writeln('Done: ',TokenInfos[Curtoken],' ',CurtokenString);
  5092. Until false;
  5093. if (ProcType in [ptOperator,ptClassOperator]) and (Parent is TPasOperator) then
  5094. TPasOperator(Parent).CorrectName;
  5095. Engine.FinishScope(stProcedureHeader,Element);
  5096. if (not IsProcType)
  5097. and (not TPasProcedure(Parent).IsForward)
  5098. and (not TPasProcedure(Parent).IsExternal)
  5099. and ((Parent.Parent is TImplementationSection)
  5100. or (Parent.Parent is TProcedureBody)
  5101. or IsAnonymous)
  5102. then
  5103. ParseProcedureBody(Parent);
  5104. end;
  5105. // starts after the semicolon
  5106. procedure TPasParser.ParseProcedureBody(Parent: TPasElement);
  5107. var
  5108. Body: TProcedureBody;
  5109. begin
  5110. Body := TProcedureBody(CreateElement(TProcedureBody, '', Parent));
  5111. TPasProcedure(Parent).Body:=Body;
  5112. ParseDeclarations(Body);
  5113. end;
  5114. function TPasParser.ParseMethodResolution(Parent: TPasElement
  5115. ): TPasMethodResolution;
  5116. var
  5117. ok: Boolean;
  5118. begin
  5119. ok:=false;
  5120. Result:=TPasMethodResolution(CreateElement(TPasMethodResolution,'',Parent));
  5121. try
  5122. if CurToken=tkfunction then
  5123. Result.ProcClass:=TPasFunction
  5124. else
  5125. Result.ProcClass:=TPasProcedure;
  5126. ExpectToken(tkIdentifier);
  5127. Result.InterfaceName:=CreatePrimitiveExpr(Result,pekIdent,CurTokenString);
  5128. ExpectToken(tkDot);
  5129. ExpectToken(tkIdentifier);
  5130. Result.InterfaceProc:=CreatePrimitiveExpr(Result,pekIdent,CurTokenString);
  5131. ExpectToken(tkEqual);
  5132. ExpectToken(tkIdentifier);
  5133. Result.ImplementationProc:=CreatePrimitiveExpr(Result,pekIdent,CurTokenString);
  5134. NextToken;
  5135. if CurToken=tkSemicolon then
  5136. else if CurToken=tkend then
  5137. UngetToken
  5138. else
  5139. CheckToken(tkSemicolon);
  5140. ok:=true;
  5141. finally
  5142. if not ok then
  5143. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  5144. end;
  5145. end;
  5146. function TPasParser.ParseProperty(Parent: TPasElement; const AName: String;
  5147. AVisibility: TPasMemberVisibility; IsClassField: boolean): TPasProperty;
  5148. function GetAccessorName(aParent: TPasElement; out Expr: TPasExpr): String;
  5149. var
  5150. Params: TParamsExpr;
  5151. Param: TPasExpr;
  5152. SrcPos: TPasSourcePos;
  5153. begin
  5154. NextToken;
  5155. // read ident.subident...
  5156. Result:=ReadDottedIdentifier(aParent,Expr,true);
  5157. // read optional array index
  5158. if CurToken <> tkSquaredBraceOpen then
  5159. UnGetToken
  5160. else
  5161. begin
  5162. Result := Result + '[';
  5163. Params:=TParamsExpr(CreateElement(TParamsExpr,'',aParent));
  5164. Params.Kind:=pekArrayParams;
  5165. Params.Value:=Expr;
  5166. Expr.Parent:=Params;
  5167. Expr:=Params;
  5168. NextToken;
  5169. case CurToken of
  5170. tkChar: Param:=CreatePrimitiveExpr(aParent,pekString, CurTokenText);
  5171. tkNumber: Param:=CreatePrimitiveExpr(aParent,pekNumber, CurTokenString);
  5172. tkIdentifier: Param:=CreatePrimitiveExpr(aParent,pekIdent, CurTokenText);
  5173. tkfalse, tktrue: Param:=CreateBoolConstExpr(aParent,pekBoolConst, CurToken=tktrue);
  5174. else
  5175. ParseExcExpectedIdentifier;
  5176. end;
  5177. Params.AddParam(Param);
  5178. Result := Result + CurTokenString;
  5179. ExpectToken(tkSquaredBraceClose);
  5180. Result := Result + ']';
  5181. end;
  5182. repeat
  5183. NextToken;
  5184. if CurToken <> tkDot then
  5185. begin
  5186. UngetToken;
  5187. break;
  5188. end;
  5189. SrcPos:=CurTokenPos;
  5190. ExpectIdentifier;
  5191. Result := Result + '.' + CurTokenString;
  5192. AddToBinaryExprChain(Expr,CreatePrimitiveExpr(aParent,pekIdent,CurTokenString),
  5193. eopSubIdent,SrcPos);
  5194. until false;
  5195. end;
  5196. procedure ParseImplements;
  5197. var
  5198. Identifier: String;
  5199. Expr: TPasExpr;
  5200. l: Integer;
  5201. begin
  5202. // comma list of identifiers
  5203. repeat
  5204. ExpectToken(tkIdentifier);
  5205. l:=length(Result.Implements);
  5206. Identifier:=ReadDottedIdentifier(Result,Expr,l=0);
  5207. if l=0 then
  5208. Result.ImplementsName := Identifier;
  5209. SetLength(Result.Implements,l+1);
  5210. Result.Implements[l]:=Expr;
  5211. until CurToken<>tkComma;
  5212. end;
  5213. var
  5214. isArray , ok, IsClass: Boolean;
  5215. ObjKind: TPasObjKind;
  5216. begin
  5217. Result:=TPasProperty(CreateElement(TPasProperty,AName,Parent,AVisibility));
  5218. if IsClassField then
  5219. Include(Result.VarModifiers,vmClass);
  5220. IsClass:=(Parent<>nil) and (Parent.ClassType=TPasClassType);
  5221. if IsClass then
  5222. ObjKind:=TPasClassType(Parent).ObjKind
  5223. else
  5224. ObjKind:=okClass;
  5225. ok:=false;
  5226. try
  5227. NextToken;
  5228. isArray:=CurToken=tkSquaredBraceOpen;
  5229. if isArray then
  5230. begin
  5231. ParseArgList(Result, Result.Args, tkSquaredBraceClose);
  5232. NextToken;
  5233. end;
  5234. if CurToken = tkColon then
  5235. begin
  5236. Result.VarType := ParseType(Result,CurSourcePos);
  5237. {$IFDEF CheckPasTreeRefCount}if Result.VarType.RefIds.IndexOf('CreateElement')>=0 then Result.VarType.ChangeRefId('CreateElement','TPasVariable.VarType'){$ENDIF};
  5238. NextToken;
  5239. end
  5240. else if not IsClass then
  5241. ParseExcTokenError(':');
  5242. if CurTokenIsIdentifier('INDEX') then
  5243. begin
  5244. NextToken;
  5245. Result.IndexExpr := DoParseExpression(Result);
  5246. end;
  5247. if CurTokenIsIdentifier('READ') then
  5248. begin
  5249. Result.ReadAccessorName := GetAccessorName(Result,Result.ReadAccessor);
  5250. NextToken;
  5251. end;
  5252. if CurTokenIsIdentifier('WRITE') then
  5253. begin
  5254. Result.WriteAccessorName := GetAccessorName(Result,Result.WriteAccessor);
  5255. NextToken;
  5256. end;
  5257. if IsClass and (ObjKind=okDispInterface) then
  5258. begin
  5259. if CurTokenIsIdentifier('READONLY') then
  5260. begin
  5261. Result.DispIDReadOnly:=True;
  5262. NextToken;
  5263. end;
  5264. if CurTokenIsIdentifier('DISPID') then
  5265. begin
  5266. NextToken;
  5267. Result.DispIDExpr := DoParseExpression(Result,Nil);
  5268. end;
  5269. end;
  5270. if IsClass and (ObjKind=okClass) and CurTokenIsIdentifier('IMPLEMENTS') then
  5271. ParseImplements;
  5272. if CurTokenIsIdentifier('STORED') then
  5273. begin
  5274. if not (ObjKind in [okClass]) then
  5275. ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['STORED',ObjKindNames[ObjKind]]);
  5276. NextToken;
  5277. if CurToken = tkTrue then
  5278. begin
  5279. Result.StoredAccessorName := 'True';
  5280. Result.StoredAccessor := CreateBoolConstExpr(Result,pekBoolConst,true);
  5281. end
  5282. else if CurToken = tkFalse then
  5283. begin
  5284. Result.StoredAccessorName := 'False';
  5285. Result.StoredAccessor := CreateBoolConstExpr(Result,pekBoolConst,false);
  5286. end
  5287. else if CurToken = tkIdentifier then
  5288. begin
  5289. UngetToken;
  5290. Result.StoredAccessorName := GetAccessorName(Result,Result.StoredAccessor);
  5291. end
  5292. else
  5293. ParseExcSyntaxError;
  5294. NextToken;
  5295. end;
  5296. if CurTokenIsIdentifier('DEFAULT') then
  5297. begin
  5298. if not (ObjKind in [okClass]) then
  5299. ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['DEFAULT',ObjKindNames[ObjKind]]);
  5300. if isArray then
  5301. ParseExc(nParserArrayPropertiesCannotHaveDefaultValue,SParserArrayPropertiesCannotHaveDefaultValue);
  5302. NextToken;
  5303. Result.DefaultExpr := DoParseExpression(Result);
  5304. // NextToken;
  5305. end
  5306. else if CurtokenIsIdentifier('NODEFAULT') then
  5307. begin
  5308. if not (ObjKind in [okClass]) then
  5309. ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['NODEFAULT',ObjKindNames[ObjKind]]);
  5310. Result.IsNodefault:=true;
  5311. if Result.DefaultExpr<>nil then
  5312. ParseExcSyntaxError;
  5313. NextToken;
  5314. end;
  5315. // Here the property ends. There can still be a 'default'
  5316. if CurToken = tkSemicolon then
  5317. begin
  5318. NextToken;
  5319. if CurTokenIsIdentifier('DEFAULT') then
  5320. begin
  5321. if (Result.VarType<>Nil) and (not isArray) then
  5322. ParseExc(nParserDefaultPropertyMustBeArray,SParserDefaultPropertyMustBeArray);
  5323. NextToken;
  5324. if CurToken = tkSemicolon then
  5325. begin
  5326. Result.IsDefault := True;
  5327. NextToken;
  5328. end
  5329. end;
  5330. // Handle hints
  5331. while DoCheckHint(Result) do
  5332. NextToken;
  5333. if Result.Hints=[] then
  5334. UngetToken;
  5335. end
  5336. else if CurToken=tkend then
  5337. // ok
  5338. else
  5339. CheckToken(tkSemicolon);
  5340. ok:=true;
  5341. finally
  5342. if not ok then
  5343. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  5344. end;
  5345. end;
  5346. // Starts after the "begin" token
  5347. procedure TPasParser.ParseProcBeginBlock(Parent: TProcedureBody);
  5348. var
  5349. BeginBlock: TPasImplBeginBlock;
  5350. SubBlock: TPasImplElement;
  5351. Proc: TPasProcedure;
  5352. begin
  5353. BeginBlock := TPasImplBeginBlock(CreateElement(TPasImplBeginBlock, '', Parent));
  5354. Parent.Body := BeginBlock;
  5355. repeat
  5356. NextToken;
  5357. // writeln('TPasParser.ParseProcBeginBlock ',curtokenstring);
  5358. if CurToken=tkend then
  5359. break
  5360. else if CurToken<>tkSemiColon then
  5361. begin
  5362. UngetToken;
  5363. ParseStatement(BeginBlock,SubBlock);
  5364. if SubBlock=nil then
  5365. ExpectToken(tkend);
  5366. end;
  5367. until false;
  5368. Proc:=Parent.Parent as TPasProcedure;
  5369. if Proc.GetProcTypeEnum in [ptAnonymousProcedure,ptAnonymousFunction] then
  5370. NextToken
  5371. else
  5372. ExpectToken(tkSemicolon);
  5373. // writeln('TPasParser.ParseProcBeginBlock ended ',curtokenstring);
  5374. end;
  5375. procedure TPasParser.ParseProcAsmBlock(Parent: TProcedureBody);
  5376. var
  5377. AsmBlock: TPasImplAsmStatement;
  5378. begin
  5379. AsmBlock:=TPasImplAsmStatement(CreateElement(TPasImplAsmStatement,'',Parent));
  5380. Parent.Body:=AsmBlock;
  5381. ParseAsmBlock(AsmBlock);
  5382. NextToken;
  5383. if not (Parent.Parent is TPasAnonymousProcedure) then
  5384. CheckToken(tkSemicolon);
  5385. end;
  5386. procedure TPasParser.ParseAsmBlock(AsmBlock: TPasImplAsmStatement);
  5387. Var
  5388. LastToken : TToken;
  5389. p: PTokenRec;
  5390. Function atEndOfAsm : Boolean;
  5391. begin
  5392. Result:=(CurToken=tkEnd) and not (LastToken in [tkAt,tkAtAt]);
  5393. end;
  5394. begin
  5395. if po_asmwhole in Options then
  5396. begin
  5397. FTokenRingCur:=0;
  5398. FTokenRingStart:=0;
  5399. FTokenRingEnd:=1;
  5400. p:=@FTokenRing[0];
  5401. p^.Comments.Clear;
  5402. repeat
  5403. Scanner.ReadNonPascalTillEndToken(true);
  5404. case Scanner.CurToken of
  5405. tkLineEnding,tkWhitespace:
  5406. AsmBlock.Tokens.Add(Scanner.CurTokenString);
  5407. tkend:
  5408. begin
  5409. p^.Token := tkend;
  5410. p^.AsString := Scanner.CurTokenString;
  5411. break;
  5412. end
  5413. else
  5414. begin
  5415. // missing end
  5416. p^.Token := tkEOF;
  5417. p^.AsString := '';
  5418. break;
  5419. end;
  5420. end;
  5421. until false;
  5422. FCurToken := p^.Token;
  5423. FCurTokenString := p^.AsString;
  5424. CheckToken(tkend);
  5425. end
  5426. else
  5427. begin
  5428. LastToken:=tkEOF;
  5429. NextToken;
  5430. While Not atEndOfAsm do
  5431. begin
  5432. AsmBlock.Tokens.Add(CurTokenText);
  5433. LastToken:=CurToken;
  5434. NextToken;
  5435. end;
  5436. end;
  5437. // Do not consume end. Current token will normally be end;
  5438. end;
  5439. // Next token is start of (compound) statement
  5440. // After parsing CurToken is on last token of statement
  5441. procedure TPasParser.ParseStatement(Parent: TPasImplBlock;
  5442. out NewImplElement: TPasImplElement);
  5443. var
  5444. CurBlock: TPasImplBlock;
  5445. {$IFDEF VerbosePasParser}
  5446. function i: string;
  5447. var
  5448. c: TPasElement;
  5449. begin
  5450. Result:='ParseImplCompoundStatement ';
  5451. c:=CurBlock;
  5452. while c<>nil do begin
  5453. Result:=Result+' ';
  5454. c:=c.Parent;
  5455. end;
  5456. end;
  5457. {$ENDIF}
  5458. function CloseBlock: boolean; // true if parent reached
  5459. var C: TPasImplBlockClass;
  5460. begin
  5461. C:=TPasImplBlockClass(CurBlock.ClassType);
  5462. if C=TPasImplExceptOn then
  5463. Engine.FinishScope(stExceptOnStatement,CurBlock)
  5464. else if C=TPasImplWithDo then
  5465. Engine.FinishScope(stWithExpr,CurBlock);
  5466. CurBlock:=CurBlock.Parent as TPasImplBlock;
  5467. Result:=CurBlock=Parent;
  5468. end;
  5469. function CloseStatement(CloseIfs: boolean): boolean; // true if parent reached
  5470. begin
  5471. if CurBlock=Parent then exit(true);
  5472. while CurBlock.CloseOnSemicolon
  5473. or (CloseIfs and (CurBlock is TPasImplIfElse)) do
  5474. if CloseBlock then exit(true);
  5475. Result:=false;
  5476. end;
  5477. procedure CreateBlock(NewBlock: TPasImplBlock);
  5478. begin
  5479. CurBlock.AddElement(NewBlock);
  5480. CurBlock:=NewBlock;
  5481. if NewImplElement=nil then NewImplElement:=CurBlock;
  5482. end;
  5483. procedure CheckSemicolon;
  5484. var
  5485. t: TToken;
  5486. begin
  5487. if (CurBlock.Elements.Count=0) then exit;
  5488. t:=GetPrevToken;
  5489. if t in [tkSemicolon,tkColon] then
  5490. exit;
  5491. if (CurBlock.ClassType=TPasImplIfElse) and (t=tkelse) then
  5492. exit;
  5493. {$IFDEF VerbosePasParser}
  5494. writeln('TPasParser.ParseStatement.CheckSemicolon Prev=',GetPrevToken,' Cur=',CurToken,' ',CurBlock.ClassName,' ',CurBlock.Elements.Count,' ',TObject(CurBlock.Elements[0]).ClassName);
  5495. {$ENDIF}
  5496. ParseExcTokenError('Semicolon');
  5497. end;
  5498. var
  5499. CmdElem: TPasImplElement;
  5500. procedure AddStatement(El: TPasImplElement);
  5501. begin
  5502. CurBlock.AddElement(El);
  5503. CmdElem:=El;
  5504. UngetToken;
  5505. end;
  5506. var
  5507. SubBlock: TPasImplElement;
  5508. Left, Right, Expr: TPasExpr;
  5509. El : TPasImplElement;
  5510. lt : TLoopType;
  5511. SrcPos: TPasSourcePos;
  5512. Name: String;
  5513. TypeEl: TPasType;
  5514. ImplRaise: TPasImplRaise;
  5515. VarEl: TPasVariable;
  5516. begin
  5517. NewImplElement:=nil;
  5518. El:=nil;
  5519. Left:=nil;
  5520. try
  5521. CurBlock := Parent;
  5522. while True do
  5523. begin
  5524. NextToken;
  5525. //WriteLn({$IFDEF VerbosePasParser}i,{$ENDIF}' Token=',CurTokenText);
  5526. case CurToken of
  5527. tkasm:
  5528. begin
  5529. CheckSemicolon;
  5530. El:=TPasImplElement(CreateElement(TPasImplAsmStatement,'',CurBlock,CurTokenPos));
  5531. ParseAsmBlock(TPasImplAsmStatement(El));
  5532. CurBlock.AddElement(El);
  5533. El:=nil;
  5534. if NewImplElement=nil then NewImplElement:=CurBlock;
  5535. if CloseStatement(False) then
  5536. break;
  5537. end;
  5538. tkbegin:
  5539. begin
  5540. CheckSemicolon;
  5541. El:=TPasImplElement(CreateElement(TPasImplBeginBlock,'',CurBlock,CurTokenPos));
  5542. CreateBlock(TPasImplBeginBlock(El));
  5543. El:=nil;
  5544. end;
  5545. tkrepeat:
  5546. begin
  5547. CheckSemicolon;
  5548. El:=TPasImplRepeatUntil(CreateElement(TPasImplRepeatUntil,'',CurBlock,CurTokenPos));
  5549. CreateBlock(TPasImplRepeatUntil(El));
  5550. El:=nil;
  5551. end;
  5552. tkIf:
  5553. begin
  5554. CheckSemicolon;
  5555. SrcPos:=CurTokenPos;
  5556. NextToken;
  5557. Left:=DoParseExpression(CurBlock);
  5558. UngetToken;
  5559. El:=TPasImplIfElse(CreateElement(TPasImplIfElse,'',CurBlock,SrcPos));
  5560. TPasImplIfElse(El).ConditionExpr:=Left;
  5561. Left.Parent:=El;
  5562. Left:=nil;
  5563. //WriteLn(i,'IF Condition="',Condition,'" Token=',CurTokenText);
  5564. CreateBlock(TPasImplIfElse(El));
  5565. El:=nil;
  5566. ExpectToken(tkthen);
  5567. end;
  5568. tkelse:
  5569. if (CurBlock is TPasImplIfElse) then
  5570. begin
  5571. if TPasImplIfElse(CurBlock).IfBranch=nil then
  5572. begin
  5573. // empty then statement e.g. if condition then else
  5574. El:=TPasImplCommand(CreateElement(TPasImplCommand,'', CurBlock,CurTokenPos));
  5575. CurBlock.AddElement(El);
  5576. El:=nil;
  5577. end;
  5578. if TPasImplIfElse(CurBlock).ElseBranch<>nil then
  5579. begin
  5580. // this and the following 3 may solve TPasImplIfElse.AddElement BUG
  5581. // ifs without begin end
  5582. // if .. then
  5583. // if .. then
  5584. // else
  5585. // else
  5586. CloseBlock;
  5587. CloseStatement(false);
  5588. end;
  5589. // Case ... else without semicolon in front.
  5590. end else if (CurBlock is TPasImplCaseStatement) then
  5591. begin
  5592. UngetToken;
  5593. CloseStatement(False);
  5594. break;
  5595. end else if (CurBlock is TPasImplWhileDo) then
  5596. begin
  5597. CloseBlock;
  5598. UngetToken;
  5599. end else if (CurBlock is TPasImplForLoop) then
  5600. begin
  5601. //if .. then for .. do smt else ..
  5602. CloseBlock;
  5603. UngetToken;
  5604. end else if (CurBlock is TPasImplWithDo) then
  5605. begin
  5606. //if .. then with .. do smt else ..
  5607. CloseBlock;
  5608. UngetToken;
  5609. end else if (CurBlock is TPasImplRaise) then
  5610. begin
  5611. //if .. then Raise Exception else ..
  5612. CloseBlock;
  5613. UngetToken;
  5614. end else if (CurBlock is TPasImplAsmStatement) then
  5615. begin
  5616. //if .. then asm end else ..
  5617. CloseBlock;
  5618. UngetToken;
  5619. end else if (CurBlock is TPasImplTryExcept) then
  5620. begin
  5621. CloseBlock;
  5622. El:=TPasImplTryExceptElse(CreateElement(TPasImplTryExceptElse,'',CurBlock,CurTokenPos));
  5623. TPasImplTry(CurBlock).ElseBranch:=TPasImplTryExceptElse(El);
  5624. CurBlock:=TPasImplTryExceptElse(El);
  5625. El:=nil;
  5626. end else
  5627. ParseExcSyntaxError;
  5628. tkwhile:
  5629. begin
  5630. // while Condition do
  5631. CheckSemicolon;
  5632. SrcPos:=CurTokenPos;
  5633. NextToken;
  5634. Left:=DoParseExpression(CurBlock);
  5635. UngetToken;
  5636. //WriteLn(i,'WHILE Condition="',Condition,'" Token=',CurTokenText);
  5637. El:=TPasImplWhileDo(CreateElement(TPasImplWhileDo,'',CurBlock,SrcPos));
  5638. TPasImplWhileDo(El).ConditionExpr:=Left;
  5639. Left.Parent:=El;
  5640. Left:=nil;
  5641. CreateBlock(TPasImplWhileDo(El));
  5642. El:=nil;
  5643. ExpectToken(tkdo);
  5644. end;
  5645. tkgoto:
  5646. begin
  5647. CheckSemicolon;
  5648. NextToken;
  5649. CurBlock.AddCommand('goto '+curtokenstring);
  5650. // expecttoken(tkSemiColon);
  5651. end;
  5652. tkfor:
  5653. begin
  5654. // for VarName := StartValue to EndValue do
  5655. // for VarName in Expression do
  5656. CheckSemicolon;
  5657. El:=TPasImplForLoop(CreateElement(TPasImplForLoop,'',CurBlock,CurTokenPos));
  5658. ExpectIdentifier;
  5659. Expr:=CreatePrimitiveExpr(El,pekIdent,CurTokenString);
  5660. TPasImplForLoop(El).VariableName:=Expr;
  5661. repeat
  5662. NextToken;
  5663. case CurToken of
  5664. tkAssign:
  5665. begin
  5666. lt:=ltNormal;
  5667. break;
  5668. end;
  5669. tkin:
  5670. begin
  5671. lt:=ltIn;
  5672. break;
  5673. end;
  5674. tkDot:
  5675. begin
  5676. SrcPos:=CurTokenPos;
  5677. ExpectIdentifier;
  5678. AddToBinaryExprChain(Expr,
  5679. CreatePrimitiveExpr(El,pekIdent,CurTokenString), eopSubIdent,SrcPos);
  5680. TPasImplForLoop(El).VariableName:=Expr;
  5681. end;
  5682. else
  5683. ParseExc(nParserExpectedAssignIn,SParserExpectedAssignIn);
  5684. end;
  5685. until false;
  5686. NextToken;
  5687. TPasImplForLoop(El).StartExpr:=DoParseExpression(El);
  5688. if (Lt=ltNormal) then
  5689. begin
  5690. if Not (CurToken in [tkTo,tkDownTo]) then
  5691. ParseExcTokenError(TokenInfos[tkTo]);
  5692. if CurToken=tkdownto then
  5693. Lt:=ltDown;
  5694. NextToken;
  5695. TPasImplForLoop(El).EndExpr:=DoParseExpression(El);
  5696. end;
  5697. TPasImplForLoop(El).LoopType:=lt;
  5698. if (CurToken<>tkDo) then
  5699. ParseExcTokenError(TokenInfos[tkDo]);
  5700. Engine.FinishScope(stForLoopHeader,El);
  5701. CreateBlock(TPasImplForLoop(El));
  5702. El:=nil;
  5703. //WriteLn(i,'FOR "',VarName,'" := ',StartValue,' to ',EndValue,' Token=',CurTokenText);
  5704. end;
  5705. tkwith:
  5706. begin
  5707. // with Expr do
  5708. // with Expr, Expr do
  5709. CheckSemicolon;
  5710. SrcPos:=CurTokenPos;
  5711. NextToken;
  5712. El:=TPasImplWithDo(CreateElement(TPasImplWithDo,'',CurBlock,SrcPos));
  5713. Expr:=DoParseExpression(CurBlock);
  5714. //writeln(i,'WITH Expr="',Expr,'" Token=',CurTokenText);
  5715. TPasImplWithDo(El).AddExpression(Expr);
  5716. Expr.Parent:=El;
  5717. Engine.BeginScope(stWithExpr,Expr);
  5718. CreateBlock(TPasImplWithDo(El));
  5719. El:=nil;
  5720. repeat
  5721. if CurToken=tkdo then break;
  5722. if CurToken<>tkComma then
  5723. ParseExcTokenError(TokenInfos[tkdo]);
  5724. NextToken;
  5725. Expr:=DoParseExpression(CurBlock);
  5726. //writeln(i,'WITH ...,Expr="',Expr,'" Token=',CurTokenText);
  5727. TPasImplWithDo(CurBlock).AddExpression(Expr);
  5728. Engine.BeginScope(stWithExpr,Expr);
  5729. until false;
  5730. end;
  5731. tkcase:
  5732. begin
  5733. CheckSemicolon;
  5734. SrcPos:=CurTokenPos;
  5735. NextToken;
  5736. Left:=DoParseExpression(CurBlock);
  5737. UngetToken;
  5738. //writeln(i,'CASE OF Expr="',Expr,'" Token=',CurTokenText);
  5739. ExpectToken(tkof);
  5740. El:=TPasImplCaseOf(CreateElement(TPasImplCaseOf,'',CurBlock,SrcPos));
  5741. TPasImplCaseOf(El).CaseExpr:=Left;
  5742. Left.Parent:=El;
  5743. Left:=nil;
  5744. CreateBlock(TPasImplCaseOf(El));
  5745. El:=nil;
  5746. repeat
  5747. NextToken;
  5748. //writeln(i,'CASE OF Token=',CurTokenText);
  5749. case CurToken of
  5750. tkend:
  5751. begin
  5752. if CurBlock.Elements.Count=0 then
  5753. ParseExc(nParserExpectCase,SParserExpectCase);
  5754. break; // end without else
  5755. end;
  5756. tkelse:
  5757. begin
  5758. // create case-else block
  5759. El:=TPasImplCaseElse(CreateElement(TPasImplCaseElse,'',CurBlock,CurTokenPos));
  5760. TPasImplCaseOf(CurBlock).ElseBranch:=TPasImplCaseElse(El);
  5761. CreateBlock(TPasImplCaseElse(El));
  5762. El:=nil;
  5763. break;
  5764. end
  5765. else
  5766. // read case values
  5767. if (curToken=tkIdentifier) and (LowerCase(CurtokenString)='otherwise') then
  5768. begin
  5769. // create case-else block
  5770. El:=TPasImplCaseElse(CreateElement(TPasImplCaseElse,'',CurBlock,CurTokenPos));
  5771. TPasImplCaseOf(CurBlock).ElseBranch:=TPasImplCaseElse(El);
  5772. CreateBlock(TPasImplCaseElse(El));
  5773. El:=nil;
  5774. break;
  5775. end
  5776. else
  5777. repeat
  5778. SrcPos:=CurTokenPos;
  5779. Left:=DoParseExpression(CurBlock);
  5780. //writeln(i,'CASE value="',Expr,'" Token=',CurTokenText);
  5781. if CurBlock is TPasImplCaseStatement then
  5782. begin
  5783. TPasImplCaseStatement(CurBlock).Expressions.Add(Left);
  5784. Left:=nil;
  5785. end
  5786. else
  5787. begin
  5788. El:=TPasImplCaseStatement(CreateElement(TPasImplCaseStatement,'',CurBlock,SrcPos));
  5789. TPasImplCaseStatement(El).AddExpression(Left);
  5790. Left:=nil;
  5791. CreateBlock(TPasImplCaseStatement(El));
  5792. El:=nil;
  5793. end;
  5794. //writeln(i,'CASE after value Token=',CurTokenText);
  5795. if (CurToken=tkComma) then
  5796. NextToken
  5797. else if (CurToken<>tkColon) then
  5798. ParseExcTokenError(TokenInfos[tkComma]);
  5799. until Curtoken=tkColon;
  5800. // read statement
  5801. ParseStatement(CurBlock,SubBlock);
  5802. CloseBlock;
  5803. if CurToken<>tkSemicolon then
  5804. begin
  5805. NextToken;
  5806. if not (CurToken in [tkSemicolon,tkelse,tkend]) then
  5807. ParseExcTokenError(TokenInfos[tkSemicolon]);
  5808. if CurToken<>tkSemicolon then
  5809. UngetToken;
  5810. end;
  5811. end;
  5812. until false;
  5813. if CurToken=tkend then
  5814. begin
  5815. if CloseBlock then break;
  5816. if CloseStatement(false) then break;
  5817. end;
  5818. end;
  5819. tktry:
  5820. begin
  5821. CheckSemicolon;
  5822. El:=TPasImplTry(CreateElement(TPasImplTry,'',CurBlock,CurTokenPos));
  5823. CreateBlock(TPasImplTry(El));
  5824. El:=nil;
  5825. end;
  5826. tkfinally:
  5827. begin
  5828. if CloseStatement(true) then
  5829. begin
  5830. UngetToken;
  5831. break;
  5832. end;
  5833. if CurBlock is TPasImplTry then
  5834. begin
  5835. El:=TPasImplTryFinally(CreateElement(TPasImplTryFinally,'',CurBlock,CurTokenPos));
  5836. TPasImplTry(CurBlock).FinallyExcept:=TPasImplTryFinally(El);
  5837. CurBlock:=TPasImplTryFinally(El);
  5838. El:=nil;
  5839. end else
  5840. ParseExcSyntaxError;
  5841. end;
  5842. tkexcept:
  5843. begin
  5844. if CloseStatement(true) then
  5845. begin
  5846. UngetToken;
  5847. break;
  5848. end;
  5849. if CurBlock is TPasImplTry then
  5850. begin
  5851. //writeln(i,'EXCEPT');
  5852. El:=TPasImplTryExcept(CreateElement(TPasImplTryExcept,'',CurBlock,CurTokenPos));
  5853. TPasImplTry(CurBlock).FinallyExcept:=TPasImplTryExcept(El);
  5854. CurBlock:=TPasImplTryExcept(El);
  5855. El:=nil;
  5856. end else
  5857. ParseExcSyntaxError;
  5858. end;
  5859. tkraise:
  5860. begin
  5861. CheckSemicolon;
  5862. ImplRaise:=TPasImplRaise(CreateElement(TPasImplRaise,'',CurBlock,CurTokenPos));
  5863. CreateBlock(ImplRaise);
  5864. NextToken;
  5865. If Curtoken in [tkElse,tkEnd,tkSemicolon] then
  5866. UnGetToken
  5867. else
  5868. begin
  5869. ImplRaise.ExceptObject:=DoParseExpression(ImplRaise);
  5870. if (CurToken=tkIdentifier) and (Uppercase(CurtokenString)='AT') then
  5871. begin
  5872. NextToken;
  5873. ImplRaise.ExceptAddr:=DoParseExpression(ImplRaise);
  5874. end;
  5875. if Curtoken in [tkElse,tkEnd,tkSemicolon] then
  5876. UngetToken
  5877. end;
  5878. end;
  5879. tkend:
  5880. begin
  5881. if CloseStatement(true) then
  5882. begin
  5883. UngetToken;
  5884. break;
  5885. end;
  5886. if CurBlock is TPasImplBeginBlock then
  5887. begin
  5888. if CloseBlock then break; // close end
  5889. if CloseStatement(false) then break;
  5890. end else if CurBlock is TPasImplCaseElse then
  5891. begin
  5892. if CloseBlock then break; // close else
  5893. if CloseBlock then break; // close caseof
  5894. if CloseStatement(false) then break;
  5895. end else if CurBlock is TPasImplTryHandler then
  5896. begin
  5897. if CloseBlock then break; // close finally/except
  5898. if CloseBlock then break; // close try
  5899. if CloseStatement(false) then break;
  5900. end else
  5901. ParseExcSyntaxError;
  5902. end;
  5903. tkSemiColon:
  5904. if CloseStatement(true) then break;
  5905. tkFinalization:
  5906. if CloseStatement(true) then
  5907. begin
  5908. UngetToken;
  5909. break;
  5910. end;
  5911. tkuntil:
  5912. begin
  5913. if CloseStatement(true) then
  5914. begin
  5915. UngetToken;
  5916. break;
  5917. end;
  5918. if CurBlock is TPasImplRepeatUntil then
  5919. begin
  5920. NextToken;
  5921. Left:=DoParseExpression(CurBlock);
  5922. UngetToken;
  5923. TPasImplRepeatUntil(CurBlock).ConditionExpr:=Left;
  5924. Left:=nil;
  5925. //WriteLn(i,'UNTIL Condition="',Condition,'" Token=',CurTokenString);
  5926. if CloseBlock then break;
  5927. end else
  5928. ParseExcSyntaxError;
  5929. end;
  5930. tkEOF:
  5931. CheckToken(tkend);
  5932. tkAt,tkAtAt,
  5933. tkIdentifier,tkspecialize,
  5934. tkNumber,tkString,tkfalse,tktrue,tkChar,
  5935. tkBraceOpen,tkSquaredBraceOpen,
  5936. tkMinus,tkPlus,tkinherited:
  5937. begin
  5938. // Do not check this here:
  5939. // if (CurToken=tkAt) and not (msDelphi in CurrentModeswitches) then
  5940. // ParseExc;
  5941. CheckSemicolon;
  5942. // On is usable as an identifier
  5943. if lowerCase(CurTokenText)='on' then
  5944. begin
  5945. // in try except:
  5946. // on E: Exception do
  5947. // on Exception do
  5948. if CurBlock is TPasImplTryExcept then
  5949. begin
  5950. SrcPos:=CurTokenPos;
  5951. ExpectIdentifier;
  5952. El:=TPasImplExceptOn(CreateElement(TPasImplExceptOn,'',CurBlock,SrcPos));
  5953. SrcPos:=CurSourcePos;
  5954. Name:=CurTokenString;
  5955. NextToken;
  5956. //writeln('ON t=',Name,' Token=',CurTokenText);
  5957. if CurToken=tkColon then
  5958. begin
  5959. // the first expression was the variable name
  5960. NextToken;
  5961. TypeEl:=ParseSimpleType(El,SrcPos,'');
  5962. TPasImplExceptOn(El).TypeEl:=TypeEl;
  5963. VarEl:=TPasVariable(CreateElement(TPasVariable,Name,El,SrcPos));
  5964. TPasImplExceptOn(El).VarEl:=VarEl;
  5965. VarEl.VarType:=TypeEl;
  5966. TypeEl.AddRef{$IFDEF CheckPasTreeRefCount}('TPasVariable.VarType'){$ENDIF};
  5967. if TypeEl.Parent=El then
  5968. TypeEl.Parent:=VarEl;
  5969. end
  5970. else
  5971. begin
  5972. UngetToken;
  5973. TPasImplExceptOn(El).TypeEl:=ParseSimpleType(El,SrcPos,'');
  5974. end;
  5975. Engine.FinishScope(stExceptOnExpr,El);
  5976. CreateBlock(TPasImplExceptOn(El));
  5977. El:=nil;
  5978. ExpectToken(tkDo);
  5979. end else
  5980. ParseExcSyntaxError;
  5981. end
  5982. else
  5983. begin
  5984. SrcPos:=CurTokenPos;
  5985. Left:=DoParseExpression(CurBlock);
  5986. case CurToken of
  5987. tkAssign,
  5988. tkAssignPlus,
  5989. tkAssignMinus,
  5990. tkAssignMul,
  5991. tkAssignDivision:
  5992. begin
  5993. // assign statement
  5994. El:=TPasImplAssign(CreateElement(TPasImplAssign,'',CurBlock,SrcPos));
  5995. TPasImplAssign(El).left:=Left;
  5996. Left.Parent:=El;
  5997. Left:=nil;
  5998. TPasImplAssign(El).Kind:=TokenToAssignKind(CurToken);
  5999. NextToken;
  6000. Right:=DoParseExpression(CurBlock);
  6001. TPasImplAssign(El).right:=Right;
  6002. Right.Parent:=El;
  6003. Right:=nil;
  6004. AddStatement(El);
  6005. El:=nil;
  6006. end;
  6007. tkColon:
  6008. begin
  6009. if not (bsGoto in Scanner.CurrentBoolSwitches) then
  6010. ParseExcTokenError(TokenInfos[tkSemicolon])
  6011. else if not (Left is TPrimitiveExpr) then
  6012. ParseExcTokenError(TokenInfos[tkSemicolon]);
  6013. // label mark. todo: check mark identifier in the list of labels
  6014. El:=TPasImplLabelMark(CreateElement(TPasImplLabelMark,'', CurBlock,SrcPos));
  6015. TPasImplLabelMark(El).LabelId:=TPrimitiveExpr(Left).Value;
  6016. ReleaseAndNil(TPasElement(Left){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
  6017. CurBlock.AddElement(El);
  6018. CmdElem:=TPasImplLabelMark(El);
  6019. El:=nil;
  6020. end;
  6021. else
  6022. // simple statement (function call)
  6023. El:=TPasImplSimple(CreateElement(TPasImplSimple,'',CurBlock,SrcPos));
  6024. TPasImplSimple(El).Expr:=Left;
  6025. Left.Parent:=El;
  6026. Left:=nil;
  6027. AddStatement(El);
  6028. El:=nil;
  6029. end;
  6030. if not (CmdElem is TPasImplLabelMark) then
  6031. if NewImplElement=nil then NewImplElement:=CmdElem;
  6032. end;
  6033. end;
  6034. else
  6035. ParseExcSyntaxError;
  6036. end;
  6037. end;
  6038. finally
  6039. if El<>nil then El.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  6040. if Left<>nil then Left.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  6041. end;
  6042. end;
  6043. procedure TPasParser.ParseLabels(AParent: TPasElement);
  6044. var
  6045. Labels: TPasLabels;
  6046. begin
  6047. Labels:=TPasLabels(CreateElement(TPasLabels, '', AParent));
  6048. repeat
  6049. Labels.Labels.Add(ExpectIdentifier);
  6050. NextToken;
  6051. if not (CurToken in [tkSemicolon, tkComma]) then
  6052. ParseExcTokenError(TokenInfos[tkSemicolon]);
  6053. until CurToken=tkSemicolon;
  6054. end;
  6055. // Starts after the "procedure" or "function" token
  6056. function TPasParser.GetProcedureClass(ProcType: TProcType): TPTreeElement;
  6057. begin
  6058. Case ProcType of
  6059. ptFunction : Result:=TPasFunction;
  6060. ptClassFunction : Result:=TPasClassFunction;
  6061. ptClassProcedure : Result:=TPasClassProcedure;
  6062. ptClassConstructor : Result:=TPasClassConstructor;
  6063. ptClassDestructor : Result:=TPasClassDestructor;
  6064. ptProcedure : Result:=TPasProcedure;
  6065. ptConstructor : Result:=TPasConstructor;
  6066. ptDestructor : Result:=TPasDestructor;
  6067. ptOperator : Result:=TPasOperator;
  6068. ptClassOperator : Result:=TPasClassOperator;
  6069. ptAnonymousProcedure: Result:=TPasAnonymousProcedure;
  6070. ptAnonymousFunction: Result:=TPasAnonymousFunction;
  6071. else
  6072. ParseExc(nParserUnknownProcedureType,SParserUnknownProcedureType,[Ord(ProcType)]);
  6073. end;
  6074. end;
  6075. function TPasParser.ParseProcedureOrFunctionDecl(Parent: TPasElement;
  6076. ProcType: TProcType; MustBeGeneric: boolean; AVisibility: TPasMemberVisibility
  6077. ): TPasProcedure;
  6078. var
  6079. NameParts: TProcedureNameParts;
  6080. NamePos: TPasSourcePos;
  6081. function ExpectProcName: string;
  6082. { Simple procedure:
  6083. Name
  6084. Method implementation of non generic class:
  6085. aClass.SubClass.Name
  6086. ObjFPC generic procedure or method declaration:
  6087. MustBeGeneric=true, Name<Templates>
  6088. Delphi generic Method Declaration:
  6089. MustBeGeneric=false, Name<Templates>
  6090. ObjFPC Method implementation of generic class:
  6091. aClass.SubClass.Name
  6092. Delphi Method implementation of generic class:
  6093. aClass<Templates>.SubClass<Templates>.Name
  6094. aClass.SubClass<Templates>.Name<Templates>
  6095. }
  6096. Var
  6097. L : TFPList;
  6098. I , Cnt, p: Integer;
  6099. CurName: String;
  6100. Part: TProcedureNamePart;
  6101. begin
  6102. Result:=ExpectIdentifier;
  6103. NamePos:=CurSourcePos;
  6104. Cnt:=1;
  6105. repeat
  6106. NextToken;
  6107. if CurToken=tkDot then
  6108. begin
  6109. if Parent is TImplementationSection then
  6110. begin
  6111. inc(Cnt);
  6112. CurName:=ExpectIdentifier;
  6113. NamePos:=CurSourcePos;
  6114. Result:=Result+'.'+CurName;
  6115. if NameParts<>nil then
  6116. begin
  6117. Part:=TProcedureNamePart.Create;
  6118. NameParts.Add(Part);
  6119. Part.Name:=CurName;
  6120. end;
  6121. end
  6122. else
  6123. ParseExcSyntaxError;
  6124. end
  6125. else if CurToken=tkLessThan then
  6126. begin
  6127. if (not MustBeGeneric) and not (msDelphi in CurrentModeswitches) then
  6128. ParseExc(nParserGenericFunctionNeedsGenericKeyword,SParserGenericFunctionNeedsGenericKeyword);
  6129. // generic templates
  6130. if NameParts=nil then
  6131. begin
  6132. // initialize NameParts
  6133. NameParts:=TProcedureNameParts.Create;
  6134. i:=0;
  6135. CurName:=Result;
  6136. repeat
  6137. Part:=TProcedureNamePart.Create;
  6138. NameParts.Add(Part);
  6139. p:=Pos('.',CurName);
  6140. if p>0 then
  6141. begin
  6142. Part.Name:=LeftStr(CurName,p-1);
  6143. System.Delete(CurName,1,p);
  6144. end
  6145. else
  6146. begin
  6147. Part.Name:=CurName;
  6148. break;
  6149. end;
  6150. inc(i);
  6151. until false;
  6152. end
  6153. else if TProcedureNamePart(NameParts[Cnt-1]).Templates<>nil then
  6154. ParseExcSyntaxError;
  6155. UnGetToken;
  6156. L:=TFPList.Create;
  6157. TProcedureNamePart(NameParts[Cnt-1]).Templates:=L;
  6158. ReadGenericArguments(L,Parent);
  6159. end
  6160. else
  6161. break;
  6162. until false;
  6163. if (NameParts=nil) and MustBeGeneric then
  6164. CheckToken(tkLessThan);
  6165. UngetToken;
  6166. end;
  6167. var
  6168. N,Name: String;
  6169. PC : TPTreeElement;
  6170. Ot : TOperatorType;
  6171. IsTokenBased , ok: Boolean;
  6172. j, i: Integer;
  6173. begin
  6174. N:='';
  6175. NameParts:=nil;
  6176. Result:=nil;
  6177. ok:=false;
  6178. try
  6179. case ProcType of
  6180. ptOperator,ptClassOperator:
  6181. begin
  6182. if MustBeGeneric then
  6183. ParseExcTokenError('procedure');
  6184. NextToken;
  6185. IsTokenBased:=CurToken<>tkIdentifier;
  6186. if IsTokenBased then
  6187. OT:=TPasOperator.TokenToOperatorType(CurTokenText)
  6188. else
  6189. begin
  6190. OT:=TPasOperator.NameToOperatorType(CurTokenString);
  6191. N:=CurTokenString;
  6192. // Case Class operator TMyRecord.+
  6193. if (OT=otUnknown) then
  6194. begin
  6195. NextToken;
  6196. if CurToken<>tkDot then
  6197. ParseExc(nErrUnknownOperatorType,SErrUnknownOperatorType,[N]);
  6198. NextToken;
  6199. IsTokenBased:=CurToken<>tkIdentifier;
  6200. if IsTokenBased then
  6201. OT:=TPasOperator.TokenToOperatorType(CurTokenText)
  6202. else
  6203. OT:=TPasOperator.NameToOperatorType(CurTokenString);
  6204. end;
  6205. end;
  6206. if (ot=otUnknown) then
  6207. ParseExc(nErrUnknownOperatorType,SErrUnknownOperatorType,[CurTokenString]);
  6208. Name:=OperatorNames[Ot];
  6209. if N<>'' then
  6210. Name:=N+'.'+Name;
  6211. NamePos:=CurTokenPos;
  6212. end;
  6213. ptAnonymousProcedure,ptAnonymousFunction:
  6214. begin
  6215. Name:='';
  6216. if MustBeGeneric then
  6217. ParseExcTokenError('generic'); // inconsistency
  6218. NamePos:=CurTokenPos;
  6219. end
  6220. else
  6221. Name:=ExpectProcName;
  6222. end;
  6223. PC:=GetProcedureClass(ProcType);
  6224. if Name<>'' then
  6225. Parent:=CheckIfOverLoaded(Parent,Name);
  6226. Result := TPasProcedure(Engine.CreateElement(PC, Name, Parent, AVisibility,
  6227. NamePos, NameParts));
  6228. if NameParts<>nil then
  6229. begin
  6230. if Result.NameParts=nil then
  6231. // CreateElement has not used the NameParts -> do it now
  6232. Result.SetNameParts(NameParts);
  6233. // sanity check
  6234. for i:=0 to Result.NameParts.Count-1 do
  6235. with TProcedureNamePart(Result.NameParts[i]) do
  6236. if Templates<>nil then
  6237. for j:=0 to Templates.Count-1 do
  6238. if TPasElement(Templates[j]).Parent<>Result then
  6239. ParseExc(nParserError,SParserError+'[20190818131750] '+TPasElement(Templates[j]).Parent.Name+':'+TPasElement(Templates[j]).Parent.ClassName);
  6240. if NameParts.Count>0 then
  6241. ParseExc(nParserError,SParserError+'[20190818131909] "'+Name+'"');
  6242. end;
  6243. case ProcType of
  6244. ptFunction, ptClassFunction, ptOperator, ptClassOperator, ptAnonymousFunction:
  6245. begin
  6246. Result.ProcType := CreateFunctionType('', 'Result', Result, False, CurTokenPos);
  6247. if (ProcType in [ptOperator, ptClassOperator]) then
  6248. begin
  6249. TPasOperator(Result).TokenBased:=IsTokenBased;
  6250. TPasOperator(Result).OperatorType:=OT;
  6251. TPasOperator(Result).CorrectName;
  6252. end;
  6253. end;
  6254. else
  6255. Result.ProcType := TPasProcedureType(CreateElement(TPasProcedureType, '', Result));
  6256. end;
  6257. ParseProcedureOrFunction(Result, Result.ProcType, ProcType, False);
  6258. Result.Hints:=Result.ProcType.Hints;
  6259. Result.HintMessage:=Result.ProcType.HintMessage;
  6260. // + is detected as 'positive', but is in fact Add if there are 2 arguments.
  6261. if (ProcType in [ptOperator, ptClassOperator]) then
  6262. With TPasOperator(Result) do
  6263. begin
  6264. if (OperatorType in [otPositive, otNegative]) then
  6265. begin
  6266. if (ProcType.Args.Count>1) then
  6267. begin
  6268. Case OperatorType of
  6269. otPositive : OperatorType:=otPlus;
  6270. otNegative : OperatorType:=otMinus;
  6271. end;
  6272. Name:=OperatorNames[OperatorType];
  6273. TPasOperator(Result).CorrectName;
  6274. end;
  6275. end;
  6276. end;
  6277. ok:=true;
  6278. finally
  6279. if NameParts<>nil then
  6280. ReleaseProcNameParts(NameParts);
  6281. if (not ok) and (Result<>nil) then
  6282. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  6283. end;
  6284. end;
  6285. // Current token is the first token after tkOf
  6286. procedure TPasParser.ParseRecordVariantParts(ARec: TPasRecordType;
  6287. AEndToken: TToken);
  6288. Var
  6289. M : TPasRecordType;
  6290. V : TPasVariant;
  6291. Done : Boolean;
  6292. begin
  6293. Repeat
  6294. V:=TPasVariant(CreateElement(TPasVariant, '', ARec));
  6295. ARec.Variants.Add(V);
  6296. Repeat
  6297. NextToken;
  6298. V.Values.Add(DoParseExpression(ARec));
  6299. if Not (CurToken in [tkComma,tkColon]) then
  6300. ParseExc(nParserExpectedCommaColon,SParserExpectedCommaColon);
  6301. Until (curToken=tkColon);
  6302. ExpectToken(tkBraceOpen);
  6303. NextToken;
  6304. M:=TPasRecordType(CreateElement(TPasRecordType,'',V));
  6305. V.Members:=M;
  6306. ParseRecordMembers(M,tkBraceClose,False);
  6307. // Current token is closing ), so we eat that
  6308. NextToken;
  6309. // If there is a semicolon, we eat that too.
  6310. if CurToken=tkSemicolon then
  6311. NextToken;
  6312. // ParseExpression starts with a nexttoken.
  6313. // So we need to determine the next token, and if it is an ending token, unget.
  6314. Done:=CurToken=AEndToken;
  6315. If not Done then
  6316. Ungettoken;
  6317. Until Done;
  6318. end;
  6319. {$ifdef VerbosePasParser}
  6320. procedure TPasParser.DumpCurToken(const Msg: String; IndentAction: TIndentAction
  6321. );
  6322. begin
  6323. {AllowWriteln}
  6324. if IndentAction=iaUndent then
  6325. FDumpIndent:=copy(FDumpIndent,1,Length(FDumpIndent)-2);
  6326. Writeln(FDumpIndent,Msg,' : ',TokenInfos[CurToken],' "',CurTokenString,'", Position: ',Scanner.CurFilename,'(',Scanner.CurRow,',',SCanner.CurColumn,') : ',Scanner.CurLine);
  6327. if IndentAction=iaIndent then
  6328. FDumpIndent:=FDumpIndent+' ';
  6329. {$ifdef pas2js}
  6330. // ToDo
  6331. {$else}
  6332. Flush(output);
  6333. {$endif}
  6334. {AllowWriteln-}
  6335. end;
  6336. {$endif}
  6337. function TPasParser.GetCurrentModeSwitches: TModeSwitches;
  6338. begin
  6339. if Assigned(FScanner) then
  6340. Result:=FScanner.CurrentModeSwitches
  6341. else
  6342. Result:=[msNone];
  6343. end;
  6344. procedure TPasParser.SetCurrentModeSwitches(AValue: TModeSwitches);
  6345. begin
  6346. if Assigned(FScanner) then
  6347. FScanner.CurrentModeSwitches:=AValue;
  6348. end;
  6349. // Starts on first token after Record or (. Ends on AEndToken
  6350. procedure TPasParser.ParseRecordMembers(ARec: TPasRecordType;
  6351. AEndToken: TToken; AllowMethods: Boolean);
  6352. var
  6353. isClass : Boolean;
  6354. procedure EnableIsClass;
  6355. begin
  6356. isClass:=True;
  6357. Scanner.SetTokenOption(toOperatorToken);
  6358. end;
  6359. procedure DisableIsClass;
  6360. begin
  6361. if not isClass then exit;
  6362. isClass:=false;
  6363. Scanner.UnSetTokenOption(toOperatorToken);
  6364. end;
  6365. Var
  6366. VariantName : String;
  6367. v : TPasMemberVisibility;
  6368. Proc: TPasProcedure;
  6369. ProcType: TProcType;
  6370. Prop : TPasProperty;
  6371. NamePos: TPasSourcePos;
  6372. OldCount, i: Integer;
  6373. CurEl: TPasElement;
  6374. LastToken: TToken;
  6375. AllowVisibility: Boolean;
  6376. begin
  6377. AllowVisibility:=msAdvancedRecords in CurrentModeswitches;
  6378. if AllowVisibility then
  6379. v:=visPublic
  6380. else
  6381. v:=visDefault;
  6382. isClass:=False;
  6383. LastToken:=tkrecord;
  6384. while CurToken<>AEndToken do
  6385. begin
  6386. SaveComments;
  6387. Case CurToken of
  6388. tkType:
  6389. begin
  6390. DisableIsClass;
  6391. if Not AllowMethods then
  6392. ParseExc(nErrRecordTypesNotAllowed,SErrRecordTypesNotAllowed);
  6393. ExpectToken(tkIdentifier);
  6394. ParseMembersLocalTypes(ARec,v);
  6395. end;
  6396. tkConst:
  6397. begin
  6398. DisableIsClass;
  6399. if Not AllowMethods then
  6400. ParseExc(nErrRecordConstantsNotAllowed,SErrRecordConstantsNotAllowed);
  6401. ExpectToken(tkIdentifier);
  6402. ParseMembersLocalConsts(ARec,v);
  6403. end;
  6404. tkVar:
  6405. begin
  6406. if Not AllowMethods then
  6407. ParseExc(nErrRecordVariablesNotAllowed,SErrRecordVariablesNotAllowed);
  6408. ExpectToken(tkIdentifier);
  6409. OldCount:=ARec.Members.Count;
  6410. ParseInlineVarDecl(ARec, ARec.Members, v, AEndToken=tkBraceClose);
  6411. for i:=OldCount to ARec.Members.Count-1 do
  6412. begin
  6413. CurEl:=TPasElement(ARec.Members[i]);
  6414. if CurEl.ClassType=TPasAttributes then continue;
  6415. if isClass then
  6416. With TPasVariable(CurEl) do
  6417. VarModifiers:=VarModifiers + [vmClass];
  6418. Engine.FinishScope(stDeclaration,TPasVariable(CurEl));
  6419. end;
  6420. end;
  6421. tkClass:
  6422. begin
  6423. if LastToken=tkclass then
  6424. ParseExc(nParserTypeSyntaxError,SParserTypeSyntaxError);
  6425. if Not AllowMethods then
  6426. begin
  6427. NextToken;
  6428. case CurToken of
  6429. tkConst: ParseExc(nErrRecordConstantsNotAllowed,SErrRecordConstantsNotAllowed);
  6430. tkvar: ParseExc(nErrRecordVariablesNotAllowed,SErrRecordVariablesNotAllowed);
  6431. else
  6432. ParseExc(nErrRecordMethodsNotAllowed,SErrRecordMethodsNotAllowed);
  6433. end;
  6434. end;
  6435. EnableIsClass;
  6436. end;
  6437. tkProperty:
  6438. begin
  6439. DisableIsClass;
  6440. if Not AllowMethods then
  6441. ParseExc(nErrRecordPropertiesNotAllowed,SErrRecordPropertiesNotAllowed);
  6442. ExpectToken(tkIdentifier);
  6443. Prop:=ParseProperty(ARec,CurtokenString,v,LastToken=tkclass);
  6444. ARec.Members.Add(Prop);
  6445. Engine.FinishScope(stDeclaration,Prop);
  6446. end;
  6447. tkOperator,
  6448. tkProcedure,
  6449. tkConstructor,
  6450. tkFunction :
  6451. begin
  6452. DisableIsClass;
  6453. if Not AllowMethods then
  6454. ParseExc(nErrRecordMethodsNotAllowed,SErrRecordMethodsNotAllowed);
  6455. ProcType:=GetProcTypeFromToken(CurToken,LastToken=tkclass);
  6456. Proc:=ParseProcedureOrFunctionDecl(ARec,ProcType,false,v);
  6457. if Proc.Parent is TPasOverloadedProc then
  6458. TPasOverloadedProc(Proc.Parent).Overloads.Add(Proc)
  6459. else
  6460. ARec.Members.Add(Proc);
  6461. Engine.FinishScope(stProcedure,Proc);
  6462. end;
  6463. tkDestructor:
  6464. ParseExc(nParserNoConstructorAllowed,SParserNoConstructorAllowed);
  6465. tkGeneric,tkSelf, // Counts as field name
  6466. tkIdentifier :
  6467. begin
  6468. If AllowVisibility and CheckVisibility(CurTokenString,v) then
  6469. begin
  6470. if not (v in [visPrivate,visPublic,visStrictPrivate]) then
  6471. ParseExc(nParserInvalidRecordVisibility,SParserInvalidRecordVisibility);
  6472. NextToken;
  6473. Continue;
  6474. end;
  6475. OldCount:=ARec.Members.Count;
  6476. ParseInlineVarDecl(ARec, ARec.Members, v, AEndToken=tkBraceClose);
  6477. for i:=OldCount to ARec.Members.Count-1 do
  6478. begin
  6479. CurEl:=TPasElement(ARec.Members[i]);
  6480. if CurEl.ClassType=TPasAttributes then continue;
  6481. if isClass then
  6482. With TPasVariable(CurEl) do
  6483. VarModifiers:=VarModifiers + [vmClass];
  6484. Engine.FinishScope(stDeclaration,TPasVariable(CurEl));
  6485. end;
  6486. end;
  6487. tkSquaredBraceOpen:
  6488. if msPrefixedAttributes in CurrentModeswitches then
  6489. ParseAttributes(ARec,true)
  6490. else
  6491. CheckToken(tkIdentifier);
  6492. tkCase :
  6493. begin
  6494. DisableIsClass;
  6495. ARec.Variants:=TFPList.Create;
  6496. NextToken;
  6497. VariantName:=CurTokenString;
  6498. NamePos:=CurSourcePos;
  6499. NextToken;
  6500. If CurToken=tkColon then
  6501. begin
  6502. ARec.VariantEl:=TPasVariable(CreateElement(TPasVariable,VariantName,ARec,NamePos));
  6503. TPasVariable(ARec.VariantEl).VarType:=ParseType(ARec,CurSourcePos);
  6504. end
  6505. else
  6506. begin
  6507. UnGetToken;
  6508. UnGetToken;
  6509. ARec.VariantEl:=ParseType(ARec,CurSourcePos);
  6510. end;
  6511. ExpectToken(tkOf);
  6512. ParseRecordVariantParts(ARec,AEndToken);
  6513. end;
  6514. else
  6515. ParseExc(nParserTypeSyntaxError,SParserTypeSyntaxError);
  6516. end;
  6517. if CurToken=AEndToken then
  6518. break;
  6519. LastToken:=CurToken;
  6520. NextToken;
  6521. end;
  6522. end;
  6523. // Starts after the "record" token
  6524. function TPasParser.ParseRecordDecl(Parent: TPasElement;
  6525. const NamePos: TPasSourcePos; const TypeName: string;
  6526. const Packmode: TPackMode): TPasRecordType;
  6527. var
  6528. ok: Boolean;
  6529. allowadvanced : Boolean;
  6530. begin
  6531. Result := TPasRecordType(CreateElement(TPasRecordType, TypeName, Parent, NamePos));
  6532. ok:=false;
  6533. try
  6534. Result.PackMode:=PackMode;
  6535. NextToken;
  6536. allowAdvanced:=(msAdvancedRecords in Scanner.CurrentModeSwitches)
  6537. and not (Parent is TProcedureBody)
  6538. and (Result.Name<>'');
  6539. ParseRecordMembers(Result,tkEnd,allowAdvanced);
  6540. Engine.FinishScope(stTypeDef,Result);
  6541. ok:=true;
  6542. finally
  6543. if not ok then
  6544. begin
  6545. Result.Parent:=nil; // clear references from members to Result
  6546. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  6547. end;
  6548. end;
  6549. end;
  6550. Function IsVisibility(S : String; var AVisibility :TPasMemberVisibility) : Boolean;
  6551. Const
  6552. VNames : array[TPasMemberVisibility] of string =
  6553. ('', 'private', 'protected', 'public', 'published', 'automated', '', '');
  6554. Var
  6555. V : TPasMemberVisibility;
  6556. begin
  6557. Result:=False;
  6558. S:=lowerCase(S);
  6559. For V :=Low(TPasMemberVisibility) to High(TPasMemberVisibility) do
  6560. begin
  6561. Result:=(VNames[V]<>'') and (S=VNames[V]);
  6562. if Result then
  6563. begin
  6564. AVisibility := v;
  6565. Exit;
  6566. end;
  6567. end;
  6568. end;
  6569. function TPasParser.CheckVisibility(S: String;
  6570. var AVisibility: TPasMemberVisibility): Boolean;
  6571. Var
  6572. B : Boolean;
  6573. begin
  6574. s := LowerCase(CurTokenString);
  6575. B:=(S='strict');
  6576. if B then
  6577. begin
  6578. NextToken;
  6579. s:=LowerCase(CurTokenString);
  6580. end;
  6581. Result:=isVisibility(S,AVisibility);
  6582. if Result then
  6583. begin
  6584. if (AVisibility=visPublished) and (msOmitRTTI in Scanner.CurrentModeSwitches) then
  6585. AVisibility:=visPublic;
  6586. if B then
  6587. case AVisibility of
  6588. visPrivate : AVisibility:=visStrictPrivate;
  6589. visProtected : AVisibility:=visStrictProtected;
  6590. else
  6591. ParseExc(nParserStrangeVisibility,SParserStrangeVisibility,[S]);
  6592. end
  6593. end
  6594. else if B then
  6595. ParseExc(nParserExpectVisibility,SParserExpectVisibility);
  6596. end;
  6597. procedure TPasParser.ProcessMethod(AType: TPasClassType; IsClass: Boolean;
  6598. AVisibility: TPasMemberVisibility; MustBeGeneric: boolean);
  6599. var
  6600. Proc: TPasProcedure;
  6601. ProcType: TProcType;
  6602. begin
  6603. ProcType:=GetProcTypeFromToken(CurToken,isClass);
  6604. Proc:=ParseProcedureOrFunctionDecl(AType,ProcType,MustBeGeneric,AVisibility);
  6605. if Proc.Parent is TPasOverloadedProc then
  6606. TPasOverloadedProc(Proc.Parent).Overloads.Add(Proc)
  6607. else
  6608. AType.Members.Add(Proc);
  6609. Engine.FinishScope(stProcedure,Proc);
  6610. end;
  6611. procedure TPasParser.ParseClassFields(AType: TPasClassType;
  6612. const AVisibility: TPasMemberVisibility; IsClassField: Boolean);
  6613. Var
  6614. VarList: TFPList;
  6615. Element: TPasElement;
  6616. I : Integer;
  6617. isStatic : Boolean;
  6618. VarEl: TPasVariable;
  6619. begin
  6620. VarList := TFPList.Create;
  6621. try
  6622. ParseInlineVarDecl(AType, VarList, AVisibility, False);
  6623. if CurToken=tkSemicolon then
  6624. begin
  6625. NextToken;
  6626. isStatic:=CurTokenIsIdentifier('static');
  6627. if isStatic then
  6628. ExpectToken(tkSemicolon)
  6629. else
  6630. UngetToken;
  6631. end;
  6632. for i := 0 to VarList.Count - 1 do
  6633. begin
  6634. Element := TPasElement(VarList[i]);
  6635. Element.Visibility := AVisibility;
  6636. AType.Members.Add(Element);
  6637. if (Element is TPasVariable) then
  6638. begin
  6639. VarEl:=TPasVariable(Element);
  6640. if IsClassField then
  6641. Include(VarEl.VarModifiers,vmClass);
  6642. if isStatic then
  6643. Include(VarEl.VarModifiers,vmStatic);
  6644. Engine.FinishScope(stDeclaration,VarEl);
  6645. end;
  6646. end;
  6647. finally
  6648. VarList.Free;
  6649. end;
  6650. end;
  6651. procedure TPasParser.ParseMembersLocalTypes(AType: TPasMembersType;
  6652. AVisibility: TPasMemberVisibility);
  6653. Var
  6654. T : TPasType;
  6655. Done : Boolean;
  6656. begin
  6657. //Writeln('Parsing local types');
  6658. while (CurToken=tkSquaredBraceOpen)
  6659. and (msPrefixedAttributes in CurrentModeswitches) do
  6660. begin
  6661. ParseAttributes(AType,true);
  6662. NextToken;
  6663. end;
  6664. Repeat
  6665. T:=ParseTypeDecl(AType);
  6666. T.Visibility:=AVisibility;
  6667. AType.Members.Add(t);
  6668. // Writeln(CurtokenString,' ',TokenInfos[Curtoken]);
  6669. NextToken;
  6670. case CurToken of
  6671. tkgeneric:
  6672. begin
  6673. NextToken;
  6674. if CurToken<>tkIdentifier then
  6675. Done:=true;
  6676. UngetToken;
  6677. end;
  6678. tkIdentifier:
  6679. Done:=CheckVisibility(CurTokenString,AVisibility);
  6680. tkSquaredBraceOpen:
  6681. if msPrefixedAttributes in CurrentModeswitches then
  6682. repeat
  6683. ParseAttributes(AType,true);
  6684. NextToken;
  6685. Done:=false;
  6686. until CurToken<>tkSquaredBraceOpen
  6687. else
  6688. Done:=true;
  6689. else
  6690. Done:=true;
  6691. end;
  6692. if Done then
  6693. UngetToken;
  6694. Until Done;
  6695. Engine.FinishScope(stTypeSection,AType);
  6696. end;
  6697. procedure TPasParser.ParseMembersLocalConsts(AType: TPasMembersType;
  6698. AVisibility: TPasMemberVisibility);
  6699. Var
  6700. C : TPasConst;
  6701. Done : Boolean;
  6702. begin
  6703. // Writeln('Parsing local consts');
  6704. while (CurToken=tkSquaredBraceOpen)
  6705. and (msPrefixedAttributes in CurrentModeswitches) do
  6706. begin
  6707. ParseAttributes(AType,true);
  6708. NextToken;
  6709. end;
  6710. Repeat
  6711. C:=ParseConstDecl(AType);
  6712. C.Visibility:=AVisibility;
  6713. AType.Members.Add(C);
  6714. Engine.FinishScope(stDeclaration,C);
  6715. //Writeln('TPasParser.ParseMembersLocalConsts ',CurtokenString,' ',TokenInfos[CurToken]);
  6716. NextToken;
  6717. if CurToken<>tkSemicolon then
  6718. exit;
  6719. NextToken;
  6720. case CurToken of
  6721. tkIdentifier:
  6722. Done:=CheckVisibility(CurTokenString,AVisibility);
  6723. tkSquaredBraceOpen:
  6724. if msPrefixedAttributes in CurrentModeswitches then
  6725. repeat
  6726. ParseAttributes(AType,true);
  6727. NextToken;
  6728. Done:=false;
  6729. until CurToken<>tkSquaredBraceOpen
  6730. else
  6731. Done:=true;
  6732. else
  6733. Done:=true;
  6734. end;
  6735. if Done then
  6736. UngetToken;
  6737. Until Done;
  6738. end;
  6739. procedure TPasParser.ParseClassMembers(AType: TPasClassType);
  6740. Type
  6741. TSectionType = (stNone,stConst,stType,stVar,stClassVar);
  6742. Var
  6743. CurVisibility : TPasMemberVisibility;
  6744. CurSection : TSectionType;
  6745. haveClass: boolean; // true means last token was class keyword
  6746. IsMethodResolution: Boolean;
  6747. LastToken: TToken;
  6748. PropEl: TPasProperty;
  6749. MethodRes: TPasMethodResolution;
  6750. begin
  6751. CurSection:=stNone;
  6752. haveClass:=false;
  6753. if Assigned(FEngine) then
  6754. CurVisibility:=FEngine.GetDefaultClassVisibility(AType)
  6755. else
  6756. CurVisibility := visPublic;
  6757. LastToken:=CurToken;
  6758. while (CurToken<>tkEnd) do
  6759. begin
  6760. //writeln('TPasParser.ParseClassMembers LastToken=',LastToken,' CurToken=',CurToken,' haveClass=',haveClass,' CurSection=',CurSection);
  6761. case CurToken of
  6762. tkType:
  6763. begin
  6764. if haveClass then
  6765. ParseExcExpectedAorB('Procedure','Function');
  6766. case AType.ObjKind of
  6767. okClass,okObject,
  6768. okClassHelper,okRecordHelper,okTypeHelper: ;
  6769. else
  6770. ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['TYPE',ObjKindNames[AType.ObjKind]]);
  6771. end;
  6772. CurSection:=stType;
  6773. NextToken;
  6774. ParseMembersLocalTypes(AType,CurVisibility);
  6775. CurSection:=stNone;
  6776. end;
  6777. tkConst:
  6778. begin
  6779. if haveClass then
  6780. ParseExcExpectedAorB('Procedure','Var');
  6781. case AType.ObjKind of
  6782. okClass,okObject,
  6783. okClassHelper,okRecordHelper,okTypeHelper: ;
  6784. else
  6785. ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['CONST',ObjKindNames[AType.ObjKind]]);
  6786. end;
  6787. CurSection:=stConst;
  6788. NextToken;
  6789. ParseMembersLocalConsts(AType,CurVisibility);
  6790. CurSection:=stNone;
  6791. end;
  6792. tkVar:
  6793. if not (CurSection in [stVar,stClassVar]) then
  6794. begin
  6795. if (AType.ObjKind in okWithFields)
  6796. or (haveClass and (AType.ObjKind in okAllHelpers)) then
  6797. // ok
  6798. else
  6799. ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['VAR',ObjKindNames[AType.ObjKind]]);
  6800. if LastToken=tkClass then
  6801. CurSection:=stClassVar
  6802. else
  6803. CurSection:=stVar;
  6804. end;
  6805. tkIdentifier:
  6806. if CheckVisibility(CurTokenString,CurVisibility) then
  6807. CurSection:=stNone
  6808. else
  6809. begin
  6810. if haveClass then
  6811. begin
  6812. if LastToken=tkclass then
  6813. ParseExcExpectedAorB('Procedure','Function');
  6814. end
  6815. else
  6816. SaveComments;
  6817. Case CurSection of
  6818. stNone,
  6819. stVar:
  6820. begin
  6821. if not (AType.ObjKind in okWithFields) then
  6822. ParseExc(nParserNoFieldsAllowed,SParserNoFieldsAllowedInX,[ObjKindNames[AType.ObjKind]]);
  6823. ParseClassFields(AType,CurVisibility,CurSection=stClassVar);
  6824. HaveClass:=False;
  6825. end;
  6826. stClassVar:
  6827. begin
  6828. if not (AType.ObjKind in okWithClassFields) then
  6829. ParseExc(nParserNoFieldsAllowed,SParserNoFieldsAllowedInX,[ObjKindNames[AType.ObjKind]]);
  6830. ParseClassFields(AType,CurVisibility,CurSection=stClassVar);
  6831. HaveClass:=False;
  6832. end;
  6833. else
  6834. Raise Exception.Create('Internal error 201704251415');
  6835. end;
  6836. end;
  6837. tkConstructor,tkDestructor:
  6838. begin
  6839. curSection:=stNone;
  6840. if not haveClass then
  6841. SaveComments;
  6842. case AType.ObjKind of
  6843. okObject,okClass: ;
  6844. okClassHelper,okTypeHelper,okRecordHelper:
  6845. begin
  6846. if (CurToken=tkdestructor) and not haveClass then
  6847. ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['destructor',ObjKindNames[AType.ObjKind]]);
  6848. end;
  6849. else
  6850. if CurToken=tkconstructor then
  6851. ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['constructor',ObjKindNames[AType.ObjKind]])
  6852. else
  6853. ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['destructor',ObjKindNames[AType.ObjKind]]);
  6854. end;
  6855. ProcessMethod(AType,HaveClass,CurVisibility,false);
  6856. haveClass:=False;
  6857. end;
  6858. tkProcedure,tkFunction:
  6859. begin
  6860. curSection:=stNone;
  6861. IsMethodResolution:=false;
  6862. if not haveClass then
  6863. begin
  6864. SaveComments;
  6865. if AType.ObjKind=okClass then
  6866. begin
  6867. NextToken;
  6868. if CurToken=tkIdentifier then
  6869. begin
  6870. NextToken;
  6871. IsMethodResolution:=CurToken=tkDot;
  6872. UngetToken;
  6873. end;
  6874. UngetToken;
  6875. end;
  6876. end;
  6877. if IsMethodResolution then
  6878. begin
  6879. MethodRes:=ParseMethodResolution(AType);
  6880. AType.Members.Add(MethodRes);
  6881. Engine.FinishScope(stDeclaration,MethodRes);
  6882. end
  6883. else
  6884. ProcessMethod(AType,HaveClass,CurVisibility,false);
  6885. haveClass:=False;
  6886. end;
  6887. tkgeneric:
  6888. begin
  6889. if msDelphi in CurrentModeswitches then
  6890. ParseExcSyntaxError; // inconsistency, tkGeneric should be in Scanner.NonTokens
  6891. if haveClass and (LastToken=tkclass) then
  6892. ParseExcTokenError('Generic Class');
  6893. case AType.ObjKind of
  6894. okClass,okObject,
  6895. okClassHelper,okRecordHelper,okTypeHelper: ;
  6896. else
  6897. ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['generic',ObjKindNames[AType.ObjKind]]);
  6898. end;
  6899. SaveComments;
  6900. CurSection:=stNone;
  6901. NextToken;
  6902. if CurToken=tkclass then
  6903. begin
  6904. haveClass:=true;
  6905. NextToken;
  6906. end
  6907. else
  6908. haveClass:=false;
  6909. if not (CurToken in [tkprocedure,tkfunction]) then
  6910. ParseExcExpectedAorB('Procedure','Function');
  6911. ProcessMethod(AType,HaveClass,CurVisibility,true);
  6912. end;
  6913. tkclass:
  6914. begin
  6915. case AType.ObjKind of
  6916. okClass,okObject,
  6917. okClassHelper,okRecordHelper,okTypeHelper: ;
  6918. else
  6919. ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['CLASS',ObjKindNames[AType.ObjKind]]);
  6920. end;
  6921. SaveComments;
  6922. HaveClass:=True;
  6923. curSection:=stNone;
  6924. end;
  6925. tkProperty:
  6926. begin
  6927. curSection:=stNone;
  6928. if not haveClass then
  6929. SaveComments;
  6930. ExpectIdentifier;
  6931. PropEl:=ParseProperty(AType,CurtokenString,CurVisibility,HaveClass);
  6932. AType.Members.Add(PropEl);
  6933. Engine.FinishScope(stDeclaration,PropEl);
  6934. HaveClass:=False;
  6935. end;
  6936. tkSquaredBraceOpen:
  6937. if msPrefixedAttributes in CurrentModeswitches then
  6938. ParseAttributes(AType,true)
  6939. else
  6940. CheckToken(tkIdentifier);
  6941. else
  6942. CheckToken(tkIdentifier);
  6943. end;
  6944. LastToken:=CurToken;
  6945. NextToken;
  6946. end;
  6947. end;
  6948. procedure TPasParser.DoParseClassType(AType: TPasClassType);
  6949. var
  6950. s: String;
  6951. Expr: TPasExpr;
  6952. begin
  6953. if (CurToken=tkIdentifier) and (AType.ObjKind=okClass) then
  6954. begin
  6955. s := LowerCase(CurTokenString);
  6956. if (s = 'sealed') or (s = 'abstract') then
  6957. begin
  6958. AType.Modifiers.Add(s);
  6959. NextToken;
  6960. end;
  6961. end;
  6962. // Parse ancestor list
  6963. AType.IsForward:=(CurToken=tkSemiColon);
  6964. if (CurToken=tkBraceOpen) then
  6965. begin
  6966. // read ancestor and interfaces
  6967. if (AType.ObjKind=okRecordHelper)
  6968. and ([msTypeHelpers,msDelphi]*Scanner.CurrentModeSwitches=[msDelphi]) then
  6969. // Delphi does not support ancestors in record helpers
  6970. CheckToken(tkend);
  6971. NextToken;
  6972. AType.AncestorType := ParseTypeReference(AType,false,Expr);
  6973. if AType.ObjKind=okClass then
  6974. while CurToken=tkComma do
  6975. begin
  6976. NextToken;
  6977. AType.Interfaces.Add(ParseTypeReference(AType,false,Expr));
  6978. end;
  6979. CheckToken(tkBraceClose);
  6980. NextToken;
  6981. AType.IsShortDefinition:=(CurToken=tkSemicolon);
  6982. end;
  6983. if (AType.ObjKind in okAllHelpers) then
  6984. begin
  6985. CheckToken(tkfor);
  6986. NextToken;
  6987. AType.HelperForType:=ParseTypeReference(AType,false,Expr);
  6988. end;
  6989. Engine.FinishScope(stAncestors,AType);
  6990. if AType.IsShortDefinition or AType.IsForward then
  6991. UngetToken
  6992. else
  6993. begin
  6994. if (AType.ObjKind in [okInterface,okDispInterface]) and (CurToken = tkSquaredBraceOpen) then
  6995. begin
  6996. NextToken;
  6997. AType.GUIDExpr:=DoParseExpression(AType);
  6998. if (CurToken<>tkSquaredBraceClose) then
  6999. ParseExcTokenError(TokenInfos[tkSquaredBraceClose]);
  7000. NextToken;
  7001. end;
  7002. ParseClassMembers(AType);
  7003. end;
  7004. end;
  7005. procedure TPasParser.DoParseClassExternalHeader(AObjKind: TPasObjKind; out
  7006. AExternalNameSpace, AExternalName: string);
  7007. begin
  7008. if ((AObjKind in [okClass,okInterface]) and (msExternalClass in CurrentModeswitches)
  7009. and CurTokenIsIdentifier('external')) then
  7010. begin
  7011. NextToken;
  7012. if CurToken<>tkString then
  7013. UnGetToken
  7014. else
  7015. AExternalNameSpace:=CurTokenString;
  7016. ExpectIdentifier;
  7017. If Not CurTokenIsIdentifier('Name') then
  7018. ParseExc(nParserExpectedExternalClassName,SParserExpectedExternalClassName);
  7019. NextToken;
  7020. if not (CurToken in [tkChar,tkString]) then
  7021. CheckToken(tkString);
  7022. AExternalName:=CurTokenString;
  7023. NextToken;
  7024. end
  7025. else
  7026. begin
  7027. AExternalNameSpace:='';
  7028. AExternalName:='';
  7029. end;
  7030. end;
  7031. procedure TPasParser.DoParseArrayType(ArrType: TPasArrayType);
  7032. var
  7033. S: String;
  7034. RangeExpr: TPasExpr;
  7035. begin
  7036. NextToken;
  7037. S:='';
  7038. case CurToken of
  7039. tkSquaredBraceOpen:
  7040. begin
  7041. // static array
  7042. if ArrType.Parent is TPasArgument then
  7043. ParseExcTokenError('of');
  7044. repeat
  7045. NextToken;
  7046. if po_arrayrangeexpr in Options then
  7047. begin
  7048. RangeExpr:=DoParseExpression(ArrType);
  7049. ArrType.AddRange(RangeExpr);
  7050. end
  7051. else if CurToken<>tkSquaredBraceClose then
  7052. S:=S+CurTokenText;
  7053. if CurToken=tkSquaredBraceClose then
  7054. break
  7055. else if CurToken=tkComma then
  7056. continue
  7057. else if po_arrayrangeexpr in Options then
  7058. ParseExcTokenError(']');
  7059. until false;
  7060. ArrType.IndexRange:=S;
  7061. ExpectToken(tkOf);
  7062. ArrType.ElType := ParseType(ArrType,CurSourcePos);
  7063. end;
  7064. tkOf:
  7065. begin
  7066. NextToken;
  7067. if CurToken = tkConst then
  7068. // array of const
  7069. begin
  7070. if not (ArrType.Parent is TPasArgument) then
  7071. ParseExcExpectedIdentifier;
  7072. end
  7073. else
  7074. begin
  7075. if (CurToken=tkarray) and (ArrType.Parent is TPasArgument) then
  7076. ParseExcExpectedIdentifier;
  7077. UngetToken;
  7078. ArrType.ElType := ParseType(ArrType,CurSourcePos);
  7079. end;
  7080. end
  7081. else
  7082. ParseExc(nParserArrayTypeSyntaxError,SParserArrayTypeSyntaxError);
  7083. end;
  7084. // TPasProcedureType parsing has eaten the semicolon;
  7085. // We know it was a local definition if the array def (ArrType) is the parent
  7086. if (ArrType.ElType is TPasProcedureType) and (ArrType.ElType.Parent=ArrType) then
  7087. UnGetToken;
  7088. end;
  7089. function TPasParser.ParseClassDecl(Parent: TPasElement;
  7090. const NamePos: TPasSourcePos; const AClassName: String;
  7091. AObjKind: TPasObjKind; PackMode: TPackMode): TPasType;
  7092. Var
  7093. ok: Boolean;
  7094. AExternalNameSpace,AExternalName : String;
  7095. PCT:TPasClassType;
  7096. begin
  7097. NextToken;
  7098. if (AObjKind = okClass) and (CurToken = tkOf) then
  7099. begin
  7100. Result := TPasClassOfType(CreateElement(TPasClassOfType, AClassName,
  7101. Parent, NamePos));
  7102. ok:=false;
  7103. try
  7104. ExpectIdentifier;
  7105. UngetToken; // Only names are allowed as following type
  7106. TPasClassOfType(Result).DestType := ParseType(Result,CurSourcePos);
  7107. Engine.FinishScope(stTypeDef,Result);
  7108. ok:=true;
  7109. finally
  7110. if not ok then
  7111. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  7112. end;
  7113. exit;
  7114. end;
  7115. DoParseClassExternalHeader(AObjKind,AExternalNameSpace,AExternalName);
  7116. if AObjKind in okAllHelpers then
  7117. begin
  7118. if not CurTokenIsIdentifier('Helper') then
  7119. ParseExcSyntaxError;
  7120. NextToken;
  7121. end;
  7122. PCT := TPasClassType(CreateElement(TPasClassType, AClassName,
  7123. Parent, NamePos));
  7124. Result:=PCT;
  7125. ok:=false;
  7126. try
  7127. PCT.HelperForType:=nil;
  7128. PCT.IsExternal:=(AExternalName<>'');
  7129. if AExternalName<>'' then
  7130. PCT.ExternalName:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalName,'''');
  7131. if AExternalNameSpace<>'' then
  7132. PCT.ExternalNameSpace:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalNameSpace,'''');
  7133. PCT.ObjKind := AObjKind;
  7134. PCT.PackMode:=PackMode;
  7135. if AObjKind=okInterface then
  7136. begin
  7137. if SameText(Scanner.CurrentValueSwitch[vsInterfaces],'CORBA') then
  7138. PCT.InterfaceType:=citCorba;
  7139. end;
  7140. DoParseClassType(PCT);
  7141. Engine.FinishScope(stTypeDef,Result);
  7142. ok:=true;
  7143. finally
  7144. if not ok then
  7145. begin
  7146. PCT.Parent:=nil; // clear references from members to PCT
  7147. Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
  7148. end;
  7149. end;
  7150. end;
  7151. function TPasParser.CreateElement(AClass: TPTreeElement; const AName: String;
  7152. AParent: TPasElement): TPasElement;
  7153. begin
  7154. Result := Engine.CreateElement(AClass, AName, AParent, visDefault, CurSourcePos);
  7155. end;
  7156. function TPasParser.CreateElement(AClass: TPTreeElement; const AName: String;
  7157. AParent: TPasElement; const ASrcPos: TPasSourcePos): TPasElement;
  7158. begin
  7159. Result := Engine.CreateElement(AClass, AName, AParent, visDefault, ASrcPos);
  7160. end;
  7161. function TPasParser.CreateElement(AClass: TPTreeElement; const AName: String;
  7162. AParent: TPasElement; AVisibility: TPasMemberVisibility): TPasElement;
  7163. begin
  7164. Result := Engine.CreateElement(AClass, AName, AParent, AVisibility,
  7165. CurSourcePos);
  7166. end;
  7167. function TPasParser.CreateElement(AClass: TPTreeElement; const AName: String;
  7168. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  7169. const ASrcPos: TPasSourcePos; TypeParams: TFPList): TPasElement;
  7170. begin
  7171. if (ASrcPos.Row=0) and (ASrcPos.FileName='') then
  7172. Result := Engine.CreateElement(AClass, AName, AParent, AVisibility, CurSourcePos, TypeParams)
  7173. else
  7174. Result := Engine.CreateElement(AClass, AName, AParent, AVisibility, ASrcPos, TypeParams);
  7175. end;
  7176. function TPasParser.CreatePrimitiveExpr(AParent: TPasElement;
  7177. AKind: TPasExprKind; const AValue: String): TPrimitiveExpr;
  7178. begin
  7179. Result:=TPrimitiveExpr(CreateElement(TPrimitiveExpr,'',AParent,CurTokenPos));
  7180. Result.Kind:=AKind;
  7181. Result.Value:=AValue;
  7182. end;
  7183. function TPasParser.CreateBoolConstExpr(AParent: TPasElement;
  7184. AKind: TPasExprKind; const ABoolValue: Boolean): TBoolConstExpr;
  7185. begin
  7186. Result:=TBoolConstExpr(CreateElement(TBoolConstExpr,'',AParent,CurTokenPos));
  7187. Result.Kind:=AKind;
  7188. Result.Value:=ABoolValue;
  7189. end;
  7190. function TPasParser.CreateBinaryExpr(AParent: TPasElement; xleft,
  7191. xright: TPasExpr; AOpCode: TExprOpCode): TBinaryExpr;
  7192. begin
  7193. Result:=CreateBinaryExpr(AParent,xleft,xright,AOpCode,CurSourcePos);
  7194. end;
  7195. function TPasParser.CreateBinaryExpr(AParent: TPasElement; xleft,
  7196. xright: TPasExpr; AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos
  7197. ): TBinaryExpr;
  7198. begin
  7199. Result:=TBinaryExpr(CreateElement(TBinaryExpr,'',AParent,ASrcPos));
  7200. Result.OpCode:=AOpCode;
  7201. Result.Kind:=pekBinary;
  7202. if xleft<>nil then
  7203. begin
  7204. Result.left:=xleft;
  7205. xleft.Parent:=Result;
  7206. end;
  7207. if xright<>nil then
  7208. begin
  7209. Result.right:=xright;
  7210. xright.Parent:=Result;
  7211. end;
  7212. end;
  7213. procedure TPasParser.AddToBinaryExprChain(var ChainFirst: TPasExpr;
  7214. Element: TPasExpr; AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos);
  7215. begin
  7216. if Element=nil then
  7217. exit
  7218. else if ChainFirst=nil then
  7219. begin
  7220. // empty chain => simply add element, no need to create TBinaryExpr
  7221. ChainFirst:=Element;
  7222. end
  7223. else
  7224. begin
  7225. // create new binary, old becomes left, Element right
  7226. ChainFirst:=CreateBinaryExpr(ChainFirst.Parent,ChainFirst,Element,AOpCode,ASrcPos);
  7227. end;
  7228. end;
  7229. {$IFDEF VerbosePasParser}
  7230. {AllowWriteln}
  7231. procedure TPasParser.WriteBinaryExprChain(Prefix: string; First, Last: TPasExpr
  7232. );
  7233. var
  7234. i: Integer;
  7235. begin
  7236. if First=nil then
  7237. begin
  7238. write(Prefix,'First=nil');
  7239. if Last=nil then
  7240. writeln('=Last')
  7241. else
  7242. begin
  7243. writeln(', ERROR Last=',Last.ClassName);
  7244. ParseExcSyntaxError;
  7245. end;
  7246. end
  7247. else if Last=nil then
  7248. begin
  7249. writeln(Prefix,'ERROR Last=nil First=',First.ClassName);
  7250. ParseExcSyntaxError;
  7251. end
  7252. else if First is TBinaryExpr then
  7253. begin
  7254. i:=0;
  7255. while First is TBinaryExpr do
  7256. begin
  7257. writeln(Prefix,Space(i*2),'bin.left=',TBinaryExpr(First).left.ClassName);
  7258. if First=Last then break;
  7259. First:=TBinaryExpr(First).right;
  7260. inc(i);
  7261. end;
  7262. if First<>Last then
  7263. begin
  7264. writeln(Prefix,Space(i*2),'ERROR Last is not last in chain');
  7265. ParseExcSyntaxError;
  7266. end;
  7267. if not (Last is TBinaryExpr) then
  7268. begin
  7269. writeln(Prefix,Space(i*2),'ERROR Last is not TBinaryExpr: ',Last.ClassName);
  7270. ParseExcSyntaxError;
  7271. end;
  7272. if TBinaryExpr(Last).right=nil then
  7273. begin
  7274. writeln(Prefix,Space(i*2),'ERROR Last.right=nil');
  7275. ParseExcSyntaxError;
  7276. end;
  7277. writeln(Prefix,Space(i*2),'last.right=',TBinaryExpr(Last).right.ClassName);
  7278. end
  7279. else if First=Last then
  7280. writeln(Prefix,'First=Last=',First.ClassName)
  7281. else
  7282. begin
  7283. write(Prefix,'ERROR First=',First.ClassName);
  7284. if Last<>nil then
  7285. writeln(' Last=',Last.ClassName)
  7286. else
  7287. writeln(' Last=nil');
  7288. end;
  7289. end;
  7290. {AllowWriteln-}
  7291. {$ENDIF}
  7292. function TPasParser.CreateUnaryExpr(AParent: TPasElement; AOperand: TPasExpr;
  7293. AOpCode: TExprOpCode): TUnaryExpr;
  7294. begin
  7295. Result:=CreateUnaryExpr(AParent,AOperand,AOpCode,CurTokenPos);
  7296. end;
  7297. function TPasParser.CreateUnaryExpr(AParent: TPasElement; AOperand: TPasExpr;
  7298. AOpCode: TExprOpCode; const ASrcPos: TPasSourcePos): TUnaryExpr;
  7299. begin
  7300. Result:=TUnaryExpr(CreateElement(TUnaryExpr,'',AParent,ASrcPos));
  7301. Result.Kind:=pekUnary;
  7302. Result.Operand:=AOperand;
  7303. Result.Operand.Parent:=Result;
  7304. Result.OpCode:=AOpCode;
  7305. end;
  7306. function TPasParser.CreateArrayValues(AParent: TPasElement): TArrayValues;
  7307. begin
  7308. Result:=TArrayValues(CreateElement(TArrayValues,'',AParent));
  7309. Result.Kind:=pekListOfExp;
  7310. end;
  7311. function TPasParser.CreateFunctionType(const AName, AResultName: String;
  7312. AParent: TPasElement; UseParentAsResultParent: Boolean;
  7313. const NamePos: TPasSourcePos; TypeParams: TFPList): TPasFunctionType;
  7314. begin
  7315. Result:=Engine.CreateFunctionType(AName,AResultName,
  7316. AParent,UseParentAsResultParent,
  7317. NamePos,TypeParams);
  7318. end;
  7319. function TPasParser.CreateInheritedExpr(AParent: TPasElement): TInheritedExpr;
  7320. begin
  7321. Result:=TInheritedExpr(CreateElement(TInheritedExpr,'',AParent,CurTokenPos));
  7322. Result.Kind:=pekInherited;
  7323. end;
  7324. function TPasParser.CreateSelfExpr(AParent: TPasElement): TSelfExpr;
  7325. begin
  7326. Result:=TSelfExpr(CreateElement(TSelfExpr,'Self',AParent,CurTokenPos));
  7327. Result.Kind:=pekSelf;
  7328. end;
  7329. function TPasParser.CreateNilExpr(AParent: TPasElement): TNilExpr;
  7330. begin
  7331. Result:=TNilExpr(CreateElement(TNilExpr,'nil',AParent,CurTokenPos));
  7332. Result.Kind:=pekNil;
  7333. end;
  7334. function TPasParser.CreateRecordValues(AParent: TPasElement): TRecordValues;
  7335. begin
  7336. Result:=TRecordValues(CreateElement(TRecordValues,'',AParent));
  7337. Result.Kind:=pekListOfExp;
  7338. end;
  7339. initialization
  7340. {$IFDEF HASFS}
  7341. DefaultFileResolverClass:=TFileResolver;
  7342. {$ENDIF}
  7343. end.