FoxCSharpParser.Mod 143 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771
  1. MODULE FoxCSharpParser;
  2. (* module originating from Alexey Gokhberg's ActiveCells# Parser *)
  3. IMPORT Strings, StringPool, Diagnostics, D := Debugging, Basic := FoxBasic, FoxScanner,
  4. Scanner := FoxCSharpScanner, SyntaxTree := FoxSyntaxTree, Global := FoxGlobal,
  5. KernelLog (* DEBUG *);
  6. CONST
  7. Trace = FALSE;
  8. (* modifiers *)
  9. Public = 0;
  10. Internal = 1;
  11. LynxCase = FoxScanner.Lowercase;
  12. TYPE
  13. Position*= Scanner.Position;
  14. LocalIdentEntry = OBJECT
  15. VAR
  16. next: LocalIdentEntry;
  17. level: LONGINT;
  18. name: SyntaxTree.Identifier;
  19. local: SyntaxTree.Identifier;
  20. END LocalIdentEntry;
  21. LocalIdentTable = OBJECT
  22. VAR
  23. head: LocalIdentEntry;
  24. level: LONGINT;
  25. suffix: LONGINT;
  26. PROCEDURE & Init;
  27. BEGIN
  28. Reset;
  29. END Init;
  30. PROCEDURE Reset;
  31. BEGIN
  32. head := NIL;
  33. level := 0;
  34. suffix := 0;
  35. END Reset;
  36. PROCEDURE OpenScope;
  37. BEGIN
  38. INC(level);
  39. END OpenScope;
  40. PROCEDURE CloseScope;
  41. VAR p: LocalIdentEntry;
  42. BEGIN
  43. p := head;
  44. WHILE (p # NIL) & (p.level = level) DO
  45. p := p.next;
  46. END;
  47. head := p;
  48. DEC(level);
  49. END CloseScope;
  50. PROCEDURE Enter(name: SyntaxTree.Identifier): SyntaxTree.Identifier;
  51. VAR p, q: LocalIdentEntry;
  52. local: SyntaxTree.Identifier;
  53. str: Scanner.IdentifierString;
  54. BEGIN
  55. IF level = 0 THEN
  56. RETURN name;
  57. END;
  58. p := head;
  59. q := NIL;
  60. WHILE (q = NIL) & (p # NIL) & (p.level = level) DO
  61. IF p.name = name THEN
  62. q := p;
  63. END;
  64. p := p.next;
  65. END;
  66. IF q # NIL THEN
  67. RETURN q.local;
  68. END;
  69. Basic.GetString(name, str);
  70. Strings.AppendChar(str, "@");
  71. INC(suffix);
  72. Basic.AppendNumber(str, suffix);
  73. local := Basic.MakeString(str);
  74. NEW(q);
  75. q.level := level;
  76. q.name := name;
  77. q.local := local;
  78. q.next := head;
  79. head := q;
  80. RETURN local;
  81. END Enter;
  82. PROCEDURE Find(name: SyntaxTree.Identifier): SyntaxTree.Identifier;
  83. VAR p: LocalIdentEntry;
  84. BEGIN
  85. p := head;
  86. WHILE (p # NIL) & (p.name # name) DO
  87. p := p.next;
  88. END;
  89. IF p # NIL THEN
  90. RETURN p.local;
  91. END;
  92. RETURN name;
  93. END Find;
  94. END LocalIdentTable;
  95. Parser* = OBJECT
  96. VAR
  97. scanner: Scanner.Scanner;
  98. symbol-: Scanner.Symbol;
  99. diagnostics: Diagnostics.Diagnostics;
  100. currentScope: SyntaxTree.Scope;
  101. recentCommentItem: ANY;
  102. recentLine: LONGINT;
  103. recentComment: SyntaxTree.Comment;
  104. moduleScope: SyntaxTree.ModuleScope;
  105. error-: BOOLEAN;
  106. initStatements: SyntaxTree.StatementSequence;
  107. initOuter: SyntaxTree.Statement;
  108. delegateModifiers: SyntaxTree.Modifier;
  109. lynxChar: SyntaxTree.Identifier;
  110. lynxSbyte: SyntaxTree.Identifier;
  111. lynxShort: SyntaxTree.Identifier;
  112. lynxInt: SyntaxTree.Identifier;
  113. lynxLong: SyntaxTree.Identifier;
  114. lynxFloat: SyntaxTree.Identifier;
  115. lynxDouble: SyntaxTree.Identifier;
  116. lynxBool: SyntaxTree.Identifier;
  117. lynxObject: SyntaxTree.Identifier;
  118. lynxString: SyntaxTree.Identifier;
  119. lynxNewobj: SyntaxTree.Identifier;
  120. lynxNewarr: SyntaxTree.Identifier;
  121. lynxAsop: SyntaxTree.Identifier;
  122. lynxUnop: SyntaxTree.Identifier;
  123. lynxBinop: SyntaxTree.Identifier;
  124. lynxSend: SyntaxTree.Identifier;
  125. lynxReceive: SyntaxTree.Identifier;
  126. lynxRecvnb: SyntaxTree.Identifier;
  127. lynxConnect: SyntaxTree.Identifier;
  128. lynxDelegate: SyntaxTree.Identifier;
  129. lynxNewsel: SyntaxTree.Identifier;
  130. lynxAddsel: SyntaxTree.Identifier;
  131. lynxSelect: SyntaxTree.Identifier;
  132. lynxSelidx: SyntaxTree.Identifier;
  133. lynxType: SyntaxTree.Identifier;
  134. identMain: SyntaxTree.Identifier;
  135. localIdentTable: LocalIdentTable;
  136. indent: LONGINT; (* for debugging purposes only *)
  137. (** constructor, init parser with scanner providing input and with diagnostics for error output *)
  138. PROCEDURE & Init*(scanner: Scanner.Scanner; diagnostics: Diagnostics.Diagnostics);
  139. BEGIN
  140. SELF.scanner := scanner;
  141. SELF.diagnostics := diagnostics;
  142. error := ~scanner.GetNextSymbol(symbol);
  143. recentCommentItem := NIL;
  144. recentComment := NIL;
  145. initStatements := NIL;
  146. initOuter := NIL;
  147. InitDelegateModifiers;
  148. InitSystemNames;
  149. StringPool.GetIndex("lynx@type", lynxType);
  150. StringPool.GetIndex("main", identMain);
  151. NEW(localIdentTable);
  152. (* debugging *)
  153. indent := 0;
  154. END Init;
  155. PROCEDURE InitDelegateModifiers;
  156. VAR name: SyntaxTree.Identifier;
  157. BEGIN
  158. StringPool.GetIndex("DELEGATE", name);
  159. delegateModifiers := SyntaxTree.NewModifier(invalidPosition, name, NIL);
  160. END InitDelegateModifiers;
  161. (*
  162. NOTE: Fox semantical analysis has been extended in order to recognize
  163. and properly support the following names of system procedures.
  164. Lynx version of FoxGlobal provides the respective bindings.
  165. *)
  166. PROCEDURE InitSystemNames;
  167. BEGIN
  168. StringPool.GetIndex(Global.LynxChar, lynxChar);
  169. StringPool.GetIndex(Global.LynxSbyte, lynxSbyte);
  170. StringPool.GetIndex(Global.LynxShort, lynxShort);
  171. StringPool.GetIndex(Global.LynxInt, lynxInt);
  172. StringPool.GetIndex(Global.LynxLong, lynxLong);
  173. StringPool.GetIndex(Global.LynxFloat, lynxFloat);
  174. StringPool.GetIndex(Global.LynxDouble, lynxDouble);
  175. StringPool.GetIndex(Global.LynxBool, lynxBool);
  176. StringPool.GetIndex(Global.LynxObject, lynxObject);
  177. StringPool.GetIndex(Global.LynxString, lynxString);
  178. StringPool.GetIndex(Global.LynxNewobj, lynxNewobj);
  179. StringPool.GetIndex(Global.LynxNewarr, lynxNewarr);
  180. StringPool.GetIndex(Global.LynxAsop, lynxAsop);
  181. StringPool.GetIndex(Global.LynxUnop, lynxUnop);
  182. StringPool.GetIndex(Global.LynxBinop, lynxBinop);
  183. StringPool.GetIndex(Global.LynxSend, lynxSend);
  184. StringPool.GetIndex(Global.LynxReceive, lynxReceive);
  185. StringPool.GetIndex(Global.LynxRecvnb, lynxRecvnb);
  186. StringPool.GetIndex(Global.LynxConnect, lynxConnect);
  187. StringPool.GetIndex(Global.LynxDelegate, lynxDelegate);
  188. StringPool.GetIndex(Global.LynxNewsel, lynxNewsel);
  189. StringPool.GetIndex(Global.LynxAddsel, lynxAddsel);
  190. StringPool.GetIndex(Global.LynxSelect, lynxSelect);
  191. StringPool.GetIndex(Global.LynxSelidx, lynxSelidx);
  192. END InitSystemNames;
  193. PROCEDURE S(CONST s: ARRAY OF CHAR); (* for debugging purposes only *)
  194. VAR i: LONGINT;
  195. BEGIN
  196. D.Ln;
  197. INC(indent);
  198. D.Int(indent, 1);
  199. FOR i := 1 TO indent DO
  200. D.Str(" ");
  201. END;
  202. D.Str("start: ");
  203. D.Str(s);
  204. D.Str(" at pos ");
  205. D.Int(symbol.position.start, 1);
  206. END S;
  207. PROCEDURE E(CONST s: ARRAY OF CHAR); (* for debugging purposes only *)
  208. VAR i: LONGINT;
  209. BEGIN
  210. D.Ln;
  211. D.Int(indent, 1);
  212. FOR i := 1 TO indent DO
  213. D.Str(" ");
  214. END;
  215. D.Str("end : ");
  216. D.Str(s);
  217. D.Str(" at pos ");
  218. D.Int(symbol.position.start, 1);
  219. END E;
  220. PROCEDURE EE(CONST s, t: ARRAY OF CHAR); (* for debugging purposes only *)
  221. VAR i: LONGINT;
  222. BEGIN
  223. D.Ln;
  224. D.Int(indent, 1);
  225. FOR i := 1 TO indent DO
  226. D.Str(" ");
  227. END;
  228. D.Str("end : ");
  229. D.Str(s);
  230. D.Str(" (");
  231. D.Str(t);
  232. D.Str(") at pos ");
  233. END EE;
  234. (** output error message and / or given code *)
  235. PROCEDURE Error(position: Position; code: LONGINT; CONST message: ARRAY OF CHAR);
  236. VAR errorMessage: ARRAY 256 OF CHAR;
  237. BEGIN
  238. Basic.ErrorC(diagnostics, scanner.source^, position, code, errorMessage);
  239. error := TRUE;
  240. (* @@@ *)
  241. HALT(100);
  242. END Error;
  243. (** helper procedures interfacing to the scanner **)
  244. (** Get next symbol from scanner and store it in object-local variable 'symbol' *)
  245. PROCEDURE NextSymbol;
  246. VAR comment: SyntaxTree.Comment;
  247. BEGIN
  248. error := ~scanner.GetNextSymbol(symbol) OR error;
  249. WHILE ~error & (symbol.token = Scanner.Comment) DO
  250. comment := SyntaxTree.NewComment(symbol.position, currentScope, symbol.string^, symbol.stringLength);
  251. moduleScope.AddComment(comment);
  252. IF recentComment = NIL THEN
  253. recentComment := comment;
  254. IF symbol.position.line = recentLine THEN
  255. IF recentCommentItem # NIL THEN
  256. IF (recentCommentItem IS SyntaxTree.Symbol) THEN
  257. IF recentCommentItem(SyntaxTree.Symbol).comment = NIL THEN
  258. recentCommentItem(SyntaxTree.Symbol).SetComment(comment)
  259. END;
  260. ELSIF (recentCommentItem IS SyntaxTree.Statement) THEN
  261. IF recentCommentItem(SyntaxTree.Statement).comment = NIL THEN
  262. recentCommentItem(SyntaxTree.Statement).SetComment(comment)
  263. END;
  264. ELSIF (recentCommentItem IS SyntaxTree.IfPart) THEN
  265. IF recentCommentItem(SyntaxTree.IfPart).comment = NIL THEN
  266. recentCommentItem(SyntaxTree.IfPart).SetComment(comment)
  267. END;
  268. ELSIF (recentCommentItem IS SyntaxTree.CasePart) THEN
  269. IF recentCommentItem(SyntaxTree.CasePart).comment = NIL THEN
  270. recentCommentItem(SyntaxTree.CasePart).SetComment(comment)
  271. END;
  272. (* LYNX+
  273. ELSIF (recentCommentItem IS SyntaxTree.WithPart) THEN
  274. IF recentCommentItem(SyntaxTree.WithPart).comment = NIL THEN
  275. recentCommentItem(SyntaxTree.WithPart).SetComment(comment)
  276. END;
  277. -LYNX *)
  278. END;
  279. comment.SetItem(recentCommentItem, TRUE);
  280. recentComment := NIL;
  281. recentCommentItem := NIL
  282. END;
  283. END;
  284. END;
  285. error := ~scanner.GetNextSymbol(symbol);
  286. END;
  287. END NextSymbol;
  288. (** Check if current symbol equals sym. If yes then return true, return false otherwise *)
  289. PROCEDURE Peek(token: Scanner.Token): BOOLEAN;
  290. VAR comment: SyntaxTree.Comment;
  291. BEGIN
  292. WHILE ~error & (symbol.token = Scanner.Comment) DO
  293. comment := SyntaxTree.NewComment(symbol.position, currentScope, symbol.string^, symbol.stringLength);
  294. moduleScope.AddComment(comment);
  295. IF recentComment = NIL THEN
  296. recentComment := comment;
  297. END;
  298. error := ~scanner.GetNextSymbol(symbol);
  299. END;
  300. RETURN symbol.token = token
  301. END Peek;
  302. (** Check if the current symbol equals sym. If yes then read next symbol, report error otherwise. Returns success value *)
  303. PROCEDURE Mandatory(token: Scanner.Token): BOOLEAN;
  304. BEGIN
  305. (* @@@ *)
  306. (*
  307. KernelLog.String("Mandatory: want ");
  308. KernelLog.Int(token, 1);
  309. KernelLog.String(" have ");
  310. KernelLog.Int(symbol.token, 1);
  311. KernelLog.Ln();
  312. *)
  313. (* because of NextSymbol! *)
  314. ASSERT(token # Scanner.Identifier);
  315. ASSERT(token # Scanner.IntegerLiteral);
  316. ASSERT(token # Scanner.RealLiteral);
  317. ASSERT(token # Scanner.CharacterLiteral);
  318. ASSERT(token # Scanner.StringLiteral);
  319. IF ~Peek(token) THEN
  320. Error(symbol.position, token, "");
  321. RETURN FALSE
  322. ELSE
  323. NextSymbol;
  324. RETURN TRUE
  325. END
  326. END Mandatory;
  327. (** Check if the current symbol equals sym. If yes then read next symbol, report error otherwise *)
  328. PROCEDURE Check(token: Scanner.Token);
  329. VAR b: BOOLEAN;
  330. BEGIN
  331. b := Mandatory(token);
  332. END Check;
  333. (** Check if current symbol is an identifier. If yes then copy identifier to name and get next symbol,
  334. report error otherwise and set name to empty name. Returns success value *)
  335. PROCEDURE MandatoryIdentifier(VAR name: SyntaxTree.Identifier): BOOLEAN;
  336. BEGIN
  337. IF Peek(Scanner.Identifier) THEN
  338. name := symbol.identifier;
  339. NextSymbol;
  340. RETURN TRUE
  341. ELSE
  342. Error(symbol.position, Scanner.Identifier, "");
  343. name := SyntaxTree.invalidIdentifier;
  344. RETURN FALSE
  345. END
  346. END MandatoryIdentifier;
  347. (** Expect an identifier (using MandatoryIdentifier) and return identifier object **)
  348. PROCEDURE Identifier(VAR position: Position): SyntaxTree.Identifier;
  349. VAR name: SyntaxTree.Identifier;
  350. identifier: SyntaxTree.Identifier;
  351. BEGIN
  352. position := symbol.position;
  353. IF MandatoryIdentifier(name) THEN
  354. identifier := name;
  355. ELSE
  356. identifier := SyntaxTree.invalidIdentifier;
  357. END;
  358. RETURN identifier
  359. END Identifier;
  360. (** Check if current symbol equals sym. If yes then get next symbol, return false otherwise *)
  361. PROCEDURE Optional(token: Scanner.Token): BOOLEAN;
  362. BEGIN
  363. (* do not use for Identifier or literal if the result is needed ! *)
  364. IF Peek(token) THEN
  365. NextSymbol;
  366. RETURN TRUE
  367. ELSE
  368. RETURN FALSE
  369. END
  370. END Optional;
  371. (* ignore one ore more symbols of type token *)
  372. PROCEDURE Ignore(token: Scanner.Token);
  373. BEGIN
  374. WHILE Optional(token) DO
  375. (* void *)
  376. END;
  377. END Ignore;
  378. (** Handling comments **)
  379. PROCEDURE SetNextInComment(c: SyntaxTree.Comment; this: ANY);
  380. BEGIN
  381. WHILE c # NIL DO
  382. c.SetItem(this, FALSE);
  383. c := c.nextComment
  384. END;
  385. END SetNextInComment;
  386. PROCEDURE CommentSymbol(symbol: SyntaxTree.Symbol);
  387. BEGIN
  388. IF (recentComment # NIL) (* & (recentComment.nextSymbol = NIL) *) THEN
  389. symbol.SetComment(recentComment);
  390. SetNextInComment(recentComment, symbol);
  391. recentComment := NIL
  392. END;
  393. recentLine := scanner.position.line;
  394. recentCommentItem := symbol;
  395. END CommentSymbol;
  396. (** Mapping tokens to AST operators **)
  397. (*
  398. Mapping table for all punctuation tokens
  399. Lynx Fox
  400. ------------------------------------------------------------
  401. Exclamation* = 1; (* ! *) Not
  402. ExclamationEqual* = 2; (* != *) Unequal
  403. Percent* = 3; (* % *) lynx@binop (rem)
  404. PercentEqual* = 4; (* %= *) lynx@asop (rem)
  405. And* = 5; (* & *) lynx@binop (and)
  406. AndEqual* = 6; (* &= *) lynx@asop (and)
  407. AndAnd* = 7; (* && *) And
  408. LeftParenthesis* = 8; (* ( *) N/A
  409. RightParenthesis* = 9; (* ) *) N/A
  410. Times* = 10; (* * *) Times
  411. TimesEqual* = 11; (* *= *) lynx@asop (mul)
  412. Plus* = 12; (* + *) Plus
  413. PlusEqual* = 13; (* += *) lynx@asop (add)
  414. PlusPlus* = 14; (* ++ *) lynx@asop (add)
  415. Comma* = 15; (* , *) N/A
  416. Minus* = 16; (* - *) Minus
  417. MinusEqual* = 17; (* -= *) lynx@asop (sub)
  418. MinusMinus* = 18; (* -- *) lynx@asop (sub)
  419. Period* = 19; (* . *) N/A
  420. Slash* = 20; (* / *) lynx@binop (div)
  421. SlashEqual* = 21; (* /= *) lynx@asop (div)
  422. Colon* = 22; (* : *) N/A
  423. Semicolon* = 23; (* ; *) N/A
  424. Less* = 24; (* < *) Less
  425. LessEqual* = 25; (* <= *) LessEqual
  426. LeftShift* = 26; (* << *) lynx@binop (shl)
  427. LeftShiftEqual* = 27; (* <<= *) lynx@asop (shl)
  428. Equal* = 28; (* = *) N/A
  429. EqualEqual* = 29; (* == *) Equal
  430. Greater* = 30; (* > *) Greater
  431. GreaterEqual* = 31; (* >= *) GreaterEqual
  432. RightShift* = 32; (* >> *) lynx@binop (shr)
  433. RightShiftEqual* = 33; (* >>= *) lynx@asop (shr)
  434. LeftBracket* = 34; (* [ *) N/A
  435. RightBracket* = 35; (* ] *) N/A
  436. Arrow* = 36; (* ^ *) lynx@binop (xor)
  437. ArrowEqual* = 37; (* ^= *) lynx@asop (xor)
  438. LeftBrace* = 38; (* { *) N/A
  439. Bar* = 39; (* | *) lynx@binop (or)
  440. BarEqual* = 40; (* |= *) lynx@asop (or)
  441. BarBar* = 41; (* || *) Or
  442. RightBrace* = 42; (* } *) N/A
  443. Tilde* = 43; (* ~ *) lynx@unop (not)
  444. *)
  445. PROCEDURE MapOperator(token: Scanner.Token): LONGINT;
  446. VAR operator: LONGINT;
  447. BEGIN
  448. CASE token OF
  449. Scanner.Exclamation:
  450. operator := FoxScanner.Not;
  451. | Scanner.ExclamationEqual:
  452. operator := FoxScanner.Unequal;
  453. | Scanner.Percent, Scanner.PercentEqual:
  454. operator := 256 + Global.LynxOpRem;
  455. | Scanner.And, Scanner.AndEqual:
  456. operator := 256 + Global.LynxOpAnd;
  457. | Scanner.AndAnd:
  458. operator := FoxScanner.And;
  459. | Scanner.Times:
  460. operator := FoxScanner.Times;
  461. | Scanner.TimesEqual:
  462. operator := 256 + Global.LynxOpMul;
  463. | Scanner.Plus:
  464. operator := FoxScanner.Plus;
  465. | Scanner.PlusEqual, Scanner.PlusPlus:
  466. operator := 256 + Global.LynxOpAdd;
  467. | Scanner.Minus:
  468. operator := FoxScanner.Minus;
  469. | Scanner.MinusEqual, Scanner.MinusMinus:
  470. operator := 256 + Global.LynxOpSub;
  471. | Scanner.Slash, Scanner.SlashEqual:
  472. operator := 256 + Global.LynxOpDiv;
  473. | Scanner.Less:
  474. operator := FoxScanner.Less;
  475. | Scanner.LessEqual:
  476. operator := FoxScanner.LessEqual;
  477. | Scanner.LeftShift, Scanner.LeftShiftEqual:
  478. operator := 256 + Global.LynxOpShl;
  479. | Scanner.EqualEqual:
  480. operator := FoxScanner.Equal;
  481. | Scanner.Greater:
  482. operator := FoxScanner.Greater;
  483. | Scanner.GreaterEqual:
  484. operator := FoxScanner.GreaterEqual;
  485. | Scanner.RightShift, Scanner.RightShiftEqual:
  486. operator := 256 + Global.LynxOpShr;
  487. | Scanner.Arrow, Scanner.ArrowEqual:
  488. operator := 256 + Global.LynxOpXor;
  489. | Scanner.Bar, Scanner.BarEqual:
  490. operator := 256 + Global.LynxOpOr;
  491. | Scanner.BarBar:
  492. operator := FoxScanner.Or;
  493. | Scanner.Tilde:
  494. operator := 256 + Global.LynxOpNot;
  495. END;
  496. RETURN operator;
  497. END MapOperator;
  498. PROCEDURE NewUnaryExpression(
  499. position: Position;
  500. operand: SyntaxTree.Expression;
  501. operator: LONGINT): SyntaxTree.Expression;
  502. VAR expressionList: SyntaxTree.ExpressionList;
  503. expression: SyntaxTree.Expression;
  504. designator: SyntaxTree.Designator;
  505. BEGIN
  506. operator := MapOperator(operator);
  507. IF operator < 256 THEN
  508. expression := SyntaxTree.NewUnaryExpression(position, operand, operator);
  509. ELSE
  510. expressionList := SyntaxTree.NewExpressionList();
  511. expression := SyntaxTree.NewIntegerValue(position, operator-256);
  512. expressionList.AddExpression(expression);
  513. expressionList.AddExpression(operand);
  514. designator := SyntaxTree.NewIdentifierDesignator(position, lynxUnop);
  515. expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
  516. END;
  517. RETURN expression;
  518. END NewUnaryExpression;
  519. PROCEDURE NewBinaryExpression(
  520. position: Position;
  521. left, right: SyntaxTree.Expression;
  522. operator: LONGINT): SyntaxTree.Expression;
  523. VAR expressionList: SyntaxTree.ExpressionList;
  524. expression: SyntaxTree.Expression;
  525. designator: SyntaxTree.Designator;
  526. BEGIN
  527. operator := MapOperator(operator);
  528. IF operator < 256 THEN
  529. expression := SyntaxTree.NewBinaryExpression(position, left, right, operator);
  530. ELSE
  531. expressionList := SyntaxTree.NewExpressionList();
  532. expression := SyntaxTree.NewIntegerValue(position, operator-256);
  533. expressionList.AddExpression(expression);
  534. expressionList.AddExpression(left);
  535. expressionList.AddExpression(right);
  536. designator := SyntaxTree.NewIdentifierDesignator(position, lynxBinop);
  537. expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
  538. END;
  539. RETURN expression;
  540. END NewBinaryExpression;
  541. PROCEDURE NewTypeExpression(position: Position): SyntaxTree.Expression;
  542. BEGIN
  543. RETURN SyntaxTree.NewIdentifierDesignator(position, lynxType);
  544. END NewTypeExpression;
  545. PROCEDURE NewReceiveExpression(
  546. position: Position; left, right: SyntaxTree.Expression): SyntaxTree.Expression;
  547. VAR expressionList: SyntaxTree.ExpressionList;
  548. expression: SyntaxTree.Expression;
  549. designator: SyntaxTree.Designator;
  550. BEGIN
  551. expressionList := SyntaxTree.NewExpressionList();
  552. expressionList.AddExpression(left);
  553. expressionList.AddExpression(right);
  554. designator := SyntaxTree.NewIdentifierDesignator(position, lynxRecvnb);
  555. expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
  556. RETURN expression;
  557. END NewReceiveExpression;
  558. PROCEDURE MapNumberType(numberType: LONGINT): LONGINT;
  559. BEGIN
  560. CASE numberType OF
  561. Scanner.IntNumber:
  562. numberType := FoxScanner.Longint;
  563. | Scanner.LongNumber:
  564. numberType := FoxScanner.Hugeint;
  565. | Scanner.FloatNumber:
  566. numberType := FoxScanner.Real;
  567. | Scanner.DoubleNumber:
  568. numberType := FoxScanner.Longreal;
  569. END;
  570. RETURN numberType;
  571. END MapNumberType;
  572. (*
  573. ACHTUNG: Initializers of members of modules, classes, structs,
  574. cells, and cellnets are collected in a special statement
  575. block. This block is inserted as the first statement in
  576. the corresponding constructors.
  577. TODO: This feature is not yet implemented. Initializers are
  578. collected but not inserted in constructors. Implement what is missing.
  579. *)
  580. (* create a statement block to collect initializers *)
  581. PROCEDURE EnterInit;
  582. VAR block: SyntaxTree.StatementBlock;
  583. BEGIN
  584. block := SyntaxTree.NewStatementBlock(invalidPosition, NIL, NIL);
  585. initOuter := block;
  586. initStatements := SyntaxTree.NewStatementSequence();
  587. block.SetStatementSequence(initStatements);
  588. END EnterInit;
  589. (** Parsing according to the EBNF **)
  590. (**
  591. type-name:
  592. identifier
  593. module-name '.' identifier
  594. **)
  595. PROCEDURE QualifiedIdentifier(): SyntaxTree.QualifiedIdentifier;
  596. VAR prefix, suffix: SyntaxTree.Identifier;
  597. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
  598. position0, position1: Position;
  599. BEGIN
  600. IF Trace THEN
  601. S("QualifiedIdentifier")
  602. END;
  603. prefix := Identifier(position0);
  604. IF prefix # SyntaxTree.invalidIdentifier THEN
  605. IF ~Optional(Scanner.Period) THEN
  606. suffix := prefix;
  607. prefix := SyntaxTree.invalidIdentifier; (* empty *)
  608. ELSE
  609. suffix := Identifier(position1);
  610. END;
  611. qualifiedIdentifier := SyntaxTree.NewQualifiedIdentifier(position0, prefix, suffix);
  612. ELSE
  613. qualifiedIdentifier := SyntaxTree.invalidQualifiedIdentifier;
  614. END;
  615. IF Trace THEN
  616. E("QualifiedIdentifier")
  617. END;
  618. RETURN qualifiedIdentifier
  619. END QualifiedIdentifier;
  620. (**
  621. expression-list:
  622. expression
  623. expression-list ',' expression
  624. **)
  625. PROCEDURE ExpressionList(expressionList: SyntaxTree.ExpressionList);
  626. VAR expression: SyntaxTree.Expression;
  627. BEGIN
  628. IF Trace THEN
  629. S("ExpressionList")
  630. END;
  631. REPEAT
  632. expression := Expression();
  633. expressionList.AddExpression(expression);
  634. UNTIL ~Optional(Scanner.Comma);
  635. IF Trace THEN
  636. E("ExpressionList")
  637. END;
  638. END ExpressionList;
  639. (**
  640. argument-list:
  641. argument
  642. argument-list ',' argument
  643. argument:
  644. expression
  645. 'ref' variable-reference
  646. variable-reference:
  647. expression
  648. **)
  649. PROCEDURE ArgumentList(expressionList: SyntaxTree.ExpressionList);
  650. VAR expression: SyntaxTree.Expression;
  651. modifier: LONGINT;
  652. BEGIN
  653. IF Trace THEN
  654. S("ArgumentList")
  655. END;
  656. REPEAT
  657. IF Optional(Scanner.Ref) THEN
  658. modifier := Scanner.Ref;
  659. ELSE
  660. modifier := -1;
  661. END;
  662. (*
  663. ACHTUNG: Modifiers cannot be validated without AST modifications,
  664. therefore 'modifier' value is not used in this release.
  665. *)
  666. expression := Expression();
  667. expressionList.AddExpression(expression);
  668. UNTIL ~Optional(Scanner.Comma);
  669. IF Trace THEN
  670. E("ArgumentList")
  671. END;
  672. END ArgumentList;
  673. (**
  674. primary-expression:
  675. array-creation-expression
  676. primary-no-array-creation-expression
  677. primary-no-array-creation-expression:
  678. literal
  679. simple-name
  680. parenthesized-expression
  681. member-access
  682. invocation-expression
  683. element-access
  684. this-access
  685. base-access
  686. object-creation-expression
  687. delegate-creation-expression
  688. receive-expression
  689. literal:
  690. boolean-literal
  691. integer-literal
  692. real-literal
  693. character-literal
  694. string-literal
  695. null-literal
  696. boolean-literal:
  697. 'true'
  698. 'false'
  699. null-literal:
  700. 'null'
  701. simple-name:
  702. identifier
  703. parenthesized-expression:
  704. '(' expression ')'
  705. member-access:
  706. primary-expression '.' identifier
  707. invocation-expression:
  708. primary-expression '(' [argument-list] ')'
  709. element-access:
  710. primary-no-array-creation-expression '[' expression-list ']'
  711. this-access:
  712. 'this'
  713. base-access:
  714. 'base' '.' identifier
  715. object-creation-expression:
  716. 'new' non-array-type '(' [argument-list] ')'
  717. array-creation-expression:
  718. 'new' non-array-type '[' expression-list ']' [rank-specifiers]
  719. delegate-creation-expression:
  720. 'new' delegate-type '(' expression ')'
  721. receive-expression:
  722. primary-expression '??' primary-expression
  723. **)
  724. PROCEDURE Accessors(expression: SyntaxTree.Expression; arrayCreation: BOOLEAN): SyntaxTree.Expression;
  725. VAR identifier: SyntaxTree.Identifier;
  726. expressionList: SyntaxTree.ExpressionList;
  727. position: Position;
  728. BEGIN
  729. LOOP
  730. position := symbol.position;
  731. IF Optional(Scanner.Period) THEN
  732. identifier := Identifier(position);
  733. expression := SyntaxTree.NewSelectorDesignator(position, expression(SyntaxTree.Designator), identifier);
  734. ELSIF Optional(Scanner.LeftParenthesis) THEN
  735. expressionList := SyntaxTree.NewExpressionList();
  736. IF ~Optional(Scanner.RightParenthesis) THEN
  737. ArgumentList(expressionList);
  738. Check(Scanner.RightParenthesis);
  739. END;
  740. expression := SyntaxTree.NewParameterDesignator(position, expression(SyntaxTree.Designator), expressionList);
  741. ELSIF (~arrayCreation) & Optional(Scanner.LeftBracket) THEN
  742. expressionList := SyntaxTree.NewExpressionList();
  743. ExpressionList(expressionList);
  744. Check(Scanner.RightBracket);
  745. (* ACHTUNG: 27-09-2012
  746. expression := SyntaxTree.NewArrowDesignator(position, expression);
  747. *)
  748. expression := SyntaxTree.NewBracketDesignator(position, expression(SyntaxTree.Designator), expressionList);
  749. ELSE
  750. EXIT;
  751. END;
  752. END;
  753. RETURN expression;
  754. END Accessors;
  755. PROCEDURE PrimaryExpression(): SyntaxTree.Expression;
  756. VAR expression: SyntaxTree.Expression;
  757. designator: SyntaxTree.Designator;
  758. realValue: SyntaxTree.RealValue;
  759. identifier: SyntaxTree.Identifier;
  760. type: SyntaxTree.Type;
  761. typeExpression: SyntaxTree.Expression;
  762. expressionList: SyntaxTree.ExpressionList;
  763. position: Position;
  764. arrayCreation: BOOLEAN;
  765. arrayType: SyntaxTree.ArrayType;
  766. pointerType: SyntaxTree.PointerType;
  767. rightExpression: SyntaxTree.Expression;
  768. i, n: LONGINT;
  769. BEGIN
  770. IF Trace THEN
  771. S("PrimaryExpression")
  772. END;
  773. position := symbol.position;
  774. arrayCreation := FALSE;
  775. IF Peek(Scanner.True) THEN
  776. expression := SyntaxTree.NewBooleanValue(position, TRUE);
  777. NextSymbol;
  778. ELSIF Peek(Scanner.False) THEN
  779. expression := SyntaxTree.NewBooleanValue(position, FALSE);
  780. NextSymbol;
  781. ELSIF Peek(Scanner.IntegerLiteral) THEN
  782. IF symbol.numberType = Scanner.IntNumber THEN
  783. expression := SyntaxTree.NewIntegerValue(position, symbol.integer);
  784. ELSIF symbol.numberType = Scanner.LongNumber THEN
  785. expression := SyntaxTree.NewIntegerValue(position, symbol.hugeint);
  786. ELSE
  787. HALT(100);
  788. END;
  789. NextSymbol;
  790. ELSIF Peek(Scanner.RealLiteral) THEN
  791. realValue := SyntaxTree.NewRealValue(position, symbol.real, symbol.numberType);
  792. expression := realValue;
  793. NextSymbol;
  794. ELSIF Peek(Scanner.CharacterLiteral) THEN
  795. expression := SyntaxTree.NewCharacterValue(position, symbol.character);
  796. NextSymbol;
  797. ELSIF Peek(Scanner.StringLiteral) THEN
  798. (*
  799. TODO: Revise this: may need a string constructor wrapper ...
  800. ... and symbol.stringLength may be important too
  801. *)
  802. expression := SyntaxTree.NewStringValue(position, symbol.string);
  803. NextSymbol;
  804. ELSIF Peek(Scanner.Identifier) THEN
  805. identifier := Identifier(position);
  806. identifier := localIdentTable.Find(identifier);
  807. expression := SyntaxTree.NewIdentifierDesignator(position, identifier);
  808. ELSIF Peek(Scanner.Null) THEN
  809. expression := SyntaxTree.NewNilValue(position);
  810. NextSymbol;
  811. ELSIF Optional(Scanner.LeftParenthesis) THEN
  812. expression := Expression();
  813. Check(Scanner.RightParenthesis);
  814. ELSIF Optional(Scanner.This) THEN
  815. expression := SyntaxTree.NewSelfDesignator(position,NIL);
  816. ELSIF Optional(Scanner.Base) THEN
  817. Check(Scanner.Period);
  818. position := symbol.position;
  819. identifier := Identifier(position);
  820. expression := SyntaxTree.NewIdentifierDesignator(position, identifier);
  821. expression := SyntaxTree.NewArrowDesignator(position, expression(SyntaxTree.Designator));
  822. ELSIF Optional(Scanner.New) THEN
  823. type := NonArrayType();
  824. expressionList := SyntaxTree.NewExpressionList();
  825. typeExpression := NewTypeExpression(position);
  826. expressionList.AddExpression(typeExpression);
  827. IF Optional(Scanner.LeftBracket) THEN
  828. arrayCreation := TRUE;
  829. ExpressionList(expressionList);
  830. Check(Scanner.RightBracket);
  831. WHILE Optional(Scanner.LeftBracket) DO
  832. type := RankSpecifier(type);
  833. Check(Scanner.RightBracket);
  834. END;
  835. n := expressionList.Length() - 1;
  836. FOR i := 1 TO n DO
  837. arrayType := SyntaxTree.NewArrayType(position, currentScope, SyntaxTree.Open);
  838. arrayType.SetArrayBase(type);
  839. type := arrayType;
  840. END;
  841. pointerType := SyntaxTree.NewPointerType(position, currentScope);
  842. pointerType.SetPointerBase(type);
  843. type := pointerType;
  844. END;
  845. typeExpression.SetType(type);
  846. IF ~arrayCreation THEN
  847. Check(Scanner.LeftParenthesis);
  848. IF ~Optional(Scanner.RightParenthesis) THEN
  849. ArgumentList(expressionList);
  850. Check(Scanner.RightParenthesis);
  851. END;
  852. designator := SyntaxTree.NewIdentifierDesignator(position, lynxNewobj);
  853. expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
  854. ELSE
  855. designator := SyntaxTree.NewIdentifierDesignator(position, lynxNewarr);
  856. expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
  857. END;
  858. ELSE
  859. Error(symbol.position, Basic.InvalidCode, "Invalid primary expression");
  860. NextSymbol;
  861. expression := SyntaxTree.invalidExpression;
  862. END;
  863. expression := Accessors(expression, arrayCreation);
  864. position := symbol.position;
  865. IF Optional(Scanner.QuestionQuestion) THEN
  866. rightExpression := PrimaryExpression();
  867. expression := NewReceiveExpression(position, expression, rightExpression);
  868. END;
  869. IF Trace THEN
  870. E("PrimaryExpression")
  871. END;
  872. RETURN expression;
  873. END PrimaryExpression;
  874. (**
  875. unary-expression:
  876. primary-expression
  877. '+' unary-expression
  878. '-' unary-expression
  879. '!' unary-expression
  880. '~' unary-expression
  881. cast-expression
  882. **)
  883. PROCEDURE UnaryExpression(): SyntaxTree.Expression;
  884. VAR expression: SyntaxTree.Expression;
  885. operator: LONGINT;
  886. position: Position;
  887. BEGIN
  888. IF Trace THEN
  889. S("UnaryExpression")
  890. END;
  891. position := symbol.position;
  892. IF Peek(Scanner.Plus) OR Peek(Scanner.Minus) OR
  893. Peek(Scanner.Exclamation) OR Peek(Scanner.Tilde) THEN
  894. operator := symbol.token;
  895. NextSymbol;
  896. expression := UnaryExpression();
  897. expression := NewUnaryExpression(position, expression, operator);
  898. ELSE
  899. (* TODO: Implement cast-expression *)
  900. expression := PrimaryExpression();
  901. END;
  902. IF Trace THEN
  903. E("UnaryExpression")
  904. END;
  905. RETURN expression;
  906. END UnaryExpression;
  907. (**
  908. multiplicative-expression:
  909. unary-expression
  910. multiplicative-expression '*' unary-expression
  911. multiplicative-expression '/' unary-expression
  912. multiplicative-expression '%' unary-expression
  913. **)
  914. PROCEDURE MultiplicativeExpression(): SyntaxTree.Expression;
  915. VAR expression, rightExpression: SyntaxTree.Expression;
  916. operator: LONGINT;
  917. position: Position;
  918. BEGIN
  919. IF Trace THEN
  920. S("MultiplicativeExpression")
  921. END;
  922. position := symbol.position;
  923. expression := UnaryExpression();
  924. WHILE Peek(Scanner.Times) OR Peek(Scanner.Slash) OR Peek(Scanner.Percent) DO
  925. operator := symbol.token;
  926. NextSymbol;
  927. rightExpression := UnaryExpression();
  928. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  929. END;
  930. IF Trace THEN
  931. E("MultiplicativeExpression")
  932. END;
  933. RETURN expression;
  934. END MultiplicativeExpression;
  935. (**
  936. additive-expression:
  937. multiplicative-expression
  938. additive-expression '+' multiplicative-expression
  939. additive-expression '–' multiplicative-expression
  940. **)
  941. PROCEDURE AdditiveExpression(): SyntaxTree.Expression;
  942. VAR expression, rightExpression: SyntaxTree.Expression;
  943. operator: LONGINT;
  944. position: Position;
  945. BEGIN
  946. IF Trace THEN
  947. S("AdditiveExpression")
  948. END;
  949. position := symbol.position;
  950. expression := MultiplicativeExpression();
  951. WHILE Peek(Scanner.Plus) OR Peek(Scanner.Minus) DO
  952. operator := symbol.token;
  953. NextSymbol;
  954. rightExpression := MultiplicativeExpression();
  955. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  956. END;
  957. IF Trace THEN
  958. E("AdditiveExpression")
  959. END;
  960. RETURN expression;
  961. END AdditiveExpression;
  962. (**
  963. shift-expression:
  964. additive-expression
  965. shift-expression '<<' additive-expression
  966. shift-expression '>>' additive-expression
  967. **)
  968. PROCEDURE ShiftExpression(): SyntaxTree.Expression;
  969. VAR expression, rightExpression: SyntaxTree.Expression;
  970. operator: LONGINT;
  971. position: Position;
  972. BEGIN
  973. IF Trace THEN
  974. S("ShiftExpression")
  975. END;
  976. position := symbol.position;
  977. expression := AdditiveExpression();
  978. WHILE Peek(Scanner.LeftShift) OR Peek(Scanner.RightShift) DO
  979. operator := symbol.token;
  980. NextSymbol;
  981. rightExpression := AdditiveExpression();
  982. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  983. END;
  984. IF Trace THEN
  985. E("ShiftExpression")
  986. END;
  987. RETURN expression;
  988. END ShiftExpression;
  989. (**
  990. relational-expression:
  991. shift-expression
  992. relational-expression '<' shift-expression
  993. relational-expression '>' shift-expression
  994. relational-expression '<=' shift-expression
  995. relational-expression '>=' shift-expression
  996. relational-expression 'is' type-name
  997. relational-expression 'as' type-name
  998. **)
  999. PROCEDURE RelationalExpression(): SyntaxTree.Expression;
  1000. VAR expression, rightExpression: SyntaxTree.Expression;
  1001. operator: LONGINT;
  1002. position: Position;
  1003. BEGIN
  1004. IF Trace THEN
  1005. S("RelationalExpression")
  1006. END;
  1007. position := symbol.position;
  1008. expression := ShiftExpression();
  1009. WHILE Peek(Scanner.Less) OR Peek(Scanner.Greater) OR
  1010. Peek(Scanner.LessEqual) OR Peek(Scanner.GreaterEqual) OR
  1011. Peek(Scanner.Is) OR Peek(Scanner.As) DO
  1012. operator := symbol.token;
  1013. NextSymbol;
  1014. rightExpression := ShiftExpression();
  1015. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1016. END;
  1017. IF Trace THEN
  1018. E("RelationalExpression")
  1019. END;
  1020. RETURN expression;
  1021. END RelationalExpression;
  1022. (**
  1023. equality-expression:
  1024. relational-expression
  1025. equality-expression '==' relational-expression
  1026. equality-expression '!=' relational-expression
  1027. **)
  1028. PROCEDURE EqualityExpression(): SyntaxTree.Expression;
  1029. VAR expression, rightExpression: SyntaxTree.Expression;
  1030. operator: LONGINT;
  1031. position: Position;
  1032. BEGIN
  1033. IF Trace THEN
  1034. S("EqualityExpression")
  1035. END;
  1036. position := symbol.position;
  1037. expression := RelationalExpression();
  1038. WHILE Peek(Scanner.EqualEqual) OR Peek(Scanner.ExclamationEqual) DO
  1039. operator := symbol.token;
  1040. NextSymbol;
  1041. rightExpression := RelationalExpression();
  1042. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1043. END;
  1044. IF Trace THEN
  1045. E("EqualityExpression")
  1046. END;
  1047. RETURN expression;
  1048. END EqualityExpression;
  1049. (**
  1050. and-expression:
  1051. equality-expression
  1052. and-expression '&' equality-expression
  1053. **)
  1054. PROCEDURE AndExpression(): SyntaxTree.Expression;
  1055. VAR expression, rightExpression: SyntaxTree.Expression;
  1056. operator: LONGINT;
  1057. position: Position;
  1058. BEGIN
  1059. IF Trace THEN
  1060. S("AndExpression")
  1061. END;
  1062. position := symbol.position;
  1063. expression := EqualityExpression();
  1064. WHILE Peek(Scanner.And) DO
  1065. operator := symbol.token;
  1066. NextSymbol;
  1067. rightExpression := EqualityExpression();
  1068. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1069. END;
  1070. IF Trace THEN
  1071. E("AndExpression")
  1072. END;
  1073. RETURN expression;
  1074. END AndExpression;
  1075. (**
  1076. exclusive-or-expression:
  1077. and-expression
  1078. exclusive-or-expression '^' and-expression
  1079. **)
  1080. PROCEDURE ExclusiveOrExpression(): SyntaxTree.Expression;
  1081. VAR expression, rightExpression: SyntaxTree.Expression;
  1082. operator: LONGINT;
  1083. position: Position;
  1084. BEGIN
  1085. IF Trace THEN
  1086. S("ExclusiveOrExpression")
  1087. END;
  1088. position := symbol.position;
  1089. expression := AndExpression();
  1090. WHILE Peek(Scanner.Arrow) DO
  1091. operator := symbol.token;
  1092. NextSymbol;
  1093. rightExpression := AndExpression();
  1094. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1095. END;
  1096. IF Trace THEN
  1097. E("ExclusiveOrExpression")
  1098. END;
  1099. RETURN expression;
  1100. END ExclusiveOrExpression;
  1101. (**
  1102. inclusive-or-expression:
  1103. exclusive-or-expression
  1104. inclusive-or-expression '|' exclusive-or-expression
  1105. **)
  1106. PROCEDURE InclusiveOrExpression(): SyntaxTree.Expression;
  1107. VAR expression, rightExpression: SyntaxTree.Expression;
  1108. operator: LONGINT;
  1109. position: Position;
  1110. BEGIN
  1111. IF Trace THEN
  1112. S("InclusiveOrExpression")
  1113. END;
  1114. position := symbol.position;
  1115. expression := ExclusiveOrExpression();
  1116. WHILE Peek(Scanner.Bar) DO
  1117. operator := symbol.token;
  1118. NextSymbol;
  1119. rightExpression := ExclusiveOrExpression();
  1120. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1121. END;
  1122. IF Trace THEN
  1123. E("InclusiveOrExpression")
  1124. END;
  1125. RETURN expression;
  1126. END InclusiveOrExpression;
  1127. (**
  1128. conditional-and-expression:
  1129. inclusive-or-expression
  1130. conditional-and-expression '&&' inclusive-or-expression
  1131. **)
  1132. PROCEDURE ConditionalAndExpression(): SyntaxTree.Expression;
  1133. VAR expression, rightExpression: SyntaxTree.Expression;
  1134. operator: LONGINT;
  1135. position: Position;
  1136. BEGIN
  1137. IF Trace THEN
  1138. S("ConditionalAndExpression")
  1139. END;
  1140. position := symbol.position;
  1141. expression := InclusiveOrExpression();
  1142. WHILE Peek(Scanner.AndAnd) DO
  1143. operator := symbol.token;
  1144. NextSymbol;
  1145. rightExpression := InclusiveOrExpression();
  1146. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1147. END;
  1148. IF Trace THEN
  1149. E("ConditionalAndExpression")
  1150. END;
  1151. RETURN expression;
  1152. END ConditionalAndExpression;
  1153. (**
  1154. conditional-or-expression:
  1155. conditional-and-expression
  1156. conditional-or-expression '||' conditional-and-expression
  1157. **)
  1158. PROCEDURE ConditionalOrExpression(): SyntaxTree.Expression;
  1159. VAR expression, rightExpression: SyntaxTree.Expression;
  1160. operator: LONGINT;
  1161. position: Position;
  1162. BEGIN
  1163. IF Trace THEN
  1164. S("ConditionalOrExpression")
  1165. END;
  1166. position := symbol.position;
  1167. expression := ConditionalAndExpression();
  1168. WHILE Peek(Scanner.BarBar) DO
  1169. operator := symbol.token;
  1170. NextSymbol;
  1171. rightExpression := ConditionalAndExpression();
  1172. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1173. END;
  1174. IF Trace THEN
  1175. E("ConditionalOrExpression")
  1176. END;
  1177. RETURN expression;
  1178. END ConditionalOrExpression;
  1179. (**
  1180. expression:
  1181. conditional-expression
  1182. conditional-expression:
  1183. conditional-or-expression
  1184. **)
  1185. PROCEDURE Expression(): SyntaxTree.Expression;
  1186. VAR expression: SyntaxTree.Expression;
  1187. BEGIN
  1188. IF Trace THEN
  1189. S("Expression")
  1190. END;
  1191. expression := ConditionalOrExpression();
  1192. IF Trace THEN
  1193. E("Expression")
  1194. END;
  1195. RETURN expression;
  1196. END Expression;
  1197. (**
  1198. local-variable-declaration:
  1199. type local-variable-declarators
  1200. **)
  1201. PROCEDURE LocalVariableDeclaration(
  1202. statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement; type: SyntaxTree.Type);
  1203. VAR previousStatements: SyntaxTree.StatementSequence;
  1204. previousOuter: SyntaxTree.Statement;
  1205. BEGIN
  1206. IF Trace THEN
  1207. S("LocalVariableDeclaration")
  1208. END;
  1209. previousStatements := initStatements;
  1210. previousOuter := initOuter;
  1211. initStatements := statements;
  1212. initOuter := outer;
  1213. IF type = NIL THEN
  1214. type := Type();
  1215. END;
  1216. REPEAT
  1217. VariableDeclarator(currentScope, {}, type, SyntaxTree.invalidIdentifier, invalidPosition);
  1218. UNTIL ~Optional(Scanner.Comma);
  1219. initStatements := previousStatements;
  1220. initOuter := previousOuter;
  1221. IF Trace THEN
  1222. E("LocalVariableDeclaration")
  1223. END;
  1224. END LocalVariableDeclaration;
  1225. (**
  1226. local-constant-declaration:
  1227. 'const' type constant-declarators
  1228. **)
  1229. PROCEDURE LocalConstantDeclaration(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1230. VAR type: SyntaxTree.Type;
  1231. BEGIN
  1232. (* ACHTUNG: Parameters 'statements' and 'outer' are not used *)
  1233. IF Trace THEN
  1234. S("LocalConstantDeclaration")
  1235. END;
  1236. type := Type();
  1237. REPEAT
  1238. ConstantDeclarator(currentScope, {}, type);
  1239. UNTIL ~Optional(Scanner.Comma);
  1240. IF Trace THEN
  1241. E("LocalConstantDeclaration")
  1242. END;
  1243. END LocalConstantDeclaration;
  1244. (**
  1245. block:
  1246. '{' [statement-list] '}'
  1247. **)
  1248. PROCEDURE Block(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1249. VAR block: SyntaxTree.StatementBlock; position: Position;
  1250. BEGIN
  1251. IF Trace THEN
  1252. S("Block")
  1253. END;
  1254. Check(Scanner.LeftBrace);
  1255. position := symbol.position; position.start := position.end;
  1256. block := SyntaxTree.NewStatementBlock(position, outer, NIL);
  1257. (* CommentStatement(block); *)
  1258. IF ~Optional(Scanner.RightBrace) THEN
  1259. localIdentTable.OpenScope;
  1260. block.SetStatementSequence(StatementList(block));
  1261. localIdentTable.CloseScope;
  1262. Check(Scanner.RightBrace);
  1263. END;
  1264. statements.AddStatement(block);
  1265. IF Trace THEN
  1266. E("Block")
  1267. END;
  1268. END Block;
  1269. (**
  1270. expression-statement:
  1271. statement-expression ';'
  1272. statement-expression:
  1273. invocation-expression
  1274. assignment
  1275. post-increment-expression
  1276. post-decrement-expression
  1277. send-expression
  1278. receive-expression
  1279. connect-expression
  1280. delegate-expression
  1281. assignment:
  1282. primary-expression assignment-operator expression
  1283. assignment-operator: one of
  1284. '=' '+=' '-=' '*=' '/=' '%=' '&=' '|=' '^=' '<<=' '>>='
  1285. post-increment-expression:
  1286. primary-expression '++'
  1287. post-decrement-expression:
  1288. primary-expression '--'
  1289. send-expression:
  1290. primary-expression '!' expression-list
  1291. receive-expression:
  1292. primary-expression '?' expression-list
  1293. connect-expression:
  1294. primary-expression '>>' primary-expression
  1295. delegate-expression:
  1296. primary-expression '<=' primary-expression
  1297. **)
  1298. PROCEDURE NewAsopStatement(
  1299. position: Position;
  1300. operator: LONGINT;
  1301. left: SyntaxTree.Designator;
  1302. right: SyntaxTree.Expression;
  1303. outer: SyntaxTree.Statement): SyntaxTree.Statement;
  1304. VAR expressionList: SyntaxTree.ExpressionList;
  1305. expression: SyntaxTree.Expression;
  1306. designator: SyntaxTree.Designator;
  1307. BEGIN
  1308. operator := MapOperator(operator);
  1309. ASSERT(operator >= 256);
  1310. expressionList := SyntaxTree.NewExpressionList();
  1311. expression := SyntaxTree.NewIntegerValue(position, operator-256);
  1312. expressionList.AddExpression(expression);
  1313. expressionList.AddExpression(left);
  1314. expressionList.AddExpression(right);
  1315. designator := SyntaxTree.NewIdentifierDesignator(position, lynxAsop);
  1316. designator := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
  1317. RETURN SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
  1318. END NewAsopStatement;
  1319. (* ACHTUNG: LYNX 15-MAY-2013 *)
  1320. PROCEDURE PatchPortReference(expression: SyntaxTree.Expression): SyntaxTree.Expression;
  1321. VAR result: SyntaxTree.Expression;
  1322. parameterDesignator: SyntaxTree.ParameterDesignator;
  1323. parameters: SyntaxTree.ExpressionList;
  1324. p0: SyntaxTree.Expression;
  1325. identifierDesignator: SyntaxTree.IdentifierDesignator;
  1326. bracketDesignator: SyntaxTree.BracketDesignator;
  1327. left, left2: SyntaxTree.Expression;
  1328. BEGIN
  1329. IF ~(expression IS SyntaxTree.ParameterDesignator) THEN
  1330. result := expression;
  1331. ELSE
  1332. parameterDesignator := expression(SyntaxTree.ParameterDesignator);
  1333. parameters := parameterDesignator.parameters;
  1334. IF parameters.Length() # 1 THEN
  1335. result := expression;
  1336. ELSE
  1337. p0 := parameters.GetExpression(0);
  1338. IF p0 IS SyntaxTree.IdentifierDesignator THEN
  1339. (* C(P) -> C.P *)
  1340. left := parameterDesignator.left;
  1341. identifierDesignator := p0(SyntaxTree.IdentifierDesignator);
  1342. result :=
  1343. SyntaxTree.NewSelectorDesignator(
  1344. expression.position, left(SyntaxTree.Designator), identifierDesignator.identifier);
  1345. ELSIF p0 IS SyntaxTree.BracketDesignator THEN
  1346. bracketDesignator := p0(SyntaxTree.BracketDesignator);
  1347. left2 := bracketDesignator.left;
  1348. IF left2 IS SyntaxTree.IdentifierDesignator THEN
  1349. (* C(P[I]) -> C.P[I] *)
  1350. left := parameterDesignator.left;
  1351. identifierDesignator := left2(SyntaxTree.IdentifierDesignator);
  1352. result :=
  1353. SyntaxTree.NewBracketDesignator(
  1354. expression.position,
  1355. SyntaxTree.NewSelectorDesignator(
  1356. expression.position,
  1357. left(SyntaxTree.Designator),
  1358. identifierDesignator.identifier),
  1359. bracketDesignator.parameters);
  1360. ELSE
  1361. result := expression;
  1362. END;
  1363. ELSE
  1364. result := expression;
  1365. END;
  1366. END;
  1367. END;
  1368. RETURN result;
  1369. END PatchPortReference;
  1370. PROCEDURE NewPortStatement(
  1371. position: Position;
  1372. name: SyntaxTree.Identifier;
  1373. left: SyntaxTree.Designator;
  1374. right: SyntaxTree.Expression;
  1375. outer: SyntaxTree.Statement): SyntaxTree.Statement;
  1376. VAR expressionList: SyntaxTree.ExpressionList;
  1377. designator: SyntaxTree.Designator;
  1378. BEGIN
  1379. expressionList := SyntaxTree.NewExpressionList();
  1380. expressionList.AddExpression(left);
  1381. expressionList.AddExpression(right);
  1382. designator := SyntaxTree.NewIdentifierDesignator(position, name);
  1383. designator := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
  1384. RETURN SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
  1385. END NewPortStatement;
  1386. PROCEDURE StatementExpression(
  1387. statements: SyntaxTree.StatementSequence;
  1388. outer: SyntaxTree.Statement;
  1389. expression: SyntaxTree.Expression): BOOLEAN;
  1390. VAR designator: SyntaxTree.Designator;
  1391. expressionList: SyntaxTree.ExpressionList;
  1392. statement: SyntaxTree.Statement;
  1393. operator: LONGINT;
  1394. position: Position;
  1395. length, i: LONGINT;
  1396. temp: SyntaxTree.Expression;
  1397. BEGIN
  1398. IF Trace THEN
  1399. S("StatementExpression")
  1400. END;
  1401. (* ACHTUNG: Only expressions of type SyntaxTree.Designator are supported
  1402. in place of primary-expression in the above productions. This is
  1403. required for compatibility with Fox back-end *)
  1404. statement := NIL;
  1405. position := symbol.position;
  1406. IF expression = NIL THEN
  1407. expression := PrimaryExpression();
  1408. END;
  1409. IF ~(expression IS SyntaxTree.Designator) THEN
  1410. Error(position, Basic.InvalidCode, "Invalid expression statement");
  1411. ELSE
  1412. designator := expression(SyntaxTree.Designator);
  1413. position := symbol.position;
  1414. IF Optional(Scanner.Equal) THEN
  1415. expression := Expression();
  1416. statement := SyntaxTree.NewAssignment(position, designator, expression, outer);
  1417. ELSIF Peek(Scanner.PlusEqual) OR Peek(Scanner.MinusEqual) OR
  1418. Peek(Scanner.TimesEqual) OR Peek(Scanner.SlashEqual) OR
  1419. Peek(Scanner.PercentEqual) OR Peek(Scanner.AndEqual) OR
  1420. Peek(Scanner.BarEqual) OR Peek(Scanner.ArrowEqual) OR
  1421. Peek(Scanner.LeftShiftEqual) OR Peek(Scanner.RightShiftEqual) THEN
  1422. operator := symbol.token;
  1423. NextSymbol;
  1424. (* lynx@asop(operator, designator, expression) *)
  1425. expression := Expression();
  1426. statement := NewAsopStatement(position, operator, designator, expression, outer);
  1427. ELSIF Optional(Scanner.PlusPlus) THEN
  1428. (* lynx@asop(PlusEqual, designator, 1) *)
  1429. operator := Scanner.PlusPlus;
  1430. expression := SyntaxTree.NewIntegerValue(position, 1);
  1431. statement := NewAsopStatement(position, operator, designator, expression, outer);
  1432. ELSIF Optional(Scanner.MinusMinus) THEN
  1433. (* lynx@asop(MinusEqual, designator, 1) *)
  1434. operator := Scanner.MinusMinus;
  1435. expression := SyntaxTree.NewIntegerValue(position, 1);
  1436. statement := NewAsopStatement(position, operator, designator, expression, outer);
  1437. (* ACHTUNG: LYNX 15-MAY-2013
  1438. ELSIF Optional(Scanner.Exclamation) THEN
  1439. (* lynx@send(designator, expression) *)
  1440. expression := Expression();
  1441. statement := NewPortStatement(position, lynxSend, designator, expression, outer);
  1442. ELSIF Optional(Scanner.Question) THEN
  1443. (* lynx@receive(designator, expression) *)
  1444. expression := Expression();
  1445. statement := NewPortStatement(position, lynxReceive, designator, expression, outer);
  1446. *)
  1447. ELSIF Optional(Scanner.Exclamation) THEN
  1448. (* lynx@send(designator, expression) *)
  1449. expressionList := SyntaxTree.NewExpressionList();
  1450. ExpressionList(expressionList);
  1451. length := expressionList.Length();
  1452. FOR i := 0 TO length - 1 DO
  1453. expression := expressionList.GetExpression(i);
  1454. statement := NewPortStatement(position, lynxSend, designator, expression, outer);
  1455. IF i < length - 1 THEN
  1456. statements.AddStatement(statement);
  1457. END;
  1458. END;
  1459. ELSIF Optional(Scanner.Question) THEN
  1460. (* lynx@receive(designator, expression) *)
  1461. expressionList := SyntaxTree.NewExpressionList();
  1462. ExpressionList(expressionList);
  1463. length := expressionList.Length();
  1464. FOR i := 0 TO length - 1 DO
  1465. expression := expressionList.GetExpression(i);
  1466. statement := NewPortStatement(position, lynxReceive, designator, expression, outer);
  1467. IF i < length - 1 THEN
  1468. statements.AddStatement(statement);
  1469. END;
  1470. END;
  1471. (* ACHTUNG: LYNX 15-MAY-2013
  1472. ELSIF Optional(Scanner.RightShift) THEN
  1473. (* lynx@connect(designator, expression) *)
  1474. expression := PrimaryExpression();
  1475. statement := NewPortStatement(position, lynxConnect, designator, expression, outer);
  1476. ELSIF Optional(Scanner.LessEqual) THEN
  1477. (* lynx@delegate(designator, expression) *)
  1478. expression := PrimaryExpression();
  1479. statement := NewPortStatement(position, lynxDelegate, designator, expression, outer);
  1480. *)
  1481. ELSIF Optional(Scanner.RightShift) THEN
  1482. (* lynx@connect(designator, expression) *)
  1483. expression := PrimaryExpression();
  1484. temp := PatchPortReference(designator);
  1485. designator := temp(SyntaxTree.Designator);
  1486. expression := PatchPortReference(expression);
  1487. statement := NewPortStatement(position, lynxConnect, designator, expression, outer);
  1488. ELSIF Optional(Scanner.LessEqual) THEN
  1489. (* lynx@delegate(designator, expression) *)
  1490. expression := PrimaryExpression();
  1491. temp := PatchPortReference(designator);
  1492. designator := temp(SyntaxTree.Designator);
  1493. expression := PatchPortReference(expression);
  1494. statement := NewPortStatement(position, lynxDelegate, designator, expression, outer);
  1495. ELSIF designator IS SyntaxTree.ParameterDesignator THEN
  1496. statement := SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
  1497. ELSE
  1498. Error(position, Basic.InvalidCode, "Invalid expression statement");
  1499. END;
  1500. END;
  1501. IF statement # NIL THEN
  1502. (* CommentStatement(statement); *)
  1503. statements.AddStatement(statement);
  1504. END;
  1505. IF Trace THEN
  1506. E("StatementExpression")
  1507. END;
  1508. RETURN statement # NIL;
  1509. END StatementExpression;
  1510. PROCEDURE ExpressionStatement(
  1511. statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement): BOOLEAN;
  1512. VAR b: BOOLEAN;
  1513. BEGIN
  1514. IF Trace THEN
  1515. S("ExpressionStatement")
  1516. END;
  1517. b := StatementExpression(statements, outer, NIL);
  1518. Check(Scanner.Semicolon);
  1519. IF Trace THEN
  1520. E("ExpressionStatement")
  1521. END;
  1522. RETURN b;
  1523. END ExpressionStatement;
  1524. (**
  1525. if-statement:
  1526. 'if' '(' boolean-expression ')' embedded-statement
  1527. 'if' '(' boolean-expression ')' embedded-statement 'else' embedded-statement
  1528. **)
  1529. PROCEDURE IfStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1530. VAR expression: SyntaxTree.Expression;
  1531. ifStatement: SyntaxTree.IfStatement;
  1532. elsePart: SyntaxTree.IfPart;
  1533. statementSequence: SyntaxTree.StatementSequence;
  1534. b: BOOLEAN;
  1535. BEGIN
  1536. IF Trace THEN
  1537. S("IfStatement")
  1538. END;
  1539. Check(Scanner.If);
  1540. ifStatement := SyntaxTree.NewIfStatement(symbol.position, outer);
  1541. (* CommentStatement(ifStatement); *)
  1542. Check(Scanner.LeftParenthesis);
  1543. expression := Expression();
  1544. Check(Scanner.RightParenthesis);
  1545. ifStatement.ifPart.SetCondition(expression);
  1546. statementSequence := SyntaxTree.NewStatementSequence();
  1547. b := EmbeddedStatement(statementSequence, ifStatement);
  1548. ifStatement.ifPart.SetStatements(statementSequence);
  1549. IF Optional(Scanner.Else) THEN
  1550. statementSequence := SyntaxTree.NewStatementSequence();
  1551. b := EmbeddedStatement(statementSequence, ifStatement);
  1552. ifStatement.SetElsePart(statementSequence);
  1553. END;
  1554. statements.AddStatement(ifStatement);
  1555. IF Trace THEN
  1556. E("IfStatement")
  1557. END;
  1558. END IfStatement;
  1559. (**
  1560. switch-statement:
  1561. 'switch' '(' expression ')' switch-block
  1562. switch-block:
  1563. '{' [switch-sections] '}'
  1564. switch-sections:
  1565. switch-section
  1566. switch-sections switch-section
  1567. switch-section:
  1568. switch-labels statement-list
  1569. switch-labels:
  1570. switch-label
  1571. switch-labels switch-label
  1572. switch-label:
  1573. 'case' constant-expression ':'
  1574. 'default' ':'
  1575. **)
  1576. PROCEDURE SwitchSection(caseStatement: SyntaxTree.CaseStatement; VAR haveDefault: BOOLEAN);
  1577. VAR casePart: SyntaxTree.CasePart;
  1578. statements: SyntaxTree.StatementSequence;
  1579. last: SyntaxTree.Statement;
  1580. element: SyntaxTree.Expression;
  1581. defaultSection: BOOLEAN;
  1582. length: LONGINT; position: Position;
  1583. BEGIN
  1584. IF Trace THEN
  1585. S("SwitchSection")
  1586. END;
  1587. casePart := SyntaxTree.NewCasePart();
  1588. defaultSection := FALSE;
  1589. WHILE Peek(Scanner.Case) OR Peek(Scanner.Default) DO
  1590. (* CommentCasePart(casePart); *)
  1591. IF Optional(Scanner.Case) THEN
  1592. element := Expression();
  1593. Check(Scanner.Colon);
  1594. casePart.elements.AddExpression(element);
  1595. ELSE
  1596. position := symbol.position;
  1597. Check(Scanner.Default);
  1598. Check(Scanner.Colon);
  1599. IF haveDefault THEN
  1600. Error(position, Basic.InvalidCode, "Duplicate default label");
  1601. ELSE
  1602. defaultSection := TRUE;
  1603. haveDefault := TRUE;
  1604. END;
  1605. END;
  1606. END;
  1607. statements := StatementList(caseStatement);
  1608. length := statements.Length();
  1609. IF length = 0 THEN
  1610. Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
  1611. ELSE
  1612. last := statements.GetStatement(length-1);
  1613. IF last IS SyntaxTree.ExitStatement THEN
  1614. statements.RemoveStatement(last);
  1615. ELSIF ~(last IS SyntaxTree.ReturnStatement) THEN
  1616. Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
  1617. END;
  1618. END;
  1619. IF ~defaultSection THEN
  1620. casePart.SetStatements(statements);
  1621. caseStatement.AddCasePart(casePart);
  1622. ELSE
  1623. (* ignore case labels, if any *)
  1624. (* ACHTUNG: these labels will not be checked for duplicates *)
  1625. caseStatement.SetElsePart(statements);
  1626. END;
  1627. IF Trace THEN
  1628. E("SwitchSection")
  1629. END;
  1630. END SwitchSection;
  1631. PROCEDURE SwitchStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1632. VAR expression: SyntaxTree.Expression;
  1633. caseStatement: SyntaxTree.CaseStatement;
  1634. haveDefault: BOOLEAN;
  1635. BEGIN
  1636. IF Trace THEN
  1637. S("SwitchStatement")
  1638. END;
  1639. Check(Scanner.Switch);
  1640. caseStatement := SyntaxTree.NewCaseStatement(symbol.position, outer);
  1641. (* CommentStatement(caseStatement); *)
  1642. Check(Scanner.LeftParenthesis);
  1643. expression := Expression();
  1644. Check(Scanner.RightParenthesis);
  1645. caseStatement.SetVariable(expression);
  1646. Check(Scanner.LeftBrace);
  1647. haveDefault := FALSE;
  1648. WHILE Peek(Scanner.Case) OR Peek(Scanner.Default) DO
  1649. SwitchSection(caseStatement, haveDefault);
  1650. END;
  1651. Check(Scanner.RightBrace);
  1652. statements.AddStatement(caseStatement);
  1653. IF Trace THEN
  1654. E("SwitchStatement")
  1655. END;
  1656. END SwitchStatement;
  1657. (**
  1658. select-statement:
  1659. 'select' select-block
  1660. select-block:
  1661. '{' select-sections '}'
  1662. select-sections:
  1663. select-section
  1664. select-sections select-section
  1665. select-section:
  1666. select-label statement-list
  1667. select-label:
  1668. 'case' [select-replicator] primary-expression '?' primary-expression ':'
  1669. select-replicator:
  1670. '(' integral-type simple-name 'in' expression ':' expression ')'
  1671. **)
  1672. (**
  1673. Fox mapping schema:
  1674. // LYNX
  1675. select {
  1676. case c ? x:
  1677. S1;
  1678. case (int i in m : n) d[i] ? y:
  1679. S2;
  1680. }
  1681. // Fox
  1682. lynx@newsel;
  1683. lynx@addsel(0, 0, c);
  1684. FOR i := m TO n DO
  1685. lynx@addsel(1, i, d[i])
  1686. END;
  1687. CASE lynx@select() OF
  1688. 0:
  1689. c ? x;
  1690. S1;
  1691. | 1:
  1692. i := lynx@selidx();
  1693. d[i] ? y;
  1694. S2;
  1695. END;
  1696. **)
  1697. PROCEDURE NewLynxNewsel(
  1698. position: Position; outer: SyntaxTree.Statement): SyntaxTree.Statement;
  1699. VAR parameters: SyntaxTree.ExpressionList;
  1700. designator: SyntaxTree.Designator;
  1701. BEGIN
  1702. parameters := SyntaxTree.NewExpressionList();
  1703. designator := SyntaxTree.NewIdentifierDesignator(position, lynxNewsel);
  1704. designator := SyntaxTree.NewParameterDesignator(position, designator, parameters);
  1705. RETURN SyntaxTree.NewProcedureCallStatement(position, FALSE, designator, outer);
  1706. END NewLynxNewsel;
  1707. PROCEDURE NewLynxAddsel(
  1708. position: Position;
  1709. index: LONGINT;
  1710. variable: SyntaxTree.Identifier;
  1711. channel: SyntaxTree.Expression;
  1712. outer: SyntaxTree.Statement): SyntaxTree.Statement;
  1713. VAR parameters: SyntaxTree.ExpressionList;
  1714. designator: SyntaxTree.Designator;
  1715. BEGIN
  1716. parameters := SyntaxTree.NewExpressionList();
  1717. parameters.AddExpression(SyntaxTree.NewIntegerValue(position, index));
  1718. IF variable # SyntaxTree.invalidIdentifier THEN
  1719. parameters.AddExpression(
  1720. SyntaxTree.NewIdentifierDesignator(position, variable));
  1721. ELSE
  1722. parameters.AddExpression(SyntaxTree.NewIntegerValue(position, 0));
  1723. END;
  1724. parameters.AddExpression(channel);
  1725. designator := SyntaxTree.NewIdentifierDesignator(position, lynxAddsel);
  1726. designator := SyntaxTree.NewParameterDesignator(position, designator, parameters);
  1727. RETURN SyntaxTree.NewProcedureCallStatement(position, FALSE, designator, outer);
  1728. END NewLynxAddsel;
  1729. PROCEDURE NewLynxSelect(position: Position): SyntaxTree.Expression;
  1730. VAR left: SyntaxTree.Designator;
  1731. parameters: SyntaxTree.ExpressionList;
  1732. BEGIN
  1733. left := SyntaxTree.NewIdentifierDesignator(position, lynxSelect);
  1734. parameters := SyntaxTree.NewExpressionList();
  1735. RETURN SyntaxTree.NewParameterDesignator(position, left, parameters);
  1736. END NewLynxSelect;
  1737. PROCEDURE NewLynxSelidx(
  1738. position: Position;
  1739. variable: SyntaxTree.Identifier;
  1740. outer: SyntaxTree.Statement): SyntaxTree.Statement;
  1741. VAR left: SyntaxTree.Designator;
  1742. parameters: SyntaxTree.ExpressionList;
  1743. right: SyntaxTree.Expression;
  1744. BEGIN
  1745. left := SyntaxTree.NewIdentifierDesignator(position, lynxSelidx);
  1746. parameters := SyntaxTree.NewExpressionList();
  1747. right := SyntaxTree.NewParameterDesignator(position, left, parameters);
  1748. left := SyntaxTree.NewIdentifierDesignator(position, variable);
  1749. RETURN SyntaxTree.NewAssignment(position, left, right, outer);
  1750. END NewLynxSelidx;
  1751. PROCEDURE SelectSection(
  1752. statements: SyntaxTree.StatementSequence;
  1753. caseStatement: SyntaxTree.CaseStatement;
  1754. index: LONGINT;
  1755. outer: SyntaxTree.Statement);
  1756. VAR typename, varname: SyntaxTree.Identifier;
  1757. type: SyntaxTree.Type;
  1758. variable: SyntaxTree.Variable;
  1759. position: Position;
  1760. from, to: SyntaxTree.Expression;
  1761. channel, target: SyntaxTree.Expression;
  1762. statement: SyntaxTree.Statement;
  1763. forStatement: SyntaxTree.ForStatement;
  1764. forBody: SyntaxTree.StatementSequence;
  1765. designator: SyntaxTree.Designator;
  1766. casePart: SyntaxTree.CasePart;
  1767. caseBody: SyntaxTree.StatementSequence;
  1768. length: LONGINT;
  1769. last: SyntaxTree.Statement;
  1770. BEGIN
  1771. IF Trace THEN
  1772. S("SelectSection")
  1773. END;
  1774. position := symbol.position;
  1775. Check(Scanner.Case);
  1776. localIdentTable.OpenScope;
  1777. IF Optional(Scanner.LeftParenthesis) THEN
  1778. IF Optional(Scanner.Sbyte) THEN
  1779. typename := lynxSbyte;
  1780. ELSIF Optional(Scanner.Short) THEN
  1781. typename := lynxShort;
  1782. ELSIF Optional(Scanner.Int) THEN
  1783. typename := lynxInt;
  1784. ELSIF Optional(Scanner.Long) THEN
  1785. typename := lynxLong;
  1786. ELSE
  1787. Error(position, Basic.InvalidCode, "Missing integral type specifier");
  1788. typename := lynxInt;
  1789. END;
  1790. type :=
  1791. SyntaxTree.NewQualifiedType(
  1792. position,
  1793. currentScope,
  1794. SyntaxTree.NewQualifiedIdentifier(
  1795. position, SyntaxTree.invalidIdentifier, typename));
  1796. varname := Identifier(position);
  1797. varname := localIdentTable.Enter(varname);
  1798. variable := SyntaxTree.NewVariable(position, varname);
  1799. CommentSymbol(variable);
  1800. variable.SetType(type);
  1801. currentScope.AddVariable(variable);
  1802. Check(Scanner.In);
  1803. from := Expression();
  1804. Check(Scanner.Colon);
  1805. to := Expression();
  1806. Check(Scanner.RightParenthesis);
  1807. ELSE
  1808. varname := SyntaxTree.invalidIdentifier;
  1809. END;
  1810. channel := PrimaryExpression();
  1811. Check(Scanner.Question);
  1812. target := PrimaryExpression();
  1813. Check(Scanner.Colon);
  1814. (* prolog *)
  1815. IF varname = SyntaxTree.invalidIdentifier THEN
  1816. statement := NewLynxAddsel(position, index, varname, channel, outer);
  1817. statements.AddStatement(statement);
  1818. ELSE
  1819. forStatement := SyntaxTree.NewForStatement(symbol.position, outer);
  1820. designator := SyntaxTree.NewIdentifierDesignator(position, varname);
  1821. forStatement.SetVariable(designator);
  1822. forStatement.SetFrom(from);
  1823. forStatement.SetTo(to);
  1824. forBody := SyntaxTree.NewStatementSequence();
  1825. statement :=
  1826. NewLynxAddsel(position, index, varname, channel, forStatement);
  1827. forBody.AddStatement(statement);
  1828. forStatement.SetStatements(forBody);
  1829. statements.AddStatement(forStatement);
  1830. END;
  1831. (* case part *)
  1832. casePart := SyntaxTree.NewCasePart();
  1833. casePart.elements.AddExpression(SyntaxTree.NewIntegerValue(position, index));
  1834. (* same logic as for switch: *)
  1835. caseBody := StatementList(caseStatement);
  1836. length := caseBody.Length();
  1837. IF length = 0 THEN
  1838. Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
  1839. ELSE
  1840. last := caseBody.GetStatement(length-1);
  1841. IF last IS SyntaxTree.ExitStatement THEN
  1842. caseBody.RemoveStatement(last);
  1843. ELSIF ~(last IS SyntaxTree.ReturnStatement) THEN
  1844. Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
  1845. END;
  1846. END;
  1847. statement := NewPortStatement(position, lynxReceive, channel(SyntaxTree.Designator), target, caseStatement);
  1848. caseBody.PrependStatement(statement);
  1849. IF varname # SyntaxTree.invalidIdentifier THEN
  1850. statement := NewLynxSelidx(position, varname, caseStatement);
  1851. caseBody.PrependStatement(statement);
  1852. END;
  1853. casePart.SetStatements(caseBody);
  1854. caseStatement.AddCasePart(casePart);
  1855. localIdentTable.CloseScope;
  1856. IF Trace THEN
  1857. E("SelectSection")
  1858. END;
  1859. END SelectSection;
  1860. PROCEDURE SelectStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1861. VAR statement: SyntaxTree.Statement;
  1862. caseStatement: SyntaxTree.CaseStatement;
  1863. expression: SyntaxTree.Expression;
  1864. index: LONGINT;
  1865. position: Position;
  1866. BEGIN
  1867. IF Trace THEN
  1868. S("SelectStatement")
  1869. END;
  1870. position := symbol.position;
  1871. Check(Scanner.Select);
  1872. statement := NewLynxNewsel(position, outer);
  1873. statements.AddStatement(statement);
  1874. caseStatement := SyntaxTree.NewCaseStatement(position, outer);
  1875. expression := NewLynxSelect(position);
  1876. caseStatement.SetVariable(expression);
  1877. Check(Scanner.LeftBrace);
  1878. index := 0;
  1879. WHILE Peek(Scanner.Case) DO
  1880. SelectSection(statements, caseStatement, index, outer);
  1881. INC(index);
  1882. END;
  1883. position := symbol.position;
  1884. Check(Scanner.RightBrace);
  1885. IF index = 0 THEN
  1886. Error(position, Basic.InvalidCode, "Empty select statement");
  1887. END;
  1888. statements.AddStatement(caseStatement);
  1889. IF Trace THEN
  1890. E("SelectStatement")
  1891. END;
  1892. END SelectStatement;
  1893. (**
  1894. while-statement:
  1895. 'while' '(' boolean-expression ')' embedded-statement
  1896. **)
  1897. PROCEDURE WhileStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1898. VAR expression: SyntaxTree.Expression;
  1899. whileStatement: SyntaxTree.WhileStatement;
  1900. statementSequence: SyntaxTree.StatementSequence;
  1901. b: BOOLEAN;
  1902. BEGIN
  1903. IF Trace THEN
  1904. S("WhileStatement")
  1905. END;
  1906. Check(Scanner.While);
  1907. whileStatement := SyntaxTree.NewWhileStatement(symbol.position, outer);
  1908. (* CommentStatement(whileStatement); *)
  1909. Check(Scanner.LeftParenthesis);
  1910. expression := Expression();
  1911. Check(Scanner.RightParenthesis);
  1912. whileStatement.SetCondition(expression);
  1913. statementSequence := SyntaxTree.NewStatementSequence();
  1914. b := EmbeddedStatement(statementSequence, whileStatement);
  1915. whileStatement.SetStatements(statementSequence);
  1916. statements.AddStatement(whileStatement);
  1917. IF Trace THEN
  1918. E("WhileStatement")
  1919. END;
  1920. END WhileStatement;
  1921. (**
  1922. do-statement:
  1923. 'do' embedded-statement 'while' '(' boolean-expression ')' ';'
  1924. **)
  1925. PROCEDURE DoStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1926. VAR expression: SyntaxTree.Expression;
  1927. repeatStatement: SyntaxTree.RepeatStatement;
  1928. statementSequence: SyntaxTree.StatementSequence;
  1929. position: Position;
  1930. b: BOOLEAN;
  1931. BEGIN
  1932. IF Trace THEN
  1933. S("DoStatement")
  1934. END;
  1935. Check(Scanner.Do);
  1936. repeatStatement := SyntaxTree.NewRepeatStatement(symbol.position, outer);
  1937. (* CommentStatement(repeatStatement); *)
  1938. statementSequence := SyntaxTree.NewStatementSequence();
  1939. b := EmbeddedStatement(statementSequence, repeatStatement);
  1940. repeatStatement.SetStatements(statementSequence);
  1941. Check(Scanner.While);
  1942. Check(Scanner.LeftParenthesis);
  1943. position := symbol.position;
  1944. expression := Expression();
  1945. Check(Scanner.RightParenthesis);
  1946. expression := NewUnaryExpression(position, expression, Scanner.Exclamation);
  1947. repeatStatement.SetCondition(expression);
  1948. statements.AddStatement(repeatStatement);
  1949. IF Trace THEN
  1950. E("DoStatement")
  1951. END;
  1952. END DoStatement;
  1953. (**
  1954. statement-expression-list:
  1955. statement-expression
  1956. statement-expression-list ',' statement-expression
  1957. **)
  1958. PROCEDURE StatementExpressionList(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1959. VAR b: BOOLEAN;
  1960. BEGIN
  1961. IF Trace THEN
  1962. S("StatementExpressionList")
  1963. END;
  1964. REPEAT
  1965. b := StatementExpression(statements, outer, NIL);
  1966. UNTIL ~Optional(Scanner.Comma);
  1967. IF Trace THEN
  1968. E("StatementExpressionList")
  1969. END;
  1970. END StatementExpressionList;
  1971. (**
  1972. for-initializer:
  1973. local-variable-declaration
  1974. statement-expression-list
  1975. **)
  1976. PROCEDURE ForInitializer(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1977. VAR isDeclaration: BOOLEAN;
  1978. b: BOOLEAN;
  1979. BEGIN
  1980. IF Trace THEN
  1981. S("ForInitializer")
  1982. END;
  1983. IF Peek(Scanner.Bool) OR Peek(Scanner.Sbyte) OR
  1984. Peek(Scanner.Short) OR Peek(Scanner.Int) OR
  1985. Peek(Scanner.Long) OR Peek(Scanner.Char) OR
  1986. Peek(Scanner.Float) OR Peek(Scanner.Double) OR
  1987. Peek(Scanner.Object) OR Peek(Scanner.String) THEN
  1988. LocalVariableDeclaration(statements, outer, NIL);
  1989. ELSIF Peek(Scanner.Identifier) THEN
  1990. (* either local-variable-declaration or statement expression *)
  1991. b := ExpressionOrDeclaration(statements, outer, isDeclaration);
  1992. IF ~isDeclaration & Optional(Scanner.Comma) THEN
  1993. StatementExpressionList(statements, outer);
  1994. END;
  1995. ELSE
  1996. StatementExpressionList(statements, outer);
  1997. END;
  1998. IF Trace THEN
  1999. E("ForInitializer")
  2000. END;
  2001. END ForInitializer;
  2002. (**
  2003. for-iterator:
  2004. statement-expression-list
  2005. **)
  2006. PROCEDURE ForIterator(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  2007. BEGIN
  2008. IF Trace THEN
  2009. S("ForIterator")
  2010. END;
  2011. StatementExpressionList(statements, outer);
  2012. IF Trace THEN
  2013. E("ForIterator")
  2014. END;
  2015. END ForIterator;
  2016. (**
  2017. for-statement:
  2018. 'for' '(' [for-initializer] ';' [for-condition] ';' [for-iterator] ')' embedded-statement
  2019. for-condition:
  2020. boolean-expression
  2021. **)
  2022. PROCEDURE ForStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  2023. VAR expression: SyntaxTree.Expression;
  2024. whileStatement: SyntaxTree.WhileStatement;
  2025. statementSequence: SyntaxTree.StatementSequence;
  2026. iterator: SyntaxTree.StatementSequence;
  2027. position: Position;
  2028. i: LONGINT;
  2029. b: BOOLEAN;
  2030. BEGIN
  2031. IF Trace THEN
  2032. S("ForStatement")
  2033. END;
  2034. Check(Scanner.For);
  2035. localIdentTable.OpenScope;
  2036. whileStatement := SyntaxTree.NewWhileStatement(symbol.position, outer);
  2037. (* CommentStatement(whileStatement); *)
  2038. Check(Scanner.LeftParenthesis);
  2039. IF ~Optional(Scanner.Semicolon) THEN
  2040. ForInitializer(statements, outer);
  2041. Check(Scanner.Semicolon);
  2042. END;
  2043. position := symbol.position;
  2044. IF ~Optional(Scanner.Semicolon) THEN
  2045. expression := Expression();
  2046. Check(Scanner.Semicolon);
  2047. ELSE
  2048. expression := SyntaxTree.NewBooleanValue(position, TRUE);
  2049. END;
  2050. IF ~Optional(Scanner.RightParenthesis) THEN
  2051. iterator := SyntaxTree.NewStatementSequence();
  2052. ForIterator(iterator, whileStatement);
  2053. Check(Scanner.RightParenthesis);
  2054. ELSE
  2055. iterator := NIL;
  2056. END;
  2057. whileStatement.SetCondition(expression);
  2058. statementSequence := SyntaxTree.NewStatementSequence();
  2059. b := EmbeddedStatement(statementSequence, whileStatement);
  2060. IF iterator # NIL THEN
  2061. FOR i := 0 TO iterator.Length() - 1 DO
  2062. statementSequence.AddStatement(iterator.GetStatement(i));
  2063. END;
  2064. END;
  2065. whileStatement.SetStatements(statementSequence);
  2066. statements.AddStatement(whileStatement);
  2067. localIdentTable.CloseScope;
  2068. IF Trace THEN
  2069. E("ForStatement")
  2070. END;
  2071. END ForStatement;
  2072. (**
  2073. return-statement:
  2074. 'return' [expression] ';'
  2075. **)
  2076. PROCEDURE ReturnStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  2077. VAR returnStatement: SyntaxTree.ReturnStatement;
  2078. expression: SyntaxTree.Expression;
  2079. BEGIN
  2080. IF Trace THEN
  2081. S("ReturnStatement")
  2082. END;
  2083. Check(Scanner.Return);
  2084. returnStatement := SyntaxTree.NewReturnStatement(symbol.position, outer);
  2085. (* CommentStatement(returnStatement); *)
  2086. IF ~Optional(Scanner.Semicolon) THEN
  2087. expression := Expression();
  2088. returnStatement.SetReturnValue(expression);
  2089. Check(Scanner.Semicolon);
  2090. END;
  2091. statements.AddStatement(returnStatement);
  2092. IF Trace THEN
  2093. E("ReturnStatement")
  2094. END;
  2095. END ReturnStatement;
  2096. (**
  2097. break-statement:
  2098. 'break' ';'
  2099. **)
  2100. PROCEDURE BreakStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  2101. VAR statement: SyntaxTree.Statement;
  2102. BEGIN
  2103. IF Trace THEN
  2104. S("BreakStatement")
  2105. END;
  2106. Check(Scanner.Break);
  2107. statement := SyntaxTree.NewExitStatement(symbol.position, outer);
  2108. (* CommentStatement(statement); *)
  2109. statements.AddStatement(statement);
  2110. Check(Scanner.Semicolon);
  2111. IF Trace THEN
  2112. E("BreakStatement")
  2113. END;
  2114. END BreakStatement;
  2115. (**
  2116. embedded-statement:
  2117. block
  2118. empty-statement
  2119. expression-statement
  2120. selection-statement
  2121. iteration-statement
  2122. jump-statement
  2123. empty-statement:
  2124. ';'
  2125. selection-statement:
  2126. if-statement
  2127. switch-statement
  2128. select-statement
  2129. iteration-statement:
  2130. while-statement
  2131. do-statement
  2132. for-statement
  2133. jump-statement:
  2134. break-statement
  2135. return-statement
  2136. **)
  2137. PROCEDURE EmbeddedStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement): BOOLEAN;
  2138. VAR result: BOOLEAN;
  2139. BEGIN
  2140. IF Trace THEN
  2141. S("EmbeddedStatement")
  2142. END;
  2143. IF Optional(Scanner.Semicolon) THEN
  2144. result := FALSE;
  2145. ELSIF Peek(Scanner.LeftBrace) THEN
  2146. Block(statements, outer);
  2147. result := TRUE;
  2148. ELSIF Peek(Scanner.If) THEN
  2149. IfStatement(statements, outer);
  2150. result := TRUE;
  2151. ELSIF Peek(Scanner.Switch) THEN
  2152. SwitchStatement(statements, outer);
  2153. result := TRUE;
  2154. ELSIF Peek(Scanner.Select) THEN
  2155. SelectStatement(statements, outer);
  2156. result := TRUE;
  2157. ELSIF Peek(Scanner.While) THEN
  2158. WhileStatement(statements, outer);
  2159. result := TRUE;
  2160. ELSIF Peek(Scanner.Do) THEN
  2161. DoStatement(statements, outer);
  2162. result := TRUE;
  2163. ELSIF Peek(Scanner.For) THEN
  2164. ForStatement(statements, outer);
  2165. result := TRUE;
  2166. ELSIF Peek(Scanner.Break) THEN
  2167. BreakStatement(statements, outer);
  2168. result := TRUE;
  2169. ELSIF Peek(Scanner.Return) THEN
  2170. ReturnStatement(statements, outer);
  2171. result := TRUE;
  2172. ELSE
  2173. result := ExpressionStatement(statements, outer);
  2174. END;
  2175. IF Trace THEN
  2176. E("EmbeddedStatement")
  2177. END;
  2178. RETURN result;
  2179. END EmbeddedStatement;
  2180. (**
  2181. statement:
  2182. declaration-statement
  2183. embedded-statement
  2184. declaration-statement:
  2185. local-variable-declaration ';'
  2186. local-constant-declaration ';'
  2187. **)
  2188. PROCEDURE ExpressionOrDeclaration(
  2189. statements: SyntaxTree.StatementSequence;
  2190. outer: SyntaxTree.Statement;
  2191. VAR isDeclaration: BOOLEAN): BOOLEAN;
  2192. VAR result: BOOLEAN;
  2193. name0, name1: SyntaxTree.Identifier;
  2194. position0, position1, position2: Position;
  2195. leftBracket: BOOLEAN;
  2196. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
  2197. type: SyntaxTree.Type;
  2198. expression: SyntaxTree.Expression;
  2199. expressionList: SyntaxTree.ExpressionList;
  2200. BEGIN
  2201. name0 := Identifier(position0);
  2202. IF Optional(Scanner.Period) THEN
  2203. name1 := Identifier(position1);
  2204. ELSE
  2205. name1 := SyntaxTree.invalidIdentifier;
  2206. END;
  2207. isDeclaration := FALSE;
  2208. leftBracket := FALSE;
  2209. position2 := symbol.position;
  2210. IF Peek(Scanner.Identifier) THEN
  2211. isDeclaration := TRUE;
  2212. ELSIF Optional(Scanner.LeftBracket) THEN
  2213. leftBracket := TRUE;
  2214. IF Peek(Scanner.RightBracket) OR Peek(Scanner.Comma) THEN
  2215. isDeclaration := TRUE;
  2216. END;
  2217. END;
  2218. IF isDeclaration THEN
  2219. (* local-variable-declaration *)
  2220. IF name1 = SyntaxTree.invalidIdentifier THEN
  2221. name1 := name0;
  2222. name0 := SyntaxTree.invalidIdentifier;
  2223. END;
  2224. qualifiedIdentifier := SyntaxTree.NewQualifiedIdentifier(position0, name0, name1);
  2225. type := SyntaxTree.NewQualifiedType(
  2226. qualifiedIdentifier.position, currentScope, qualifiedIdentifier);
  2227. IF leftBracket THEN
  2228. type := RankSpecifier(type);
  2229. Check(Scanner.RightBracket);
  2230. END;
  2231. WHILE Optional(Scanner.LeftBracket) DO
  2232. type := RankSpecifier(type);
  2233. Check(Scanner.RightBracket);
  2234. END;
  2235. LocalVariableDeclaration(statements, outer, type);
  2236. ELSE
  2237. (* expression-statement *)
  2238. name0 := localIdentTable.Find(name0);
  2239. expression := SyntaxTree.NewIdentifierDesignator(position0, name0);
  2240. IF name1 # SyntaxTree.invalidIdentifier THEN
  2241. expression := SyntaxTree.NewSelectorDesignator(position1, expression(SyntaxTree.Designator), name1);
  2242. END;
  2243. IF leftBracket THEN
  2244. expressionList := SyntaxTree.NewExpressionList();
  2245. ExpressionList(expressionList);
  2246. Check(Scanner.RightBracket);
  2247. expression := SyntaxTree.NewBracketDesignator(position2, expression(SyntaxTree.Designator), expressionList);
  2248. END;
  2249. expression := Accessors(expression, FALSE);
  2250. result := StatementExpression(statements, outer, expression);
  2251. END;
  2252. RETURN result;
  2253. END ExpressionOrDeclaration;
  2254. PROCEDURE Statement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement): BOOLEAN;
  2255. VAR result: BOOLEAN;
  2256. isDeclaration: BOOLEAN;
  2257. BEGIN
  2258. IF Trace THEN
  2259. S("Statement")
  2260. END;
  2261. IF Peek(Scanner.Const) THEN
  2262. LocalConstantDeclaration(statements, outer);
  2263. Check(Scanner.Semicolon);
  2264. result := TRUE;
  2265. ELSIF Peek(Scanner.Bool) OR Peek(Scanner.Sbyte) OR
  2266. Peek(Scanner.Short) OR Peek(Scanner.Int) OR
  2267. Peek(Scanner.Long) OR Peek(Scanner.Char) OR
  2268. Peek(Scanner.Float) OR Peek(Scanner.Double) OR
  2269. Peek(Scanner.Object) OR Peek(Scanner.String) THEN
  2270. LocalVariableDeclaration(statements, outer, NIL);
  2271. Check(Scanner.Semicolon);
  2272. result := TRUE;
  2273. ELSIF Peek(Scanner.Identifier) THEN
  2274. (* either local-variable-declaration or statement expression *)
  2275. result := ExpressionOrDeclaration(statements, outer, isDeclaration);
  2276. Check(Scanner.Semicolon);
  2277. ELSE
  2278. result := EmbeddedStatement(statements, outer);
  2279. END;
  2280. IF Trace THEN
  2281. E("Statement")
  2282. END;
  2283. RETURN result;
  2284. END Statement;
  2285. (**
  2286. statement-list:
  2287. statement
  2288. statement-list statement
  2289. **)
  2290. PROCEDURE StatementList(outer: SyntaxTree.Statement): SyntaxTree.StatementSequence;
  2291. VAR statements: SyntaxTree.StatementSequence;
  2292. b: BOOLEAN;
  2293. BEGIN
  2294. IF Trace THEN
  2295. S("StatementList")
  2296. END;
  2297. statements := SyntaxTree.NewStatementSequence();
  2298. REPEAT
  2299. b := Statement(statements, outer);
  2300. UNTIL Peek(Scanner.RightBrace) OR Peek(Scanner.Case) OR Peek(Scanner.Default) ;
  2301. IF Trace THEN
  2302. E("StatementList")
  2303. END;
  2304. RETURN statements;
  2305. END StatementList;
  2306. (**
  2307. block:
  2308. '{' [statement-list] '}'
  2309. **)
  2310. PROCEDURE Body(scope: SyntaxTree.ProcedureScope): SyntaxTree.Body;
  2311. VAR body: SyntaxTree.Body;
  2312. previousScope: SyntaxTree.Scope;
  2313. BEGIN
  2314. IF Trace THEN
  2315. S("Body")
  2316. END;
  2317. previousScope := currentScope;
  2318. currentScope := scope;
  2319. Check(Scanner.LeftBrace);
  2320. body := SyntaxTree.NewBody(symbol.position, scope);
  2321. IF ~Optional(Scanner.RightBrace) THEN
  2322. body.SetStatementSequence(StatementList(body));
  2323. Check(Scanner.RightBrace);
  2324. END;
  2325. currentScope := previousScope;
  2326. IF Trace THEN
  2327. E("Body")
  2328. END;
  2329. RETURN body;
  2330. END Body;
  2331. (**
  2332. type:
  2333. value-type
  2334. reference-type
  2335. port-type
  2336. value-type:
  2337. struct-type
  2338. struct-type:
  2339. type-name
  2340. simple-type
  2341. simple-type:
  2342. numeric-type
  2343. 'bool'
  2344. numeric-type:
  2345. integral-type
  2346. floating-point-type
  2347. integral-type:
  2348. 'sbyte'
  2349. 'short'
  2350. 'int'
  2351. 'long'
  2352. 'char'
  2353. floating-point-type:
  2354. 'float'
  2355. 'double'
  2356. reference-type:
  2357. class-type
  2358. array-type
  2359. delegate-type
  2360. class-type:
  2361. type-name
  2362. 'object'
  2363. 'string'
  2364. array-type:
  2365. non-array-type rank-specifiers
  2366. non-array-type:
  2367. value-type
  2368. class-type
  2369. delegate-type
  2370. rank-specifiers:
  2371. rank-specifier
  2372. rank-specifiers rank-specifier
  2373. rank-specifier:
  2374. '[' [dim-separators] ']'
  2375. dim-separators:
  2376. ','
  2377. dim-separators ','
  2378. delegate-type:
  2379. type-name
  2380. **)
  2381. PROCEDURE RankSpecifier(type: SyntaxTree.Type): SyntaxTree.Type;
  2382. VAR position: Position;
  2383. arrayType: SyntaxTree.ArrayType;
  2384. pointerType: SyntaxTree.PointerType;
  2385. BEGIN
  2386. IF Trace THEN
  2387. S("RankSpecifier")
  2388. END;
  2389. position := symbol.position;
  2390. REPEAT
  2391. arrayType := SyntaxTree.NewArrayType(position, currentScope, SyntaxTree.Open);
  2392. arrayType.SetArrayBase(type);
  2393. type := arrayType;
  2394. UNTIL ~Optional(Scanner.Comma);
  2395. pointerType := SyntaxTree.NewPointerType(position, currentScope);
  2396. pointerType.SetPointerBase(type);
  2397. type := pointerType;
  2398. IF Trace THEN
  2399. E("RankSpecifier")
  2400. END;
  2401. RETURN type;
  2402. END RankSpecifier;
  2403. PROCEDURE NonArrayType(): SyntaxTree.Type;
  2404. VAR type: SyntaxTree.Type;
  2405. position: Position;
  2406. name: SyntaxTree.Identifier;
  2407. direction: LONGINT;
  2408. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
  2409. BEGIN
  2410. IF Trace THEN
  2411. S("NonArrayType")
  2412. END;
  2413. position := symbol.position;
  2414. name := SyntaxTree.invalidIdentifier;
  2415. direction := -1;
  2416. IF Optional(Scanner.Bool) THEN
  2417. name := lynxBool;
  2418. ELSIF Optional(Scanner.Sbyte) THEN
  2419. name := lynxSbyte;
  2420. ELSIF Optional(Scanner.Short) THEN
  2421. name := lynxShort;
  2422. ELSIF Optional(Scanner.Int) THEN
  2423. name := lynxInt;
  2424. ELSIF Optional(Scanner.Long) THEN
  2425. name := lynxLong;
  2426. ELSIF Optional(Scanner.Char) THEN
  2427. name := lynxChar;
  2428. ELSIF Optional(Scanner.Float) THEN
  2429. name := lynxFloat;
  2430. ELSIF Optional(Scanner.Double) THEN
  2431. name := lynxDouble;
  2432. ELSIF Optional(Scanner.Object) THEN
  2433. name := lynxObject;
  2434. ELSIF Optional(Scanner.String) THEN
  2435. name := lynxString;
  2436. ELSIF Optional(Scanner.In) THEN
  2437. direction := SyntaxTree.InPort;
  2438. ELSIF Optional(Scanner.Out) THEN
  2439. direction := SyntaxTree.OutPort;
  2440. END;
  2441. IF direction >= 0 THEN
  2442. type := SyntaxTree.NewPortType(position, direction, NIL, currentScope);
  2443. ELSE
  2444. IF name # SyntaxTree.invalidIdentifier THEN
  2445. qualifiedIdentifier :=
  2446. SyntaxTree.NewQualifiedIdentifier(
  2447. position, SyntaxTree.invalidIdentifier, name);
  2448. ELSE
  2449. qualifiedIdentifier := QualifiedIdentifier();
  2450. END;
  2451. type := SyntaxTree.NewQualifiedType(
  2452. qualifiedIdentifier.position, currentScope, qualifiedIdentifier);
  2453. END;
  2454. IF Trace THEN
  2455. E("NonArrayType")
  2456. END;
  2457. RETURN type;
  2458. END NonArrayType;
  2459. PROCEDURE Type(): SyntaxTree.Type;
  2460. VAR type: SyntaxTree.Type;
  2461. BEGIN
  2462. IF Trace THEN
  2463. S("Type")
  2464. END;
  2465. type := NonArrayType();
  2466. WHILE Optional(Scanner.LeftBracket) DO
  2467. type := RankSpecifier(type);
  2468. Check(Scanner.RightBracket);
  2469. END;
  2470. IF Trace THEN
  2471. E("Type")
  2472. END;
  2473. RETURN type;
  2474. END Type;
  2475. (**
  2476. attributes:
  2477. '[' attribute-list ']'
  2478. attribute-list:
  2479. attribute
  2480. attribute-list ',' attribute
  2481. attribute:
  2482. attribute-name [attribute-argument]
  2483. attribute-name:
  2484. identifier
  2485. attribute-argument:
  2486. '(' attribute-argument-expression ')'
  2487. attribute-argument-expression:
  2488. expression
  2489. **)
  2490. PROCEDURE AppendModifier(VAR list: SyntaxTree.Modifier; modifier: SyntaxTree.Modifier);
  2491. VAR this, next: SyntaxTree.Modifier;
  2492. BEGIN
  2493. IF list = NIL THEN
  2494. list := modifier
  2495. ELSE
  2496. this := list;
  2497. next := list.nextModifier;
  2498. WHILE next # NIL DO
  2499. this := next;
  2500. next := this.nextModifier;
  2501. END;
  2502. this.SetNext(modifier);
  2503. END;
  2504. END AppendModifier;
  2505. PROCEDURE Attributes(): SyntaxTree.Modifier;
  2506. VAR identifier: SyntaxTree.Identifier;
  2507. modifier, list: SyntaxTree.Modifier;
  2508. position: Position;
  2509. expression: SyntaxTree.Expression;
  2510. BEGIN
  2511. IF Trace THEN
  2512. S("Attributes")
  2513. END;
  2514. (* left bracket already consumed *)
  2515. list := NIL;
  2516. REPEAT
  2517. position := symbol.position;
  2518. identifier := Identifier(position);
  2519. IF Optional(Scanner.LeftParenthesis) THEN
  2520. expression := Expression();
  2521. Check(Scanner.RightParenthesis);
  2522. ELSE
  2523. expression := NIL;
  2524. END;
  2525. modifier := SyntaxTree.NewModifier(position, identifier, expression);
  2526. AppendModifier(list, modifier);
  2527. UNTIL ~Optional(Scanner.Comma);
  2528. Check(Scanner.RightBracket);
  2529. IF Trace THEN
  2530. E("Attributes")
  2531. END;
  2532. RETURN list;
  2533. END Attributes;
  2534. (**
  2535. constant-modifiers:
  2536. constant-modifier
  2537. constant-modifiers constant-modifier
  2538. constant-modifier:
  2539. 'public'
  2540. field-modifiers:
  2541. field-modifier
  2542. field-modifiers field-modifier
  2543. field-modifier:
  2544. 'public'
  2545. 'internal'
  2546. method-modifiers:
  2547. method-modifier
  2548. method-modifiers method-modifier
  2549. method-modifier:
  2550. 'public'
  2551. constructor-modifiers:
  2552. constructor-modifier
  2553. constructor-modifiers constructor-modifier
  2554. constructor-modifier:
  2555. public
  2556. class-modifiers:
  2557. class-modifier
  2558. class-modifiers class-modifier
  2559. class-modifier:
  2560. 'public'
  2561. struct-modifiers:
  2562. struct-modifier
  2563. struct-modifiers struct-modifier
  2564. struct-modifier:
  2565. 'public'
  2566. delegate-modifiers:
  2567. delegate-modifier
  2568. delegate-modifiers delegate-modifier
  2569. delegate-modifier:
  2570. 'public'
  2571. **)
  2572. PROCEDURE Modifiers(VAR modifiers: SET);
  2573. BEGIN
  2574. modifiers := {};
  2575. LOOP
  2576. IF Optional(Scanner.Public) THEN
  2577. INCL(modifiers, Public);
  2578. ELSIF Optional(Scanner.Internal) THEN
  2579. INCL(modifiers, Internal);
  2580. ELSE
  2581. EXIT;
  2582. END;
  2583. END;
  2584. END Modifiers;
  2585. PROCEDURE IdentifierAccess(modifiers: SET; allowedReadOnly: BOOLEAN): SET;
  2586. VAR access: SET;
  2587. BEGIN
  2588. IF modifiers * {Public, Internal} = {Public, Internal} THEN
  2589. Error(symbol.position, Basic.InvalidCode, "conflicting modifiers");
  2590. END;
  2591. IF Public IN modifiers THEN
  2592. access := SyntaxTree.Public + SyntaxTree.Protected + SyntaxTree.Internal;
  2593. ELSIF Internal IN modifiers THEN
  2594. IF ~allowedReadOnly THEN
  2595. Error(symbol.position, Basic.InvalidCode, "may not be defined internal")
  2596. ELSE
  2597. access := SyntaxTree.ReadOnly + {SyntaxTree.InternalWrite};
  2598. END;
  2599. ELSE
  2600. access := SyntaxTree.Internal;
  2601. END;
  2602. RETURN access;
  2603. END IdentifierAccess;
  2604. (**
  2605. constant-declaration:
  2606. [constant-modifiers] 'const' type constant-declarators ';'
  2607. constant-declarators:
  2608. constant-declarator
  2609. constant-declarators ',' constant-declarator
  2610. constant-declarator:
  2611. identifier '=' constant-expression
  2612. **)
  2613. PROCEDURE ConstantDeclarator(
  2614. parentScope: SyntaxTree.Scope;
  2615. modifiers: SET;
  2616. type: SyntaxTree.Type);
  2617. VAR name: SyntaxTree.Identifier;
  2618. position: Position;
  2619. constant: SyntaxTree.Constant;
  2620. expression: SyntaxTree.Expression;
  2621. access: SET;
  2622. BEGIN
  2623. IF Trace THEN
  2624. S("ConstantDeclarator")
  2625. END;
  2626. name := Identifier(position);
  2627. name := localIdentTable.Enter(name);
  2628. access := IdentifierAccess(modifiers, FALSE);
  2629. constant := SyntaxTree.NewConstant(position, name);
  2630. CommentSymbol(constant);
  2631. constant.SetAccess(access);
  2632. (* ACHTUNG: Make sure that Fox semantic checker will respect a type set at this stage: *)
  2633. constant.SetType(type);
  2634. Check(Scanner.Equal);
  2635. expression := Expression();
  2636. constant.SetValue(expression);
  2637. parentScope.AddConstant(constant);
  2638. IF Trace THEN
  2639. E("ConstantDeclarator")
  2640. END;
  2641. END ConstantDeclarator;
  2642. PROCEDURE ConstantDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
  2643. VAR type: SyntaxTree.Type;
  2644. BEGIN
  2645. IF Trace THEN
  2646. S("ConstantDeclaration")
  2647. END;
  2648. type := Type();
  2649. REPEAT
  2650. ConstantDeclarator(parentScope, modifiers, type);
  2651. UNTIL ~Optional(Scanner.Comma);
  2652. Check(Scanner.Semicolon);
  2653. IF Trace THEN
  2654. E("ConstantDeclaration")
  2655. END;
  2656. END ConstantDeclaration;
  2657. (**
  2658. field-declaration:
  2659. [field-modifiers] type variable-declarators ';'
  2660. field-modifiers:
  2661. field-modifier
  2662. field-modifiers field-modifier
  2663. variable-declarators:
  2664. variable-declarator
  2665. variable-declarators ',' variable-declarator
  2666. variable-declarator:
  2667. identifier
  2668. identifier '=' variable-initializer
  2669. variable-initializer:
  2670. expression
  2671. // array-initializer
  2672. **)
  2673. PROCEDURE VariableDeclarator(
  2674. parentScope: SyntaxTree.Scope;
  2675. modifiers: SET;
  2676. type: SyntaxTree.Type;
  2677. name: SyntaxTree.Identifier;
  2678. position: Position);
  2679. VAR variable: SyntaxTree.Variable;
  2680. expression: SyntaxTree.Expression;
  2681. designator: SyntaxTree.Designator;
  2682. statement: SyntaxTree.Statement;
  2683. start: Position;
  2684. access: SET;
  2685. BEGIN
  2686. IF Trace THEN
  2687. S("VariableDeclarator")
  2688. END;
  2689. IF name = SyntaxTree.invalidIdentifier THEN
  2690. name := Identifier(position);
  2691. END;
  2692. name := localIdentTable.Enter(name);
  2693. access := IdentifierAccess(modifiers, TRUE);
  2694. variable := SyntaxTree.NewVariable(position, name);
  2695. CommentSymbol(variable);
  2696. variable.SetAccess(access);
  2697. variable.SetType(type);
  2698. parentScope.AddVariable(variable);
  2699. start := symbol.position;
  2700. (* 'initOuter' is set to NIL in contexts where initialization is not yet implemented *)
  2701. IF (initOuter # NIL) & Optional(Scanner.Equal) THEN
  2702. (* ACHTUNG: array-initializer form is not supported *)
  2703. designator := SyntaxTree.NewIdentifierDesignator(position, name);
  2704. expression := Expression();
  2705. statement := SyntaxTree.NewAssignment(start, designator, expression, initOuter);
  2706. initStatements.AddStatement(statement);
  2707. END;
  2708. IF Trace THEN
  2709. E("VariableDeclarator")
  2710. END;
  2711. END VariableDeclarator;
  2712. PROCEDURE FieldDeclaration(
  2713. parentScope: SyntaxTree.Scope;
  2714. modifiers: SET;
  2715. type: SyntaxTree.Type;
  2716. name: SyntaxTree.Identifier;
  2717. position: Position);
  2718. BEGIN
  2719. IF Trace THEN
  2720. S("FieldDeclaration")
  2721. END;
  2722. REPEAT
  2723. VariableDeclarator(parentScope, modifiers, type, name, position);
  2724. name := SyntaxTree.invalidIdentifier;
  2725. position := invalidPosition;
  2726. UNTIL ~Optional(Scanner.Comma);
  2727. Check(Scanner.Semicolon);
  2728. IF Trace THEN
  2729. E("FieldDeclaration")
  2730. END;
  2731. END FieldDeclaration;
  2732. (**
  2733. formal-parameter-list:
  2734. fixed-parameters
  2735. fixed-parameters:
  2736. fixed-parameter
  2737. fixed-parameters ',' fixed-parameter
  2738. fixed-parameter:
  2739. [parameter-modifier] type identifier
  2740. parameter-modifier:
  2741. 'ref'
  2742. **)
  2743. PROCEDURE FixedParameter(procedureType: SyntaxTree.ProcedureType; parentScope: SyntaxTree.Scope);
  2744. VAR type: SyntaxTree.Type;
  2745. name: SyntaxTree.Identifier;
  2746. parameter: SyntaxTree.Parameter;
  2747. kind: LONGINT; position: Position;
  2748. BEGIN
  2749. IF Trace THEN
  2750. S("FixedParameter")
  2751. END;
  2752. IF Optional(Scanner.Ref) THEN
  2753. kind := SyntaxTree.VarParameter;
  2754. ELSE
  2755. kind := SyntaxTree.ValueParameter;
  2756. END;
  2757. type := Type();
  2758. name := Identifier(position);
  2759. parameter := SyntaxTree.NewParameter(position, procedureType, name, kind);
  2760. procedureType.AddParameter(parameter);
  2761. parameter.SetType(type);
  2762. IF Trace THEN
  2763. E("FixedParameter")
  2764. END;
  2765. END FixedParameter;
  2766. PROCEDURE FormalParameterList(
  2767. procedureType: SyntaxTree.ProcedureType;
  2768. parentScope: SyntaxTree.Scope;
  2769. returnType: SyntaxTree.Type);
  2770. BEGIN
  2771. IF Trace THEN
  2772. S("FormalParameterList")
  2773. END;
  2774. Check(Scanner.LeftParenthesis);
  2775. IF ~Optional(Scanner.RightParenthesis) THEN
  2776. REPEAT
  2777. FixedParameter(procedureType, parentScope);
  2778. UNTIL ~Optional(Scanner.Comma);
  2779. Check(Scanner.RightParenthesis);
  2780. END;
  2781. IF returnType # NIL THEN
  2782. procedureType.SetReturnType(returnType);
  2783. END;
  2784. IF Trace THEN
  2785. E("FormalParameterList")
  2786. END;
  2787. END FormalParameterList;
  2788. (**
  2789. constructor-initializer:
  2790. ':' 'base' '(' [argument-list] ')'
  2791. **)
  2792. PROCEDURE ConstructorInitializer(scope: SyntaxTree.ProcedureScope);
  2793. BEGIN
  2794. IF Trace THEN
  2795. S("ConstructorInitializer")
  2796. END;
  2797. (* TODO *)
  2798. IF Trace THEN
  2799. E("ConstructorInitializer")
  2800. END;
  2801. END ConstructorInitializer;
  2802. (**
  2803. method-declaration:
  2804. method-header method-body
  2805. method-header:
  2806. [method-modifiers] return-type member-name '(' [formal-parameter-list] ')'
  2807. return-type:
  2808. type
  2809. 'void'
  2810. member-name:
  2811. identifier
  2812. method-body:
  2813. block
  2814. constructor-declaration:
  2815. [constructor-modifiers] constructor-declarator constructor-body
  2816. constructor-declarator:
  2817. identifier ( [formal-parameter-list] ) [constructor-initializer]
  2818. constructor-body:
  2819. block
  2820. **)
  2821. PROCEDURE ProcedureDeclaration(
  2822. parentScope: SyntaxTree.Scope;
  2823. modifiers: SET;
  2824. type: SyntaxTree.Type;
  2825. name: SyntaxTree.Identifier;
  2826. position: Position;
  2827. isConstructor: BOOLEAN);
  2828. VAR procedure: SyntaxTree.Procedure;
  2829. procedureType: SyntaxTree.ProcedureType;
  2830. procedureScope: SyntaxTree.ProcedureScope;
  2831. previousScope: SyntaxTree.Scope;
  2832. access: SET;
  2833. body: SyntaxTree.Body;
  2834. BEGIN
  2835. procedureType := SyntaxTree.NewProcedureType(position, parentScope);
  2836. access := IdentifierAccess(modifiers, FALSE);
  2837. procedureScope := SyntaxTree.NewProcedureScope(parentScope);
  2838. procedure := SyntaxTree.NewProcedure(position, name, procedureScope);
  2839. procedure.SetConstructor(isConstructor);
  2840. CommentSymbol(procedure);
  2841. procedure.SetAccess(access);
  2842. procedure.SetType(procedureType);
  2843. FormalParameterList(procedureType, procedureScope, type);
  2844. IF isConstructor & Optional(Scanner.Colon) THEN
  2845. (* TODO: Connect initializer to the body *)
  2846. ConstructorInitializer(procedureScope);
  2847. END;
  2848. previousScope := currentScope;
  2849. currentScope := procedureScope;
  2850. body := Body(procedureScope);
  2851. currentScope := previousScope;
  2852. procedureScope.SetBody(body);
  2853. parentScope.AddProcedure(procedure);
  2854. END ProcedureDeclaration;
  2855. PROCEDURE MethodDeclaration(
  2856. parentScope: SyntaxTree.Scope;
  2857. modifiers: SET;
  2858. type: SyntaxTree.Type;
  2859. name: SyntaxTree.Identifier;
  2860. position: Position);
  2861. BEGIN
  2862. IF Trace THEN
  2863. S("MethodDeclaration")
  2864. END;
  2865. localIdentTable.Reset;
  2866. IF (name = identMain) &
  2867. (parentScope IS SyntaxTree.CellScope) &
  2868. ~parentScope(SyntaxTree.CellScope).ownerCell.isCellNet THEN
  2869. (* bodies of cells are represented as main() functions *)
  2870. BodyDeclaration(parentScope, modifiers, type, name, position);
  2871. ELSE
  2872. ProcedureDeclaration(parentScope, modifiers, type, name, position, FALSE);
  2873. END;
  2874. IF Trace THEN
  2875. E("MethodDeclaration")
  2876. END;
  2877. END MethodDeclaration;
  2878. PROCEDURE ConstructorDeclaration(
  2879. parentScope: SyntaxTree.Scope;
  2880. modifiers: SET;
  2881. name: SyntaxTree.Identifier;
  2882. position: Position);
  2883. BEGIN
  2884. IF Trace THEN
  2885. S("ConstructorDeclaration")
  2886. END;
  2887. localIdentTable.Reset;
  2888. IF (parentScope IS SyntaxTree.ModuleScope) OR
  2889. ((parentScope IS SyntaxTree.CellScope) &
  2890. parentScope(SyntaxTree.CellScope).ownerCell.isCellNet) THEN
  2891. (* bodies of modules and cellnets are represented as constructors *)
  2892. BodyDeclaration(parentScope, modifiers, NIL, name, position);
  2893. ELSE
  2894. ProcedureDeclaration(parentScope, modifiers, NIL, name, position, TRUE);
  2895. END;
  2896. IF Trace THEN
  2897. E("ConstructorDeclaration")
  2898. END;
  2899. END ConstructorDeclaration;
  2900. PROCEDURE BodyDeclaration(
  2901. parentScope: SyntaxTree.Scope;
  2902. modifiers: SET;
  2903. type: SyntaxTree.Type;
  2904. name: SyntaxTree.Identifier;
  2905. position: Position);
  2906. VAR procedureScope: SyntaxTree.ProcedureScope;
  2907. procedureType: SyntaxTree.ProcedureType;
  2908. procedure: SyntaxTree.Procedure;
  2909. BEGIN
  2910. procedureScope := SyntaxTree.NewProcedureScope(parentScope);
  2911. IF parentScope IS SyntaxTree.ModuleScope THEN
  2912. procedure := SyntaxTree.NewProcedure(position, Global.ModuleBodyName, procedureScope);
  2913. procedure.SetAccess(SyntaxTree.Hidden);
  2914. ELSE
  2915. procedure := SyntaxTree.NewProcedure(position, Global.RecordBodyName, procedureScope);
  2916. procedure.SetAccess(SyntaxTree.Public+SyntaxTree.Protected+SyntaxTree.Internal);
  2917. END;
  2918. parentScope.AddProcedure(procedure);
  2919. procedureType := SyntaxTree.NewProcedureType(position, parentScope);
  2920. FormalParameterList(procedureType, procedureScope, type);
  2921. IF procedureType.numberParameters # 0 THEN
  2922. Error(position, Basic.InvalidCode, "constructor/main has parameters");
  2923. ELSIF procedureType.returnType # NIL THEN
  2924. Error(position, Basic.InvalidCode, "constructor/main returns value");
  2925. END;
  2926. procedure.SetType(procedureType);
  2927. procedure.SetBodyProcedure(TRUE);
  2928. procedureScope.SetBody(Body(procedureScope));
  2929. IF parentScope IS SyntaxTree.ModuleScope THEN
  2930. parentScope(SyntaxTree.ModuleScope).SetBodyProcedure(procedure);
  2931. ELSE
  2932. parentScope(SyntaxTree.CellScope).SetBodyProcedure(procedure);
  2933. END;
  2934. END BodyDeclaration;
  2935. (**
  2936. class-declaration:
  2937. [class-modifiers] 'class' identifier [class-base] class-body [';']
  2938. class-base:
  2939. ':' class-type
  2940. class-body:
  2941. '{' [class-member-declarations] '}'
  2942. class-member-declarations:
  2943. class-member-declaration
  2944. class-member-declarations class-member-declaration
  2945. class-member-declaration:
  2946. constant-declaration
  2947. field-declaration
  2948. method-declaration
  2949. constructor-declaration
  2950. type-declaration
  2951. type-declaration:
  2952. class-declaration
  2953. struct-declaration
  2954. delegate-declaration
  2955. cell-declaration
  2956. cellnet-declaration
  2957. **)
  2958. PROCEDURE MemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  2959. VAR attributes: SyntaxTree.Modifier;
  2960. modifiers: SET;
  2961. type: SyntaxTree.Type;
  2962. name: SyntaxTree.Identifier;
  2963. position: Position;
  2964. BEGIN
  2965. IF Optional(Scanner.LeftBracket) THEN
  2966. attributes := Attributes();
  2967. ELSE
  2968. attributes := NIL;
  2969. END;
  2970. Modifiers(modifiers);
  2971. IF Optional(Scanner.Const) THEN
  2972. ConstantDeclaration(parentScope, modifiers);
  2973. ELSIF Optional(Scanner.Class) THEN
  2974. ClassDeclaration(parentScope, modifiers);
  2975. ELSIF Optional(Scanner.Struct) THEN
  2976. StructDeclaration(parentScope, modifiers);
  2977. ELSIF Optional(Scanner.Delegate) THEN
  2978. DelegateDeclaration(parentScope, modifiers);
  2979. ELSIF Optional(Scanner.Cell) THEN
  2980. CellDeclaration(parentScope, modifiers, attributes, FALSE);
  2981. ELSIF Optional(Scanner.Cellnet) THEN
  2982. CellDeclaration(parentScope, modifiers, attributes, TRUE);
  2983. ELSIF Peek(Scanner.Identifier) & (symbol.identifier = parentName) THEN
  2984. name := Identifier(position);
  2985. ConstructorDeclaration(parentScope, modifiers, name, position);
  2986. ELSIF Optional(Scanner.Void) THEN
  2987. name := Identifier(position);
  2988. MethodDeclaration(parentScope, modifiers, NIL, name, position);
  2989. ELSE
  2990. type := Type();
  2991. name := Identifier(position);
  2992. IF Peek(Scanner.LeftParenthesis) THEN
  2993. MethodDeclaration(parentScope, modifiers, type, name, position);
  2994. ELSE
  2995. FieldDeclaration(parentScope, modifiers, type, name, position);
  2996. END;
  2997. END;
  2998. END MemberDeclaration;
  2999. PROCEDURE ClassMemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3000. BEGIN
  3001. IF Trace THEN
  3002. S("ClassMemberDeclaration")
  3003. END;
  3004. MemberDeclaration(parentScope, parentName);
  3005. IF Trace THEN
  3006. E("ClassMemberDeclaration")
  3007. END;
  3008. END ClassMemberDeclaration;
  3009. PROCEDURE ClassMemberDeclarations(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3010. VAR previousScope: SyntaxTree.Scope;
  3011. BEGIN
  3012. IF Trace THEN
  3013. S("ClassMemberDeclarations")
  3014. END;
  3015. previousScope := currentScope;
  3016. currentScope := parentScope;
  3017. WHILE ~Peek(Scanner.RightBrace) DO
  3018. ClassMemberDeclaration(parentScope, parentName);
  3019. END;
  3020. currentScope := previousScope;
  3021. IF Trace THEN
  3022. E("ClassMemberDeclarations")
  3023. END;
  3024. END ClassMemberDeclarations;
  3025. PROCEDURE ClassDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
  3026. VAR name: SyntaxTree.Identifier;
  3027. position: Position;
  3028. typeDeclaration: SyntaxTree.TypeDeclaration;
  3029. access: SET;
  3030. objectType: SyntaxTree.RecordType;
  3031. pointerType: SyntaxTree.PointerType;
  3032. recordScope: SyntaxTree.RecordScope;
  3033. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
  3034. baseType: SyntaxTree.Type;
  3035. previousStatements: SyntaxTree.StatementSequence;
  3036. previousOuter: SyntaxTree.Statement;
  3037. b: BOOLEAN;
  3038. BEGIN
  3039. IF Trace THEN
  3040. S("ClassDeclaration")
  3041. END;
  3042. previousStatements := initStatements;
  3043. previousOuter := initOuter;
  3044. (* TODO: Implement initialization of fields *)
  3045. initStatements := NIL;
  3046. initOuter := NIL;
  3047. EnterInit;
  3048. (* symbol 'class' already consumed *)
  3049. name := Identifier(position);
  3050. access := IdentifierAccess(modifiers, FALSE);
  3051. typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
  3052. CommentSymbol(typeDeclaration);
  3053. recordScope := SyntaxTree.NewRecordScope(parentScope);
  3054. pointerType := SyntaxTree.NewPointerType(position, parentScope);
  3055. objectType := SyntaxTree.NewRecordType(position, parentScope, recordScope);
  3056. objectType.IsObject(TRUE);
  3057. objectType.SetPointerType(pointerType);
  3058. pointerType.SetPointerBase(objectType);
  3059. IF Optional(Scanner.Colon) THEN
  3060. qualifiedIdentifier := QualifiedIdentifier();
  3061. baseType := SyntaxTree.NewQualifiedType(
  3062. qualifiedIdentifier.position, parentScope, qualifiedIdentifier);
  3063. objectType.SetBaseType(baseType);
  3064. END;
  3065. Check(Scanner.LeftBrace);
  3066. ClassMemberDeclarations(recordScope, name);
  3067. Check(Scanner.RightBrace);
  3068. b := Optional(Scanner.Semicolon);
  3069. pointerType.SetTypeDeclaration(typeDeclaration);
  3070. typeDeclaration.SetDeclaredType(pointerType);
  3071. typeDeclaration.SetAccess(access);
  3072. parentScope.AddTypeDeclaration(typeDeclaration);
  3073. initStatements := previousStatements;
  3074. initOuter := previousOuter;
  3075. IF Trace THEN
  3076. E("ClassDeclaration")
  3077. END;
  3078. END ClassDeclaration;
  3079. (**
  3080. struct-declaration:
  3081. [struct-modifiers] 'struct' identifier struct-body [';']
  3082. struct-body:
  3083. '{' [struct-member-declarations] '}'
  3084. struct-member-declarations:
  3085. struct-member-declaration
  3086. struct-member-declarations struct-member-declaration
  3087. struct-member-declaration:
  3088. constant-declaration
  3089. field-declaration
  3090. method-declaration
  3091. constructor-declaration
  3092. type-declaration
  3093. **)
  3094. PROCEDURE StructMemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3095. BEGIN
  3096. IF Trace THEN
  3097. S("StructMemberDeclaration")
  3098. END;
  3099. MemberDeclaration(parentScope, parentName);
  3100. IF Trace THEN
  3101. E("StructMemberDeclaration")
  3102. END;
  3103. END StructMemberDeclaration;
  3104. PROCEDURE StructMemberDeclarations(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3105. VAR previousScope: SyntaxTree.Scope;
  3106. BEGIN
  3107. IF Trace THEN
  3108. S("StructMemberDeclarations")
  3109. END;
  3110. previousScope := currentScope;
  3111. currentScope := parentScope;
  3112. WHILE ~Peek(Scanner.RightBrace) DO
  3113. StructMemberDeclaration(parentScope, parentName);
  3114. END;
  3115. currentScope := previousScope;
  3116. IF Trace THEN
  3117. E("StructMemberDeclarations")
  3118. END;
  3119. END StructMemberDeclarations;
  3120. PROCEDURE StructDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
  3121. VAR name: SyntaxTree.Identifier;
  3122. position: Position;
  3123. typeDeclaration: SyntaxTree.TypeDeclaration;
  3124. access: SET;
  3125. recordType: SyntaxTree.RecordType;
  3126. recordScope: SyntaxTree.RecordScope;
  3127. previousStatements: SyntaxTree.StatementSequence;
  3128. previousOuter: SyntaxTree.Statement;
  3129. b: BOOLEAN;
  3130. BEGIN
  3131. IF Trace THEN
  3132. S("StructDeclaration")
  3133. END;
  3134. previousStatements := initStatements;
  3135. previousOuter := initOuter;
  3136. (* TODO: Implement initialization of fields *)
  3137. initStatements := NIL;
  3138. initOuter := NIL;
  3139. (* symbol 'struct' already consumed *)
  3140. name := Identifier(position);
  3141. access := IdentifierAccess(modifiers, FALSE);
  3142. typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
  3143. CommentSymbol(typeDeclaration);
  3144. recordScope := SyntaxTree.NewRecordScope(parentScope);
  3145. recordType := SyntaxTree.NewRecordType(position, parentScope, recordScope);
  3146. Check(Scanner.LeftBrace);
  3147. StructMemberDeclarations(recordScope, name);
  3148. Check(Scanner.RightBrace);
  3149. b := Optional(Scanner.Semicolon);
  3150. recordType.SetTypeDeclaration(typeDeclaration);
  3151. typeDeclaration.SetDeclaredType(recordType);
  3152. typeDeclaration.SetAccess(access);
  3153. parentScope.AddTypeDeclaration(typeDeclaration);
  3154. initStatements := previousStatements;
  3155. initOuter := previousOuter;
  3156. IF Trace THEN
  3157. E("StructDeclaration")
  3158. END;
  3159. END StructDeclaration;
  3160. (**
  3161. delegate-declaration:
  3162. [delegate-modifiers] 'delegate' return-type identifier '(' [formal-parameter-list] ')' ';'
  3163. **)
  3164. PROCEDURE DelegateDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
  3165. VAR returnType: SyntaxTree.Type;
  3166. name: SyntaxTree.Identifier;
  3167. position: Position;
  3168. typeDeclaration: SyntaxTree.TypeDeclaration;
  3169. access: SET;
  3170. procedureType: SyntaxTree.ProcedureType;
  3171. BEGIN
  3172. IF Trace THEN
  3173. S("DelegateDeclaration")
  3174. END;
  3175. (* symbol 'delegate' already consumed *)
  3176. IF Optional(Scanner.Void) THEN
  3177. returnType := NIL;
  3178. ELSE
  3179. returnType := Type();
  3180. END;
  3181. name := Identifier(position);
  3182. access := IdentifierAccess(modifiers, FALSE);
  3183. typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
  3184. CommentSymbol(typeDeclaration);
  3185. procedureType := SyntaxTree.NewProcedureType(position, parentScope);
  3186. procedureType.SetModifiers(delegateModifiers);
  3187. (* ACHTUNG: Should we create a fictionary parentScope for parameters? *)
  3188. FormalParameterList(procedureType, parentScope, returnType);
  3189. procedureType.SetTypeDeclaration(typeDeclaration);
  3190. typeDeclaration.SetDeclaredType(procedureType);
  3191. typeDeclaration.SetAccess(access);
  3192. parentScope.AddTypeDeclaration(typeDeclaration);
  3193. IF Trace THEN
  3194. E("DelegateDeclaration")
  3195. END;
  3196. END DelegateDeclaration;
  3197. (**
  3198. port-list:
  3199. port-declaration
  3200. port-list ',' port-declaration
  3201. port-declaration:
  3202. port-type ['[' constant-expression ']'] identifier
  3203. port-type:
  3204. 'in'
  3205. 'out'
  3206. **)
  3207. PROCEDURE PortDeclaration(cell: SyntaxTree.CellType; parentScope: SyntaxTree.Scope);
  3208. VAR position: Position;
  3209. direction: LONGINT;
  3210. type: SyntaxTree.Type;
  3211. arrayType: SyntaxTree.ArrayType;
  3212. expression: SyntaxTree.Expression;
  3213. name: SyntaxTree.Identifier;
  3214. parameter: SyntaxTree.Parameter;
  3215. BEGIN
  3216. IF Trace THEN
  3217. S("PortDeclaration")
  3218. END;
  3219. position := symbol.position;
  3220. IF Optional(Scanner.In) THEN
  3221. direction := SyntaxTree.InPort;
  3222. ELSIF Optional(Scanner.Out) THEN
  3223. direction := SyntaxTree.OutPort;
  3224. ELSE
  3225. Error(position, Basic.InvalidCode, "invalid direction, expected in or out");
  3226. END;
  3227. type := SyntaxTree.NewPortType(position, direction, NIL, parentScope);
  3228. IF Optional(Scanner.LeftBracket) THEN
  3229. expression := Expression();
  3230. arrayType := SyntaxTree.NewArrayType(position, parentScope, SyntaxTree.Static);
  3231. arrayType.SetArrayBase(type);
  3232. arrayType.SetLength(expression);
  3233. type := arrayType;
  3234. Check(Scanner.RightBracket);
  3235. END;
  3236. name := Identifier(position);
  3237. parameter := SyntaxTree.NewParameter(position, cell, name, SyntaxTree.ValueParameter);
  3238. cell.AddParameter(parameter);
  3239. parameter.SetType(type);
  3240. IF Trace THEN
  3241. E("PortDeclaration")
  3242. END;
  3243. END PortDeclaration;
  3244. PROCEDURE PortList(cell: SyntaxTree.CellType; parentScope: SyntaxTree.Scope);
  3245. BEGIN
  3246. IF Trace THEN
  3247. S("PortList")
  3248. END;
  3249. Check(Scanner.LeftParenthesis);
  3250. IF ~Optional(Scanner.RightParenthesis) THEN
  3251. REPEAT
  3252. PortDeclaration(cell, parentScope);
  3253. UNTIL ~Optional(Scanner.Comma);
  3254. Check(Scanner.RightParenthesis);
  3255. END;
  3256. IF Trace THEN
  3257. E("PortList")
  3258. END;
  3259. END PortList;
  3260. (**
  3261. cell-declaration:
  3262. [cell-modifiers] 'cell' identifier ['(' [cell-parameter-list] ')'] cell-body [';']
  3263. cell-body:
  3264. '{' [cell-member-declarations] '}'
  3265. cell-member-declarations:
  3266. cell-member-declaration
  3267. cell-member-declarations cell-member-declaration
  3268. cell-member-declaration:
  3269. constant-declaration
  3270. field-declaration
  3271. method-declaration
  3272. constructor-declaration
  3273. type-declaration
  3274. cellnet-declaration:
  3275. [cell-modifiers] 'cellnet' identifier ['(' [cell-parameter-list] ')'] cell-body [';']
  3276. **)
  3277. PROCEDURE CellMemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3278. BEGIN
  3279. IF Trace THEN
  3280. S("CellMemberDeclaration")
  3281. END;
  3282. MemberDeclaration(parentScope, parentName);
  3283. IF Trace THEN
  3284. E("CellMemberDeclaration")
  3285. END;
  3286. END CellMemberDeclaration;
  3287. PROCEDURE CellMemberDeclarations(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3288. VAR previousScope: SyntaxTree.Scope;
  3289. BEGIN
  3290. IF Trace THEN
  3291. S("CellMemberDeclarations")
  3292. END;
  3293. previousScope := currentScope;
  3294. currentScope := parentScope;
  3295. WHILE ~Peek(Scanner.RightBrace) DO
  3296. CellMemberDeclaration(parentScope, parentName);
  3297. END;
  3298. currentScope := previousScope;
  3299. IF Trace THEN
  3300. E("CellMemberDeclarations")
  3301. END;
  3302. END CellMemberDeclarations;
  3303. PROCEDURE CellDeclaration(
  3304. parentScope: SyntaxTree.Scope;
  3305. modifiers: SET;
  3306. attributes: SyntaxTree.Modifier;
  3307. isCellNet: BOOLEAN);
  3308. VAR name: SyntaxTree.Identifier;
  3309. position: Position;
  3310. access: SET;
  3311. typeDeclaration: SyntaxTree.TypeDeclaration;
  3312. cellScope: SyntaxTree.CellScope;
  3313. cellType: SyntaxTree.CellType;
  3314. previousStatements: SyntaxTree.StatementSequence;
  3315. previousOuter: SyntaxTree.Statement;
  3316. b: BOOLEAN;
  3317. BEGIN
  3318. IF Trace THEN
  3319. S("CellDeclaration")
  3320. END;
  3321. previousStatements := initStatements;
  3322. previousOuter := initOuter;
  3323. (* TODO: Implement initialization of fields *)
  3324. initStatements := NIL;
  3325. initOuter := NIL;
  3326. (* symbol 'cell' already consumed *)
  3327. name := Identifier(position);
  3328. access := IdentifierAccess(modifiers, FALSE);
  3329. typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
  3330. CommentSymbol(typeDeclaration);
  3331. cellScope := SyntaxTree.NewCellScope(parentScope);
  3332. cellType := SyntaxTree.NewCellType(position, parentScope, cellScope);
  3333. cellType.IsCellNet(isCellNet);
  3334. cellScope.SetOwnerCell(cellType);
  3335. IF attributes # NIL THEN
  3336. cellType.SetModifiers(attributes);
  3337. END;
  3338. IF Peek(Scanner.LeftParenthesis) THEN
  3339. PortList(cellType, cellScope);
  3340. END;
  3341. EnterInit;
  3342. Check(Scanner.LeftBrace);
  3343. CellMemberDeclarations(cellScope, name);
  3344. Check(Scanner.RightBrace);
  3345. b := Optional(Scanner.Semicolon);
  3346. cellType.SetTypeDeclaration(typeDeclaration);
  3347. typeDeclaration.SetDeclaredType(cellType);
  3348. typeDeclaration.SetAccess(access);
  3349. parentScope.AddTypeDeclaration(typeDeclaration);
  3350. initStatements := previousStatements;
  3351. initOuter := previousOuter;
  3352. IF Trace THEN
  3353. E("CellDeclaration")
  3354. END;
  3355. END CellDeclaration;
  3356. (**
  3357. import-directives:
  3358. import-directive
  3359. import-directives import-directive
  3360. import-directive:
  3361. import-alias-directive
  3362. import-module-directive
  3363. import-alias-directive:
  3364. 'import' identifier '=' module-name ';'
  3365. import-module-directive:
  3366. 'import' module-name ';'
  3367. module-name:
  3368. identifier
  3369. **)
  3370. PROCEDURE ImportDirective(moduleScope: SyntaxTree.ModuleScope);
  3371. VAR alias, name, context: SyntaxTree.Identifier;
  3372. import: SyntaxTree.Import;
  3373. position, idPosition: Position;
  3374. BEGIN
  3375. IF Trace THEN
  3376. S("ImportDirective")
  3377. END;
  3378. (* import symbol already consumed *)
  3379. position := symbol.position;
  3380. alias := Identifier(idPosition);
  3381. IF alias # SyntaxTree.invalidIdentifier THEN
  3382. IF Optional(Scanner.Equal) THEN
  3383. name := Identifier(idPosition);
  3384. ELSE
  3385. name := alias;
  3386. END;
  3387. import := SyntaxTree.NewImport(position, alias, name, TRUE);
  3388. CommentSymbol(import);
  3389. moduleScope.AddImport(import);
  3390. END;
  3391. Check(Scanner.Semicolon);
  3392. IF Trace THEN
  3393. E("ImportDirective");
  3394. END;
  3395. END ImportDirective;
  3396. PROCEDURE ImportDirectives(moduleScope: SyntaxTree.ModuleScope);
  3397. BEGIN
  3398. IF Trace THEN
  3399. S("ImportDirectives")
  3400. END;
  3401. WHILE Optional(Scanner.Import) DO
  3402. ImportDirective(moduleScope);
  3403. END;
  3404. IF Trace THEN
  3405. E("ImportDirectives");
  3406. END;
  3407. END ImportDirectives;
  3408. (**
  3409. compilation-unit:
  3410. 'module' identifier '{' [import-directives] [class-member-declarations] '}' [';']
  3411. 'cellnet' identifier '{' [import-directives] [class-member-declarations] '}' [';']
  3412. **)
  3413. PROCEDURE Module*(): SyntaxTree.Module;
  3414. VAR moduleName, context: SyntaxTree.Identifier;
  3415. module: SyntaxTree.Module;
  3416. position: Position;
  3417. isCellNet: BOOLEAN;
  3418. scannerDiagnostics: Diagnostics.Diagnostics;
  3419. b: BOOLEAN;
  3420. BEGIN
  3421. IF Trace THEN
  3422. S("Module")
  3423. END;
  3424. position := symbol.position;
  3425. (* needed to feed in comment already before module starts: *)
  3426. moduleScope := SyntaxTree.NewModuleScope();
  3427. currentScope := moduleScope;
  3428. isCellNet := Optional(Scanner.Cellnet);
  3429. IF isCellNet OR Mandatory(Scanner.Module) THEN
  3430. moduleName := Identifier(position);
  3431. module := SyntaxTree.NewModule(scanner.source^, position, moduleName, moduleScope, LynxCase);
  3432. IF isCellNet THEN
  3433. module.SetCellNet(TRUE);
  3434. END;
  3435. module.SetType(SyntaxTree.moduleType);
  3436. CommentSymbol(module);
  3437. Check(Scanner.LeftBrace);
  3438. IF Peek(Scanner.Import) THEN
  3439. ImportDirectives(moduleScope)
  3440. END;
  3441. EnterInit;
  3442. ClassMemberDeclarations(moduleScope, moduleName);
  3443. Check(Scanner.RightBrace);
  3444. b := Optional(Scanner.Semicolon);
  3445. IF ~error & ~scanner.error THEN
  3446. (* read ahead to read comments *)
  3447. scannerDiagnostics := NIL;
  3448. scanner.ResetErrorDiagnostics(scannerDiagnostics);
  3449. NextSymbol;
  3450. scanner.ResetErrorDiagnostics(scannerDiagnostics);
  3451. (* do not use Check for not reading after end of module *)
  3452. SetNextInComment(recentComment, module);
  3453. module.SetClosingComment(recentComment);
  3454. recentComment := NIL;
  3455. END;
  3456. END;
  3457. IF Trace THEN
  3458. E("Module")
  3459. END;
  3460. RETURN module
  3461. END Module;
  3462. END Parser; (* Parser *)
  3463. VAR invalidPosition: Position;
  3464. (** parser retrieval **)
  3465. PROCEDURE NewParser*(scanner: Scanner.Scanner; diagnostics: Diagnostics.Diagnostics): Parser;
  3466. VAR parser: Parser;
  3467. BEGIN
  3468. NEW(parser, scanner, diagnostics);
  3469. RETURN parser;
  3470. END NewParser;
  3471. BEGIN
  3472. invalidPosition.start := -1;
  3473. END FoxCSharpParser.