123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771 |
- MODULE FoxCSharpParser;
- (* module originating from Alexey Gokhberg's ActiveCells# Parser *)
- IMPORT Strings, StringPool, Diagnostics, D := Debugging, Basic := FoxBasic, FoxScanner,
- Scanner := FoxCSharpScanner, SyntaxTree := FoxSyntaxTree, Global := FoxGlobal,
- KernelLog (* DEBUG *);
- CONST
- Trace = FALSE;
- (* modifiers *)
- Public = 0;
- Internal = 1;
- LynxCase = FoxScanner.Lowercase;
- TYPE
- Position*= Scanner.Position;
- LocalIdentEntry = OBJECT
- VAR
- next: LocalIdentEntry;
- level: LONGINT;
- name: SyntaxTree.Identifier;
- local: SyntaxTree.Identifier;
- END LocalIdentEntry;
- LocalIdentTable = OBJECT
- VAR
- head: LocalIdentEntry;
- level: LONGINT;
- suffix: LONGINT;
- PROCEDURE & Init;
- BEGIN
- Reset;
- END Init;
- PROCEDURE Reset;
- BEGIN
- head := NIL;
- level := 0;
- suffix := 0;
- END Reset;
- PROCEDURE OpenScope;
- BEGIN
- INC(level);
- END OpenScope;
- PROCEDURE CloseScope;
- VAR p: LocalIdentEntry;
- BEGIN
- p := head;
- WHILE (p # NIL) & (p.level = level) DO
- p := p.next;
- END;
- head := p;
- DEC(level);
- END CloseScope;
- PROCEDURE Enter(name: SyntaxTree.Identifier): SyntaxTree.Identifier;
- VAR p, q: LocalIdentEntry;
- local: SyntaxTree.Identifier;
- str: Scanner.IdentifierString;
- BEGIN
- IF level = 0 THEN
- RETURN name;
- END;
- p := head;
- q := NIL;
- WHILE (q = NIL) & (p # NIL) & (p.level = level) DO
- IF p.name = name THEN
- q := p;
- END;
- p := p.next;
- END;
- IF q # NIL THEN
- RETURN q.local;
- END;
- Basic.GetString(name, str);
- Strings.AppendChar(str, "@");
- INC(suffix);
- Basic.AppendNumber(str, suffix);
- local := Basic.MakeString(str);
- NEW(q);
- q.level := level;
- q.name := name;
- q.local := local;
- q.next := head;
- head := q;
- RETURN local;
- END Enter;
- PROCEDURE Find(name: SyntaxTree.Identifier): SyntaxTree.Identifier;
- VAR p: LocalIdentEntry;
- BEGIN
- p := head;
- WHILE (p # NIL) & (p.name # name) DO
- p := p.next;
- END;
- IF p # NIL THEN
- RETURN p.local;
- END;
- RETURN name;
- END Find;
- END LocalIdentTable;
- Parser* = OBJECT
- VAR
- scanner: Scanner.Scanner;
- symbol-: Scanner.Symbol;
- diagnostics: Diagnostics.Diagnostics;
- currentScope: SyntaxTree.Scope;
- recentCommentItem: ANY;
- recentLine: LONGINT;
- recentComment: SyntaxTree.Comment;
- moduleScope: SyntaxTree.ModuleScope;
- error-: BOOLEAN;
- initStatements: SyntaxTree.StatementSequence;
- initOuter: SyntaxTree.Statement;
- delegateModifiers: SyntaxTree.Modifier;
- lynxChar: SyntaxTree.Identifier;
- lynxSbyte: SyntaxTree.Identifier;
- lynxShort: SyntaxTree.Identifier;
- lynxInt: SyntaxTree.Identifier;
- lynxLong: SyntaxTree.Identifier;
- lynxFloat: SyntaxTree.Identifier;
- lynxDouble: SyntaxTree.Identifier;
- lynxBool: SyntaxTree.Identifier;
- lynxObject: SyntaxTree.Identifier;
- lynxString: SyntaxTree.Identifier;
- lynxNewobj: SyntaxTree.Identifier;
- lynxNewarr: SyntaxTree.Identifier;
- lynxAsop: SyntaxTree.Identifier;
- lynxUnop: SyntaxTree.Identifier;
- lynxBinop: SyntaxTree.Identifier;
- lynxSend: SyntaxTree.Identifier;
- lynxReceive: SyntaxTree.Identifier;
- lynxRecvnb: SyntaxTree.Identifier;
- lynxConnect: SyntaxTree.Identifier;
- lynxDelegate: SyntaxTree.Identifier;
- lynxNewsel: SyntaxTree.Identifier;
- lynxAddsel: SyntaxTree.Identifier;
- lynxSelect: SyntaxTree.Identifier;
- lynxSelidx: SyntaxTree.Identifier;
- lynxType: SyntaxTree.Identifier;
- identMain: SyntaxTree.Identifier;
- localIdentTable: LocalIdentTable;
- indent: LONGINT; (* for debugging purposes only *)
- (** constructor, init parser with scanner providing input and with diagnostics for error output *)
- PROCEDURE & Init*(scanner: Scanner.Scanner; diagnostics: Diagnostics.Diagnostics);
- BEGIN
- SELF.scanner := scanner;
- SELF.diagnostics := diagnostics;
- error := ~scanner.GetNextSymbol(symbol);
- recentCommentItem := NIL;
- recentComment := NIL;
- initStatements := NIL;
- initOuter := NIL;
- InitDelegateModifiers;
- InitSystemNames;
- StringPool.GetIndex("lynx@type", lynxType);
- StringPool.GetIndex("main", identMain);
- NEW(localIdentTable);
- (* debugging *)
- indent := 0;
- END Init;
- PROCEDURE InitDelegateModifiers;
- VAR name: SyntaxTree.Identifier;
- BEGIN
- StringPool.GetIndex("DELEGATE", name);
- delegateModifiers := SyntaxTree.NewModifier(invalidPosition, name, NIL);
- END InitDelegateModifiers;
- (*
- NOTE: Fox semantical analysis has been extended in order to recognize
- and properly support the following names of system procedures.
- Lynx version of FoxGlobal provides the respective bindings.
- *)
- PROCEDURE InitSystemNames;
- BEGIN
- StringPool.GetIndex(Global.LynxChar, lynxChar);
- StringPool.GetIndex(Global.LynxSbyte, lynxSbyte);
- StringPool.GetIndex(Global.LynxShort, lynxShort);
- StringPool.GetIndex(Global.LynxInt, lynxInt);
- StringPool.GetIndex(Global.LynxLong, lynxLong);
- StringPool.GetIndex(Global.LynxFloat, lynxFloat);
- StringPool.GetIndex(Global.LynxDouble, lynxDouble);
- StringPool.GetIndex(Global.LynxBool, lynxBool);
- StringPool.GetIndex(Global.LynxObject, lynxObject);
- StringPool.GetIndex(Global.LynxString, lynxString);
- StringPool.GetIndex(Global.LynxNewobj, lynxNewobj);
- StringPool.GetIndex(Global.LynxNewarr, lynxNewarr);
- StringPool.GetIndex(Global.LynxAsop, lynxAsop);
- StringPool.GetIndex(Global.LynxUnop, lynxUnop);
- StringPool.GetIndex(Global.LynxBinop, lynxBinop);
- StringPool.GetIndex(Global.LynxSend, lynxSend);
- StringPool.GetIndex(Global.LynxReceive, lynxReceive);
- StringPool.GetIndex(Global.LynxRecvnb, lynxRecvnb);
- StringPool.GetIndex(Global.LynxConnect, lynxConnect);
- StringPool.GetIndex(Global.LynxDelegate, lynxDelegate);
- StringPool.GetIndex(Global.LynxNewsel, lynxNewsel);
- StringPool.GetIndex(Global.LynxAddsel, lynxAddsel);
- StringPool.GetIndex(Global.LynxSelect, lynxSelect);
- StringPool.GetIndex(Global.LynxSelidx, lynxSelidx);
- END InitSystemNames;
- PROCEDURE S(CONST s: ARRAY OF CHAR); (* for debugging purposes only *)
- VAR i: LONGINT;
- BEGIN
- D.Ln;
- INC(indent);
- D.Int(indent, 1);
- FOR i := 1 TO indent DO
- D.Str(" ");
- END;
- D.Str("start: ");
- D.Str(s);
- D.Str(" at pos ");
- D.Int(symbol.position.start, 1);
- END S;
- PROCEDURE E(CONST s: ARRAY OF CHAR); (* for debugging purposes only *)
- VAR i: LONGINT;
- BEGIN
- D.Ln;
- D.Int(indent, 1);
- FOR i := 1 TO indent DO
- D.Str(" ");
- END;
- D.Str("end : ");
- D.Str(s);
- D.Str(" at pos ");
- D.Int(symbol.position.start, 1);
- END E;
- PROCEDURE EE(CONST s, t: ARRAY OF CHAR); (* for debugging purposes only *)
- VAR i: LONGINT;
- BEGIN
- D.Ln;
- D.Int(indent, 1);
- FOR i := 1 TO indent DO
- D.Str(" ");
- END;
- D.Str("end : ");
- D.Str(s);
- D.Str(" (");
- D.Str(t);
- D.Str(") at pos ");
- END EE;
- (** output error message and / or given code *)
- PROCEDURE Error(position: Position; code: LONGINT; CONST message: ARRAY OF CHAR);
- VAR errorMessage: ARRAY 256 OF CHAR;
- BEGIN
- Basic.ErrorC(diagnostics, scanner.source^, position, code, errorMessage);
- error := TRUE;
- (* @@@ *)
- HALT(100);
- END Error;
- (** helper procedures interfacing to the scanner **)
- (** Get next symbol from scanner and store it in object-local variable 'symbol' *)
- PROCEDURE NextSymbol;
- VAR comment: SyntaxTree.Comment;
- BEGIN
- error := ~scanner.GetNextSymbol(symbol) OR error;
- WHILE ~error & (symbol.token = Scanner.Comment) DO
- comment := SyntaxTree.NewComment(symbol.position, currentScope, symbol.string^, symbol.stringLength);
- moduleScope.AddComment(comment);
- IF recentComment = NIL THEN
- recentComment := comment;
- IF symbol.position.line = recentLine THEN
- IF recentCommentItem # NIL THEN
- IF (recentCommentItem IS SyntaxTree.Symbol) THEN
- IF recentCommentItem(SyntaxTree.Symbol).comment = NIL THEN
- recentCommentItem(SyntaxTree.Symbol).SetComment(comment)
- END;
- ELSIF (recentCommentItem IS SyntaxTree.Statement) THEN
- IF recentCommentItem(SyntaxTree.Statement).comment = NIL THEN
- recentCommentItem(SyntaxTree.Statement).SetComment(comment)
- END;
- ELSIF (recentCommentItem IS SyntaxTree.IfPart) THEN
- IF recentCommentItem(SyntaxTree.IfPart).comment = NIL THEN
- recentCommentItem(SyntaxTree.IfPart).SetComment(comment)
- END;
- ELSIF (recentCommentItem IS SyntaxTree.CasePart) THEN
- IF recentCommentItem(SyntaxTree.CasePart).comment = NIL THEN
- recentCommentItem(SyntaxTree.CasePart).SetComment(comment)
- END;
- (* LYNX+
- ELSIF (recentCommentItem IS SyntaxTree.WithPart) THEN
- IF recentCommentItem(SyntaxTree.WithPart).comment = NIL THEN
- recentCommentItem(SyntaxTree.WithPart).SetComment(comment)
- END;
- -LYNX *)
- END;
- comment.SetItem(recentCommentItem, TRUE);
- recentComment := NIL;
- recentCommentItem := NIL
- END;
- END;
- END;
- error := ~scanner.GetNextSymbol(symbol);
- END;
- END NextSymbol;
- (** Check if current symbol equals sym. If yes then return true, return false otherwise *)
- PROCEDURE Peek(token: Scanner.Token): BOOLEAN;
- VAR comment: SyntaxTree.Comment;
- BEGIN
- WHILE ~error & (symbol.token = Scanner.Comment) DO
- comment := SyntaxTree.NewComment(symbol.position, currentScope, symbol.string^, symbol.stringLength);
- moduleScope.AddComment(comment);
- IF recentComment = NIL THEN
- recentComment := comment;
- END;
- error := ~scanner.GetNextSymbol(symbol);
- END;
- RETURN symbol.token = token
- END Peek;
- (** Check if the current symbol equals sym. If yes then read next symbol, report error otherwise. Returns success value *)
- PROCEDURE Mandatory(token: Scanner.Token): BOOLEAN;
- BEGIN
- (* @@@ *)
- (*
- KernelLog.String("Mandatory: want ");
- KernelLog.Int(token, 1);
- KernelLog.String(" have ");
- KernelLog.Int(symbol.token, 1);
- KernelLog.Ln();
- *)
- (* because of NextSymbol! *)
- ASSERT(token # Scanner.Identifier);
- ASSERT(token # Scanner.IntegerLiteral);
- ASSERT(token # Scanner.RealLiteral);
- ASSERT(token # Scanner.CharacterLiteral);
- ASSERT(token # Scanner.StringLiteral);
- IF ~Peek(token) THEN
- Error(symbol.position, token, "");
- RETURN FALSE
- ELSE
- NextSymbol;
- RETURN TRUE
- END
- END Mandatory;
- (** Check if the current symbol equals sym. If yes then read next symbol, report error otherwise *)
- PROCEDURE Check(token: Scanner.Token);
- VAR b: BOOLEAN;
- BEGIN
- b := Mandatory(token);
- END Check;
- (** Check if current symbol is an identifier. If yes then copy identifier to name and get next symbol,
- report error otherwise and set name to empty name. Returns success value *)
- PROCEDURE MandatoryIdentifier(VAR name: SyntaxTree.Identifier): BOOLEAN;
- BEGIN
- IF Peek(Scanner.Identifier) THEN
- name := symbol.identifier;
- NextSymbol;
- RETURN TRUE
- ELSE
- Error(symbol.position, Scanner.Identifier, "");
- name := SyntaxTree.invalidIdentifier;
- RETURN FALSE
- END
- END MandatoryIdentifier;
- (** Expect an identifier (using MandatoryIdentifier) and return identifier object **)
- PROCEDURE Identifier(VAR position: Position): SyntaxTree.Identifier;
- VAR name: SyntaxTree.Identifier;
- identifier: SyntaxTree.Identifier;
- BEGIN
- position := symbol.position;
- IF MandatoryIdentifier(name) THEN
- identifier := name;
- ELSE
- identifier := SyntaxTree.invalidIdentifier;
- END;
- RETURN identifier
- END Identifier;
- (** Check if current symbol equals sym. If yes then get next symbol, return false otherwise *)
- PROCEDURE Optional(token: Scanner.Token): BOOLEAN;
- BEGIN
- (* do not use for Identifier or literal if the result is needed ! *)
- IF Peek(token) THEN
- NextSymbol;
- RETURN TRUE
- ELSE
- RETURN FALSE
- END
- END Optional;
- (* ignore one ore more symbols of type token *)
- PROCEDURE Ignore(token: Scanner.Token);
- BEGIN
- WHILE Optional(token) DO
- (* void *)
- END;
- END Ignore;
- (** Handling comments **)
- PROCEDURE SetNextInComment(c: SyntaxTree.Comment; this: ANY);
- BEGIN
- WHILE c # NIL DO
- c.SetItem(this, FALSE);
- c := c.nextComment
- END;
- END SetNextInComment;
- PROCEDURE CommentSymbol(symbol: SyntaxTree.Symbol);
- BEGIN
- IF (recentComment # NIL) (* & (recentComment.nextSymbol = NIL) *) THEN
- symbol.SetComment(recentComment);
- SetNextInComment(recentComment, symbol);
- recentComment := NIL
- END;
- recentLine := scanner.position.line;
- recentCommentItem := symbol;
- END CommentSymbol;
- (** Mapping tokens to AST operators **)
- (*
- Mapping table for all punctuation tokens
- Lynx Fox
- ------------------------------------------------------------
- Exclamation* = 1; (* ! *) Not
- ExclamationEqual* = 2; (* != *) Unequal
- Percent* = 3; (* % *) lynx@binop (rem)
- PercentEqual* = 4; (* %= *) lynx@asop (rem)
- And* = 5; (* & *) lynx@binop (and)
- AndEqual* = 6; (* &= *) lynx@asop (and)
- AndAnd* = 7; (* && *) And
- LeftParenthesis* = 8; (* ( *) N/A
- RightParenthesis* = 9; (* ) *) N/A
- Times* = 10; (* * *) Times
- TimesEqual* = 11; (* *= *) lynx@asop (mul)
- Plus* = 12; (* + *) Plus
- PlusEqual* = 13; (* += *) lynx@asop (add)
- PlusPlus* = 14; (* ++ *) lynx@asop (add)
- Comma* = 15; (* , *) N/A
- Minus* = 16; (* - *) Minus
- MinusEqual* = 17; (* -= *) lynx@asop (sub)
- MinusMinus* = 18; (* -- *) lynx@asop (sub)
- Period* = 19; (* . *) N/A
- Slash* = 20; (* / *) lynx@binop (div)
- SlashEqual* = 21; (* /= *) lynx@asop (div)
- Colon* = 22; (* : *) N/A
- Semicolon* = 23; (* ; *) N/A
- Less* = 24; (* < *) Less
- LessEqual* = 25; (* <= *) LessEqual
- LeftShift* = 26; (* << *) lynx@binop (shl)
- LeftShiftEqual* = 27; (* <<= *) lynx@asop (shl)
- Equal* = 28; (* = *) N/A
- EqualEqual* = 29; (* == *) Equal
- Greater* = 30; (* > *) Greater
- GreaterEqual* = 31; (* >= *) GreaterEqual
- RightShift* = 32; (* >> *) lynx@binop (shr)
- RightShiftEqual* = 33; (* >>= *) lynx@asop (shr)
- LeftBracket* = 34; (* [ *) N/A
- RightBracket* = 35; (* ] *) N/A
- Arrow* = 36; (* ^ *) lynx@binop (xor)
- ArrowEqual* = 37; (* ^= *) lynx@asop (xor)
- LeftBrace* = 38; (* { *) N/A
- Bar* = 39; (* | *) lynx@binop (or)
- BarEqual* = 40; (* |= *) lynx@asop (or)
- BarBar* = 41; (* || *) Or
- RightBrace* = 42; (* } *) N/A
- Tilde* = 43; (* ~ *) lynx@unop (not)
- *)
- PROCEDURE MapOperator(token: Scanner.Token): LONGINT;
- VAR operator: LONGINT;
- BEGIN
- CASE token OF
- Scanner.Exclamation:
- operator := FoxScanner.Not;
- | Scanner.ExclamationEqual:
- operator := FoxScanner.Unequal;
- | Scanner.Percent, Scanner.PercentEqual:
- operator := 256 + Global.LynxOpRem;
- | Scanner.And, Scanner.AndEqual:
- operator := 256 + Global.LynxOpAnd;
- | Scanner.AndAnd:
- operator := FoxScanner.And;
- | Scanner.Times:
- operator := FoxScanner.Times;
- | Scanner.TimesEqual:
- operator := 256 + Global.LynxOpMul;
- | Scanner.Plus:
- operator := FoxScanner.Plus;
- | Scanner.PlusEqual, Scanner.PlusPlus:
- operator := 256 + Global.LynxOpAdd;
- | Scanner.Minus:
- operator := FoxScanner.Minus;
- | Scanner.MinusEqual, Scanner.MinusMinus:
- operator := 256 + Global.LynxOpSub;
- | Scanner.Slash, Scanner.SlashEqual:
- operator := 256 + Global.LynxOpDiv;
- | Scanner.Less:
- operator := FoxScanner.Less;
- | Scanner.LessEqual:
- operator := FoxScanner.LessEqual;
- | Scanner.LeftShift, Scanner.LeftShiftEqual:
- operator := 256 + Global.LynxOpShl;
- | Scanner.EqualEqual:
- operator := FoxScanner.Equal;
- | Scanner.Greater:
- operator := FoxScanner.Greater;
- | Scanner.GreaterEqual:
- operator := FoxScanner.GreaterEqual;
- | Scanner.RightShift, Scanner.RightShiftEqual:
- operator := 256 + Global.LynxOpShr;
- | Scanner.Arrow, Scanner.ArrowEqual:
- operator := 256 + Global.LynxOpXor;
- | Scanner.Bar, Scanner.BarEqual:
- operator := 256 + Global.LynxOpOr;
- | Scanner.BarBar:
- operator := FoxScanner.Or;
- | Scanner.Tilde:
- operator := 256 + Global.LynxOpNot;
- END;
- RETURN operator;
- END MapOperator;
- PROCEDURE NewUnaryExpression(
- position: Position;
- operand: SyntaxTree.Expression;
- operator: LONGINT): SyntaxTree.Expression;
- VAR expressionList: SyntaxTree.ExpressionList;
- expression: SyntaxTree.Expression;
- designator: SyntaxTree.Designator;
- BEGIN
- operator := MapOperator(operator);
- IF operator < 256 THEN
- expression := SyntaxTree.NewUnaryExpression(position, operand, operator);
- ELSE
- expressionList := SyntaxTree.NewExpressionList();
- expression := SyntaxTree.NewIntegerValue(position, operator-256);
- expressionList.AddExpression(expression);
- expressionList.AddExpression(operand);
- designator := SyntaxTree.NewIdentifierDesignator(position, lynxUnop);
- expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
- END;
- RETURN expression;
- END NewUnaryExpression;
- PROCEDURE NewBinaryExpression(
- position: Position;
- left, right: SyntaxTree.Expression;
- operator: LONGINT): SyntaxTree.Expression;
- VAR expressionList: SyntaxTree.ExpressionList;
- expression: SyntaxTree.Expression;
- designator: SyntaxTree.Designator;
- BEGIN
- operator := MapOperator(operator);
- IF operator < 256 THEN
- expression := SyntaxTree.NewBinaryExpression(position, left, right, operator);
- ELSE
- expressionList := SyntaxTree.NewExpressionList();
- expression := SyntaxTree.NewIntegerValue(position, operator-256);
- expressionList.AddExpression(expression);
- expressionList.AddExpression(left);
- expressionList.AddExpression(right);
- designator := SyntaxTree.NewIdentifierDesignator(position, lynxBinop);
- expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
- END;
- RETURN expression;
- END NewBinaryExpression;
- PROCEDURE NewTypeExpression(position: Position): SyntaxTree.Expression;
- BEGIN
- RETURN SyntaxTree.NewIdentifierDesignator(position, lynxType);
- END NewTypeExpression;
- PROCEDURE NewReceiveExpression(
- position: Position; left, right: SyntaxTree.Expression): SyntaxTree.Expression;
- VAR expressionList: SyntaxTree.ExpressionList;
- expression: SyntaxTree.Expression;
- designator: SyntaxTree.Designator;
- BEGIN
- expressionList := SyntaxTree.NewExpressionList();
- expressionList.AddExpression(left);
- expressionList.AddExpression(right);
- designator := SyntaxTree.NewIdentifierDesignator(position, lynxRecvnb);
- expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
- RETURN expression;
- END NewReceiveExpression;
- PROCEDURE MapNumberType(numberType: LONGINT): LONGINT;
- BEGIN
- CASE numberType OF
- Scanner.IntNumber:
- numberType := FoxScanner.Longint;
- | Scanner.LongNumber:
- numberType := FoxScanner.Hugeint;
- | Scanner.FloatNumber:
- numberType := FoxScanner.Real;
- | Scanner.DoubleNumber:
- numberType := FoxScanner.Longreal;
- END;
- RETURN numberType;
- END MapNumberType;
- (*
- ACHTUNG: Initializers of members of modules, classes, structs,
- cells, and cellnets are collected in a special statement
- block. This block is inserted as the first statement in
- the corresponding constructors.
- TODO: This feature is not yet implemented. Initializers are
- collected but not inserted in constructors. Implement what is missing.
- *)
- (* create a statement block to collect initializers *)
- PROCEDURE EnterInit;
- VAR block: SyntaxTree.StatementBlock;
- BEGIN
- block := SyntaxTree.NewStatementBlock(invalidPosition, NIL, NIL);
- initOuter := block;
- initStatements := SyntaxTree.NewStatementSequence();
- block.SetStatementSequence(initStatements);
- END EnterInit;
- (** Parsing according to the EBNF **)
- (**
- type-name:
- identifier
- module-name '.' identifier
- **)
- PROCEDURE QualifiedIdentifier(): SyntaxTree.QualifiedIdentifier;
- VAR prefix, suffix: SyntaxTree.Identifier;
- qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
- position0, position1: Position;
- BEGIN
- IF Trace THEN
- S("QualifiedIdentifier")
- END;
- prefix := Identifier(position0);
- IF prefix # SyntaxTree.invalidIdentifier THEN
- IF ~Optional(Scanner.Period) THEN
- suffix := prefix;
- prefix := SyntaxTree.invalidIdentifier; (* empty *)
- ELSE
- suffix := Identifier(position1);
- END;
- qualifiedIdentifier := SyntaxTree.NewQualifiedIdentifier(position0, prefix, suffix);
- ELSE
- qualifiedIdentifier := SyntaxTree.invalidQualifiedIdentifier;
- END;
- IF Trace THEN
- E("QualifiedIdentifier")
- END;
- RETURN qualifiedIdentifier
- END QualifiedIdentifier;
- (**
- expression-list:
- expression
- expression-list ',' expression
- **)
- PROCEDURE ExpressionList(expressionList: SyntaxTree.ExpressionList);
- VAR expression: SyntaxTree.Expression;
- BEGIN
- IF Trace THEN
- S("ExpressionList")
- END;
- REPEAT
- expression := Expression();
- expressionList.AddExpression(expression);
- UNTIL ~Optional(Scanner.Comma);
- IF Trace THEN
- E("ExpressionList")
- END;
- END ExpressionList;
- (**
- argument-list:
- argument
- argument-list ',' argument
- argument:
- expression
- 'ref' variable-reference
- variable-reference:
- expression
- **)
- PROCEDURE ArgumentList(expressionList: SyntaxTree.ExpressionList);
- VAR expression: SyntaxTree.Expression;
- modifier: LONGINT;
- BEGIN
- IF Trace THEN
- S("ArgumentList")
- END;
- REPEAT
- IF Optional(Scanner.Ref) THEN
- modifier := Scanner.Ref;
- ELSE
- modifier := -1;
- END;
- (*
- ACHTUNG: Modifiers cannot be validated without AST modifications,
- therefore 'modifier' value is not used in this release.
- *)
- expression := Expression();
- expressionList.AddExpression(expression);
- UNTIL ~Optional(Scanner.Comma);
- IF Trace THEN
- E("ArgumentList")
- END;
- END ArgumentList;
- (**
- primary-expression:
- array-creation-expression
- primary-no-array-creation-expression
- primary-no-array-creation-expression:
- literal
- simple-name
- parenthesized-expression
- member-access
- invocation-expression
- element-access
- this-access
- base-access
- object-creation-expression
- delegate-creation-expression
- receive-expression
- literal:
- boolean-literal
- integer-literal
- real-literal
- character-literal
- string-literal
- null-literal
- boolean-literal:
- 'true'
- 'false'
- null-literal:
- 'null'
- simple-name:
- identifier
- parenthesized-expression:
- '(' expression ')'
- member-access:
- primary-expression '.' identifier
- invocation-expression:
- primary-expression '(' [argument-list] ')'
- element-access:
- primary-no-array-creation-expression '[' expression-list ']'
- this-access:
- 'this'
- base-access:
- 'base' '.' identifier
- object-creation-expression:
- 'new' non-array-type '(' [argument-list] ')'
- array-creation-expression:
- 'new' non-array-type '[' expression-list ']' [rank-specifiers]
- delegate-creation-expression:
- 'new' delegate-type '(' expression ')'
- receive-expression:
- primary-expression '??' primary-expression
- **)
- PROCEDURE Accessors(expression: SyntaxTree.Expression; arrayCreation: BOOLEAN): SyntaxTree.Expression;
- VAR identifier: SyntaxTree.Identifier;
- expressionList: SyntaxTree.ExpressionList;
- position: Position;
- BEGIN
- LOOP
- position := symbol.position;
- IF Optional(Scanner.Period) THEN
- identifier := Identifier(position);
- expression := SyntaxTree.NewSelectorDesignator(position, expression(SyntaxTree.Designator), identifier);
- ELSIF Optional(Scanner.LeftParenthesis) THEN
- expressionList := SyntaxTree.NewExpressionList();
- IF ~Optional(Scanner.RightParenthesis) THEN
- ArgumentList(expressionList);
- Check(Scanner.RightParenthesis);
- END;
- expression := SyntaxTree.NewParameterDesignator(position, expression(SyntaxTree.Designator), expressionList);
- ELSIF (~arrayCreation) & Optional(Scanner.LeftBracket) THEN
- expressionList := SyntaxTree.NewExpressionList();
- ExpressionList(expressionList);
- Check(Scanner.RightBracket);
- (* ACHTUNG: 27-09-2012
- expression := SyntaxTree.NewArrowDesignator(position, expression);
- *)
- expression := SyntaxTree.NewBracketDesignator(position, expression(SyntaxTree.Designator), expressionList);
- ELSE
- EXIT;
- END;
- END;
- RETURN expression;
- END Accessors;
- PROCEDURE PrimaryExpression(): SyntaxTree.Expression;
- VAR expression: SyntaxTree.Expression;
- designator: SyntaxTree.Designator;
- realValue: SyntaxTree.RealValue;
- identifier: SyntaxTree.Identifier;
- type: SyntaxTree.Type;
- typeExpression: SyntaxTree.Expression;
- expressionList: SyntaxTree.ExpressionList;
- position: Position;
- arrayCreation: BOOLEAN;
- arrayType: SyntaxTree.ArrayType;
- pointerType: SyntaxTree.PointerType;
- rightExpression: SyntaxTree.Expression;
- i, n: LONGINT;
- BEGIN
- IF Trace THEN
- S("PrimaryExpression")
- END;
- position := symbol.position;
- arrayCreation := FALSE;
- IF Peek(Scanner.True) THEN
- expression := SyntaxTree.NewBooleanValue(position, TRUE);
- NextSymbol;
- ELSIF Peek(Scanner.False) THEN
- expression := SyntaxTree.NewBooleanValue(position, FALSE);
- NextSymbol;
- ELSIF Peek(Scanner.IntegerLiteral) THEN
- IF symbol.numberType = Scanner.IntNumber THEN
- expression := SyntaxTree.NewIntegerValue(position, symbol.integer);
- ELSIF symbol.numberType = Scanner.LongNumber THEN
- expression := SyntaxTree.NewIntegerValue(position, symbol.hugeint);
- ELSE
- HALT(100);
- END;
- NextSymbol;
- ELSIF Peek(Scanner.RealLiteral) THEN
- realValue := SyntaxTree.NewRealValue(position, symbol.real, symbol.numberType);
- expression := realValue;
- NextSymbol;
- ELSIF Peek(Scanner.CharacterLiteral) THEN
- expression := SyntaxTree.NewCharacterValue(position, symbol.character);
- NextSymbol;
- ELSIF Peek(Scanner.StringLiteral) THEN
- (*
- TODO: Revise this: may need a string constructor wrapper ...
- ... and symbol.stringLength may be important too
- *)
- expression := SyntaxTree.NewStringValue(position, symbol.string);
- NextSymbol;
- ELSIF Peek(Scanner.Identifier) THEN
- identifier := Identifier(position);
- identifier := localIdentTable.Find(identifier);
- expression := SyntaxTree.NewIdentifierDesignator(position, identifier);
- ELSIF Peek(Scanner.Null) THEN
- expression := SyntaxTree.NewNilValue(position);
- NextSymbol;
- ELSIF Optional(Scanner.LeftParenthesis) THEN
- expression := Expression();
- Check(Scanner.RightParenthesis);
- ELSIF Optional(Scanner.This) THEN
- expression := SyntaxTree.NewSelfDesignator(position,NIL);
- ELSIF Optional(Scanner.Base) THEN
- Check(Scanner.Period);
- position := symbol.position;
- identifier := Identifier(position);
- expression := SyntaxTree.NewIdentifierDesignator(position, identifier);
- expression := SyntaxTree.NewArrowDesignator(position, expression(SyntaxTree.Designator));
- ELSIF Optional(Scanner.New) THEN
- type := NonArrayType();
- expressionList := SyntaxTree.NewExpressionList();
- typeExpression := NewTypeExpression(position);
- expressionList.AddExpression(typeExpression);
- IF Optional(Scanner.LeftBracket) THEN
- arrayCreation := TRUE;
- ExpressionList(expressionList);
- Check(Scanner.RightBracket);
- WHILE Optional(Scanner.LeftBracket) DO
- type := RankSpecifier(type);
- Check(Scanner.RightBracket);
- END;
- n := expressionList.Length() - 1;
- FOR i := 1 TO n DO
- arrayType := SyntaxTree.NewArrayType(position, currentScope, SyntaxTree.Open);
- arrayType.SetArrayBase(type);
- type := arrayType;
- END;
- pointerType := SyntaxTree.NewPointerType(position, currentScope);
- pointerType.SetPointerBase(type);
- type := pointerType;
- END;
- typeExpression.SetType(type);
- IF ~arrayCreation THEN
- Check(Scanner.LeftParenthesis);
- IF ~Optional(Scanner.RightParenthesis) THEN
- ArgumentList(expressionList);
- Check(Scanner.RightParenthesis);
- END;
- designator := SyntaxTree.NewIdentifierDesignator(position, lynxNewobj);
- expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
- ELSE
- designator := SyntaxTree.NewIdentifierDesignator(position, lynxNewarr);
- expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
- END;
- ELSE
- Error(symbol.position, Basic.InvalidCode, "Invalid primary expression");
- NextSymbol;
- expression := SyntaxTree.invalidExpression;
- END;
- expression := Accessors(expression, arrayCreation);
- position := symbol.position;
- IF Optional(Scanner.QuestionQuestion) THEN
- rightExpression := PrimaryExpression();
- expression := NewReceiveExpression(position, expression, rightExpression);
- END;
- IF Trace THEN
- E("PrimaryExpression")
- END;
- RETURN expression;
- END PrimaryExpression;
- (**
- unary-expression:
- primary-expression
- '+' unary-expression
- '-' unary-expression
- '!' unary-expression
- '~' unary-expression
- cast-expression
- **)
- PROCEDURE UnaryExpression(): SyntaxTree.Expression;
- VAR expression: SyntaxTree.Expression;
- operator: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("UnaryExpression")
- END;
- position := symbol.position;
- IF Peek(Scanner.Plus) OR Peek(Scanner.Minus) OR
- Peek(Scanner.Exclamation) OR Peek(Scanner.Tilde) THEN
- operator := symbol.token;
- NextSymbol;
- expression := UnaryExpression();
- expression := NewUnaryExpression(position, expression, operator);
- ELSE
- (* TODO: Implement cast-expression *)
- expression := PrimaryExpression();
- END;
- IF Trace THEN
- E("UnaryExpression")
- END;
- RETURN expression;
- END UnaryExpression;
- (**
- multiplicative-expression:
- unary-expression
- multiplicative-expression '*' unary-expression
- multiplicative-expression '/' unary-expression
- multiplicative-expression '%' unary-expression
- **)
- PROCEDURE MultiplicativeExpression(): SyntaxTree.Expression;
- VAR expression, rightExpression: SyntaxTree.Expression;
- operator: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("MultiplicativeExpression")
- END;
- position := symbol.position;
- expression := UnaryExpression();
- WHILE Peek(Scanner.Times) OR Peek(Scanner.Slash) OR Peek(Scanner.Percent) DO
- operator := symbol.token;
- NextSymbol;
- rightExpression := UnaryExpression();
- expression := NewBinaryExpression(position, expression, rightExpression, operator);
- END;
- IF Trace THEN
- E("MultiplicativeExpression")
- END;
- RETURN expression;
- END MultiplicativeExpression;
- (**
- additive-expression:
- multiplicative-expression
- additive-expression '+' multiplicative-expression
- additive-expression '' multiplicative-expression
- **)
- PROCEDURE AdditiveExpression(): SyntaxTree.Expression;
- VAR expression, rightExpression: SyntaxTree.Expression;
- operator: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("AdditiveExpression")
- END;
- position := symbol.position;
- expression := MultiplicativeExpression();
- WHILE Peek(Scanner.Plus) OR Peek(Scanner.Minus) DO
- operator := symbol.token;
- NextSymbol;
- rightExpression := MultiplicativeExpression();
- expression := NewBinaryExpression(position, expression, rightExpression, operator);
- END;
- IF Trace THEN
- E("AdditiveExpression")
- END;
- RETURN expression;
- END AdditiveExpression;
- (**
- shift-expression:
- additive-expression
- shift-expression '<<' additive-expression
- shift-expression '>>' additive-expression
- **)
- PROCEDURE ShiftExpression(): SyntaxTree.Expression;
- VAR expression, rightExpression: SyntaxTree.Expression;
- operator: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("ShiftExpression")
- END;
- position := symbol.position;
- expression := AdditiveExpression();
- WHILE Peek(Scanner.LeftShift) OR Peek(Scanner.RightShift) DO
- operator := symbol.token;
- NextSymbol;
- rightExpression := AdditiveExpression();
- expression := NewBinaryExpression(position, expression, rightExpression, operator);
- END;
- IF Trace THEN
- E("ShiftExpression")
- END;
- RETURN expression;
- END ShiftExpression;
- (**
- relational-expression:
- shift-expression
- relational-expression '<' shift-expression
- relational-expression '>' shift-expression
- relational-expression '<=' shift-expression
- relational-expression '>=' shift-expression
- relational-expression 'is' type-name
- relational-expression 'as' type-name
- **)
- PROCEDURE RelationalExpression(): SyntaxTree.Expression;
- VAR expression, rightExpression: SyntaxTree.Expression;
- operator: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("RelationalExpression")
- END;
- position := symbol.position;
- expression := ShiftExpression();
- WHILE Peek(Scanner.Less) OR Peek(Scanner.Greater) OR
- Peek(Scanner.LessEqual) OR Peek(Scanner.GreaterEqual) OR
- Peek(Scanner.Is) OR Peek(Scanner.As) DO
- operator := symbol.token;
- NextSymbol;
- rightExpression := ShiftExpression();
- expression := NewBinaryExpression(position, expression, rightExpression, operator);
- END;
- IF Trace THEN
- E("RelationalExpression")
- END;
- RETURN expression;
- END RelationalExpression;
- (**
- equality-expression:
- relational-expression
- equality-expression '==' relational-expression
- equality-expression '!=' relational-expression
- **)
- PROCEDURE EqualityExpression(): SyntaxTree.Expression;
- VAR expression, rightExpression: SyntaxTree.Expression;
- operator: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("EqualityExpression")
- END;
- position := symbol.position;
- expression := RelationalExpression();
- WHILE Peek(Scanner.EqualEqual) OR Peek(Scanner.ExclamationEqual) DO
- operator := symbol.token;
- NextSymbol;
- rightExpression := RelationalExpression();
- expression := NewBinaryExpression(position, expression, rightExpression, operator);
- END;
- IF Trace THEN
- E("EqualityExpression")
- END;
- RETURN expression;
- END EqualityExpression;
- (**
- and-expression:
- equality-expression
- and-expression '&' equality-expression
- **)
- PROCEDURE AndExpression(): SyntaxTree.Expression;
- VAR expression, rightExpression: SyntaxTree.Expression;
- operator: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("AndExpression")
- END;
- position := symbol.position;
- expression := EqualityExpression();
- WHILE Peek(Scanner.And) DO
- operator := symbol.token;
- NextSymbol;
- rightExpression := EqualityExpression();
- expression := NewBinaryExpression(position, expression, rightExpression, operator);
- END;
- IF Trace THEN
- E("AndExpression")
- END;
- RETURN expression;
- END AndExpression;
- (**
- exclusive-or-expression:
- and-expression
- exclusive-or-expression '^' and-expression
- **)
- PROCEDURE ExclusiveOrExpression(): SyntaxTree.Expression;
- VAR expression, rightExpression: SyntaxTree.Expression;
- operator: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("ExclusiveOrExpression")
- END;
- position := symbol.position;
- expression := AndExpression();
- WHILE Peek(Scanner.Arrow) DO
- operator := symbol.token;
- NextSymbol;
- rightExpression := AndExpression();
- expression := NewBinaryExpression(position, expression, rightExpression, operator);
- END;
- IF Trace THEN
- E("ExclusiveOrExpression")
- END;
- RETURN expression;
- END ExclusiveOrExpression;
- (**
- inclusive-or-expression:
- exclusive-or-expression
- inclusive-or-expression '|' exclusive-or-expression
- **)
- PROCEDURE InclusiveOrExpression(): SyntaxTree.Expression;
- VAR expression, rightExpression: SyntaxTree.Expression;
- operator: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("InclusiveOrExpression")
- END;
- position := symbol.position;
- expression := ExclusiveOrExpression();
- WHILE Peek(Scanner.Bar) DO
- operator := symbol.token;
- NextSymbol;
- rightExpression := ExclusiveOrExpression();
- expression := NewBinaryExpression(position, expression, rightExpression, operator);
- END;
- IF Trace THEN
- E("InclusiveOrExpression")
- END;
- RETURN expression;
- END InclusiveOrExpression;
- (**
- conditional-and-expression:
- inclusive-or-expression
- conditional-and-expression '&&' inclusive-or-expression
- **)
- PROCEDURE ConditionalAndExpression(): SyntaxTree.Expression;
- VAR expression, rightExpression: SyntaxTree.Expression;
- operator: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("ConditionalAndExpression")
- END;
- position := symbol.position;
- expression := InclusiveOrExpression();
- WHILE Peek(Scanner.AndAnd) DO
- operator := symbol.token;
- NextSymbol;
- rightExpression := InclusiveOrExpression();
- expression := NewBinaryExpression(position, expression, rightExpression, operator);
- END;
- IF Trace THEN
- E("ConditionalAndExpression")
- END;
- RETURN expression;
- END ConditionalAndExpression;
- (**
- conditional-or-expression:
- conditional-and-expression
- conditional-or-expression '||' conditional-and-expression
- **)
- PROCEDURE ConditionalOrExpression(): SyntaxTree.Expression;
- VAR expression, rightExpression: SyntaxTree.Expression;
- operator: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("ConditionalOrExpression")
- END;
- position := symbol.position;
- expression := ConditionalAndExpression();
- WHILE Peek(Scanner.BarBar) DO
- operator := symbol.token;
- NextSymbol;
- rightExpression := ConditionalAndExpression();
- expression := NewBinaryExpression(position, expression, rightExpression, operator);
- END;
- IF Trace THEN
- E("ConditionalOrExpression")
- END;
- RETURN expression;
- END ConditionalOrExpression;
- (**
- expression:
- conditional-expression
- conditional-expression:
- conditional-or-expression
- **)
- PROCEDURE Expression(): SyntaxTree.Expression;
- VAR expression: SyntaxTree.Expression;
- BEGIN
- IF Trace THEN
- S("Expression")
- END;
- expression := ConditionalOrExpression();
- IF Trace THEN
- E("Expression")
- END;
- RETURN expression;
- END Expression;
- (**
- local-variable-declaration:
- type local-variable-declarators
- **)
- PROCEDURE LocalVariableDeclaration(
- statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement; type: SyntaxTree.Type);
- VAR previousStatements: SyntaxTree.StatementSequence;
- previousOuter: SyntaxTree.Statement;
- BEGIN
- IF Trace THEN
- S("LocalVariableDeclaration")
- END;
- previousStatements := initStatements;
- previousOuter := initOuter;
- initStatements := statements;
- initOuter := outer;
- IF type = NIL THEN
- type := Type();
- END;
- REPEAT
- VariableDeclarator(currentScope, {}, type, SyntaxTree.invalidIdentifier, invalidPosition);
- UNTIL ~Optional(Scanner.Comma);
- initStatements := previousStatements;
- initOuter := previousOuter;
- IF Trace THEN
- E("LocalVariableDeclaration")
- END;
- END LocalVariableDeclaration;
- (**
- local-constant-declaration:
- 'const' type constant-declarators
- **)
- PROCEDURE LocalConstantDeclaration(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR type: SyntaxTree.Type;
- BEGIN
- (* ACHTUNG: Parameters 'statements' and 'outer' are not used *)
- IF Trace THEN
- S("LocalConstantDeclaration")
- END;
- type := Type();
- REPEAT
- ConstantDeclarator(currentScope, {}, type);
- UNTIL ~Optional(Scanner.Comma);
- IF Trace THEN
- E("LocalConstantDeclaration")
- END;
- END LocalConstantDeclaration;
- (**
- block:
- '{' [statement-list] '}'
- **)
- PROCEDURE Block(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR block: SyntaxTree.StatementBlock; position: Position;
- BEGIN
- IF Trace THEN
- S("Block")
- END;
- Check(Scanner.LeftBrace);
- position := symbol.position; position.start := position.end;
- block := SyntaxTree.NewStatementBlock(position, outer, NIL);
- (* CommentStatement(block); *)
- IF ~Optional(Scanner.RightBrace) THEN
- localIdentTable.OpenScope;
- block.SetStatementSequence(StatementList(block));
- localIdentTable.CloseScope;
- Check(Scanner.RightBrace);
- END;
- statements.AddStatement(block);
- IF Trace THEN
- E("Block")
- END;
- END Block;
- (**
- expression-statement:
- statement-expression ';'
- statement-expression:
- invocation-expression
- assignment
- post-increment-expression
- post-decrement-expression
- send-expression
- receive-expression
- connect-expression
- delegate-expression
- assignment:
- primary-expression assignment-operator expression
- assignment-operator: one of
- '=' '+=' '-=' '*=' '/=' '%=' '&=' '|=' '^=' '<<=' '>>='
- post-increment-expression:
- primary-expression '++'
- post-decrement-expression:
- primary-expression '--'
- send-expression:
- primary-expression '!' expression-list
- receive-expression:
- primary-expression '?' expression-list
- connect-expression:
- primary-expression '>>' primary-expression
- delegate-expression:
- primary-expression '<=' primary-expression
- **)
- PROCEDURE NewAsopStatement(
- position: Position;
- operator: LONGINT;
- left: SyntaxTree.Designator;
- right: SyntaxTree.Expression;
- outer: SyntaxTree.Statement): SyntaxTree.Statement;
- VAR expressionList: SyntaxTree.ExpressionList;
- expression: SyntaxTree.Expression;
- designator: SyntaxTree.Designator;
- BEGIN
- operator := MapOperator(operator);
- ASSERT(operator >= 256);
- expressionList := SyntaxTree.NewExpressionList();
- expression := SyntaxTree.NewIntegerValue(position, operator-256);
- expressionList.AddExpression(expression);
- expressionList.AddExpression(left);
- expressionList.AddExpression(right);
- designator := SyntaxTree.NewIdentifierDesignator(position, lynxAsop);
- designator := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
- RETURN SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
- END NewAsopStatement;
- (* ACHTUNG: LYNX 15-MAY-2013 *)
- PROCEDURE PatchPortReference(expression: SyntaxTree.Expression): SyntaxTree.Expression;
- VAR result: SyntaxTree.Expression;
- parameterDesignator: SyntaxTree.ParameterDesignator;
- parameters: SyntaxTree.ExpressionList;
- p0: SyntaxTree.Expression;
- identifierDesignator: SyntaxTree.IdentifierDesignator;
- bracketDesignator: SyntaxTree.BracketDesignator;
- left, left2: SyntaxTree.Expression;
- BEGIN
- IF ~(expression IS SyntaxTree.ParameterDesignator) THEN
- result := expression;
- ELSE
- parameterDesignator := expression(SyntaxTree.ParameterDesignator);
- parameters := parameterDesignator.parameters;
- IF parameters.Length() # 1 THEN
- result := expression;
- ELSE
- p0 := parameters.GetExpression(0);
- IF p0 IS SyntaxTree.IdentifierDesignator THEN
- (* C(P) -> C.P *)
- left := parameterDesignator.left;
- identifierDesignator := p0(SyntaxTree.IdentifierDesignator);
- result :=
- SyntaxTree.NewSelectorDesignator(
- expression.position, left(SyntaxTree.Designator), identifierDesignator.identifier);
- ELSIF p0 IS SyntaxTree.BracketDesignator THEN
- bracketDesignator := p0(SyntaxTree.BracketDesignator);
- left2 := bracketDesignator.left;
- IF left2 IS SyntaxTree.IdentifierDesignator THEN
- (* C(P[I]) -> C.P[I] *)
- left := parameterDesignator.left;
- identifierDesignator := left2(SyntaxTree.IdentifierDesignator);
- result :=
- SyntaxTree.NewBracketDesignator(
- expression.position,
- SyntaxTree.NewSelectorDesignator(
- expression.position,
- left(SyntaxTree.Designator),
- identifierDesignator.identifier),
- bracketDesignator.parameters);
- ELSE
- result := expression;
- END;
- ELSE
- result := expression;
- END;
- END;
- END;
- RETURN result;
- END PatchPortReference;
- PROCEDURE NewPortStatement(
- position: Position;
- name: SyntaxTree.Identifier;
- left: SyntaxTree.Designator;
- right: SyntaxTree.Expression;
- outer: SyntaxTree.Statement): SyntaxTree.Statement;
- VAR expressionList: SyntaxTree.ExpressionList;
- designator: SyntaxTree.Designator;
- BEGIN
- expressionList := SyntaxTree.NewExpressionList();
- expressionList.AddExpression(left);
- expressionList.AddExpression(right);
- designator := SyntaxTree.NewIdentifierDesignator(position, name);
- designator := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
- RETURN SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
- END NewPortStatement;
- PROCEDURE StatementExpression(
- statements: SyntaxTree.StatementSequence;
- outer: SyntaxTree.Statement;
- expression: SyntaxTree.Expression): BOOLEAN;
- VAR designator: SyntaxTree.Designator;
- expressionList: SyntaxTree.ExpressionList;
- statement: SyntaxTree.Statement;
- operator: LONGINT;
- position: Position;
- length, i: LONGINT;
- temp: SyntaxTree.Expression;
- BEGIN
- IF Trace THEN
- S("StatementExpression")
- END;
- (* ACHTUNG: Only expressions of type SyntaxTree.Designator are supported
- in place of primary-expression in the above productions. This is
- required for compatibility with Fox back-end *)
- statement := NIL;
- position := symbol.position;
- IF expression = NIL THEN
- expression := PrimaryExpression();
- END;
- IF ~(expression IS SyntaxTree.Designator) THEN
- Error(position, Basic.InvalidCode, "Invalid expression statement");
- ELSE
- designator := expression(SyntaxTree.Designator);
- position := symbol.position;
- IF Optional(Scanner.Equal) THEN
- expression := Expression();
- statement := SyntaxTree.NewAssignment(position, designator, expression, outer);
- ELSIF Peek(Scanner.PlusEqual) OR Peek(Scanner.MinusEqual) OR
- Peek(Scanner.TimesEqual) OR Peek(Scanner.SlashEqual) OR
- Peek(Scanner.PercentEqual) OR Peek(Scanner.AndEqual) OR
- Peek(Scanner.BarEqual) OR Peek(Scanner.ArrowEqual) OR
- Peek(Scanner.LeftShiftEqual) OR Peek(Scanner.RightShiftEqual) THEN
- operator := symbol.token;
- NextSymbol;
- (* lynx@asop(operator, designator, expression) *)
- expression := Expression();
- statement := NewAsopStatement(position, operator, designator, expression, outer);
- ELSIF Optional(Scanner.PlusPlus) THEN
- (* lynx@asop(PlusEqual, designator, 1) *)
- operator := Scanner.PlusPlus;
- expression := SyntaxTree.NewIntegerValue(position, 1);
- statement := NewAsopStatement(position, operator, designator, expression, outer);
- ELSIF Optional(Scanner.MinusMinus) THEN
- (* lynx@asop(MinusEqual, designator, 1) *)
- operator := Scanner.MinusMinus;
- expression := SyntaxTree.NewIntegerValue(position, 1);
- statement := NewAsopStatement(position, operator, designator, expression, outer);
- (* ACHTUNG: LYNX 15-MAY-2013
- ELSIF Optional(Scanner.Exclamation) THEN
- (* lynx@send(designator, expression) *)
- expression := Expression();
- statement := NewPortStatement(position, lynxSend, designator, expression, outer);
- ELSIF Optional(Scanner.Question) THEN
- (* lynx@receive(designator, expression) *)
- expression := Expression();
- statement := NewPortStatement(position, lynxReceive, designator, expression, outer);
- *)
- ELSIF Optional(Scanner.Exclamation) THEN
- (* lynx@send(designator, expression) *)
- expressionList := SyntaxTree.NewExpressionList();
- ExpressionList(expressionList);
- length := expressionList.Length();
- FOR i := 0 TO length - 1 DO
- expression := expressionList.GetExpression(i);
- statement := NewPortStatement(position, lynxSend, designator, expression, outer);
- IF i < length - 1 THEN
- statements.AddStatement(statement);
- END;
- END;
- ELSIF Optional(Scanner.Question) THEN
- (* lynx@receive(designator, expression) *)
- expressionList := SyntaxTree.NewExpressionList();
- ExpressionList(expressionList);
- length := expressionList.Length();
- FOR i := 0 TO length - 1 DO
- expression := expressionList.GetExpression(i);
- statement := NewPortStatement(position, lynxReceive, designator, expression, outer);
- IF i < length - 1 THEN
- statements.AddStatement(statement);
- END;
- END;
- (* ACHTUNG: LYNX 15-MAY-2013
- ELSIF Optional(Scanner.RightShift) THEN
- (* lynx@connect(designator, expression) *)
- expression := PrimaryExpression();
- statement := NewPortStatement(position, lynxConnect, designator, expression, outer);
- ELSIF Optional(Scanner.LessEqual) THEN
- (* lynx@delegate(designator, expression) *)
- expression := PrimaryExpression();
- statement := NewPortStatement(position, lynxDelegate, designator, expression, outer);
- *)
- ELSIF Optional(Scanner.RightShift) THEN
- (* lynx@connect(designator, expression) *)
- expression := PrimaryExpression();
- temp := PatchPortReference(designator);
- designator := temp(SyntaxTree.Designator);
- expression := PatchPortReference(expression);
- statement := NewPortStatement(position, lynxConnect, designator, expression, outer);
- ELSIF Optional(Scanner.LessEqual) THEN
- (* lynx@delegate(designator, expression) *)
- expression := PrimaryExpression();
- temp := PatchPortReference(designator);
- designator := temp(SyntaxTree.Designator);
- expression := PatchPortReference(expression);
- statement := NewPortStatement(position, lynxDelegate, designator, expression, outer);
- ELSIF designator IS SyntaxTree.ParameterDesignator THEN
- statement := SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
- ELSE
- Error(position, Basic.InvalidCode, "Invalid expression statement");
- END;
- END;
- IF statement # NIL THEN
- (* CommentStatement(statement); *)
- statements.AddStatement(statement);
- END;
- IF Trace THEN
- E("StatementExpression")
- END;
- RETURN statement # NIL;
- END StatementExpression;
- PROCEDURE ExpressionStatement(
- statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement): BOOLEAN;
- VAR b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("ExpressionStatement")
- END;
- b := StatementExpression(statements, outer, NIL);
- Check(Scanner.Semicolon);
- IF Trace THEN
- E("ExpressionStatement")
- END;
- RETURN b;
- END ExpressionStatement;
- (**
- if-statement:
- 'if' '(' boolean-expression ')' embedded-statement
- 'if' '(' boolean-expression ')' embedded-statement 'else' embedded-statement
- **)
- PROCEDURE IfStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR expression: SyntaxTree.Expression;
- ifStatement: SyntaxTree.IfStatement;
- elsePart: SyntaxTree.IfPart;
- statementSequence: SyntaxTree.StatementSequence;
- b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("IfStatement")
- END;
- Check(Scanner.If);
- ifStatement := SyntaxTree.NewIfStatement(symbol.position, outer);
- (* CommentStatement(ifStatement); *)
- Check(Scanner.LeftParenthesis);
- expression := Expression();
- Check(Scanner.RightParenthesis);
- ifStatement.ifPart.SetCondition(expression);
- statementSequence := SyntaxTree.NewStatementSequence();
- b := EmbeddedStatement(statementSequence, ifStatement);
- ifStatement.ifPart.SetStatements(statementSequence);
- IF Optional(Scanner.Else) THEN
- statementSequence := SyntaxTree.NewStatementSequence();
- b := EmbeddedStatement(statementSequence, ifStatement);
- ifStatement.SetElsePart(statementSequence);
- END;
- statements.AddStatement(ifStatement);
- IF Trace THEN
- E("IfStatement")
- END;
- END IfStatement;
- (**
- switch-statement:
- 'switch' '(' expression ')' switch-block
- switch-block:
- '{' [switch-sections] '}'
- switch-sections:
- switch-section
- switch-sections switch-section
- switch-section:
- switch-labels statement-list
- switch-labels:
- switch-label
- switch-labels switch-label
- switch-label:
- 'case' constant-expression ':'
- 'default' ':'
- **)
- PROCEDURE SwitchSection(caseStatement: SyntaxTree.CaseStatement; VAR haveDefault: BOOLEAN);
- VAR casePart: SyntaxTree.CasePart;
- statements: SyntaxTree.StatementSequence;
- last: SyntaxTree.Statement;
- element: SyntaxTree.Expression;
- defaultSection: BOOLEAN;
- length: LONGINT; position: Position;
- BEGIN
- IF Trace THEN
- S("SwitchSection")
- END;
- casePart := SyntaxTree.NewCasePart();
- defaultSection := FALSE;
- WHILE Peek(Scanner.Case) OR Peek(Scanner.Default) DO
- (* CommentCasePart(casePart); *)
- IF Optional(Scanner.Case) THEN
- element := Expression();
- Check(Scanner.Colon);
- casePart.elements.AddExpression(element);
- ELSE
- position := symbol.position;
- Check(Scanner.Default);
- Check(Scanner.Colon);
- IF haveDefault THEN
- Error(position, Basic.InvalidCode, "Duplicate default label");
- ELSE
- defaultSection := TRUE;
- haveDefault := TRUE;
- END;
- END;
- END;
- statements := StatementList(caseStatement);
- length := statements.Length();
- IF length = 0 THEN
- Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
- ELSE
- last := statements.GetStatement(length-1);
- IF last IS SyntaxTree.ExitStatement THEN
- statements.RemoveStatement(last);
- ELSIF ~(last IS SyntaxTree.ReturnStatement) THEN
- Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
- END;
- END;
- IF ~defaultSection THEN
- casePart.SetStatements(statements);
- caseStatement.AddCasePart(casePart);
- ELSE
- (* ignore case labels, if any *)
- (* ACHTUNG: these labels will not be checked for duplicates *)
- caseStatement.SetElsePart(statements);
- END;
- IF Trace THEN
- E("SwitchSection")
- END;
- END SwitchSection;
- PROCEDURE SwitchStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR expression: SyntaxTree.Expression;
- caseStatement: SyntaxTree.CaseStatement;
- haveDefault: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("SwitchStatement")
- END;
- Check(Scanner.Switch);
- caseStatement := SyntaxTree.NewCaseStatement(symbol.position, outer);
- (* CommentStatement(caseStatement); *)
- Check(Scanner.LeftParenthesis);
- expression := Expression();
- Check(Scanner.RightParenthesis);
- caseStatement.SetVariable(expression);
- Check(Scanner.LeftBrace);
- haveDefault := FALSE;
- WHILE Peek(Scanner.Case) OR Peek(Scanner.Default) DO
- SwitchSection(caseStatement, haveDefault);
- END;
- Check(Scanner.RightBrace);
- statements.AddStatement(caseStatement);
- IF Trace THEN
- E("SwitchStatement")
- END;
- END SwitchStatement;
- (**
- select-statement:
- 'select' select-block
- select-block:
- '{' select-sections '}'
- select-sections:
- select-section
- select-sections select-section
- select-section:
- select-label statement-list
- select-label:
- 'case' [select-replicator] primary-expression '?' primary-expression ':'
- select-replicator:
- '(' integral-type simple-name 'in' expression ':' expression ')'
- **)
- (**
- Fox mapping schema:
- // LYNX
- select {
- case c ? x:
- S1;
- case (int i in m : n) d[i] ? y:
- S2;
- }
- // Fox
- lynx@newsel;
- lynx@addsel(0, 0, c);
- FOR i := m TO n DO
- lynx@addsel(1, i, d[i])
- END;
- CASE lynx@select() OF
- 0:
- c ? x;
- S1;
- | 1:
- i := lynx@selidx();
- d[i] ? y;
- S2;
- END;
- **)
- PROCEDURE NewLynxNewsel(
- position: Position; outer: SyntaxTree.Statement): SyntaxTree.Statement;
- VAR parameters: SyntaxTree.ExpressionList;
- designator: SyntaxTree.Designator;
- BEGIN
- parameters := SyntaxTree.NewExpressionList();
- designator := SyntaxTree.NewIdentifierDesignator(position, lynxNewsel);
- designator := SyntaxTree.NewParameterDesignator(position, designator, parameters);
- RETURN SyntaxTree.NewProcedureCallStatement(position, FALSE, designator, outer);
- END NewLynxNewsel;
- PROCEDURE NewLynxAddsel(
- position: Position;
- index: LONGINT;
- variable: SyntaxTree.Identifier;
- channel: SyntaxTree.Expression;
- outer: SyntaxTree.Statement): SyntaxTree.Statement;
- VAR parameters: SyntaxTree.ExpressionList;
- designator: SyntaxTree.Designator;
- BEGIN
- parameters := SyntaxTree.NewExpressionList();
- parameters.AddExpression(SyntaxTree.NewIntegerValue(position, index));
- IF variable # SyntaxTree.invalidIdentifier THEN
- parameters.AddExpression(
- SyntaxTree.NewIdentifierDesignator(position, variable));
- ELSE
- parameters.AddExpression(SyntaxTree.NewIntegerValue(position, 0));
- END;
- parameters.AddExpression(channel);
- designator := SyntaxTree.NewIdentifierDesignator(position, lynxAddsel);
- designator := SyntaxTree.NewParameterDesignator(position, designator, parameters);
- RETURN SyntaxTree.NewProcedureCallStatement(position, FALSE, designator, outer);
- END NewLynxAddsel;
- PROCEDURE NewLynxSelect(position: Position): SyntaxTree.Expression;
- VAR left: SyntaxTree.Designator;
- parameters: SyntaxTree.ExpressionList;
- BEGIN
- left := SyntaxTree.NewIdentifierDesignator(position, lynxSelect);
- parameters := SyntaxTree.NewExpressionList();
- RETURN SyntaxTree.NewParameterDesignator(position, left, parameters);
- END NewLynxSelect;
- PROCEDURE NewLynxSelidx(
- position: Position;
- variable: SyntaxTree.Identifier;
- outer: SyntaxTree.Statement): SyntaxTree.Statement;
- VAR left: SyntaxTree.Designator;
- parameters: SyntaxTree.ExpressionList;
- right: SyntaxTree.Expression;
- BEGIN
- left := SyntaxTree.NewIdentifierDesignator(position, lynxSelidx);
- parameters := SyntaxTree.NewExpressionList();
- right := SyntaxTree.NewParameterDesignator(position, left, parameters);
- left := SyntaxTree.NewIdentifierDesignator(position, variable);
- RETURN SyntaxTree.NewAssignment(position, left, right, outer);
- END NewLynxSelidx;
- PROCEDURE SelectSection(
- statements: SyntaxTree.StatementSequence;
- caseStatement: SyntaxTree.CaseStatement;
- index: LONGINT;
- outer: SyntaxTree.Statement);
- VAR typename, varname: SyntaxTree.Identifier;
- type: SyntaxTree.Type;
- variable: SyntaxTree.Variable;
- position: Position;
- from, to: SyntaxTree.Expression;
- channel, target: SyntaxTree.Expression;
- statement: SyntaxTree.Statement;
- forStatement: SyntaxTree.ForStatement;
- forBody: SyntaxTree.StatementSequence;
- designator: SyntaxTree.Designator;
- casePart: SyntaxTree.CasePart;
- caseBody: SyntaxTree.StatementSequence;
- length: LONGINT;
- last: SyntaxTree.Statement;
- BEGIN
- IF Trace THEN
- S("SelectSection")
- END;
- position := symbol.position;
- Check(Scanner.Case);
- localIdentTable.OpenScope;
- IF Optional(Scanner.LeftParenthesis) THEN
- IF Optional(Scanner.Sbyte) THEN
- typename := lynxSbyte;
- ELSIF Optional(Scanner.Short) THEN
- typename := lynxShort;
- ELSIF Optional(Scanner.Int) THEN
- typename := lynxInt;
- ELSIF Optional(Scanner.Long) THEN
- typename := lynxLong;
- ELSE
- Error(position, Basic.InvalidCode, "Missing integral type specifier");
- typename := lynxInt;
- END;
- type :=
- SyntaxTree.NewQualifiedType(
- position,
- currentScope,
- SyntaxTree.NewQualifiedIdentifier(
- position, SyntaxTree.invalidIdentifier, typename));
- varname := Identifier(position);
- varname := localIdentTable.Enter(varname);
- variable := SyntaxTree.NewVariable(position, varname);
- CommentSymbol(variable);
- variable.SetType(type);
- currentScope.AddVariable(variable);
- Check(Scanner.In);
- from := Expression();
- Check(Scanner.Colon);
- to := Expression();
- Check(Scanner.RightParenthesis);
- ELSE
- varname := SyntaxTree.invalidIdentifier;
- END;
- channel := PrimaryExpression();
- Check(Scanner.Question);
- target := PrimaryExpression();
- Check(Scanner.Colon);
- (* prolog *)
- IF varname = SyntaxTree.invalidIdentifier THEN
- statement := NewLynxAddsel(position, index, varname, channel, outer);
- statements.AddStatement(statement);
- ELSE
- forStatement := SyntaxTree.NewForStatement(symbol.position, outer);
- designator := SyntaxTree.NewIdentifierDesignator(position, varname);
- forStatement.SetVariable(designator);
- forStatement.SetFrom(from);
- forStatement.SetTo(to);
- forBody := SyntaxTree.NewStatementSequence();
- statement :=
- NewLynxAddsel(position, index, varname, channel, forStatement);
- forBody.AddStatement(statement);
- forStatement.SetStatements(forBody);
- statements.AddStatement(forStatement);
- END;
- (* case part *)
- casePart := SyntaxTree.NewCasePart();
- casePart.elements.AddExpression(SyntaxTree.NewIntegerValue(position, index));
- (* same logic as for switch: *)
- caseBody := StatementList(caseStatement);
- length := caseBody.Length();
- IF length = 0 THEN
- Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
- ELSE
- last := caseBody.GetStatement(length-1);
- IF last IS SyntaxTree.ExitStatement THEN
- caseBody.RemoveStatement(last);
- ELSIF ~(last IS SyntaxTree.ReturnStatement) THEN
- Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
- END;
- END;
- statement := NewPortStatement(position, lynxReceive, channel(SyntaxTree.Designator), target, caseStatement);
- caseBody.PrependStatement(statement);
- IF varname # SyntaxTree.invalidIdentifier THEN
- statement := NewLynxSelidx(position, varname, caseStatement);
- caseBody.PrependStatement(statement);
- END;
- casePart.SetStatements(caseBody);
- caseStatement.AddCasePart(casePart);
- localIdentTable.CloseScope;
- IF Trace THEN
- E("SelectSection")
- END;
- END SelectSection;
- PROCEDURE SelectStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR statement: SyntaxTree.Statement;
- caseStatement: SyntaxTree.CaseStatement;
- expression: SyntaxTree.Expression;
- index: LONGINT;
- position: Position;
- BEGIN
- IF Trace THEN
- S("SelectStatement")
- END;
- position := symbol.position;
- Check(Scanner.Select);
- statement := NewLynxNewsel(position, outer);
- statements.AddStatement(statement);
- caseStatement := SyntaxTree.NewCaseStatement(position, outer);
- expression := NewLynxSelect(position);
- caseStatement.SetVariable(expression);
- Check(Scanner.LeftBrace);
- index := 0;
- WHILE Peek(Scanner.Case) DO
- SelectSection(statements, caseStatement, index, outer);
- INC(index);
- END;
- position := symbol.position;
- Check(Scanner.RightBrace);
- IF index = 0 THEN
- Error(position, Basic.InvalidCode, "Empty select statement");
- END;
- statements.AddStatement(caseStatement);
- IF Trace THEN
- E("SelectStatement")
- END;
- END SelectStatement;
- (**
- while-statement:
- 'while' '(' boolean-expression ')' embedded-statement
- **)
- PROCEDURE WhileStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR expression: SyntaxTree.Expression;
- whileStatement: SyntaxTree.WhileStatement;
- statementSequence: SyntaxTree.StatementSequence;
- b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("WhileStatement")
- END;
- Check(Scanner.While);
- whileStatement := SyntaxTree.NewWhileStatement(symbol.position, outer);
- (* CommentStatement(whileStatement); *)
- Check(Scanner.LeftParenthesis);
- expression := Expression();
- Check(Scanner.RightParenthesis);
- whileStatement.SetCondition(expression);
- statementSequence := SyntaxTree.NewStatementSequence();
- b := EmbeddedStatement(statementSequence, whileStatement);
- whileStatement.SetStatements(statementSequence);
- statements.AddStatement(whileStatement);
- IF Trace THEN
- E("WhileStatement")
- END;
- END WhileStatement;
- (**
- do-statement:
- 'do' embedded-statement 'while' '(' boolean-expression ')' ';'
- **)
- PROCEDURE DoStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR expression: SyntaxTree.Expression;
- repeatStatement: SyntaxTree.RepeatStatement;
- statementSequence: SyntaxTree.StatementSequence;
- position: Position;
- b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("DoStatement")
- END;
- Check(Scanner.Do);
- repeatStatement := SyntaxTree.NewRepeatStatement(symbol.position, outer);
- (* CommentStatement(repeatStatement); *)
- statementSequence := SyntaxTree.NewStatementSequence();
- b := EmbeddedStatement(statementSequence, repeatStatement);
- repeatStatement.SetStatements(statementSequence);
- Check(Scanner.While);
- Check(Scanner.LeftParenthesis);
- position := symbol.position;
- expression := Expression();
- Check(Scanner.RightParenthesis);
- expression := NewUnaryExpression(position, expression, Scanner.Exclamation);
- repeatStatement.SetCondition(expression);
- statements.AddStatement(repeatStatement);
- IF Trace THEN
- E("DoStatement")
- END;
- END DoStatement;
- (**
- statement-expression-list:
- statement-expression
- statement-expression-list ',' statement-expression
- **)
- PROCEDURE StatementExpressionList(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("StatementExpressionList")
- END;
- REPEAT
- b := StatementExpression(statements, outer, NIL);
- UNTIL ~Optional(Scanner.Comma);
- IF Trace THEN
- E("StatementExpressionList")
- END;
- END StatementExpressionList;
- (**
- for-initializer:
- local-variable-declaration
- statement-expression-list
- **)
- PROCEDURE ForInitializer(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR isDeclaration: BOOLEAN;
- b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("ForInitializer")
- END;
- IF Peek(Scanner.Bool) OR Peek(Scanner.Sbyte) OR
- Peek(Scanner.Short) OR Peek(Scanner.Int) OR
- Peek(Scanner.Long) OR Peek(Scanner.Char) OR
- Peek(Scanner.Float) OR Peek(Scanner.Double) OR
- Peek(Scanner.Object) OR Peek(Scanner.String) THEN
- LocalVariableDeclaration(statements, outer, NIL);
- ELSIF Peek(Scanner.Identifier) THEN
- (* either local-variable-declaration or statement expression *)
- b := ExpressionOrDeclaration(statements, outer, isDeclaration);
- IF ~isDeclaration & Optional(Scanner.Comma) THEN
- StatementExpressionList(statements, outer);
- END;
- ELSE
- StatementExpressionList(statements, outer);
- END;
- IF Trace THEN
- E("ForInitializer")
- END;
- END ForInitializer;
- (**
- for-iterator:
- statement-expression-list
- **)
- PROCEDURE ForIterator(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- BEGIN
- IF Trace THEN
- S("ForIterator")
- END;
- StatementExpressionList(statements, outer);
- IF Trace THEN
- E("ForIterator")
- END;
- END ForIterator;
- (**
- for-statement:
- 'for' '(' [for-initializer] ';' [for-condition] ';' [for-iterator] ')' embedded-statement
- for-condition:
- boolean-expression
- **)
- PROCEDURE ForStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR expression: SyntaxTree.Expression;
- whileStatement: SyntaxTree.WhileStatement;
- statementSequence: SyntaxTree.StatementSequence;
- iterator: SyntaxTree.StatementSequence;
- position: Position;
- i: LONGINT;
- b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("ForStatement")
- END;
- Check(Scanner.For);
- localIdentTable.OpenScope;
- whileStatement := SyntaxTree.NewWhileStatement(symbol.position, outer);
- (* CommentStatement(whileStatement); *)
- Check(Scanner.LeftParenthesis);
- IF ~Optional(Scanner.Semicolon) THEN
- ForInitializer(statements, outer);
- Check(Scanner.Semicolon);
- END;
- position := symbol.position;
- IF ~Optional(Scanner.Semicolon) THEN
- expression := Expression();
- Check(Scanner.Semicolon);
- ELSE
- expression := SyntaxTree.NewBooleanValue(position, TRUE);
- END;
- IF ~Optional(Scanner.RightParenthesis) THEN
- iterator := SyntaxTree.NewStatementSequence();
- ForIterator(iterator, whileStatement);
- Check(Scanner.RightParenthesis);
- ELSE
- iterator := NIL;
- END;
- whileStatement.SetCondition(expression);
- statementSequence := SyntaxTree.NewStatementSequence();
- b := EmbeddedStatement(statementSequence, whileStatement);
- IF iterator # NIL THEN
- FOR i := 0 TO iterator.Length() - 1 DO
- statementSequence.AddStatement(iterator.GetStatement(i));
- END;
- END;
- whileStatement.SetStatements(statementSequence);
- statements.AddStatement(whileStatement);
- localIdentTable.CloseScope;
- IF Trace THEN
- E("ForStatement")
- END;
- END ForStatement;
- (**
- return-statement:
- 'return' [expression] ';'
- **)
- PROCEDURE ReturnStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR returnStatement: SyntaxTree.ReturnStatement;
- expression: SyntaxTree.Expression;
- BEGIN
- IF Trace THEN
- S("ReturnStatement")
- END;
- Check(Scanner.Return);
- returnStatement := SyntaxTree.NewReturnStatement(symbol.position, outer);
- (* CommentStatement(returnStatement); *)
- IF ~Optional(Scanner.Semicolon) THEN
- expression := Expression();
- returnStatement.SetReturnValue(expression);
- Check(Scanner.Semicolon);
- END;
- statements.AddStatement(returnStatement);
- IF Trace THEN
- E("ReturnStatement")
- END;
- END ReturnStatement;
- (**
- break-statement:
- 'break' ';'
- **)
- PROCEDURE BreakStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
- VAR statement: SyntaxTree.Statement;
- BEGIN
- IF Trace THEN
- S("BreakStatement")
- END;
- Check(Scanner.Break);
- statement := SyntaxTree.NewExitStatement(symbol.position, outer);
- (* CommentStatement(statement); *)
- statements.AddStatement(statement);
- Check(Scanner.Semicolon);
- IF Trace THEN
- E("BreakStatement")
- END;
- END BreakStatement;
- (**
- embedded-statement:
- block
- empty-statement
- expression-statement
- selection-statement
- iteration-statement
- jump-statement
- empty-statement:
- ';'
- selection-statement:
- if-statement
- switch-statement
- select-statement
- iteration-statement:
- while-statement
- do-statement
- for-statement
- jump-statement:
- break-statement
- return-statement
- **)
- PROCEDURE EmbeddedStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement): BOOLEAN;
- VAR result: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("EmbeddedStatement")
- END;
- IF Optional(Scanner.Semicolon) THEN
- result := FALSE;
- ELSIF Peek(Scanner.LeftBrace) THEN
- Block(statements, outer);
- result := TRUE;
- ELSIF Peek(Scanner.If) THEN
- IfStatement(statements, outer);
- result := TRUE;
- ELSIF Peek(Scanner.Switch) THEN
- SwitchStatement(statements, outer);
- result := TRUE;
- ELSIF Peek(Scanner.Select) THEN
- SelectStatement(statements, outer);
- result := TRUE;
- ELSIF Peek(Scanner.While) THEN
- WhileStatement(statements, outer);
- result := TRUE;
- ELSIF Peek(Scanner.Do) THEN
- DoStatement(statements, outer);
- result := TRUE;
- ELSIF Peek(Scanner.For) THEN
- ForStatement(statements, outer);
- result := TRUE;
- ELSIF Peek(Scanner.Break) THEN
- BreakStatement(statements, outer);
- result := TRUE;
- ELSIF Peek(Scanner.Return) THEN
- ReturnStatement(statements, outer);
- result := TRUE;
- ELSE
- result := ExpressionStatement(statements, outer);
- END;
- IF Trace THEN
- E("EmbeddedStatement")
- END;
- RETURN result;
- END EmbeddedStatement;
- (**
- statement:
- declaration-statement
- embedded-statement
- declaration-statement:
- local-variable-declaration ';'
- local-constant-declaration ';'
- **)
- PROCEDURE ExpressionOrDeclaration(
- statements: SyntaxTree.StatementSequence;
- outer: SyntaxTree.Statement;
- VAR isDeclaration: BOOLEAN): BOOLEAN;
- VAR result: BOOLEAN;
- name0, name1: SyntaxTree.Identifier;
- position0, position1, position2: Position;
- leftBracket: BOOLEAN;
- qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
- type: SyntaxTree.Type;
- expression: SyntaxTree.Expression;
- expressionList: SyntaxTree.ExpressionList;
- BEGIN
- name0 := Identifier(position0);
- IF Optional(Scanner.Period) THEN
- name1 := Identifier(position1);
- ELSE
- name1 := SyntaxTree.invalidIdentifier;
- END;
- isDeclaration := FALSE;
- leftBracket := FALSE;
- position2 := symbol.position;
- IF Peek(Scanner.Identifier) THEN
- isDeclaration := TRUE;
- ELSIF Optional(Scanner.LeftBracket) THEN
- leftBracket := TRUE;
- IF Peek(Scanner.RightBracket) OR Peek(Scanner.Comma) THEN
- isDeclaration := TRUE;
- END;
- END;
- IF isDeclaration THEN
- (* local-variable-declaration *)
- IF name1 = SyntaxTree.invalidIdentifier THEN
- name1 := name0;
- name0 := SyntaxTree.invalidIdentifier;
- END;
- qualifiedIdentifier := SyntaxTree.NewQualifiedIdentifier(position0, name0, name1);
- type := SyntaxTree.NewQualifiedType(
- qualifiedIdentifier.position, currentScope, qualifiedIdentifier);
- IF leftBracket THEN
- type := RankSpecifier(type);
- Check(Scanner.RightBracket);
- END;
- WHILE Optional(Scanner.LeftBracket) DO
- type := RankSpecifier(type);
- Check(Scanner.RightBracket);
- END;
- LocalVariableDeclaration(statements, outer, type);
- ELSE
- (* expression-statement *)
- name0 := localIdentTable.Find(name0);
- expression := SyntaxTree.NewIdentifierDesignator(position0, name0);
- IF name1 # SyntaxTree.invalidIdentifier THEN
- expression := SyntaxTree.NewSelectorDesignator(position1, expression(SyntaxTree.Designator), name1);
- END;
- IF leftBracket THEN
- expressionList := SyntaxTree.NewExpressionList();
- ExpressionList(expressionList);
- Check(Scanner.RightBracket);
- expression := SyntaxTree.NewBracketDesignator(position2, expression(SyntaxTree.Designator), expressionList);
- END;
- expression := Accessors(expression, FALSE);
- result := StatementExpression(statements, outer, expression);
- END;
- RETURN result;
- END ExpressionOrDeclaration;
- PROCEDURE Statement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement): BOOLEAN;
- VAR result: BOOLEAN;
- isDeclaration: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("Statement")
- END;
- IF Peek(Scanner.Const) THEN
- LocalConstantDeclaration(statements, outer);
- Check(Scanner.Semicolon);
- result := TRUE;
- ELSIF Peek(Scanner.Bool) OR Peek(Scanner.Sbyte) OR
- Peek(Scanner.Short) OR Peek(Scanner.Int) OR
- Peek(Scanner.Long) OR Peek(Scanner.Char) OR
- Peek(Scanner.Float) OR Peek(Scanner.Double) OR
- Peek(Scanner.Object) OR Peek(Scanner.String) THEN
- LocalVariableDeclaration(statements, outer, NIL);
- Check(Scanner.Semicolon);
- result := TRUE;
- ELSIF Peek(Scanner.Identifier) THEN
- (* either local-variable-declaration or statement expression *)
- result := ExpressionOrDeclaration(statements, outer, isDeclaration);
- Check(Scanner.Semicolon);
- ELSE
- result := EmbeddedStatement(statements, outer);
- END;
- IF Trace THEN
- E("Statement")
- END;
- RETURN result;
- END Statement;
- (**
- statement-list:
- statement
- statement-list statement
- **)
- PROCEDURE StatementList(outer: SyntaxTree.Statement): SyntaxTree.StatementSequence;
- VAR statements: SyntaxTree.StatementSequence;
- b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("StatementList")
- END;
- statements := SyntaxTree.NewStatementSequence();
- REPEAT
- b := Statement(statements, outer);
- UNTIL Peek(Scanner.RightBrace) OR Peek(Scanner.Case) OR Peek(Scanner.Default) ;
- IF Trace THEN
- E("StatementList")
- END;
- RETURN statements;
- END StatementList;
- (**
- block:
- '{' [statement-list] '}'
- **)
- PROCEDURE Body(scope: SyntaxTree.ProcedureScope): SyntaxTree.Body;
- VAR body: SyntaxTree.Body;
- previousScope: SyntaxTree.Scope;
- BEGIN
- IF Trace THEN
- S("Body")
- END;
- previousScope := currentScope;
- currentScope := scope;
- Check(Scanner.LeftBrace);
- body := SyntaxTree.NewBody(symbol.position, scope);
- IF ~Optional(Scanner.RightBrace) THEN
- body.SetStatementSequence(StatementList(body));
- Check(Scanner.RightBrace);
- END;
- currentScope := previousScope;
- IF Trace THEN
- E("Body")
- END;
- RETURN body;
- END Body;
- (**
- type:
- value-type
- reference-type
- port-type
- value-type:
- struct-type
- struct-type:
- type-name
- simple-type
- simple-type:
- numeric-type
- 'bool'
- numeric-type:
- integral-type
- floating-point-type
- integral-type:
- 'sbyte'
- 'short'
- 'int'
- 'long'
- 'char'
- floating-point-type:
- 'float'
- 'double'
- reference-type:
- class-type
- array-type
- delegate-type
- class-type:
- type-name
- 'object'
- 'string'
- array-type:
- non-array-type rank-specifiers
- non-array-type:
- value-type
- class-type
- delegate-type
- rank-specifiers:
- rank-specifier
- rank-specifiers rank-specifier
- rank-specifier:
- '[' [dim-separators] ']'
- dim-separators:
- ','
- dim-separators ','
- delegate-type:
- type-name
- **)
- PROCEDURE RankSpecifier(type: SyntaxTree.Type): SyntaxTree.Type;
- VAR position: Position;
- arrayType: SyntaxTree.ArrayType;
- pointerType: SyntaxTree.PointerType;
- BEGIN
- IF Trace THEN
- S("RankSpecifier")
- END;
- position := symbol.position;
- REPEAT
- arrayType := SyntaxTree.NewArrayType(position, currentScope, SyntaxTree.Open);
- arrayType.SetArrayBase(type);
- type := arrayType;
- UNTIL ~Optional(Scanner.Comma);
- pointerType := SyntaxTree.NewPointerType(position, currentScope);
- pointerType.SetPointerBase(type);
- type := pointerType;
- IF Trace THEN
- E("RankSpecifier")
- END;
- RETURN type;
- END RankSpecifier;
- PROCEDURE NonArrayType(): SyntaxTree.Type;
- VAR type: SyntaxTree.Type;
- position: Position;
- name: SyntaxTree.Identifier;
- direction: LONGINT;
- qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
- BEGIN
- IF Trace THEN
- S("NonArrayType")
- END;
- position := symbol.position;
- name := SyntaxTree.invalidIdentifier;
- direction := -1;
- IF Optional(Scanner.Bool) THEN
- name := lynxBool;
- ELSIF Optional(Scanner.Sbyte) THEN
- name := lynxSbyte;
- ELSIF Optional(Scanner.Short) THEN
- name := lynxShort;
- ELSIF Optional(Scanner.Int) THEN
- name := lynxInt;
- ELSIF Optional(Scanner.Long) THEN
- name := lynxLong;
- ELSIF Optional(Scanner.Char) THEN
- name := lynxChar;
- ELSIF Optional(Scanner.Float) THEN
- name := lynxFloat;
- ELSIF Optional(Scanner.Double) THEN
- name := lynxDouble;
- ELSIF Optional(Scanner.Object) THEN
- name := lynxObject;
- ELSIF Optional(Scanner.String) THEN
- name := lynxString;
- ELSIF Optional(Scanner.In) THEN
- direction := SyntaxTree.InPort;
- ELSIF Optional(Scanner.Out) THEN
- direction := SyntaxTree.OutPort;
- END;
- IF direction >= 0 THEN
- type := SyntaxTree.NewPortType(position, direction, NIL, currentScope);
- ELSE
- IF name # SyntaxTree.invalidIdentifier THEN
- qualifiedIdentifier :=
- SyntaxTree.NewQualifiedIdentifier(
- position, SyntaxTree.invalidIdentifier, name);
- ELSE
- qualifiedIdentifier := QualifiedIdentifier();
- END;
- type := SyntaxTree.NewQualifiedType(
- qualifiedIdentifier.position, currentScope, qualifiedIdentifier);
- END;
- IF Trace THEN
- E("NonArrayType")
- END;
- RETURN type;
- END NonArrayType;
- PROCEDURE Type(): SyntaxTree.Type;
- VAR type: SyntaxTree.Type;
- BEGIN
- IF Trace THEN
- S("Type")
- END;
- type := NonArrayType();
- WHILE Optional(Scanner.LeftBracket) DO
- type := RankSpecifier(type);
- Check(Scanner.RightBracket);
- END;
- IF Trace THEN
- E("Type")
- END;
- RETURN type;
- END Type;
- (**
- attributes:
- '[' attribute-list ']'
- attribute-list:
- attribute
- attribute-list ',' attribute
- attribute:
- attribute-name [attribute-argument]
- attribute-name:
- identifier
- attribute-argument:
- '(' attribute-argument-expression ')'
- attribute-argument-expression:
- expression
- **)
- PROCEDURE AppendModifier(VAR list: SyntaxTree.Modifier; modifier: SyntaxTree.Modifier);
- VAR this, next: SyntaxTree.Modifier;
- BEGIN
- IF list = NIL THEN
- list := modifier
- ELSE
- this := list;
- next := list.nextModifier;
- WHILE next # NIL DO
- this := next;
- next := this.nextModifier;
- END;
- this.SetNext(modifier);
- END;
- END AppendModifier;
- PROCEDURE Attributes(): SyntaxTree.Modifier;
- VAR identifier: SyntaxTree.Identifier;
- modifier, list: SyntaxTree.Modifier;
- position: Position;
- expression: SyntaxTree.Expression;
- BEGIN
- IF Trace THEN
- S("Attributes")
- END;
- (* left bracket already consumed *)
- list := NIL;
- REPEAT
- position := symbol.position;
- identifier := Identifier(position);
- IF Optional(Scanner.LeftParenthesis) THEN
- expression := Expression();
- Check(Scanner.RightParenthesis);
- ELSE
- expression := NIL;
- END;
- modifier := SyntaxTree.NewModifier(position, identifier, expression);
- AppendModifier(list, modifier);
- UNTIL ~Optional(Scanner.Comma);
- Check(Scanner.RightBracket);
- IF Trace THEN
- E("Attributes")
- END;
- RETURN list;
- END Attributes;
- (**
- constant-modifiers:
- constant-modifier
- constant-modifiers constant-modifier
- constant-modifier:
- 'public'
- field-modifiers:
- field-modifier
- field-modifiers field-modifier
- field-modifier:
- 'public'
- 'internal'
- method-modifiers:
- method-modifier
- method-modifiers method-modifier
- method-modifier:
- 'public'
- constructor-modifiers:
- constructor-modifier
- constructor-modifiers constructor-modifier
- constructor-modifier:
- public
- class-modifiers:
- class-modifier
- class-modifiers class-modifier
- class-modifier:
- 'public'
- struct-modifiers:
- struct-modifier
- struct-modifiers struct-modifier
- struct-modifier:
- 'public'
- delegate-modifiers:
- delegate-modifier
- delegate-modifiers delegate-modifier
- delegate-modifier:
- 'public'
- **)
- PROCEDURE Modifiers(VAR modifiers: SET);
- BEGIN
- modifiers := {};
- LOOP
- IF Optional(Scanner.Public) THEN
- INCL(modifiers, Public);
- ELSIF Optional(Scanner.Internal) THEN
- INCL(modifiers, Internal);
- ELSE
- EXIT;
- END;
- END;
- END Modifiers;
- PROCEDURE IdentifierAccess(modifiers: SET; allowedReadOnly: BOOLEAN): SET;
- VAR access: SET;
- BEGIN
- IF modifiers * {Public, Internal} = {Public, Internal} THEN
- Error(symbol.position, Basic.InvalidCode, "conflicting modifiers");
- END;
- IF Public IN modifiers THEN
- access := SyntaxTree.Public + SyntaxTree.Protected + SyntaxTree.Internal;
- ELSIF Internal IN modifiers THEN
- IF ~allowedReadOnly THEN
- Error(symbol.position, Basic.InvalidCode, "may not be defined internal")
- ELSE
- access := SyntaxTree.ReadOnly + {SyntaxTree.InternalWrite};
- END;
- ELSE
- access := SyntaxTree.Internal;
- END;
- RETURN access;
- END IdentifierAccess;
- (**
- constant-declaration:
- [constant-modifiers] 'const' type constant-declarators ';'
- constant-declarators:
- constant-declarator
- constant-declarators ',' constant-declarator
- constant-declarator:
- identifier '=' constant-expression
- **)
- PROCEDURE ConstantDeclarator(
- parentScope: SyntaxTree.Scope;
- modifiers: SET;
- type: SyntaxTree.Type);
- VAR name: SyntaxTree.Identifier;
- position: Position;
- constant: SyntaxTree.Constant;
- expression: SyntaxTree.Expression;
- access: SET;
- BEGIN
- IF Trace THEN
- S("ConstantDeclarator")
- END;
- name := Identifier(position);
- name := localIdentTable.Enter(name);
- access := IdentifierAccess(modifiers, FALSE);
- constant := SyntaxTree.NewConstant(position, name);
- CommentSymbol(constant);
- constant.SetAccess(access);
- (* ACHTUNG: Make sure that Fox semantic checker will respect a type set at this stage: *)
- constant.SetType(type);
- Check(Scanner.Equal);
- expression := Expression();
- constant.SetValue(expression);
- parentScope.AddConstant(constant);
- IF Trace THEN
- E("ConstantDeclarator")
- END;
- END ConstantDeclarator;
- PROCEDURE ConstantDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
- VAR type: SyntaxTree.Type;
- BEGIN
- IF Trace THEN
- S("ConstantDeclaration")
- END;
- type := Type();
- REPEAT
- ConstantDeclarator(parentScope, modifiers, type);
- UNTIL ~Optional(Scanner.Comma);
- Check(Scanner.Semicolon);
- IF Trace THEN
- E("ConstantDeclaration")
- END;
- END ConstantDeclaration;
- (**
- field-declaration:
- [field-modifiers] type variable-declarators ';'
- field-modifiers:
- field-modifier
- field-modifiers field-modifier
- variable-declarators:
- variable-declarator
- variable-declarators ',' variable-declarator
- variable-declarator:
- identifier
- identifier '=' variable-initializer
- variable-initializer:
- expression
- // array-initializer
- **)
- PROCEDURE VariableDeclarator(
- parentScope: SyntaxTree.Scope;
- modifiers: SET;
- type: SyntaxTree.Type;
- name: SyntaxTree.Identifier;
- position: Position);
- VAR variable: SyntaxTree.Variable;
- expression: SyntaxTree.Expression;
- designator: SyntaxTree.Designator;
- statement: SyntaxTree.Statement;
- start: Position;
- access: SET;
- BEGIN
- IF Trace THEN
- S("VariableDeclarator")
- END;
- IF name = SyntaxTree.invalidIdentifier THEN
- name := Identifier(position);
- END;
- name := localIdentTable.Enter(name);
- access := IdentifierAccess(modifiers, TRUE);
- variable := SyntaxTree.NewVariable(position, name);
- CommentSymbol(variable);
- variable.SetAccess(access);
- variable.SetType(type);
- parentScope.AddVariable(variable);
- start := symbol.position;
- (* 'initOuter' is set to NIL in contexts where initialization is not yet implemented *)
- IF (initOuter # NIL) & Optional(Scanner.Equal) THEN
- (* ACHTUNG: array-initializer form is not supported *)
- designator := SyntaxTree.NewIdentifierDesignator(position, name);
- expression := Expression();
- statement := SyntaxTree.NewAssignment(start, designator, expression, initOuter);
- initStatements.AddStatement(statement);
- END;
- IF Trace THEN
- E("VariableDeclarator")
- END;
- END VariableDeclarator;
- PROCEDURE FieldDeclaration(
- parentScope: SyntaxTree.Scope;
- modifiers: SET;
- type: SyntaxTree.Type;
- name: SyntaxTree.Identifier;
- position: Position);
- BEGIN
- IF Trace THEN
- S("FieldDeclaration")
- END;
- REPEAT
- VariableDeclarator(parentScope, modifiers, type, name, position);
- name := SyntaxTree.invalidIdentifier;
- position := invalidPosition;
- UNTIL ~Optional(Scanner.Comma);
- Check(Scanner.Semicolon);
- IF Trace THEN
- E("FieldDeclaration")
- END;
- END FieldDeclaration;
- (**
- formal-parameter-list:
- fixed-parameters
- fixed-parameters:
- fixed-parameter
- fixed-parameters ',' fixed-parameter
- fixed-parameter:
- [parameter-modifier] type identifier
- parameter-modifier:
- 'ref'
- **)
- PROCEDURE FixedParameter(procedureType: SyntaxTree.ProcedureType; parentScope: SyntaxTree.Scope);
- VAR type: SyntaxTree.Type;
- name: SyntaxTree.Identifier;
- parameter: SyntaxTree.Parameter;
- kind: LONGINT; position: Position;
- BEGIN
- IF Trace THEN
- S("FixedParameter")
- END;
- IF Optional(Scanner.Ref) THEN
- kind := SyntaxTree.VarParameter;
- ELSE
- kind := SyntaxTree.ValueParameter;
- END;
- type := Type();
- name := Identifier(position);
- parameter := SyntaxTree.NewParameter(position, procedureType, name, kind);
- procedureType.AddParameter(parameter);
- parameter.SetType(type);
- IF Trace THEN
- E("FixedParameter")
- END;
- END FixedParameter;
- PROCEDURE FormalParameterList(
- procedureType: SyntaxTree.ProcedureType;
- parentScope: SyntaxTree.Scope;
- returnType: SyntaxTree.Type);
- BEGIN
- IF Trace THEN
- S("FormalParameterList")
- END;
- Check(Scanner.LeftParenthesis);
- IF ~Optional(Scanner.RightParenthesis) THEN
- REPEAT
- FixedParameter(procedureType, parentScope);
- UNTIL ~Optional(Scanner.Comma);
- Check(Scanner.RightParenthesis);
- END;
- IF returnType # NIL THEN
- procedureType.SetReturnType(returnType);
- END;
- IF Trace THEN
- E("FormalParameterList")
- END;
- END FormalParameterList;
- (**
- constructor-initializer:
- ':' 'base' '(' [argument-list] ')'
- **)
- PROCEDURE ConstructorInitializer(scope: SyntaxTree.ProcedureScope);
- BEGIN
- IF Trace THEN
- S("ConstructorInitializer")
- END;
- (* TODO *)
- IF Trace THEN
- E("ConstructorInitializer")
- END;
- END ConstructorInitializer;
- (**
- method-declaration:
- method-header method-body
- method-header:
- [method-modifiers] return-type member-name '(' [formal-parameter-list] ')'
- return-type:
- type
- 'void'
- member-name:
- identifier
- method-body:
- block
- constructor-declaration:
- [constructor-modifiers] constructor-declarator constructor-body
- constructor-declarator:
- identifier ( [formal-parameter-list] ) [constructor-initializer]
- constructor-body:
- block
- **)
- PROCEDURE ProcedureDeclaration(
- parentScope: SyntaxTree.Scope;
- modifiers: SET;
- type: SyntaxTree.Type;
- name: SyntaxTree.Identifier;
- position: Position;
- isConstructor: BOOLEAN);
- VAR procedure: SyntaxTree.Procedure;
- procedureType: SyntaxTree.ProcedureType;
- procedureScope: SyntaxTree.ProcedureScope;
- previousScope: SyntaxTree.Scope;
- access: SET;
- body: SyntaxTree.Body;
- BEGIN
- procedureType := SyntaxTree.NewProcedureType(position, parentScope);
- access := IdentifierAccess(modifiers, FALSE);
- procedureScope := SyntaxTree.NewProcedureScope(parentScope);
- procedure := SyntaxTree.NewProcedure(position, name, procedureScope);
- procedure.SetConstructor(isConstructor);
- CommentSymbol(procedure);
- procedure.SetAccess(access);
- procedure.SetType(procedureType);
- FormalParameterList(procedureType, procedureScope, type);
- IF isConstructor & Optional(Scanner.Colon) THEN
- (* TODO: Connect initializer to the body *)
- ConstructorInitializer(procedureScope);
- END;
- previousScope := currentScope;
- currentScope := procedureScope;
- body := Body(procedureScope);
- currentScope := previousScope;
- procedureScope.SetBody(body);
- parentScope.AddProcedure(procedure);
- END ProcedureDeclaration;
- PROCEDURE MethodDeclaration(
- parentScope: SyntaxTree.Scope;
- modifiers: SET;
- type: SyntaxTree.Type;
- name: SyntaxTree.Identifier;
- position: Position);
- BEGIN
- IF Trace THEN
- S("MethodDeclaration")
- END;
- localIdentTable.Reset;
- IF (name = identMain) &
- (parentScope IS SyntaxTree.CellScope) &
- ~parentScope(SyntaxTree.CellScope).ownerCell.isCellNet THEN
- (* bodies of cells are represented as main() functions *)
- BodyDeclaration(parentScope, modifiers, type, name, position);
- ELSE
- ProcedureDeclaration(parentScope, modifiers, type, name, position, FALSE);
- END;
- IF Trace THEN
- E("MethodDeclaration")
- END;
- END MethodDeclaration;
- PROCEDURE ConstructorDeclaration(
- parentScope: SyntaxTree.Scope;
- modifiers: SET;
- name: SyntaxTree.Identifier;
- position: Position);
- BEGIN
- IF Trace THEN
- S("ConstructorDeclaration")
- END;
- localIdentTable.Reset;
- IF (parentScope IS SyntaxTree.ModuleScope) OR
- ((parentScope IS SyntaxTree.CellScope) &
- parentScope(SyntaxTree.CellScope).ownerCell.isCellNet) THEN
- (* bodies of modules and cellnets are represented as constructors *)
- BodyDeclaration(parentScope, modifiers, NIL, name, position);
- ELSE
- ProcedureDeclaration(parentScope, modifiers, NIL, name, position, TRUE);
- END;
- IF Trace THEN
- E("ConstructorDeclaration")
- END;
- END ConstructorDeclaration;
- PROCEDURE BodyDeclaration(
- parentScope: SyntaxTree.Scope;
- modifiers: SET;
- type: SyntaxTree.Type;
- name: SyntaxTree.Identifier;
- position: Position);
- VAR procedureScope: SyntaxTree.ProcedureScope;
- procedureType: SyntaxTree.ProcedureType;
- procedure: SyntaxTree.Procedure;
- BEGIN
- procedureScope := SyntaxTree.NewProcedureScope(parentScope);
- IF parentScope IS SyntaxTree.ModuleScope THEN
- procedure := SyntaxTree.NewProcedure(position, Global.ModuleBodyName, procedureScope);
- procedure.SetAccess(SyntaxTree.Hidden);
- ELSE
- procedure := SyntaxTree.NewProcedure(position, Global.RecordBodyName, procedureScope);
- procedure.SetAccess(SyntaxTree.Public+SyntaxTree.Protected+SyntaxTree.Internal);
- END;
- parentScope.AddProcedure(procedure);
- procedureType := SyntaxTree.NewProcedureType(position, parentScope);
- FormalParameterList(procedureType, procedureScope, type);
- IF procedureType.numberParameters # 0 THEN
- Error(position, Basic.InvalidCode, "constructor/main has parameters");
- ELSIF procedureType.returnType # NIL THEN
- Error(position, Basic.InvalidCode, "constructor/main returns value");
- END;
- procedure.SetType(procedureType);
- procedure.SetBodyProcedure(TRUE);
- procedureScope.SetBody(Body(procedureScope));
- IF parentScope IS SyntaxTree.ModuleScope THEN
- parentScope(SyntaxTree.ModuleScope).SetBodyProcedure(procedure);
- ELSE
- parentScope(SyntaxTree.CellScope).SetBodyProcedure(procedure);
- END;
- END BodyDeclaration;
- (**
- class-declaration:
- [class-modifiers] 'class' identifier [class-base] class-body [';']
- class-base:
- ':' class-type
- class-body:
- '{' [class-member-declarations] '}'
- class-member-declarations:
- class-member-declaration
- class-member-declarations class-member-declaration
- class-member-declaration:
- constant-declaration
- field-declaration
- method-declaration
- constructor-declaration
- type-declaration
- type-declaration:
- class-declaration
- struct-declaration
- delegate-declaration
- cell-declaration
- cellnet-declaration
- **)
- PROCEDURE MemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
- VAR attributes: SyntaxTree.Modifier;
- modifiers: SET;
- type: SyntaxTree.Type;
- name: SyntaxTree.Identifier;
- position: Position;
- BEGIN
- IF Optional(Scanner.LeftBracket) THEN
- attributes := Attributes();
- ELSE
- attributes := NIL;
- END;
- Modifiers(modifiers);
- IF Optional(Scanner.Const) THEN
- ConstantDeclaration(parentScope, modifiers);
- ELSIF Optional(Scanner.Class) THEN
- ClassDeclaration(parentScope, modifiers);
- ELSIF Optional(Scanner.Struct) THEN
- StructDeclaration(parentScope, modifiers);
- ELSIF Optional(Scanner.Delegate) THEN
- DelegateDeclaration(parentScope, modifiers);
- ELSIF Optional(Scanner.Cell) THEN
- CellDeclaration(parentScope, modifiers, attributes, FALSE);
- ELSIF Optional(Scanner.Cellnet) THEN
- CellDeclaration(parentScope, modifiers, attributes, TRUE);
- ELSIF Peek(Scanner.Identifier) & (symbol.identifier = parentName) THEN
- name := Identifier(position);
- ConstructorDeclaration(parentScope, modifiers, name, position);
- ELSIF Optional(Scanner.Void) THEN
- name := Identifier(position);
- MethodDeclaration(parentScope, modifiers, NIL, name, position);
- ELSE
- type := Type();
- name := Identifier(position);
- IF Peek(Scanner.LeftParenthesis) THEN
- MethodDeclaration(parentScope, modifiers, type, name, position);
- ELSE
- FieldDeclaration(parentScope, modifiers, type, name, position);
- END;
- END;
- END MemberDeclaration;
- PROCEDURE ClassMemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
- BEGIN
- IF Trace THEN
- S("ClassMemberDeclaration")
- END;
- MemberDeclaration(parentScope, parentName);
- IF Trace THEN
- E("ClassMemberDeclaration")
- END;
- END ClassMemberDeclaration;
- PROCEDURE ClassMemberDeclarations(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
- VAR previousScope: SyntaxTree.Scope;
- BEGIN
- IF Trace THEN
- S("ClassMemberDeclarations")
- END;
- previousScope := currentScope;
- currentScope := parentScope;
- WHILE ~Peek(Scanner.RightBrace) DO
- ClassMemberDeclaration(parentScope, parentName);
- END;
- currentScope := previousScope;
- IF Trace THEN
- E("ClassMemberDeclarations")
- END;
- END ClassMemberDeclarations;
- PROCEDURE ClassDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
- VAR name: SyntaxTree.Identifier;
- position: Position;
- typeDeclaration: SyntaxTree.TypeDeclaration;
- access: SET;
- objectType: SyntaxTree.RecordType;
- pointerType: SyntaxTree.PointerType;
- recordScope: SyntaxTree.RecordScope;
- qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
- baseType: SyntaxTree.Type;
- previousStatements: SyntaxTree.StatementSequence;
- previousOuter: SyntaxTree.Statement;
- b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("ClassDeclaration")
- END;
- previousStatements := initStatements;
- previousOuter := initOuter;
- (* TODO: Implement initialization of fields *)
- initStatements := NIL;
- initOuter := NIL;
- EnterInit;
- (* symbol 'class' already consumed *)
- name := Identifier(position);
- access := IdentifierAccess(modifiers, FALSE);
- typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
- CommentSymbol(typeDeclaration);
- recordScope := SyntaxTree.NewRecordScope(parentScope);
- pointerType := SyntaxTree.NewPointerType(position, parentScope);
- objectType := SyntaxTree.NewRecordType(position, parentScope, recordScope);
- objectType.IsObject(TRUE);
- objectType.SetPointerType(pointerType);
- pointerType.SetPointerBase(objectType);
- IF Optional(Scanner.Colon) THEN
- qualifiedIdentifier := QualifiedIdentifier();
- baseType := SyntaxTree.NewQualifiedType(
- qualifiedIdentifier.position, parentScope, qualifiedIdentifier);
- objectType.SetBaseType(baseType);
- END;
- Check(Scanner.LeftBrace);
- ClassMemberDeclarations(recordScope, name);
- Check(Scanner.RightBrace);
- b := Optional(Scanner.Semicolon);
- pointerType.SetTypeDeclaration(typeDeclaration);
- typeDeclaration.SetDeclaredType(pointerType);
- typeDeclaration.SetAccess(access);
- parentScope.AddTypeDeclaration(typeDeclaration);
- initStatements := previousStatements;
- initOuter := previousOuter;
- IF Trace THEN
- E("ClassDeclaration")
- END;
- END ClassDeclaration;
- (**
- struct-declaration:
- [struct-modifiers] 'struct' identifier struct-body [';']
- struct-body:
- '{' [struct-member-declarations] '}'
- struct-member-declarations:
- struct-member-declaration
- struct-member-declarations struct-member-declaration
- struct-member-declaration:
- constant-declaration
- field-declaration
- method-declaration
- constructor-declaration
- type-declaration
- **)
- PROCEDURE StructMemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
- BEGIN
- IF Trace THEN
- S("StructMemberDeclaration")
- END;
- MemberDeclaration(parentScope, parentName);
- IF Trace THEN
- E("StructMemberDeclaration")
- END;
- END StructMemberDeclaration;
- PROCEDURE StructMemberDeclarations(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
- VAR previousScope: SyntaxTree.Scope;
- BEGIN
- IF Trace THEN
- S("StructMemberDeclarations")
- END;
- previousScope := currentScope;
- currentScope := parentScope;
- WHILE ~Peek(Scanner.RightBrace) DO
- StructMemberDeclaration(parentScope, parentName);
- END;
- currentScope := previousScope;
- IF Trace THEN
- E("StructMemberDeclarations")
- END;
- END StructMemberDeclarations;
- PROCEDURE StructDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
- VAR name: SyntaxTree.Identifier;
- position: Position;
- typeDeclaration: SyntaxTree.TypeDeclaration;
- access: SET;
- recordType: SyntaxTree.RecordType;
- recordScope: SyntaxTree.RecordScope;
- previousStatements: SyntaxTree.StatementSequence;
- previousOuter: SyntaxTree.Statement;
- b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("StructDeclaration")
- END;
- previousStatements := initStatements;
- previousOuter := initOuter;
- (* TODO: Implement initialization of fields *)
- initStatements := NIL;
- initOuter := NIL;
- (* symbol 'struct' already consumed *)
- name := Identifier(position);
- access := IdentifierAccess(modifiers, FALSE);
- typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
- CommentSymbol(typeDeclaration);
- recordScope := SyntaxTree.NewRecordScope(parentScope);
- recordType := SyntaxTree.NewRecordType(position, parentScope, recordScope);
- Check(Scanner.LeftBrace);
- StructMemberDeclarations(recordScope, name);
- Check(Scanner.RightBrace);
- b := Optional(Scanner.Semicolon);
- recordType.SetTypeDeclaration(typeDeclaration);
- typeDeclaration.SetDeclaredType(recordType);
- typeDeclaration.SetAccess(access);
- parentScope.AddTypeDeclaration(typeDeclaration);
- initStatements := previousStatements;
- initOuter := previousOuter;
- IF Trace THEN
- E("StructDeclaration")
- END;
- END StructDeclaration;
- (**
- delegate-declaration:
- [delegate-modifiers] 'delegate' return-type identifier '(' [formal-parameter-list] ')' ';'
- **)
- PROCEDURE DelegateDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
- VAR returnType: SyntaxTree.Type;
- name: SyntaxTree.Identifier;
- position: Position;
- typeDeclaration: SyntaxTree.TypeDeclaration;
- access: SET;
- procedureType: SyntaxTree.ProcedureType;
- BEGIN
- IF Trace THEN
- S("DelegateDeclaration")
- END;
- (* symbol 'delegate' already consumed *)
- IF Optional(Scanner.Void) THEN
- returnType := NIL;
- ELSE
- returnType := Type();
- END;
- name := Identifier(position);
- access := IdentifierAccess(modifiers, FALSE);
- typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
- CommentSymbol(typeDeclaration);
- procedureType := SyntaxTree.NewProcedureType(position, parentScope);
- procedureType.SetModifiers(delegateModifiers);
- (* ACHTUNG: Should we create a fictionary parentScope for parameters? *)
- FormalParameterList(procedureType, parentScope, returnType);
- procedureType.SetTypeDeclaration(typeDeclaration);
- typeDeclaration.SetDeclaredType(procedureType);
- typeDeclaration.SetAccess(access);
- parentScope.AddTypeDeclaration(typeDeclaration);
- IF Trace THEN
- E("DelegateDeclaration")
- END;
- END DelegateDeclaration;
- (**
- port-list:
- port-declaration
- port-list ',' port-declaration
- port-declaration:
- port-type ['[' constant-expression ']'] identifier
- port-type:
- 'in'
- 'out'
- **)
- PROCEDURE PortDeclaration(cell: SyntaxTree.CellType; parentScope: SyntaxTree.Scope);
- VAR position: Position;
- direction: LONGINT;
- type: SyntaxTree.Type;
- arrayType: SyntaxTree.ArrayType;
- expression: SyntaxTree.Expression;
- name: SyntaxTree.Identifier;
- parameter: SyntaxTree.Parameter;
- BEGIN
- IF Trace THEN
- S("PortDeclaration")
- END;
- position := symbol.position;
- IF Optional(Scanner.In) THEN
- direction := SyntaxTree.InPort;
- ELSIF Optional(Scanner.Out) THEN
- direction := SyntaxTree.OutPort;
- ELSE
- Error(position, Basic.InvalidCode, "invalid direction, expected in or out");
- END;
- type := SyntaxTree.NewPortType(position, direction, NIL, parentScope);
- IF Optional(Scanner.LeftBracket) THEN
- expression := Expression();
- arrayType := SyntaxTree.NewArrayType(position, parentScope, SyntaxTree.Static);
- arrayType.SetArrayBase(type);
- arrayType.SetLength(expression);
- type := arrayType;
- Check(Scanner.RightBracket);
- END;
- name := Identifier(position);
- parameter := SyntaxTree.NewParameter(position, cell, name, SyntaxTree.ValueParameter);
- cell.AddParameter(parameter);
- parameter.SetType(type);
- IF Trace THEN
- E("PortDeclaration")
- END;
- END PortDeclaration;
- PROCEDURE PortList(cell: SyntaxTree.CellType; parentScope: SyntaxTree.Scope);
- BEGIN
- IF Trace THEN
- S("PortList")
- END;
- Check(Scanner.LeftParenthesis);
- IF ~Optional(Scanner.RightParenthesis) THEN
- REPEAT
- PortDeclaration(cell, parentScope);
- UNTIL ~Optional(Scanner.Comma);
- Check(Scanner.RightParenthesis);
- END;
- IF Trace THEN
- E("PortList")
- END;
- END PortList;
- (**
- cell-declaration:
- [cell-modifiers] 'cell' identifier ['(' [cell-parameter-list] ')'] cell-body [';']
- cell-body:
- '{' [cell-member-declarations] '}'
- cell-member-declarations:
- cell-member-declaration
- cell-member-declarations cell-member-declaration
- cell-member-declaration:
- constant-declaration
- field-declaration
- method-declaration
- constructor-declaration
- type-declaration
- cellnet-declaration:
- [cell-modifiers] 'cellnet' identifier ['(' [cell-parameter-list] ')'] cell-body [';']
- **)
- PROCEDURE CellMemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
- BEGIN
- IF Trace THEN
- S("CellMemberDeclaration")
- END;
- MemberDeclaration(parentScope, parentName);
- IF Trace THEN
- E("CellMemberDeclaration")
- END;
- END CellMemberDeclaration;
- PROCEDURE CellMemberDeclarations(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
- VAR previousScope: SyntaxTree.Scope;
- BEGIN
- IF Trace THEN
- S("CellMemberDeclarations")
- END;
- previousScope := currentScope;
- currentScope := parentScope;
- WHILE ~Peek(Scanner.RightBrace) DO
- CellMemberDeclaration(parentScope, parentName);
- END;
- currentScope := previousScope;
- IF Trace THEN
- E("CellMemberDeclarations")
- END;
- END CellMemberDeclarations;
- PROCEDURE CellDeclaration(
- parentScope: SyntaxTree.Scope;
- modifiers: SET;
- attributes: SyntaxTree.Modifier;
- isCellNet: BOOLEAN);
- VAR name: SyntaxTree.Identifier;
- position: Position;
- access: SET;
- typeDeclaration: SyntaxTree.TypeDeclaration;
- cellScope: SyntaxTree.CellScope;
- cellType: SyntaxTree.CellType;
- previousStatements: SyntaxTree.StatementSequence;
- previousOuter: SyntaxTree.Statement;
- b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("CellDeclaration")
- END;
- previousStatements := initStatements;
- previousOuter := initOuter;
- (* TODO: Implement initialization of fields *)
- initStatements := NIL;
- initOuter := NIL;
- (* symbol 'cell' already consumed *)
- name := Identifier(position);
- access := IdentifierAccess(modifiers, FALSE);
- typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
- CommentSymbol(typeDeclaration);
- cellScope := SyntaxTree.NewCellScope(parentScope);
- cellType := SyntaxTree.NewCellType(position, parentScope, cellScope);
- cellType.IsCellNet(isCellNet);
- cellScope.SetOwnerCell(cellType);
- IF attributes # NIL THEN
- cellType.SetModifiers(attributes);
- END;
- IF Peek(Scanner.LeftParenthesis) THEN
- PortList(cellType, cellScope);
- END;
- EnterInit;
- Check(Scanner.LeftBrace);
- CellMemberDeclarations(cellScope, name);
- Check(Scanner.RightBrace);
- b := Optional(Scanner.Semicolon);
- cellType.SetTypeDeclaration(typeDeclaration);
- typeDeclaration.SetDeclaredType(cellType);
- typeDeclaration.SetAccess(access);
- parentScope.AddTypeDeclaration(typeDeclaration);
- initStatements := previousStatements;
- initOuter := previousOuter;
- IF Trace THEN
- E("CellDeclaration")
- END;
- END CellDeclaration;
- (**
- import-directives:
- import-directive
- import-directives import-directive
- import-directive:
- import-alias-directive
- import-module-directive
- import-alias-directive:
- 'import' identifier '=' module-name ';'
- import-module-directive:
- 'import' module-name ';'
- module-name:
- identifier
- **)
- PROCEDURE ImportDirective(moduleScope: SyntaxTree.ModuleScope);
- VAR alias, name, context: SyntaxTree.Identifier;
- import: SyntaxTree.Import;
- position, idPosition: Position;
- BEGIN
- IF Trace THEN
- S("ImportDirective")
- END;
- (* import symbol already consumed *)
- position := symbol.position;
- alias := Identifier(idPosition);
- IF alias # SyntaxTree.invalidIdentifier THEN
- IF Optional(Scanner.Equal) THEN
- name := Identifier(idPosition);
- ELSE
- name := alias;
- END;
- import := SyntaxTree.NewImport(position, alias, name, TRUE);
- CommentSymbol(import);
- moduleScope.AddImport(import);
- END;
- Check(Scanner.Semicolon);
- IF Trace THEN
- E("ImportDirective");
- END;
- END ImportDirective;
- PROCEDURE ImportDirectives(moduleScope: SyntaxTree.ModuleScope);
- BEGIN
- IF Trace THEN
- S("ImportDirectives")
- END;
- WHILE Optional(Scanner.Import) DO
- ImportDirective(moduleScope);
- END;
- IF Trace THEN
- E("ImportDirectives");
- END;
- END ImportDirectives;
- (**
- compilation-unit:
- 'module' identifier '{' [import-directives] [class-member-declarations] '}' [';']
- 'cellnet' identifier '{' [import-directives] [class-member-declarations] '}' [';']
- **)
- PROCEDURE Module*(): SyntaxTree.Module;
- VAR moduleName, context: SyntaxTree.Identifier;
- module: SyntaxTree.Module;
- position: Position;
- isCellNet: BOOLEAN;
- scannerDiagnostics: Diagnostics.Diagnostics;
- b: BOOLEAN;
- BEGIN
- IF Trace THEN
- S("Module")
- END;
- position := symbol.position;
- (* needed to feed in comment already before module starts: *)
- moduleScope := SyntaxTree.NewModuleScope();
- currentScope := moduleScope;
- isCellNet := Optional(Scanner.Cellnet);
- IF isCellNet OR Mandatory(Scanner.Module) THEN
- moduleName := Identifier(position);
- module := SyntaxTree.NewModule(scanner.source^, position, moduleName, moduleScope, LynxCase);
- IF isCellNet THEN
- module.SetCellNet(TRUE);
- END;
- module.SetType(SyntaxTree.moduleType);
- CommentSymbol(module);
- Check(Scanner.LeftBrace);
- IF Peek(Scanner.Import) THEN
- ImportDirectives(moduleScope)
- END;
- EnterInit;
- ClassMemberDeclarations(moduleScope, moduleName);
- Check(Scanner.RightBrace);
- b := Optional(Scanner.Semicolon);
- IF ~error & ~scanner.error THEN
- (* read ahead to read comments *)
- scannerDiagnostics := NIL;
- scanner.ResetErrorDiagnostics(scannerDiagnostics);
- NextSymbol;
- scanner.ResetErrorDiagnostics(scannerDiagnostics);
- (* do not use Check for not reading after end of module *)
- SetNextInComment(recentComment, module);
- module.SetClosingComment(recentComment);
- recentComment := NIL;
- END;
- END;
- IF Trace THEN
- E("Module")
- END;
- RETURN module
- END Module;
- END Parser; (* Parser *)
- VAR invalidPosition: Position;
- (** parser retrieval **)
- PROCEDURE NewParser*(scanner: Scanner.Scanner; diagnostics: Diagnostics.Diagnostics): Parser;
- VAR parser: Parser;
- BEGIN
- NEW(parser, scanner, diagnostics);
- RETURN parser;
- END NewParser;
- BEGIN
- invalidPosition.start := -1;
- END FoxCSharpParser.
|