pparser.pp 257 KB

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