FoxCSharpParser.Mod 143 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772
  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);
  792. realValue.SetSubtype(MapNumberType(symbol.numberType));
  793. expression := realValue;
  794. NextSymbol;
  795. ELSIF Peek(Scanner.CharacterLiteral) THEN
  796. expression := SyntaxTree.NewCharacterValue(position, symbol.character);
  797. NextSymbol;
  798. ELSIF Peek(Scanner.StringLiteral) THEN
  799. (*
  800. TODO: Revise this: may need a string constructor wrapper ...
  801. ... and symbol.stringLength may be important too
  802. *)
  803. expression := SyntaxTree.NewStringValue(position, symbol.string);
  804. NextSymbol;
  805. ELSIF Peek(Scanner.Identifier) THEN
  806. identifier := Identifier(position);
  807. identifier := localIdentTable.Find(identifier);
  808. expression := SyntaxTree.NewIdentifierDesignator(position, identifier);
  809. ELSIF Peek(Scanner.Null) THEN
  810. expression := SyntaxTree.NewNilValue(position);
  811. NextSymbol;
  812. ELSIF Optional(Scanner.LeftParenthesis) THEN
  813. expression := Expression();
  814. Check(Scanner.RightParenthesis);
  815. ELSIF Optional(Scanner.This) THEN
  816. expression := SyntaxTree.NewSelfDesignator(position);
  817. ELSIF Optional(Scanner.Base) THEN
  818. Check(Scanner.Period);
  819. position := symbol.position;
  820. identifier := Identifier(position);
  821. expression := SyntaxTree.NewIdentifierDesignator(position, identifier);
  822. expression := SyntaxTree.NewArrowDesignator(position, expression(SyntaxTree.Designator));
  823. ELSIF Optional(Scanner.New) THEN
  824. type := NonArrayType();
  825. expressionList := SyntaxTree.NewExpressionList();
  826. typeExpression := NewTypeExpression(position);
  827. expressionList.AddExpression(typeExpression);
  828. IF Optional(Scanner.LeftBracket) THEN
  829. arrayCreation := TRUE;
  830. ExpressionList(expressionList);
  831. Check(Scanner.RightBracket);
  832. WHILE Optional(Scanner.LeftBracket) DO
  833. type := RankSpecifier(type);
  834. Check(Scanner.RightBracket);
  835. END;
  836. n := expressionList.Length() - 1;
  837. FOR i := 1 TO n DO
  838. arrayType := SyntaxTree.NewArrayType(position, currentScope, SyntaxTree.Open);
  839. arrayType.SetArrayBase(type);
  840. type := arrayType;
  841. END;
  842. pointerType := SyntaxTree.NewPointerType(position, currentScope);
  843. pointerType.SetPointerBase(type);
  844. type := pointerType;
  845. END;
  846. typeExpression.SetType(type);
  847. IF ~arrayCreation THEN
  848. Check(Scanner.LeftParenthesis);
  849. IF ~Optional(Scanner.RightParenthesis) THEN
  850. ArgumentList(expressionList);
  851. Check(Scanner.RightParenthesis);
  852. END;
  853. designator := SyntaxTree.NewIdentifierDesignator(position, lynxNewobj);
  854. expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
  855. ELSE
  856. designator := SyntaxTree.NewIdentifierDesignator(position, lynxNewarr);
  857. expression := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
  858. END;
  859. ELSE
  860. Error(symbol.position, Basic.InvalidCode, "Invalid primary expression");
  861. NextSymbol;
  862. expression := SyntaxTree.invalidExpression;
  863. END;
  864. expression := Accessors(expression, arrayCreation);
  865. position := symbol.position;
  866. IF Optional(Scanner.QuestionQuestion) THEN
  867. rightExpression := PrimaryExpression();
  868. expression := NewReceiveExpression(position, expression, rightExpression);
  869. END;
  870. IF Trace THEN
  871. E("PrimaryExpression")
  872. END;
  873. RETURN expression;
  874. END PrimaryExpression;
  875. (**
  876. unary-expression:
  877. primary-expression
  878. '+' unary-expression
  879. '-' unary-expression
  880. '!' unary-expression
  881. '~' unary-expression
  882. cast-expression
  883. **)
  884. PROCEDURE UnaryExpression(): SyntaxTree.Expression;
  885. VAR expression: SyntaxTree.Expression;
  886. operator: LONGINT;
  887. position: Position;
  888. BEGIN
  889. IF Trace THEN
  890. S("UnaryExpression")
  891. END;
  892. position := symbol.position;
  893. IF Peek(Scanner.Plus) OR Peek(Scanner.Minus) OR
  894. Peek(Scanner.Exclamation) OR Peek(Scanner.Tilde) THEN
  895. operator := symbol.token;
  896. NextSymbol;
  897. expression := UnaryExpression();
  898. expression := NewUnaryExpression(position, expression, operator);
  899. ELSE
  900. (* TODO: Implement cast-expression *)
  901. expression := PrimaryExpression();
  902. END;
  903. IF Trace THEN
  904. E("UnaryExpression")
  905. END;
  906. RETURN expression;
  907. END UnaryExpression;
  908. (**
  909. multiplicative-expression:
  910. unary-expression
  911. multiplicative-expression '*' unary-expression
  912. multiplicative-expression '/' unary-expression
  913. multiplicative-expression '%' unary-expression
  914. **)
  915. PROCEDURE MultiplicativeExpression(): SyntaxTree.Expression;
  916. VAR expression, rightExpression: SyntaxTree.Expression;
  917. operator: LONGINT;
  918. position: Position;
  919. BEGIN
  920. IF Trace THEN
  921. S("MultiplicativeExpression")
  922. END;
  923. position := symbol.position;
  924. expression := UnaryExpression();
  925. WHILE Peek(Scanner.Times) OR Peek(Scanner.Slash) OR Peek(Scanner.Percent) DO
  926. operator := symbol.token;
  927. NextSymbol;
  928. rightExpression := UnaryExpression();
  929. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  930. END;
  931. IF Trace THEN
  932. E("MultiplicativeExpression")
  933. END;
  934. RETURN expression;
  935. END MultiplicativeExpression;
  936. (**
  937. additive-expression:
  938. multiplicative-expression
  939. additive-expression '+' multiplicative-expression
  940. additive-expression '–' multiplicative-expression
  941. **)
  942. PROCEDURE AdditiveExpression(): SyntaxTree.Expression;
  943. VAR expression, rightExpression: SyntaxTree.Expression;
  944. operator: LONGINT;
  945. position: Position;
  946. BEGIN
  947. IF Trace THEN
  948. S("AdditiveExpression")
  949. END;
  950. position := symbol.position;
  951. expression := MultiplicativeExpression();
  952. WHILE Peek(Scanner.Plus) OR Peek(Scanner.Minus) DO
  953. operator := symbol.token;
  954. NextSymbol;
  955. rightExpression := MultiplicativeExpression();
  956. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  957. END;
  958. IF Trace THEN
  959. E("AdditiveExpression")
  960. END;
  961. RETURN expression;
  962. END AdditiveExpression;
  963. (**
  964. shift-expression:
  965. additive-expression
  966. shift-expression '<<' additive-expression
  967. shift-expression '>>' additive-expression
  968. **)
  969. PROCEDURE ShiftExpression(): SyntaxTree.Expression;
  970. VAR expression, rightExpression: SyntaxTree.Expression;
  971. operator: LONGINT;
  972. position: Position;
  973. BEGIN
  974. IF Trace THEN
  975. S("ShiftExpression")
  976. END;
  977. position := symbol.position;
  978. expression := AdditiveExpression();
  979. WHILE Peek(Scanner.LeftShift) OR Peek(Scanner.RightShift) DO
  980. operator := symbol.token;
  981. NextSymbol;
  982. rightExpression := AdditiveExpression();
  983. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  984. END;
  985. IF Trace THEN
  986. E("ShiftExpression")
  987. END;
  988. RETURN expression;
  989. END ShiftExpression;
  990. (**
  991. relational-expression:
  992. shift-expression
  993. relational-expression '<' shift-expression
  994. relational-expression '>' shift-expression
  995. relational-expression '<=' shift-expression
  996. relational-expression '>=' shift-expression
  997. relational-expression 'is' type-name
  998. relational-expression 'as' type-name
  999. **)
  1000. PROCEDURE RelationalExpression(): SyntaxTree.Expression;
  1001. VAR expression, rightExpression: SyntaxTree.Expression;
  1002. operator: LONGINT;
  1003. position: Position;
  1004. BEGIN
  1005. IF Trace THEN
  1006. S("RelationalExpression")
  1007. END;
  1008. position := symbol.position;
  1009. expression := ShiftExpression();
  1010. WHILE Peek(Scanner.Less) OR Peek(Scanner.Greater) OR
  1011. Peek(Scanner.LessEqual) OR Peek(Scanner.GreaterEqual) OR
  1012. Peek(Scanner.Is) OR Peek(Scanner.As) DO
  1013. operator := symbol.token;
  1014. NextSymbol;
  1015. rightExpression := ShiftExpression();
  1016. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1017. END;
  1018. IF Trace THEN
  1019. E("RelationalExpression")
  1020. END;
  1021. RETURN expression;
  1022. END RelationalExpression;
  1023. (**
  1024. equality-expression:
  1025. relational-expression
  1026. equality-expression '==' relational-expression
  1027. equality-expression '!=' relational-expression
  1028. **)
  1029. PROCEDURE EqualityExpression(): SyntaxTree.Expression;
  1030. VAR expression, rightExpression: SyntaxTree.Expression;
  1031. operator: LONGINT;
  1032. position: Position;
  1033. BEGIN
  1034. IF Trace THEN
  1035. S("EqualityExpression")
  1036. END;
  1037. position := symbol.position;
  1038. expression := RelationalExpression();
  1039. WHILE Peek(Scanner.EqualEqual) OR Peek(Scanner.ExclamationEqual) DO
  1040. operator := symbol.token;
  1041. NextSymbol;
  1042. rightExpression := RelationalExpression();
  1043. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1044. END;
  1045. IF Trace THEN
  1046. E("EqualityExpression")
  1047. END;
  1048. RETURN expression;
  1049. END EqualityExpression;
  1050. (**
  1051. and-expression:
  1052. equality-expression
  1053. and-expression '&' equality-expression
  1054. **)
  1055. PROCEDURE AndExpression(): SyntaxTree.Expression;
  1056. VAR expression, rightExpression: SyntaxTree.Expression;
  1057. operator: LONGINT;
  1058. position: Position;
  1059. BEGIN
  1060. IF Trace THEN
  1061. S("AndExpression")
  1062. END;
  1063. position := symbol.position;
  1064. expression := EqualityExpression();
  1065. WHILE Peek(Scanner.And) DO
  1066. operator := symbol.token;
  1067. NextSymbol;
  1068. rightExpression := EqualityExpression();
  1069. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1070. END;
  1071. IF Trace THEN
  1072. E("AndExpression")
  1073. END;
  1074. RETURN expression;
  1075. END AndExpression;
  1076. (**
  1077. exclusive-or-expression:
  1078. and-expression
  1079. exclusive-or-expression '^' and-expression
  1080. **)
  1081. PROCEDURE ExclusiveOrExpression(): SyntaxTree.Expression;
  1082. VAR expression, rightExpression: SyntaxTree.Expression;
  1083. operator: LONGINT;
  1084. position: Position;
  1085. BEGIN
  1086. IF Trace THEN
  1087. S("ExclusiveOrExpression")
  1088. END;
  1089. position := symbol.position;
  1090. expression := AndExpression();
  1091. WHILE Peek(Scanner.Arrow) DO
  1092. operator := symbol.token;
  1093. NextSymbol;
  1094. rightExpression := AndExpression();
  1095. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1096. END;
  1097. IF Trace THEN
  1098. E("ExclusiveOrExpression")
  1099. END;
  1100. RETURN expression;
  1101. END ExclusiveOrExpression;
  1102. (**
  1103. inclusive-or-expression:
  1104. exclusive-or-expression
  1105. inclusive-or-expression '|' exclusive-or-expression
  1106. **)
  1107. PROCEDURE InclusiveOrExpression(): SyntaxTree.Expression;
  1108. VAR expression, rightExpression: SyntaxTree.Expression;
  1109. operator: LONGINT;
  1110. position: Position;
  1111. BEGIN
  1112. IF Trace THEN
  1113. S("InclusiveOrExpression")
  1114. END;
  1115. position := symbol.position;
  1116. expression := ExclusiveOrExpression();
  1117. WHILE Peek(Scanner.Bar) DO
  1118. operator := symbol.token;
  1119. NextSymbol;
  1120. rightExpression := ExclusiveOrExpression();
  1121. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1122. END;
  1123. IF Trace THEN
  1124. E("InclusiveOrExpression")
  1125. END;
  1126. RETURN expression;
  1127. END InclusiveOrExpression;
  1128. (**
  1129. conditional-and-expression:
  1130. inclusive-or-expression
  1131. conditional-and-expression '&&' inclusive-or-expression
  1132. **)
  1133. PROCEDURE ConditionalAndExpression(): SyntaxTree.Expression;
  1134. VAR expression, rightExpression: SyntaxTree.Expression;
  1135. operator: LONGINT;
  1136. position: Position;
  1137. BEGIN
  1138. IF Trace THEN
  1139. S("ConditionalAndExpression")
  1140. END;
  1141. position := symbol.position;
  1142. expression := InclusiveOrExpression();
  1143. WHILE Peek(Scanner.AndAnd) DO
  1144. operator := symbol.token;
  1145. NextSymbol;
  1146. rightExpression := InclusiveOrExpression();
  1147. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1148. END;
  1149. IF Trace THEN
  1150. E("ConditionalAndExpression")
  1151. END;
  1152. RETURN expression;
  1153. END ConditionalAndExpression;
  1154. (**
  1155. conditional-or-expression:
  1156. conditional-and-expression
  1157. conditional-or-expression '||' conditional-and-expression
  1158. **)
  1159. PROCEDURE ConditionalOrExpression(): SyntaxTree.Expression;
  1160. VAR expression, rightExpression: SyntaxTree.Expression;
  1161. operator: LONGINT;
  1162. position: Position;
  1163. BEGIN
  1164. IF Trace THEN
  1165. S("ConditionalOrExpression")
  1166. END;
  1167. position := symbol.position;
  1168. expression := ConditionalAndExpression();
  1169. WHILE Peek(Scanner.BarBar) DO
  1170. operator := symbol.token;
  1171. NextSymbol;
  1172. rightExpression := ConditionalAndExpression();
  1173. expression := NewBinaryExpression(position, expression, rightExpression, operator);
  1174. END;
  1175. IF Trace THEN
  1176. E("ConditionalOrExpression")
  1177. END;
  1178. RETURN expression;
  1179. END ConditionalOrExpression;
  1180. (**
  1181. expression:
  1182. conditional-expression
  1183. conditional-expression:
  1184. conditional-or-expression
  1185. **)
  1186. PROCEDURE Expression(): SyntaxTree.Expression;
  1187. VAR expression: SyntaxTree.Expression;
  1188. BEGIN
  1189. IF Trace THEN
  1190. S("Expression")
  1191. END;
  1192. expression := ConditionalOrExpression();
  1193. IF Trace THEN
  1194. E("Expression")
  1195. END;
  1196. RETURN expression;
  1197. END Expression;
  1198. (**
  1199. local-variable-declaration:
  1200. type local-variable-declarators
  1201. **)
  1202. PROCEDURE LocalVariableDeclaration(
  1203. statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement; type: SyntaxTree.Type);
  1204. VAR previousStatements: SyntaxTree.StatementSequence;
  1205. previousOuter: SyntaxTree.Statement;
  1206. BEGIN
  1207. IF Trace THEN
  1208. S("LocalVariableDeclaration")
  1209. END;
  1210. previousStatements := initStatements;
  1211. previousOuter := initOuter;
  1212. initStatements := statements;
  1213. initOuter := outer;
  1214. IF type = NIL THEN
  1215. type := Type();
  1216. END;
  1217. REPEAT
  1218. VariableDeclarator(currentScope, {}, type, SyntaxTree.invalidIdentifier, invalidPosition);
  1219. UNTIL ~Optional(Scanner.Comma);
  1220. initStatements := previousStatements;
  1221. initOuter := previousOuter;
  1222. IF Trace THEN
  1223. E("LocalVariableDeclaration")
  1224. END;
  1225. END LocalVariableDeclaration;
  1226. (**
  1227. local-constant-declaration:
  1228. 'const' type constant-declarators
  1229. **)
  1230. PROCEDURE LocalConstantDeclaration(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1231. VAR type: SyntaxTree.Type;
  1232. BEGIN
  1233. (* ACHTUNG: Parameters 'statements' and 'outer' are not used *)
  1234. IF Trace THEN
  1235. S("LocalConstantDeclaration")
  1236. END;
  1237. type := Type();
  1238. REPEAT
  1239. ConstantDeclarator(currentScope, {}, type);
  1240. UNTIL ~Optional(Scanner.Comma);
  1241. IF Trace THEN
  1242. E("LocalConstantDeclaration")
  1243. END;
  1244. END LocalConstantDeclaration;
  1245. (**
  1246. block:
  1247. '{' [statement-list] '}'
  1248. **)
  1249. PROCEDURE Block(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1250. VAR block: SyntaxTree.StatementBlock; position: Position;
  1251. BEGIN
  1252. IF Trace THEN
  1253. S("Block")
  1254. END;
  1255. Check(Scanner.LeftBrace);
  1256. position := symbol.position; position.start := position.end;
  1257. block := SyntaxTree.NewStatementBlock(position, outer, NIL);
  1258. (* CommentStatement(block); *)
  1259. IF ~Optional(Scanner.RightBrace) THEN
  1260. localIdentTable.OpenScope;
  1261. block.SetStatementSequence(StatementList(block));
  1262. localIdentTable.CloseScope;
  1263. Check(Scanner.RightBrace);
  1264. END;
  1265. statements.AddStatement(block);
  1266. IF Trace THEN
  1267. E("Block")
  1268. END;
  1269. END Block;
  1270. (**
  1271. expression-statement:
  1272. statement-expression ';'
  1273. statement-expression:
  1274. invocation-expression
  1275. assignment
  1276. post-increment-expression
  1277. post-decrement-expression
  1278. send-expression
  1279. receive-expression
  1280. connect-expression
  1281. delegate-expression
  1282. assignment:
  1283. primary-expression assignment-operator expression
  1284. assignment-operator: one of
  1285. '=' '+=' '-=' '*=' '/=' '%=' '&=' '|=' '^=' '<<=' '>>='
  1286. post-increment-expression:
  1287. primary-expression '++'
  1288. post-decrement-expression:
  1289. primary-expression '--'
  1290. send-expression:
  1291. primary-expression '!' expression-list
  1292. receive-expression:
  1293. primary-expression '?' expression-list
  1294. connect-expression:
  1295. primary-expression '>>' primary-expression
  1296. delegate-expression:
  1297. primary-expression '<=' primary-expression
  1298. **)
  1299. PROCEDURE NewAsopStatement(
  1300. position: Position;
  1301. operator: LONGINT;
  1302. left: SyntaxTree.Designator;
  1303. right: SyntaxTree.Expression;
  1304. outer: SyntaxTree.Statement): SyntaxTree.Statement;
  1305. VAR expressionList: SyntaxTree.ExpressionList;
  1306. expression: SyntaxTree.Expression;
  1307. designator: SyntaxTree.Designator;
  1308. BEGIN
  1309. operator := MapOperator(operator);
  1310. ASSERT(operator >= 256);
  1311. expressionList := SyntaxTree.NewExpressionList();
  1312. expression := SyntaxTree.NewIntegerValue(position, operator-256);
  1313. expressionList.AddExpression(expression);
  1314. expressionList.AddExpression(left);
  1315. expressionList.AddExpression(right);
  1316. designator := SyntaxTree.NewIdentifierDesignator(position, lynxAsop);
  1317. designator := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
  1318. RETURN SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
  1319. END NewAsopStatement;
  1320. (* ACHTUNG: LYNX 15-MAY-2013 *)
  1321. PROCEDURE PatchPortReference(expression: SyntaxTree.Expression): SyntaxTree.Expression;
  1322. VAR result: SyntaxTree.Expression;
  1323. parameterDesignator: SyntaxTree.ParameterDesignator;
  1324. parameters: SyntaxTree.ExpressionList;
  1325. p0: SyntaxTree.Expression;
  1326. identifierDesignator: SyntaxTree.IdentifierDesignator;
  1327. bracketDesignator: SyntaxTree.BracketDesignator;
  1328. left, left2: SyntaxTree.Expression;
  1329. BEGIN
  1330. IF ~(expression IS SyntaxTree.ParameterDesignator) THEN
  1331. result := expression;
  1332. ELSE
  1333. parameterDesignator := expression(SyntaxTree.ParameterDesignator);
  1334. parameters := parameterDesignator.parameters;
  1335. IF parameters.Length() # 1 THEN
  1336. result := expression;
  1337. ELSE
  1338. p0 := parameters.GetExpression(0);
  1339. IF p0 IS SyntaxTree.IdentifierDesignator THEN
  1340. (* C(P) -> C.P *)
  1341. left := parameterDesignator.left;
  1342. identifierDesignator := p0(SyntaxTree.IdentifierDesignator);
  1343. result :=
  1344. SyntaxTree.NewSelectorDesignator(
  1345. expression.position, left(SyntaxTree.Designator), identifierDesignator.identifier);
  1346. ELSIF p0 IS SyntaxTree.BracketDesignator THEN
  1347. bracketDesignator := p0(SyntaxTree.BracketDesignator);
  1348. left2 := bracketDesignator.left;
  1349. IF left2 IS SyntaxTree.IdentifierDesignator THEN
  1350. (* C(P[I]) -> C.P[I] *)
  1351. left := parameterDesignator.left;
  1352. identifierDesignator := left2(SyntaxTree.IdentifierDesignator);
  1353. result :=
  1354. SyntaxTree.NewBracketDesignator(
  1355. expression.position,
  1356. SyntaxTree.NewSelectorDesignator(
  1357. expression.position,
  1358. left(SyntaxTree.Designator),
  1359. identifierDesignator.identifier),
  1360. bracketDesignator.parameters);
  1361. ELSE
  1362. result := expression;
  1363. END;
  1364. ELSE
  1365. result := expression;
  1366. END;
  1367. END;
  1368. END;
  1369. RETURN result;
  1370. END PatchPortReference;
  1371. PROCEDURE NewPortStatement(
  1372. position: Position;
  1373. name: SyntaxTree.Identifier;
  1374. left: SyntaxTree.Designator;
  1375. right: SyntaxTree.Expression;
  1376. outer: SyntaxTree.Statement): SyntaxTree.Statement;
  1377. VAR expressionList: SyntaxTree.ExpressionList;
  1378. designator: SyntaxTree.Designator;
  1379. BEGIN
  1380. expressionList := SyntaxTree.NewExpressionList();
  1381. expressionList.AddExpression(left);
  1382. expressionList.AddExpression(right);
  1383. designator := SyntaxTree.NewIdentifierDesignator(position, name);
  1384. designator := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
  1385. RETURN SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
  1386. END NewPortStatement;
  1387. PROCEDURE StatementExpression(
  1388. statements: SyntaxTree.StatementSequence;
  1389. outer: SyntaxTree.Statement;
  1390. expression: SyntaxTree.Expression): BOOLEAN;
  1391. VAR designator: SyntaxTree.Designator;
  1392. expressionList: SyntaxTree.ExpressionList;
  1393. statement: SyntaxTree.Statement;
  1394. operator: LONGINT;
  1395. position: Position;
  1396. length, i: LONGINT;
  1397. temp: SyntaxTree.Expression;
  1398. BEGIN
  1399. IF Trace THEN
  1400. S("StatementExpression")
  1401. END;
  1402. (* ACHTUNG: Only expressions of type SyntaxTree.Designator are supported
  1403. in place of primary-expression in the above productions. This is
  1404. required for compatibility with Fox back-end *)
  1405. statement := NIL;
  1406. position := symbol.position;
  1407. IF expression = NIL THEN
  1408. expression := PrimaryExpression();
  1409. END;
  1410. IF ~(expression IS SyntaxTree.Designator) THEN
  1411. Error(position, Basic.InvalidCode, "Invalid expression statement");
  1412. ELSE
  1413. designator := expression(SyntaxTree.Designator);
  1414. position := symbol.position;
  1415. IF Optional(Scanner.Equal) THEN
  1416. expression := Expression();
  1417. statement := SyntaxTree.NewAssignment(position, designator, expression, outer);
  1418. ELSIF Peek(Scanner.PlusEqual) OR Peek(Scanner.MinusEqual) OR
  1419. Peek(Scanner.TimesEqual) OR Peek(Scanner.SlashEqual) OR
  1420. Peek(Scanner.PercentEqual) OR Peek(Scanner.AndEqual) OR
  1421. Peek(Scanner.BarEqual) OR Peek(Scanner.ArrowEqual) OR
  1422. Peek(Scanner.LeftShiftEqual) OR Peek(Scanner.RightShiftEqual) THEN
  1423. operator := symbol.token;
  1424. NextSymbol;
  1425. (* lynx@asop(operator, designator, expression) *)
  1426. expression := Expression();
  1427. statement := NewAsopStatement(position, operator, designator, expression, outer);
  1428. ELSIF Optional(Scanner.PlusPlus) THEN
  1429. (* lynx@asop(PlusEqual, designator, 1) *)
  1430. operator := Scanner.PlusPlus;
  1431. expression := SyntaxTree.NewIntegerValue(position, 1);
  1432. statement := NewAsopStatement(position, operator, designator, expression, outer);
  1433. ELSIF Optional(Scanner.MinusMinus) THEN
  1434. (* lynx@asop(MinusEqual, designator, 1) *)
  1435. operator := Scanner.MinusMinus;
  1436. expression := SyntaxTree.NewIntegerValue(position, 1);
  1437. statement := NewAsopStatement(position, operator, designator, expression, outer);
  1438. (* ACHTUNG: LYNX 15-MAY-2013
  1439. ELSIF Optional(Scanner.Exclamation) THEN
  1440. (* lynx@send(designator, expression) *)
  1441. expression := Expression();
  1442. statement := NewPortStatement(position, lynxSend, designator, expression, outer);
  1443. ELSIF Optional(Scanner.Question) THEN
  1444. (* lynx@receive(designator, expression) *)
  1445. expression := Expression();
  1446. statement := NewPortStatement(position, lynxReceive, designator, expression, outer);
  1447. *)
  1448. ELSIF Optional(Scanner.Exclamation) THEN
  1449. (* lynx@send(designator, expression) *)
  1450. expressionList := SyntaxTree.NewExpressionList();
  1451. ExpressionList(expressionList);
  1452. length := expressionList.Length();
  1453. FOR i := 0 TO length - 1 DO
  1454. expression := expressionList.GetExpression(i);
  1455. statement := NewPortStatement(position, lynxSend, designator, expression, outer);
  1456. IF i < length - 1 THEN
  1457. statements.AddStatement(statement);
  1458. END;
  1459. END;
  1460. ELSIF Optional(Scanner.Question) THEN
  1461. (* lynx@receive(designator, expression) *)
  1462. expressionList := SyntaxTree.NewExpressionList();
  1463. ExpressionList(expressionList);
  1464. length := expressionList.Length();
  1465. FOR i := 0 TO length - 1 DO
  1466. expression := expressionList.GetExpression(i);
  1467. statement := NewPortStatement(position, lynxReceive, designator, expression, outer);
  1468. IF i < length - 1 THEN
  1469. statements.AddStatement(statement);
  1470. END;
  1471. END;
  1472. (* ACHTUNG: LYNX 15-MAY-2013
  1473. ELSIF Optional(Scanner.RightShift) THEN
  1474. (* lynx@connect(designator, expression) *)
  1475. expression := PrimaryExpression();
  1476. statement := NewPortStatement(position, lynxConnect, designator, expression, outer);
  1477. ELSIF Optional(Scanner.LessEqual) THEN
  1478. (* lynx@delegate(designator, expression) *)
  1479. expression := PrimaryExpression();
  1480. statement := NewPortStatement(position, lynxDelegate, designator, expression, outer);
  1481. *)
  1482. ELSIF Optional(Scanner.RightShift) THEN
  1483. (* lynx@connect(designator, expression) *)
  1484. expression := PrimaryExpression();
  1485. temp := PatchPortReference(designator);
  1486. designator := temp(SyntaxTree.Designator);
  1487. expression := PatchPortReference(expression);
  1488. statement := NewPortStatement(position, lynxConnect, designator, expression, outer);
  1489. ELSIF Optional(Scanner.LessEqual) THEN
  1490. (* lynx@delegate(designator, expression) *)
  1491. expression := PrimaryExpression();
  1492. temp := PatchPortReference(designator);
  1493. designator := temp(SyntaxTree.Designator);
  1494. expression := PatchPortReference(expression);
  1495. statement := NewPortStatement(position, lynxDelegate, designator, expression, outer);
  1496. ELSIF designator IS SyntaxTree.ParameterDesignator THEN
  1497. statement := SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
  1498. ELSE
  1499. Error(position, Basic.InvalidCode, "Invalid expression statement");
  1500. END;
  1501. END;
  1502. IF statement # NIL THEN
  1503. (* CommentStatement(statement); *)
  1504. statements.AddStatement(statement);
  1505. END;
  1506. IF Trace THEN
  1507. E("StatementExpression")
  1508. END;
  1509. RETURN statement # NIL;
  1510. END StatementExpression;
  1511. PROCEDURE ExpressionStatement(
  1512. statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement): BOOLEAN;
  1513. VAR b: BOOLEAN;
  1514. BEGIN
  1515. IF Trace THEN
  1516. S("ExpressionStatement")
  1517. END;
  1518. b := StatementExpression(statements, outer, NIL);
  1519. Check(Scanner.Semicolon);
  1520. IF Trace THEN
  1521. E("ExpressionStatement")
  1522. END;
  1523. RETURN b;
  1524. END ExpressionStatement;
  1525. (**
  1526. if-statement:
  1527. 'if' '(' boolean-expression ')' embedded-statement
  1528. 'if' '(' boolean-expression ')' embedded-statement 'else' embedded-statement
  1529. **)
  1530. PROCEDURE IfStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1531. VAR expression: SyntaxTree.Expression;
  1532. ifStatement: SyntaxTree.IfStatement;
  1533. elsePart: SyntaxTree.IfPart;
  1534. statementSequence: SyntaxTree.StatementSequence;
  1535. b: BOOLEAN;
  1536. BEGIN
  1537. IF Trace THEN
  1538. S("IfStatement")
  1539. END;
  1540. Check(Scanner.If);
  1541. ifStatement := SyntaxTree.NewIfStatement(symbol.position, outer);
  1542. (* CommentStatement(ifStatement); *)
  1543. Check(Scanner.LeftParenthesis);
  1544. expression := Expression();
  1545. Check(Scanner.RightParenthesis);
  1546. ifStatement.ifPart.SetCondition(expression);
  1547. statementSequence := SyntaxTree.NewStatementSequence();
  1548. b := EmbeddedStatement(statementSequence, ifStatement);
  1549. ifStatement.ifPart.SetStatements(statementSequence);
  1550. IF Optional(Scanner.Else) THEN
  1551. statementSequence := SyntaxTree.NewStatementSequence();
  1552. b := EmbeddedStatement(statementSequence, ifStatement);
  1553. ifStatement.SetElsePart(statementSequence);
  1554. END;
  1555. statements.AddStatement(ifStatement);
  1556. IF Trace THEN
  1557. E("IfStatement")
  1558. END;
  1559. END IfStatement;
  1560. (**
  1561. switch-statement:
  1562. 'switch' '(' expression ')' switch-block
  1563. switch-block:
  1564. '{' [switch-sections] '}'
  1565. switch-sections:
  1566. switch-section
  1567. switch-sections switch-section
  1568. switch-section:
  1569. switch-labels statement-list
  1570. switch-labels:
  1571. switch-label
  1572. switch-labels switch-label
  1573. switch-label:
  1574. 'case' constant-expression ':'
  1575. 'default' ':'
  1576. **)
  1577. PROCEDURE SwitchSection(caseStatement: SyntaxTree.CaseStatement; VAR haveDefault: BOOLEAN);
  1578. VAR casePart: SyntaxTree.CasePart;
  1579. statements: SyntaxTree.StatementSequence;
  1580. last: SyntaxTree.Statement;
  1581. element: SyntaxTree.Expression;
  1582. defaultSection: BOOLEAN;
  1583. length: LONGINT; position: Position;
  1584. BEGIN
  1585. IF Trace THEN
  1586. S("SwitchSection")
  1587. END;
  1588. casePart := SyntaxTree.NewCasePart();
  1589. defaultSection := FALSE;
  1590. WHILE Peek(Scanner.Case) OR Peek(Scanner.Default) DO
  1591. (* CommentCasePart(casePart); *)
  1592. IF Optional(Scanner.Case) THEN
  1593. element := Expression();
  1594. Check(Scanner.Colon);
  1595. casePart.elements.AddExpression(element);
  1596. ELSE
  1597. position := symbol.position;
  1598. Check(Scanner.Default);
  1599. Check(Scanner.Colon);
  1600. IF haveDefault THEN
  1601. Error(position, Basic.InvalidCode, "Duplicate default label");
  1602. ELSE
  1603. defaultSection := TRUE;
  1604. haveDefault := TRUE;
  1605. END;
  1606. END;
  1607. END;
  1608. statements := StatementList(caseStatement);
  1609. length := statements.Length();
  1610. IF length = 0 THEN
  1611. Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
  1612. ELSE
  1613. last := statements.GetStatement(length-1);
  1614. IF last IS SyntaxTree.ExitStatement THEN
  1615. statements.RemoveStatement(last);
  1616. ELSIF ~(last IS SyntaxTree.ReturnStatement) THEN
  1617. Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
  1618. END;
  1619. END;
  1620. IF ~defaultSection THEN
  1621. casePart.SetStatements(statements);
  1622. caseStatement.AddCasePart(casePart);
  1623. ELSE
  1624. (* ignore case labels, if any *)
  1625. (* ACHTUNG: these labels will not be checked for duplicates *)
  1626. caseStatement.SetElsePart(statements);
  1627. END;
  1628. IF Trace THEN
  1629. E("SwitchSection")
  1630. END;
  1631. END SwitchSection;
  1632. PROCEDURE SwitchStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1633. VAR expression: SyntaxTree.Expression;
  1634. caseStatement: SyntaxTree.CaseStatement;
  1635. haveDefault: BOOLEAN;
  1636. BEGIN
  1637. IF Trace THEN
  1638. S("SwitchStatement")
  1639. END;
  1640. Check(Scanner.Switch);
  1641. caseStatement := SyntaxTree.NewCaseStatement(symbol.position, outer);
  1642. (* CommentStatement(caseStatement); *)
  1643. Check(Scanner.LeftParenthesis);
  1644. expression := Expression();
  1645. Check(Scanner.RightParenthesis);
  1646. caseStatement.SetVariable(expression);
  1647. Check(Scanner.LeftBrace);
  1648. haveDefault := FALSE;
  1649. WHILE Peek(Scanner.Case) OR Peek(Scanner.Default) DO
  1650. SwitchSection(caseStatement, haveDefault);
  1651. END;
  1652. Check(Scanner.RightBrace);
  1653. statements.AddStatement(caseStatement);
  1654. IF Trace THEN
  1655. E("SwitchStatement")
  1656. END;
  1657. END SwitchStatement;
  1658. (**
  1659. select-statement:
  1660. 'select' select-block
  1661. select-block:
  1662. '{' select-sections '}'
  1663. select-sections:
  1664. select-section
  1665. select-sections select-section
  1666. select-section:
  1667. select-label statement-list
  1668. select-label:
  1669. 'case' [select-replicator] primary-expression '?' primary-expression ':'
  1670. select-replicator:
  1671. '(' integral-type simple-name 'in' expression ':' expression ')'
  1672. **)
  1673. (**
  1674. Fox mapping schema:
  1675. // LYNX
  1676. select {
  1677. case c ? x:
  1678. S1;
  1679. case (int i in m : n) d[i] ? y:
  1680. S2;
  1681. }
  1682. // Fox
  1683. lynx@newsel;
  1684. lynx@addsel(0, 0, c);
  1685. FOR i := m TO n DO
  1686. lynx@addsel(1, i, d[i])
  1687. END;
  1688. CASE lynx@select() OF
  1689. 0:
  1690. c ? x;
  1691. S1;
  1692. | 1:
  1693. i := lynx@selidx();
  1694. d[i] ? y;
  1695. S2;
  1696. END;
  1697. **)
  1698. PROCEDURE NewLynxNewsel(
  1699. position: Position; outer: SyntaxTree.Statement): SyntaxTree.Statement;
  1700. VAR parameters: SyntaxTree.ExpressionList;
  1701. designator: SyntaxTree.Designator;
  1702. BEGIN
  1703. parameters := SyntaxTree.NewExpressionList();
  1704. designator := SyntaxTree.NewIdentifierDesignator(position, lynxNewsel);
  1705. designator := SyntaxTree.NewParameterDesignator(position, designator, parameters);
  1706. RETURN SyntaxTree.NewProcedureCallStatement(position, FALSE, designator, outer);
  1707. END NewLynxNewsel;
  1708. PROCEDURE NewLynxAddsel(
  1709. position: Position;
  1710. index: LONGINT;
  1711. variable: SyntaxTree.Identifier;
  1712. channel: SyntaxTree.Expression;
  1713. outer: SyntaxTree.Statement): SyntaxTree.Statement;
  1714. VAR parameters: SyntaxTree.ExpressionList;
  1715. designator: SyntaxTree.Designator;
  1716. BEGIN
  1717. parameters := SyntaxTree.NewExpressionList();
  1718. parameters.AddExpression(SyntaxTree.NewIntegerValue(position, index));
  1719. IF variable # SyntaxTree.invalidIdentifier THEN
  1720. parameters.AddExpression(
  1721. SyntaxTree.NewIdentifierDesignator(position, variable));
  1722. ELSE
  1723. parameters.AddExpression(SyntaxTree.NewIntegerValue(position, 0));
  1724. END;
  1725. parameters.AddExpression(channel);
  1726. designator := SyntaxTree.NewIdentifierDesignator(position, lynxAddsel);
  1727. designator := SyntaxTree.NewParameterDesignator(position, designator, parameters);
  1728. RETURN SyntaxTree.NewProcedureCallStatement(position, FALSE, designator, outer);
  1729. END NewLynxAddsel;
  1730. PROCEDURE NewLynxSelect(position: Position): SyntaxTree.Expression;
  1731. VAR left: SyntaxTree.Designator;
  1732. parameters: SyntaxTree.ExpressionList;
  1733. BEGIN
  1734. left := SyntaxTree.NewIdentifierDesignator(position, lynxSelect);
  1735. parameters := SyntaxTree.NewExpressionList();
  1736. RETURN SyntaxTree.NewParameterDesignator(position, left, parameters);
  1737. END NewLynxSelect;
  1738. PROCEDURE NewLynxSelidx(
  1739. position: Position;
  1740. variable: SyntaxTree.Identifier;
  1741. outer: SyntaxTree.Statement): SyntaxTree.Statement;
  1742. VAR left: SyntaxTree.Designator;
  1743. parameters: SyntaxTree.ExpressionList;
  1744. right: SyntaxTree.Expression;
  1745. BEGIN
  1746. left := SyntaxTree.NewIdentifierDesignator(position, lynxSelidx);
  1747. parameters := SyntaxTree.NewExpressionList();
  1748. right := SyntaxTree.NewParameterDesignator(position, left, parameters);
  1749. left := SyntaxTree.NewIdentifierDesignator(position, variable);
  1750. RETURN SyntaxTree.NewAssignment(position, left, right, outer);
  1751. END NewLynxSelidx;
  1752. PROCEDURE SelectSection(
  1753. statements: SyntaxTree.StatementSequence;
  1754. caseStatement: SyntaxTree.CaseStatement;
  1755. index: LONGINT;
  1756. outer: SyntaxTree.Statement);
  1757. VAR typename, varname: SyntaxTree.Identifier;
  1758. type: SyntaxTree.Type;
  1759. variable: SyntaxTree.Variable;
  1760. position: Position;
  1761. from, to: SyntaxTree.Expression;
  1762. channel, target: SyntaxTree.Expression;
  1763. statement: SyntaxTree.Statement;
  1764. forStatement: SyntaxTree.ForStatement;
  1765. forBody: SyntaxTree.StatementSequence;
  1766. designator: SyntaxTree.Designator;
  1767. casePart: SyntaxTree.CasePart;
  1768. caseBody: SyntaxTree.StatementSequence;
  1769. length: LONGINT;
  1770. last: SyntaxTree.Statement;
  1771. BEGIN
  1772. IF Trace THEN
  1773. S("SelectSection")
  1774. END;
  1775. position := symbol.position;
  1776. Check(Scanner.Case);
  1777. localIdentTable.OpenScope;
  1778. IF Optional(Scanner.LeftParenthesis) THEN
  1779. IF Optional(Scanner.Sbyte) THEN
  1780. typename := lynxSbyte;
  1781. ELSIF Optional(Scanner.Short) THEN
  1782. typename := lynxShort;
  1783. ELSIF Optional(Scanner.Int) THEN
  1784. typename := lynxInt;
  1785. ELSIF Optional(Scanner.Long) THEN
  1786. typename := lynxLong;
  1787. ELSE
  1788. Error(position, Basic.InvalidCode, "Missing integral type specifier");
  1789. typename := lynxInt;
  1790. END;
  1791. type :=
  1792. SyntaxTree.NewQualifiedType(
  1793. position,
  1794. currentScope,
  1795. SyntaxTree.NewQualifiedIdentifier(
  1796. position, SyntaxTree.invalidIdentifier, typename));
  1797. varname := Identifier(position);
  1798. varname := localIdentTable.Enter(varname);
  1799. variable := SyntaxTree.NewVariable(position, varname);
  1800. CommentSymbol(variable);
  1801. variable.SetType(type);
  1802. currentScope.AddVariable(variable);
  1803. Check(Scanner.In);
  1804. from := Expression();
  1805. Check(Scanner.Colon);
  1806. to := Expression();
  1807. Check(Scanner.RightParenthesis);
  1808. ELSE
  1809. varname := SyntaxTree.invalidIdentifier;
  1810. END;
  1811. channel := PrimaryExpression();
  1812. Check(Scanner.Question);
  1813. target := PrimaryExpression();
  1814. Check(Scanner.Colon);
  1815. (* prolog *)
  1816. IF varname = SyntaxTree.invalidIdentifier THEN
  1817. statement := NewLynxAddsel(position, index, varname, channel, outer);
  1818. statements.AddStatement(statement);
  1819. ELSE
  1820. forStatement := SyntaxTree.NewForStatement(symbol.position, outer);
  1821. designator := SyntaxTree.NewIdentifierDesignator(position, varname);
  1822. forStatement.SetVariable(designator);
  1823. forStatement.SetFrom(from);
  1824. forStatement.SetTo(to);
  1825. forBody := SyntaxTree.NewStatementSequence();
  1826. statement :=
  1827. NewLynxAddsel(position, index, varname, channel, forStatement);
  1828. forBody.AddStatement(statement);
  1829. forStatement.SetStatements(forBody);
  1830. statements.AddStatement(forStatement);
  1831. END;
  1832. (* case part *)
  1833. casePart := SyntaxTree.NewCasePart();
  1834. casePart.elements.AddExpression(SyntaxTree.NewIntegerValue(position, index));
  1835. (* same logic as for switch: *)
  1836. caseBody := StatementList(caseStatement);
  1837. length := caseBody.Length();
  1838. IF length = 0 THEN
  1839. Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
  1840. ELSE
  1841. last := caseBody.GetStatement(length-1);
  1842. IF last IS SyntaxTree.ExitStatement THEN
  1843. caseBody.RemoveStatement(last);
  1844. ELSIF ~(last IS SyntaxTree.ReturnStatement) THEN
  1845. Error(symbol.position, Basic.InvalidCode, "Fall through in switch section");
  1846. END;
  1847. END;
  1848. statement := NewPortStatement(position, lynxReceive, channel(SyntaxTree.Designator), target, caseStatement);
  1849. caseBody.PrependStatement(statement);
  1850. IF varname # SyntaxTree.invalidIdentifier THEN
  1851. statement := NewLynxSelidx(position, varname, caseStatement);
  1852. caseBody.PrependStatement(statement);
  1853. END;
  1854. casePart.SetStatements(caseBody);
  1855. caseStatement.AddCasePart(casePart);
  1856. localIdentTable.CloseScope;
  1857. IF Trace THEN
  1858. E("SelectSection")
  1859. END;
  1860. END SelectSection;
  1861. PROCEDURE SelectStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1862. VAR statement: SyntaxTree.Statement;
  1863. caseStatement: SyntaxTree.CaseStatement;
  1864. expression: SyntaxTree.Expression;
  1865. index: LONGINT;
  1866. position: Position;
  1867. BEGIN
  1868. IF Trace THEN
  1869. S("SelectStatement")
  1870. END;
  1871. position := symbol.position;
  1872. Check(Scanner.Select);
  1873. statement := NewLynxNewsel(position, outer);
  1874. statements.AddStatement(statement);
  1875. caseStatement := SyntaxTree.NewCaseStatement(position, outer);
  1876. expression := NewLynxSelect(position);
  1877. caseStatement.SetVariable(expression);
  1878. Check(Scanner.LeftBrace);
  1879. index := 0;
  1880. WHILE Peek(Scanner.Case) DO
  1881. SelectSection(statements, caseStatement, index, outer);
  1882. INC(index);
  1883. END;
  1884. position := symbol.position;
  1885. Check(Scanner.RightBrace);
  1886. IF index = 0 THEN
  1887. Error(position, Basic.InvalidCode, "Empty select statement");
  1888. END;
  1889. statements.AddStatement(caseStatement);
  1890. IF Trace THEN
  1891. E("SelectStatement")
  1892. END;
  1893. END SelectStatement;
  1894. (**
  1895. while-statement:
  1896. 'while' '(' boolean-expression ')' embedded-statement
  1897. **)
  1898. PROCEDURE WhileStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1899. VAR expression: SyntaxTree.Expression;
  1900. whileStatement: SyntaxTree.WhileStatement;
  1901. statementSequence: SyntaxTree.StatementSequence;
  1902. b: BOOLEAN;
  1903. BEGIN
  1904. IF Trace THEN
  1905. S("WhileStatement")
  1906. END;
  1907. Check(Scanner.While);
  1908. whileStatement := SyntaxTree.NewWhileStatement(symbol.position, outer);
  1909. (* CommentStatement(whileStatement); *)
  1910. Check(Scanner.LeftParenthesis);
  1911. expression := Expression();
  1912. Check(Scanner.RightParenthesis);
  1913. whileStatement.SetCondition(expression);
  1914. statementSequence := SyntaxTree.NewStatementSequence();
  1915. b := EmbeddedStatement(statementSequence, whileStatement);
  1916. whileStatement.SetStatements(statementSequence);
  1917. statements.AddStatement(whileStatement);
  1918. IF Trace THEN
  1919. E("WhileStatement")
  1920. END;
  1921. END WhileStatement;
  1922. (**
  1923. do-statement:
  1924. 'do' embedded-statement 'while' '(' boolean-expression ')' ';'
  1925. **)
  1926. PROCEDURE DoStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1927. VAR expression: SyntaxTree.Expression;
  1928. repeatStatement: SyntaxTree.RepeatStatement;
  1929. statementSequence: SyntaxTree.StatementSequence;
  1930. position: Position;
  1931. b: BOOLEAN;
  1932. BEGIN
  1933. IF Trace THEN
  1934. S("DoStatement")
  1935. END;
  1936. Check(Scanner.Do);
  1937. repeatStatement := SyntaxTree.NewRepeatStatement(symbol.position, outer);
  1938. (* CommentStatement(repeatStatement); *)
  1939. statementSequence := SyntaxTree.NewStatementSequence();
  1940. b := EmbeddedStatement(statementSequence, repeatStatement);
  1941. repeatStatement.SetStatements(statementSequence);
  1942. Check(Scanner.While);
  1943. Check(Scanner.LeftParenthesis);
  1944. position := symbol.position;
  1945. expression := Expression();
  1946. Check(Scanner.RightParenthesis);
  1947. expression := NewUnaryExpression(position, expression, Scanner.Exclamation);
  1948. repeatStatement.SetCondition(expression);
  1949. statements.AddStatement(repeatStatement);
  1950. IF Trace THEN
  1951. E("DoStatement")
  1952. END;
  1953. END DoStatement;
  1954. (**
  1955. statement-expression-list:
  1956. statement-expression
  1957. statement-expression-list ',' statement-expression
  1958. **)
  1959. PROCEDURE StatementExpressionList(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1960. VAR b: BOOLEAN;
  1961. BEGIN
  1962. IF Trace THEN
  1963. S("StatementExpressionList")
  1964. END;
  1965. REPEAT
  1966. b := StatementExpression(statements, outer, NIL);
  1967. UNTIL ~Optional(Scanner.Comma);
  1968. IF Trace THEN
  1969. E("StatementExpressionList")
  1970. END;
  1971. END StatementExpressionList;
  1972. (**
  1973. for-initializer:
  1974. local-variable-declaration
  1975. statement-expression-list
  1976. **)
  1977. PROCEDURE ForInitializer(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  1978. VAR isDeclaration: BOOLEAN;
  1979. b: BOOLEAN;
  1980. BEGIN
  1981. IF Trace THEN
  1982. S("ForInitializer")
  1983. END;
  1984. IF Peek(Scanner.Bool) OR Peek(Scanner.Sbyte) OR
  1985. Peek(Scanner.Short) OR Peek(Scanner.Int) OR
  1986. Peek(Scanner.Long) OR Peek(Scanner.Char) OR
  1987. Peek(Scanner.Float) OR Peek(Scanner.Double) OR
  1988. Peek(Scanner.Object) OR Peek(Scanner.String) THEN
  1989. LocalVariableDeclaration(statements, outer, NIL);
  1990. ELSIF Peek(Scanner.Identifier) THEN
  1991. (* either local-variable-declaration or statement expression *)
  1992. b := ExpressionOrDeclaration(statements, outer, isDeclaration);
  1993. IF ~isDeclaration & Optional(Scanner.Comma) THEN
  1994. StatementExpressionList(statements, outer);
  1995. END;
  1996. ELSE
  1997. StatementExpressionList(statements, outer);
  1998. END;
  1999. IF Trace THEN
  2000. E("ForInitializer")
  2001. END;
  2002. END ForInitializer;
  2003. (**
  2004. for-iterator:
  2005. statement-expression-list
  2006. **)
  2007. PROCEDURE ForIterator(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  2008. BEGIN
  2009. IF Trace THEN
  2010. S("ForIterator")
  2011. END;
  2012. StatementExpressionList(statements, outer);
  2013. IF Trace THEN
  2014. E("ForIterator")
  2015. END;
  2016. END ForIterator;
  2017. (**
  2018. for-statement:
  2019. 'for' '(' [for-initializer] ';' [for-condition] ';' [for-iterator] ')' embedded-statement
  2020. for-condition:
  2021. boolean-expression
  2022. **)
  2023. PROCEDURE ForStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  2024. VAR expression: SyntaxTree.Expression;
  2025. whileStatement: SyntaxTree.WhileStatement;
  2026. statementSequence: SyntaxTree.StatementSequence;
  2027. iterator: SyntaxTree.StatementSequence;
  2028. position: Position;
  2029. i: LONGINT;
  2030. b: BOOLEAN;
  2031. BEGIN
  2032. IF Trace THEN
  2033. S("ForStatement")
  2034. END;
  2035. Check(Scanner.For);
  2036. localIdentTable.OpenScope;
  2037. whileStatement := SyntaxTree.NewWhileStatement(symbol.position, outer);
  2038. (* CommentStatement(whileStatement); *)
  2039. Check(Scanner.LeftParenthesis);
  2040. IF ~Optional(Scanner.Semicolon) THEN
  2041. ForInitializer(statements, outer);
  2042. Check(Scanner.Semicolon);
  2043. END;
  2044. position := symbol.position;
  2045. IF ~Optional(Scanner.Semicolon) THEN
  2046. expression := Expression();
  2047. Check(Scanner.Semicolon);
  2048. ELSE
  2049. expression := SyntaxTree.NewBooleanValue(position, TRUE);
  2050. END;
  2051. IF ~Optional(Scanner.RightParenthesis) THEN
  2052. iterator := SyntaxTree.NewStatementSequence();
  2053. ForIterator(iterator, whileStatement);
  2054. Check(Scanner.RightParenthesis);
  2055. ELSE
  2056. iterator := NIL;
  2057. END;
  2058. whileStatement.SetCondition(expression);
  2059. statementSequence := SyntaxTree.NewStatementSequence();
  2060. b := EmbeddedStatement(statementSequence, whileStatement);
  2061. IF iterator # NIL THEN
  2062. FOR i := 0 TO iterator.Length() - 1 DO
  2063. statementSequence.AddStatement(iterator.GetStatement(i));
  2064. END;
  2065. END;
  2066. whileStatement.SetStatements(statementSequence);
  2067. statements.AddStatement(whileStatement);
  2068. localIdentTable.CloseScope;
  2069. IF Trace THEN
  2070. E("ForStatement")
  2071. END;
  2072. END ForStatement;
  2073. (**
  2074. return-statement:
  2075. 'return' [expression] ';'
  2076. **)
  2077. PROCEDURE ReturnStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  2078. VAR returnStatement: SyntaxTree.ReturnStatement;
  2079. expression: SyntaxTree.Expression;
  2080. BEGIN
  2081. IF Trace THEN
  2082. S("ReturnStatement")
  2083. END;
  2084. Check(Scanner.Return);
  2085. returnStatement := SyntaxTree.NewReturnStatement(symbol.position, outer);
  2086. (* CommentStatement(returnStatement); *)
  2087. IF ~Optional(Scanner.Semicolon) THEN
  2088. expression := Expression();
  2089. returnStatement.SetReturnValue(expression);
  2090. Check(Scanner.Semicolon);
  2091. END;
  2092. statements.AddStatement(returnStatement);
  2093. IF Trace THEN
  2094. E("ReturnStatement")
  2095. END;
  2096. END ReturnStatement;
  2097. (**
  2098. break-statement:
  2099. 'break' ';'
  2100. **)
  2101. PROCEDURE BreakStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement);
  2102. VAR statement: SyntaxTree.Statement;
  2103. BEGIN
  2104. IF Trace THEN
  2105. S("BreakStatement")
  2106. END;
  2107. Check(Scanner.Break);
  2108. statement := SyntaxTree.NewExitStatement(symbol.position, outer);
  2109. (* CommentStatement(statement); *)
  2110. statements.AddStatement(statement);
  2111. Check(Scanner.Semicolon);
  2112. IF Trace THEN
  2113. E("BreakStatement")
  2114. END;
  2115. END BreakStatement;
  2116. (**
  2117. embedded-statement:
  2118. block
  2119. empty-statement
  2120. expression-statement
  2121. selection-statement
  2122. iteration-statement
  2123. jump-statement
  2124. empty-statement:
  2125. ';'
  2126. selection-statement:
  2127. if-statement
  2128. switch-statement
  2129. select-statement
  2130. iteration-statement:
  2131. while-statement
  2132. do-statement
  2133. for-statement
  2134. jump-statement:
  2135. break-statement
  2136. return-statement
  2137. **)
  2138. PROCEDURE EmbeddedStatement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement): BOOLEAN;
  2139. VAR result: BOOLEAN;
  2140. BEGIN
  2141. IF Trace THEN
  2142. S("EmbeddedStatement")
  2143. END;
  2144. IF Optional(Scanner.Semicolon) THEN
  2145. result := FALSE;
  2146. ELSIF Peek(Scanner.LeftBrace) THEN
  2147. Block(statements, outer);
  2148. result := TRUE;
  2149. ELSIF Peek(Scanner.If) THEN
  2150. IfStatement(statements, outer);
  2151. result := TRUE;
  2152. ELSIF Peek(Scanner.Switch) THEN
  2153. SwitchStatement(statements, outer);
  2154. result := TRUE;
  2155. ELSIF Peek(Scanner.Select) THEN
  2156. SelectStatement(statements, outer);
  2157. result := TRUE;
  2158. ELSIF Peek(Scanner.While) THEN
  2159. WhileStatement(statements, outer);
  2160. result := TRUE;
  2161. ELSIF Peek(Scanner.Do) THEN
  2162. DoStatement(statements, outer);
  2163. result := TRUE;
  2164. ELSIF Peek(Scanner.For) THEN
  2165. ForStatement(statements, outer);
  2166. result := TRUE;
  2167. ELSIF Peek(Scanner.Break) THEN
  2168. BreakStatement(statements, outer);
  2169. result := TRUE;
  2170. ELSIF Peek(Scanner.Return) THEN
  2171. ReturnStatement(statements, outer);
  2172. result := TRUE;
  2173. ELSE
  2174. result := ExpressionStatement(statements, outer);
  2175. END;
  2176. IF Trace THEN
  2177. E("EmbeddedStatement")
  2178. END;
  2179. RETURN result;
  2180. END EmbeddedStatement;
  2181. (**
  2182. statement:
  2183. declaration-statement
  2184. embedded-statement
  2185. declaration-statement:
  2186. local-variable-declaration ';'
  2187. local-constant-declaration ';'
  2188. **)
  2189. PROCEDURE ExpressionOrDeclaration(
  2190. statements: SyntaxTree.StatementSequence;
  2191. outer: SyntaxTree.Statement;
  2192. VAR isDeclaration: BOOLEAN): BOOLEAN;
  2193. VAR result: BOOLEAN;
  2194. name0, name1: SyntaxTree.Identifier;
  2195. position0, position1, position2: Position;
  2196. leftBracket: BOOLEAN;
  2197. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
  2198. type: SyntaxTree.Type;
  2199. expression: SyntaxTree.Expression;
  2200. expressionList: SyntaxTree.ExpressionList;
  2201. BEGIN
  2202. name0 := Identifier(position0);
  2203. IF Optional(Scanner.Period) THEN
  2204. name1 := Identifier(position1);
  2205. ELSE
  2206. name1 := SyntaxTree.invalidIdentifier;
  2207. END;
  2208. isDeclaration := FALSE;
  2209. leftBracket := FALSE;
  2210. position2 := symbol.position;
  2211. IF Peek(Scanner.Identifier) THEN
  2212. isDeclaration := TRUE;
  2213. ELSIF Optional(Scanner.LeftBracket) THEN
  2214. leftBracket := TRUE;
  2215. IF Peek(Scanner.RightBracket) OR Peek(Scanner.Comma) THEN
  2216. isDeclaration := TRUE;
  2217. END;
  2218. END;
  2219. IF isDeclaration THEN
  2220. (* local-variable-declaration *)
  2221. IF name1 = SyntaxTree.invalidIdentifier THEN
  2222. name1 := name0;
  2223. name0 := SyntaxTree.invalidIdentifier;
  2224. END;
  2225. qualifiedIdentifier := SyntaxTree.NewQualifiedIdentifier(position0, name0, name1);
  2226. type := SyntaxTree.NewQualifiedType(
  2227. qualifiedIdentifier.position, currentScope, qualifiedIdentifier);
  2228. IF leftBracket THEN
  2229. type := RankSpecifier(type);
  2230. Check(Scanner.RightBracket);
  2231. END;
  2232. WHILE Optional(Scanner.LeftBracket) DO
  2233. type := RankSpecifier(type);
  2234. Check(Scanner.RightBracket);
  2235. END;
  2236. LocalVariableDeclaration(statements, outer, type);
  2237. ELSE
  2238. (* expression-statement *)
  2239. name0 := localIdentTable.Find(name0);
  2240. expression := SyntaxTree.NewIdentifierDesignator(position0, name0);
  2241. IF name1 # SyntaxTree.invalidIdentifier THEN
  2242. expression := SyntaxTree.NewSelectorDesignator(position1, expression(SyntaxTree.Designator), name1);
  2243. END;
  2244. IF leftBracket THEN
  2245. expressionList := SyntaxTree.NewExpressionList();
  2246. ExpressionList(expressionList);
  2247. Check(Scanner.RightBracket);
  2248. expression := SyntaxTree.NewBracketDesignator(position2, expression(SyntaxTree.Designator), expressionList);
  2249. END;
  2250. expression := Accessors(expression, FALSE);
  2251. result := StatementExpression(statements, outer, expression);
  2252. END;
  2253. RETURN result;
  2254. END ExpressionOrDeclaration;
  2255. PROCEDURE Statement(statements: SyntaxTree.StatementSequence; outer: SyntaxTree.Statement): BOOLEAN;
  2256. VAR result: BOOLEAN;
  2257. isDeclaration: BOOLEAN;
  2258. BEGIN
  2259. IF Trace THEN
  2260. S("Statement")
  2261. END;
  2262. IF Peek(Scanner.Const) THEN
  2263. LocalConstantDeclaration(statements, outer);
  2264. Check(Scanner.Semicolon);
  2265. result := TRUE;
  2266. ELSIF Peek(Scanner.Bool) OR Peek(Scanner.Sbyte) OR
  2267. Peek(Scanner.Short) OR Peek(Scanner.Int) OR
  2268. Peek(Scanner.Long) OR Peek(Scanner.Char) OR
  2269. Peek(Scanner.Float) OR Peek(Scanner.Double) OR
  2270. Peek(Scanner.Object) OR Peek(Scanner.String) THEN
  2271. LocalVariableDeclaration(statements, outer, NIL);
  2272. Check(Scanner.Semicolon);
  2273. result := TRUE;
  2274. ELSIF Peek(Scanner.Identifier) THEN
  2275. (* either local-variable-declaration or statement expression *)
  2276. result := ExpressionOrDeclaration(statements, outer, isDeclaration);
  2277. Check(Scanner.Semicolon);
  2278. ELSE
  2279. result := EmbeddedStatement(statements, outer);
  2280. END;
  2281. IF Trace THEN
  2282. E("Statement")
  2283. END;
  2284. RETURN result;
  2285. END Statement;
  2286. (**
  2287. statement-list:
  2288. statement
  2289. statement-list statement
  2290. **)
  2291. PROCEDURE StatementList(outer: SyntaxTree.Statement): SyntaxTree.StatementSequence;
  2292. VAR statements: SyntaxTree.StatementSequence;
  2293. b: BOOLEAN;
  2294. BEGIN
  2295. IF Trace THEN
  2296. S("StatementList")
  2297. END;
  2298. statements := SyntaxTree.NewStatementSequence();
  2299. REPEAT
  2300. b := Statement(statements, outer);
  2301. UNTIL Peek(Scanner.RightBrace) OR Peek(Scanner.Case) OR Peek(Scanner.Default) ;
  2302. IF Trace THEN
  2303. E("StatementList")
  2304. END;
  2305. RETURN statements;
  2306. END StatementList;
  2307. (**
  2308. block:
  2309. '{' [statement-list] '}'
  2310. **)
  2311. PROCEDURE Body(scope: SyntaxTree.ProcedureScope): SyntaxTree.Body;
  2312. VAR body: SyntaxTree.Body;
  2313. previousScope: SyntaxTree.Scope;
  2314. BEGIN
  2315. IF Trace THEN
  2316. S("Body")
  2317. END;
  2318. previousScope := currentScope;
  2319. currentScope := scope;
  2320. Check(Scanner.LeftBrace);
  2321. body := SyntaxTree.NewBody(symbol.position, scope);
  2322. IF ~Optional(Scanner.RightBrace) THEN
  2323. body.SetStatementSequence(StatementList(body));
  2324. Check(Scanner.RightBrace);
  2325. END;
  2326. currentScope := previousScope;
  2327. IF Trace THEN
  2328. E("Body")
  2329. END;
  2330. RETURN body;
  2331. END Body;
  2332. (**
  2333. type:
  2334. value-type
  2335. reference-type
  2336. port-type
  2337. value-type:
  2338. struct-type
  2339. struct-type:
  2340. type-name
  2341. simple-type
  2342. simple-type:
  2343. numeric-type
  2344. 'bool'
  2345. numeric-type:
  2346. integral-type
  2347. floating-point-type
  2348. integral-type:
  2349. 'sbyte'
  2350. 'short'
  2351. 'int'
  2352. 'long'
  2353. 'char'
  2354. floating-point-type:
  2355. 'float'
  2356. 'double'
  2357. reference-type:
  2358. class-type
  2359. array-type
  2360. delegate-type
  2361. class-type:
  2362. type-name
  2363. 'object'
  2364. 'string'
  2365. array-type:
  2366. non-array-type rank-specifiers
  2367. non-array-type:
  2368. value-type
  2369. class-type
  2370. delegate-type
  2371. rank-specifiers:
  2372. rank-specifier
  2373. rank-specifiers rank-specifier
  2374. rank-specifier:
  2375. '[' [dim-separators] ']'
  2376. dim-separators:
  2377. ','
  2378. dim-separators ','
  2379. delegate-type:
  2380. type-name
  2381. **)
  2382. PROCEDURE RankSpecifier(type: SyntaxTree.Type): SyntaxTree.Type;
  2383. VAR position: Position;
  2384. arrayType: SyntaxTree.ArrayType;
  2385. pointerType: SyntaxTree.PointerType;
  2386. BEGIN
  2387. IF Trace THEN
  2388. S("RankSpecifier")
  2389. END;
  2390. position := symbol.position;
  2391. REPEAT
  2392. arrayType := SyntaxTree.NewArrayType(position, currentScope, SyntaxTree.Open);
  2393. arrayType.SetArrayBase(type);
  2394. type := arrayType;
  2395. UNTIL ~Optional(Scanner.Comma);
  2396. pointerType := SyntaxTree.NewPointerType(position, currentScope);
  2397. pointerType.SetPointerBase(type);
  2398. type := pointerType;
  2399. IF Trace THEN
  2400. E("RankSpecifier")
  2401. END;
  2402. RETURN type;
  2403. END RankSpecifier;
  2404. PROCEDURE NonArrayType(): SyntaxTree.Type;
  2405. VAR type: SyntaxTree.Type;
  2406. position: Position;
  2407. name: SyntaxTree.Identifier;
  2408. direction: LONGINT;
  2409. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
  2410. BEGIN
  2411. IF Trace THEN
  2412. S("NonArrayType")
  2413. END;
  2414. position := symbol.position;
  2415. name := SyntaxTree.invalidIdentifier;
  2416. direction := -1;
  2417. IF Optional(Scanner.Bool) THEN
  2418. name := lynxBool;
  2419. ELSIF Optional(Scanner.Sbyte) THEN
  2420. name := lynxSbyte;
  2421. ELSIF Optional(Scanner.Short) THEN
  2422. name := lynxShort;
  2423. ELSIF Optional(Scanner.Int) THEN
  2424. name := lynxInt;
  2425. ELSIF Optional(Scanner.Long) THEN
  2426. name := lynxLong;
  2427. ELSIF Optional(Scanner.Char) THEN
  2428. name := lynxChar;
  2429. ELSIF Optional(Scanner.Float) THEN
  2430. name := lynxFloat;
  2431. ELSIF Optional(Scanner.Double) THEN
  2432. name := lynxDouble;
  2433. ELSIF Optional(Scanner.Object) THEN
  2434. name := lynxObject;
  2435. ELSIF Optional(Scanner.String) THEN
  2436. name := lynxString;
  2437. ELSIF Optional(Scanner.In) THEN
  2438. direction := SyntaxTree.InPort;
  2439. ELSIF Optional(Scanner.Out) THEN
  2440. direction := SyntaxTree.OutPort;
  2441. END;
  2442. IF direction >= 0 THEN
  2443. type := SyntaxTree.NewPortType(position, direction, NIL, currentScope);
  2444. ELSE
  2445. IF name # SyntaxTree.invalidIdentifier THEN
  2446. qualifiedIdentifier :=
  2447. SyntaxTree.NewQualifiedIdentifier(
  2448. position, SyntaxTree.invalidIdentifier, name);
  2449. ELSE
  2450. qualifiedIdentifier := QualifiedIdentifier();
  2451. END;
  2452. type := SyntaxTree.NewQualifiedType(
  2453. qualifiedIdentifier.position, currentScope, qualifiedIdentifier);
  2454. END;
  2455. IF Trace THEN
  2456. E("NonArrayType")
  2457. END;
  2458. RETURN type;
  2459. END NonArrayType;
  2460. PROCEDURE Type(): SyntaxTree.Type;
  2461. VAR type: SyntaxTree.Type;
  2462. BEGIN
  2463. IF Trace THEN
  2464. S("Type")
  2465. END;
  2466. type := NonArrayType();
  2467. WHILE Optional(Scanner.LeftBracket) DO
  2468. type := RankSpecifier(type);
  2469. Check(Scanner.RightBracket);
  2470. END;
  2471. IF Trace THEN
  2472. E("Type")
  2473. END;
  2474. RETURN type;
  2475. END Type;
  2476. (**
  2477. attributes:
  2478. '[' attribute-list ']'
  2479. attribute-list:
  2480. attribute
  2481. attribute-list ',' attribute
  2482. attribute:
  2483. attribute-name [attribute-argument]
  2484. attribute-name:
  2485. identifier
  2486. attribute-argument:
  2487. '(' attribute-argument-expression ')'
  2488. attribute-argument-expression:
  2489. expression
  2490. **)
  2491. PROCEDURE AppendModifier(VAR list: SyntaxTree.Modifier; modifier: SyntaxTree.Modifier);
  2492. VAR this, next: SyntaxTree.Modifier;
  2493. BEGIN
  2494. IF list = NIL THEN
  2495. list := modifier
  2496. ELSE
  2497. this := list;
  2498. next := list.nextModifier;
  2499. WHILE next # NIL DO
  2500. this := next;
  2501. next := this.nextModifier;
  2502. END;
  2503. this.SetNext(modifier);
  2504. END;
  2505. END AppendModifier;
  2506. PROCEDURE Attributes(): SyntaxTree.Modifier;
  2507. VAR identifier: SyntaxTree.Identifier;
  2508. modifier, list: SyntaxTree.Modifier;
  2509. position: Position;
  2510. expression: SyntaxTree.Expression;
  2511. BEGIN
  2512. IF Trace THEN
  2513. S("Attributes")
  2514. END;
  2515. (* left bracket already consumed *)
  2516. list := NIL;
  2517. REPEAT
  2518. position := symbol.position;
  2519. identifier := Identifier(position);
  2520. IF Optional(Scanner.LeftParenthesis) THEN
  2521. expression := Expression();
  2522. Check(Scanner.RightParenthesis);
  2523. ELSE
  2524. expression := NIL;
  2525. END;
  2526. modifier := SyntaxTree.NewModifier(position, identifier, expression);
  2527. AppendModifier(list, modifier);
  2528. UNTIL ~Optional(Scanner.Comma);
  2529. Check(Scanner.RightBracket);
  2530. IF Trace THEN
  2531. E("Attributes")
  2532. END;
  2533. RETURN list;
  2534. END Attributes;
  2535. (**
  2536. constant-modifiers:
  2537. constant-modifier
  2538. constant-modifiers constant-modifier
  2539. constant-modifier:
  2540. 'public'
  2541. field-modifiers:
  2542. field-modifier
  2543. field-modifiers field-modifier
  2544. field-modifier:
  2545. 'public'
  2546. 'internal'
  2547. method-modifiers:
  2548. method-modifier
  2549. method-modifiers method-modifier
  2550. method-modifier:
  2551. 'public'
  2552. constructor-modifiers:
  2553. constructor-modifier
  2554. constructor-modifiers constructor-modifier
  2555. constructor-modifier:
  2556. public
  2557. class-modifiers:
  2558. class-modifier
  2559. class-modifiers class-modifier
  2560. class-modifier:
  2561. 'public'
  2562. struct-modifiers:
  2563. struct-modifier
  2564. struct-modifiers struct-modifier
  2565. struct-modifier:
  2566. 'public'
  2567. delegate-modifiers:
  2568. delegate-modifier
  2569. delegate-modifiers delegate-modifier
  2570. delegate-modifier:
  2571. 'public'
  2572. **)
  2573. PROCEDURE Modifiers(VAR modifiers: SET);
  2574. BEGIN
  2575. modifiers := {};
  2576. LOOP
  2577. IF Optional(Scanner.Public) THEN
  2578. INCL(modifiers, Public);
  2579. ELSIF Optional(Scanner.Internal) THEN
  2580. INCL(modifiers, Internal);
  2581. ELSE
  2582. EXIT;
  2583. END;
  2584. END;
  2585. END Modifiers;
  2586. PROCEDURE IdentifierAccess(modifiers: SET; allowedReadOnly: BOOLEAN): SET;
  2587. VAR access: SET;
  2588. BEGIN
  2589. IF modifiers * {Public, Internal} = {Public, Internal} THEN
  2590. Error(symbol.position, Basic.InvalidCode, "conflicting modifiers");
  2591. END;
  2592. IF Public IN modifiers THEN
  2593. access := SyntaxTree.Public + SyntaxTree.Protected + SyntaxTree.Internal;
  2594. ELSIF Internal IN modifiers THEN
  2595. IF ~allowedReadOnly THEN
  2596. Error(symbol.position, Basic.InvalidCode, "may not be defined internal")
  2597. ELSE
  2598. access := SyntaxTree.ReadOnly + {SyntaxTree.InternalWrite};
  2599. END;
  2600. ELSE
  2601. access := SyntaxTree.Internal;
  2602. END;
  2603. RETURN access;
  2604. END IdentifierAccess;
  2605. (**
  2606. constant-declaration:
  2607. [constant-modifiers] 'const' type constant-declarators ';'
  2608. constant-declarators:
  2609. constant-declarator
  2610. constant-declarators ',' constant-declarator
  2611. constant-declarator:
  2612. identifier '=' constant-expression
  2613. **)
  2614. PROCEDURE ConstantDeclarator(
  2615. parentScope: SyntaxTree.Scope;
  2616. modifiers: SET;
  2617. type: SyntaxTree.Type);
  2618. VAR name: SyntaxTree.Identifier;
  2619. position: Position;
  2620. constant: SyntaxTree.Constant;
  2621. expression: SyntaxTree.Expression;
  2622. access: SET;
  2623. BEGIN
  2624. IF Trace THEN
  2625. S("ConstantDeclarator")
  2626. END;
  2627. name := Identifier(position);
  2628. name := localIdentTable.Enter(name);
  2629. access := IdentifierAccess(modifiers, FALSE);
  2630. constant := SyntaxTree.NewConstant(position, name);
  2631. CommentSymbol(constant);
  2632. constant.SetAccess(access);
  2633. (* ACHTUNG: Make sure that Fox semantic checker will respect a type set at this stage: *)
  2634. constant.SetType(type);
  2635. Check(Scanner.Equal);
  2636. expression := Expression();
  2637. constant.SetValue(expression);
  2638. parentScope.AddConstant(constant);
  2639. IF Trace THEN
  2640. E("ConstantDeclarator")
  2641. END;
  2642. END ConstantDeclarator;
  2643. PROCEDURE ConstantDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
  2644. VAR type: SyntaxTree.Type;
  2645. BEGIN
  2646. IF Trace THEN
  2647. S("ConstantDeclaration")
  2648. END;
  2649. type := Type();
  2650. REPEAT
  2651. ConstantDeclarator(parentScope, modifiers, type);
  2652. UNTIL ~Optional(Scanner.Comma);
  2653. Check(Scanner.Semicolon);
  2654. IF Trace THEN
  2655. E("ConstantDeclaration")
  2656. END;
  2657. END ConstantDeclaration;
  2658. (**
  2659. field-declaration:
  2660. [field-modifiers] type variable-declarators ';'
  2661. field-modifiers:
  2662. field-modifier
  2663. field-modifiers field-modifier
  2664. variable-declarators:
  2665. variable-declarator
  2666. variable-declarators ',' variable-declarator
  2667. variable-declarator:
  2668. identifier
  2669. identifier '=' variable-initializer
  2670. variable-initializer:
  2671. expression
  2672. // array-initializer
  2673. **)
  2674. PROCEDURE VariableDeclarator(
  2675. parentScope: SyntaxTree.Scope;
  2676. modifiers: SET;
  2677. type: SyntaxTree.Type;
  2678. name: SyntaxTree.Identifier;
  2679. position: Position);
  2680. VAR variable: SyntaxTree.Variable;
  2681. expression: SyntaxTree.Expression;
  2682. designator: SyntaxTree.Designator;
  2683. statement: SyntaxTree.Statement;
  2684. start: Position;
  2685. access: SET;
  2686. BEGIN
  2687. IF Trace THEN
  2688. S("VariableDeclarator")
  2689. END;
  2690. IF name = SyntaxTree.invalidIdentifier THEN
  2691. name := Identifier(position);
  2692. END;
  2693. name := localIdentTable.Enter(name);
  2694. access := IdentifierAccess(modifiers, TRUE);
  2695. variable := SyntaxTree.NewVariable(position, name);
  2696. CommentSymbol(variable);
  2697. variable.SetAccess(access);
  2698. variable.SetType(type);
  2699. parentScope.AddVariable(variable);
  2700. start := symbol.position;
  2701. (* 'initOuter' is set to NIL in contexts where initialization is not yet implemented *)
  2702. IF (initOuter # NIL) & Optional(Scanner.Equal) THEN
  2703. (* ACHTUNG: array-initializer form is not supported *)
  2704. designator := SyntaxTree.NewIdentifierDesignator(position, name);
  2705. expression := Expression();
  2706. statement := SyntaxTree.NewAssignment(start, designator, expression, initOuter);
  2707. initStatements.AddStatement(statement);
  2708. END;
  2709. IF Trace THEN
  2710. E("VariableDeclarator")
  2711. END;
  2712. END VariableDeclarator;
  2713. PROCEDURE FieldDeclaration(
  2714. parentScope: SyntaxTree.Scope;
  2715. modifiers: SET;
  2716. type: SyntaxTree.Type;
  2717. name: SyntaxTree.Identifier;
  2718. position: Position);
  2719. BEGIN
  2720. IF Trace THEN
  2721. S("FieldDeclaration")
  2722. END;
  2723. REPEAT
  2724. VariableDeclarator(parentScope, modifiers, type, name, position);
  2725. name := SyntaxTree.invalidIdentifier;
  2726. position := invalidPosition;
  2727. UNTIL ~Optional(Scanner.Comma);
  2728. Check(Scanner.Semicolon);
  2729. IF Trace THEN
  2730. E("FieldDeclaration")
  2731. END;
  2732. END FieldDeclaration;
  2733. (**
  2734. formal-parameter-list:
  2735. fixed-parameters
  2736. fixed-parameters:
  2737. fixed-parameter
  2738. fixed-parameters ',' fixed-parameter
  2739. fixed-parameter:
  2740. [parameter-modifier] type identifier
  2741. parameter-modifier:
  2742. 'ref'
  2743. **)
  2744. PROCEDURE FixedParameter(procedureType: SyntaxTree.ProcedureType; parentScope: SyntaxTree.Scope);
  2745. VAR type: SyntaxTree.Type;
  2746. name: SyntaxTree.Identifier;
  2747. parameter: SyntaxTree.Parameter;
  2748. kind: LONGINT; position: Position;
  2749. BEGIN
  2750. IF Trace THEN
  2751. S("FixedParameter")
  2752. END;
  2753. IF Optional(Scanner.Ref) THEN
  2754. kind := SyntaxTree.VarParameter;
  2755. ELSE
  2756. kind := SyntaxTree.ValueParameter;
  2757. END;
  2758. type := Type();
  2759. name := Identifier(position);
  2760. parameter := SyntaxTree.NewParameter(position, procedureType, name, kind);
  2761. procedureType.AddParameter(parameter);
  2762. parameter.SetType(type);
  2763. IF Trace THEN
  2764. E("FixedParameter")
  2765. END;
  2766. END FixedParameter;
  2767. PROCEDURE FormalParameterList(
  2768. procedureType: SyntaxTree.ProcedureType;
  2769. parentScope: SyntaxTree.Scope;
  2770. returnType: SyntaxTree.Type);
  2771. BEGIN
  2772. IF Trace THEN
  2773. S("FormalParameterList")
  2774. END;
  2775. Check(Scanner.LeftParenthesis);
  2776. IF ~Optional(Scanner.RightParenthesis) THEN
  2777. REPEAT
  2778. FixedParameter(procedureType, parentScope);
  2779. UNTIL ~Optional(Scanner.Comma);
  2780. Check(Scanner.RightParenthesis);
  2781. END;
  2782. IF returnType # NIL THEN
  2783. procedureType.SetReturnType(returnType);
  2784. END;
  2785. IF Trace THEN
  2786. E("FormalParameterList")
  2787. END;
  2788. END FormalParameterList;
  2789. (**
  2790. constructor-initializer:
  2791. ':' 'base' '(' [argument-list] ')'
  2792. **)
  2793. PROCEDURE ConstructorInitializer(scope: SyntaxTree.ProcedureScope);
  2794. BEGIN
  2795. IF Trace THEN
  2796. S("ConstructorInitializer")
  2797. END;
  2798. (* TODO *)
  2799. IF Trace THEN
  2800. E("ConstructorInitializer")
  2801. END;
  2802. END ConstructorInitializer;
  2803. (**
  2804. method-declaration:
  2805. method-header method-body
  2806. method-header:
  2807. [method-modifiers] return-type member-name '(' [formal-parameter-list] ')'
  2808. return-type:
  2809. type
  2810. 'void'
  2811. member-name:
  2812. identifier
  2813. method-body:
  2814. block
  2815. constructor-declaration:
  2816. [constructor-modifiers] constructor-declarator constructor-body
  2817. constructor-declarator:
  2818. identifier ( [formal-parameter-list] ) [constructor-initializer]
  2819. constructor-body:
  2820. block
  2821. **)
  2822. PROCEDURE ProcedureDeclaration(
  2823. parentScope: SyntaxTree.Scope;
  2824. modifiers: SET;
  2825. type: SyntaxTree.Type;
  2826. name: SyntaxTree.Identifier;
  2827. position: Position;
  2828. isConstructor: BOOLEAN);
  2829. VAR procedure: SyntaxTree.Procedure;
  2830. procedureType: SyntaxTree.ProcedureType;
  2831. procedureScope: SyntaxTree.ProcedureScope;
  2832. previousScope: SyntaxTree.Scope;
  2833. access: SET;
  2834. body: SyntaxTree.Body;
  2835. BEGIN
  2836. procedureType := SyntaxTree.NewProcedureType(position, parentScope);
  2837. access := IdentifierAccess(modifiers, FALSE);
  2838. procedureScope := SyntaxTree.NewProcedureScope(parentScope);
  2839. procedure := SyntaxTree.NewProcedure(position, name, procedureScope);
  2840. procedure.SetConstructor(isConstructor);
  2841. CommentSymbol(procedure);
  2842. procedure.SetAccess(access);
  2843. procedure.SetType(procedureType);
  2844. FormalParameterList(procedureType, procedureScope, type);
  2845. IF isConstructor & Optional(Scanner.Colon) THEN
  2846. (* TODO: Connect initializer to the body *)
  2847. ConstructorInitializer(procedureScope);
  2848. END;
  2849. previousScope := currentScope;
  2850. currentScope := procedureScope;
  2851. body := Body(procedureScope);
  2852. currentScope := previousScope;
  2853. procedureScope.SetBody(body);
  2854. parentScope.AddProcedure(procedure);
  2855. END ProcedureDeclaration;
  2856. PROCEDURE MethodDeclaration(
  2857. parentScope: SyntaxTree.Scope;
  2858. modifiers: SET;
  2859. type: SyntaxTree.Type;
  2860. name: SyntaxTree.Identifier;
  2861. position: Position);
  2862. BEGIN
  2863. IF Trace THEN
  2864. S("MethodDeclaration")
  2865. END;
  2866. localIdentTable.Reset;
  2867. IF (name = identMain) &
  2868. (parentScope IS SyntaxTree.CellScope) &
  2869. ~parentScope(SyntaxTree.CellScope).ownerCell.isCellNet THEN
  2870. (* bodies of cells are represented as main() functions *)
  2871. BodyDeclaration(parentScope, modifiers, type, name, position);
  2872. ELSE
  2873. ProcedureDeclaration(parentScope, modifiers, type, name, position, FALSE);
  2874. END;
  2875. IF Trace THEN
  2876. E("MethodDeclaration")
  2877. END;
  2878. END MethodDeclaration;
  2879. PROCEDURE ConstructorDeclaration(
  2880. parentScope: SyntaxTree.Scope;
  2881. modifiers: SET;
  2882. name: SyntaxTree.Identifier;
  2883. position: Position);
  2884. BEGIN
  2885. IF Trace THEN
  2886. S("ConstructorDeclaration")
  2887. END;
  2888. localIdentTable.Reset;
  2889. IF (parentScope IS SyntaxTree.ModuleScope) OR
  2890. ((parentScope IS SyntaxTree.CellScope) &
  2891. parentScope(SyntaxTree.CellScope).ownerCell.isCellNet) THEN
  2892. (* bodies of modules and cellnets are represented as constructors *)
  2893. BodyDeclaration(parentScope, modifiers, NIL, name, position);
  2894. ELSE
  2895. ProcedureDeclaration(parentScope, modifiers, NIL, name, position, TRUE);
  2896. END;
  2897. IF Trace THEN
  2898. E("ConstructorDeclaration")
  2899. END;
  2900. END ConstructorDeclaration;
  2901. PROCEDURE BodyDeclaration(
  2902. parentScope: SyntaxTree.Scope;
  2903. modifiers: SET;
  2904. type: SyntaxTree.Type;
  2905. name: SyntaxTree.Identifier;
  2906. position: Position);
  2907. VAR procedureScope: SyntaxTree.ProcedureScope;
  2908. procedureType: SyntaxTree.ProcedureType;
  2909. procedure: SyntaxTree.Procedure;
  2910. BEGIN
  2911. procedureScope := SyntaxTree.NewProcedureScope(parentScope);
  2912. IF parentScope IS SyntaxTree.ModuleScope THEN
  2913. procedure := SyntaxTree.NewProcedure(position, Global.ModuleBodyName, procedureScope);
  2914. procedure.SetAccess(SyntaxTree.Hidden);
  2915. ELSE
  2916. procedure := SyntaxTree.NewProcedure(position, Global.RecordBodyName, procedureScope);
  2917. procedure.SetAccess(SyntaxTree.Public+SyntaxTree.Protected+SyntaxTree.Internal);
  2918. END;
  2919. parentScope.AddProcedure(procedure);
  2920. procedureType := SyntaxTree.NewProcedureType(position, parentScope);
  2921. FormalParameterList(procedureType, procedureScope, type);
  2922. IF procedureType.numberParameters # 0 THEN
  2923. Error(position, Basic.InvalidCode, "constructor/main has parameters");
  2924. ELSIF procedureType.returnType # NIL THEN
  2925. Error(position, Basic.InvalidCode, "constructor/main returns value");
  2926. END;
  2927. procedure.SetType(procedureType);
  2928. procedure.SetBodyProcedure(TRUE);
  2929. procedureScope.SetBody(Body(procedureScope));
  2930. IF parentScope IS SyntaxTree.ModuleScope THEN
  2931. parentScope(SyntaxTree.ModuleScope).SetBodyProcedure(procedure);
  2932. ELSE
  2933. parentScope(SyntaxTree.CellScope).SetBodyProcedure(procedure);
  2934. END;
  2935. END BodyDeclaration;
  2936. (**
  2937. class-declaration:
  2938. [class-modifiers] 'class' identifier [class-base] class-body [';']
  2939. class-base:
  2940. ':' class-type
  2941. class-body:
  2942. '{' [class-member-declarations] '}'
  2943. class-member-declarations:
  2944. class-member-declaration
  2945. class-member-declarations class-member-declaration
  2946. class-member-declaration:
  2947. constant-declaration
  2948. field-declaration
  2949. method-declaration
  2950. constructor-declaration
  2951. type-declaration
  2952. type-declaration:
  2953. class-declaration
  2954. struct-declaration
  2955. delegate-declaration
  2956. cell-declaration
  2957. cellnet-declaration
  2958. **)
  2959. PROCEDURE MemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  2960. VAR attributes: SyntaxTree.Modifier;
  2961. modifiers: SET;
  2962. type: SyntaxTree.Type;
  2963. name: SyntaxTree.Identifier;
  2964. position: Position;
  2965. BEGIN
  2966. IF Optional(Scanner.LeftBracket) THEN
  2967. attributes := Attributes();
  2968. ELSE
  2969. attributes := NIL;
  2970. END;
  2971. Modifiers(modifiers);
  2972. IF Optional(Scanner.Const) THEN
  2973. ConstantDeclaration(parentScope, modifiers);
  2974. ELSIF Optional(Scanner.Class) THEN
  2975. ClassDeclaration(parentScope, modifiers);
  2976. ELSIF Optional(Scanner.Struct) THEN
  2977. StructDeclaration(parentScope, modifiers);
  2978. ELSIF Optional(Scanner.Delegate) THEN
  2979. DelegateDeclaration(parentScope, modifiers);
  2980. ELSIF Optional(Scanner.Cell) THEN
  2981. CellDeclaration(parentScope, modifiers, attributes, FALSE);
  2982. ELSIF Optional(Scanner.Cellnet) THEN
  2983. CellDeclaration(parentScope, modifiers, attributes, TRUE);
  2984. ELSIF Peek(Scanner.Identifier) & (symbol.identifier = parentName) THEN
  2985. name := Identifier(position);
  2986. ConstructorDeclaration(parentScope, modifiers, name, position);
  2987. ELSIF Optional(Scanner.Void) THEN
  2988. name := Identifier(position);
  2989. MethodDeclaration(parentScope, modifiers, NIL, name, position);
  2990. ELSE
  2991. type := Type();
  2992. name := Identifier(position);
  2993. IF Peek(Scanner.LeftParenthesis) THEN
  2994. MethodDeclaration(parentScope, modifiers, type, name, position);
  2995. ELSE
  2996. FieldDeclaration(parentScope, modifiers, type, name, position);
  2997. END;
  2998. END;
  2999. END MemberDeclaration;
  3000. PROCEDURE ClassMemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3001. BEGIN
  3002. IF Trace THEN
  3003. S("ClassMemberDeclaration")
  3004. END;
  3005. MemberDeclaration(parentScope, parentName);
  3006. IF Trace THEN
  3007. E("ClassMemberDeclaration")
  3008. END;
  3009. END ClassMemberDeclaration;
  3010. PROCEDURE ClassMemberDeclarations(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3011. VAR previousScope: SyntaxTree.Scope;
  3012. BEGIN
  3013. IF Trace THEN
  3014. S("ClassMemberDeclarations")
  3015. END;
  3016. previousScope := currentScope;
  3017. currentScope := parentScope;
  3018. WHILE ~Peek(Scanner.RightBrace) DO
  3019. ClassMemberDeclaration(parentScope, parentName);
  3020. END;
  3021. currentScope := previousScope;
  3022. IF Trace THEN
  3023. E("ClassMemberDeclarations")
  3024. END;
  3025. END ClassMemberDeclarations;
  3026. PROCEDURE ClassDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
  3027. VAR name: SyntaxTree.Identifier;
  3028. position: Position;
  3029. typeDeclaration: SyntaxTree.TypeDeclaration;
  3030. access: SET;
  3031. objectType: SyntaxTree.RecordType;
  3032. pointerType: SyntaxTree.PointerType;
  3033. recordScope: SyntaxTree.RecordScope;
  3034. qualifiedIdentifier: SyntaxTree.QualifiedIdentifier;
  3035. baseType: SyntaxTree.Type;
  3036. previousStatements: SyntaxTree.StatementSequence;
  3037. previousOuter: SyntaxTree.Statement;
  3038. b: BOOLEAN;
  3039. BEGIN
  3040. IF Trace THEN
  3041. S("ClassDeclaration")
  3042. END;
  3043. previousStatements := initStatements;
  3044. previousOuter := initOuter;
  3045. (* TODO: Implement initialization of fields *)
  3046. initStatements := NIL;
  3047. initOuter := NIL;
  3048. EnterInit;
  3049. (* symbol 'class' already consumed *)
  3050. name := Identifier(position);
  3051. access := IdentifierAccess(modifiers, FALSE);
  3052. typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
  3053. CommentSymbol(typeDeclaration);
  3054. recordScope := SyntaxTree.NewRecordScope(parentScope);
  3055. pointerType := SyntaxTree.NewPointerType(position, parentScope);
  3056. objectType := SyntaxTree.NewRecordType(position, parentScope, recordScope);
  3057. objectType.IsObject(TRUE);
  3058. objectType.SetPointerType(pointerType);
  3059. pointerType.SetPointerBase(objectType);
  3060. IF Optional(Scanner.Colon) THEN
  3061. qualifiedIdentifier := QualifiedIdentifier();
  3062. baseType := SyntaxTree.NewQualifiedType(
  3063. qualifiedIdentifier.position, parentScope, qualifiedIdentifier);
  3064. objectType.SetBaseType(baseType);
  3065. END;
  3066. Check(Scanner.LeftBrace);
  3067. ClassMemberDeclarations(recordScope, name);
  3068. Check(Scanner.RightBrace);
  3069. b := Optional(Scanner.Semicolon);
  3070. pointerType.SetTypeDeclaration(typeDeclaration);
  3071. typeDeclaration.SetDeclaredType(pointerType);
  3072. typeDeclaration.SetAccess(access);
  3073. parentScope.AddTypeDeclaration(typeDeclaration);
  3074. initStatements := previousStatements;
  3075. initOuter := previousOuter;
  3076. IF Trace THEN
  3077. E("ClassDeclaration")
  3078. END;
  3079. END ClassDeclaration;
  3080. (**
  3081. struct-declaration:
  3082. [struct-modifiers] 'struct' identifier struct-body [';']
  3083. struct-body:
  3084. '{' [struct-member-declarations] '}'
  3085. struct-member-declarations:
  3086. struct-member-declaration
  3087. struct-member-declarations struct-member-declaration
  3088. struct-member-declaration:
  3089. constant-declaration
  3090. field-declaration
  3091. method-declaration
  3092. constructor-declaration
  3093. type-declaration
  3094. **)
  3095. PROCEDURE StructMemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3096. BEGIN
  3097. IF Trace THEN
  3098. S("StructMemberDeclaration")
  3099. END;
  3100. MemberDeclaration(parentScope, parentName);
  3101. IF Trace THEN
  3102. E("StructMemberDeclaration")
  3103. END;
  3104. END StructMemberDeclaration;
  3105. PROCEDURE StructMemberDeclarations(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3106. VAR previousScope: SyntaxTree.Scope;
  3107. BEGIN
  3108. IF Trace THEN
  3109. S("StructMemberDeclarations")
  3110. END;
  3111. previousScope := currentScope;
  3112. currentScope := parentScope;
  3113. WHILE ~Peek(Scanner.RightBrace) DO
  3114. StructMemberDeclaration(parentScope, parentName);
  3115. END;
  3116. currentScope := previousScope;
  3117. IF Trace THEN
  3118. E("StructMemberDeclarations")
  3119. END;
  3120. END StructMemberDeclarations;
  3121. PROCEDURE StructDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
  3122. VAR name: SyntaxTree.Identifier;
  3123. position: Position;
  3124. typeDeclaration: SyntaxTree.TypeDeclaration;
  3125. access: SET;
  3126. recordType: SyntaxTree.RecordType;
  3127. recordScope: SyntaxTree.RecordScope;
  3128. previousStatements: SyntaxTree.StatementSequence;
  3129. previousOuter: SyntaxTree.Statement;
  3130. b: BOOLEAN;
  3131. BEGIN
  3132. IF Trace THEN
  3133. S("StructDeclaration")
  3134. END;
  3135. previousStatements := initStatements;
  3136. previousOuter := initOuter;
  3137. (* TODO: Implement initialization of fields *)
  3138. initStatements := NIL;
  3139. initOuter := NIL;
  3140. (* symbol 'struct' already consumed *)
  3141. name := Identifier(position);
  3142. access := IdentifierAccess(modifiers, FALSE);
  3143. typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
  3144. CommentSymbol(typeDeclaration);
  3145. recordScope := SyntaxTree.NewRecordScope(parentScope);
  3146. recordType := SyntaxTree.NewRecordType(position, parentScope, recordScope);
  3147. Check(Scanner.LeftBrace);
  3148. StructMemberDeclarations(recordScope, name);
  3149. Check(Scanner.RightBrace);
  3150. b := Optional(Scanner.Semicolon);
  3151. recordType.SetTypeDeclaration(typeDeclaration);
  3152. typeDeclaration.SetDeclaredType(recordType);
  3153. typeDeclaration.SetAccess(access);
  3154. parentScope.AddTypeDeclaration(typeDeclaration);
  3155. initStatements := previousStatements;
  3156. initOuter := previousOuter;
  3157. IF Trace THEN
  3158. E("StructDeclaration")
  3159. END;
  3160. END StructDeclaration;
  3161. (**
  3162. delegate-declaration:
  3163. [delegate-modifiers] 'delegate' return-type identifier '(' [formal-parameter-list] ')' ';'
  3164. **)
  3165. PROCEDURE DelegateDeclaration(parentScope: SyntaxTree.Scope; modifiers: SET);
  3166. VAR returnType: SyntaxTree.Type;
  3167. name: SyntaxTree.Identifier;
  3168. position: Position;
  3169. typeDeclaration: SyntaxTree.TypeDeclaration;
  3170. access: SET;
  3171. procedureType: SyntaxTree.ProcedureType;
  3172. BEGIN
  3173. IF Trace THEN
  3174. S("DelegateDeclaration")
  3175. END;
  3176. (* symbol 'delegate' already consumed *)
  3177. IF Optional(Scanner.Void) THEN
  3178. returnType := NIL;
  3179. ELSE
  3180. returnType := Type();
  3181. END;
  3182. name := Identifier(position);
  3183. access := IdentifierAccess(modifiers, FALSE);
  3184. typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
  3185. CommentSymbol(typeDeclaration);
  3186. procedureType := SyntaxTree.NewProcedureType(position, parentScope);
  3187. procedureType.SetModifiers(delegateModifiers);
  3188. (* ACHTUNG: Should we create a fictionary parentScope for parameters? *)
  3189. FormalParameterList(procedureType, parentScope, returnType);
  3190. procedureType.SetTypeDeclaration(typeDeclaration);
  3191. typeDeclaration.SetDeclaredType(procedureType);
  3192. typeDeclaration.SetAccess(access);
  3193. parentScope.AddTypeDeclaration(typeDeclaration);
  3194. IF Trace THEN
  3195. E("DelegateDeclaration")
  3196. END;
  3197. END DelegateDeclaration;
  3198. (**
  3199. port-list:
  3200. port-declaration
  3201. port-list ',' port-declaration
  3202. port-declaration:
  3203. port-type ['[' constant-expression ']'] identifier
  3204. port-type:
  3205. 'in'
  3206. 'out'
  3207. **)
  3208. PROCEDURE PortDeclaration(cell: SyntaxTree.CellType; parentScope: SyntaxTree.Scope);
  3209. VAR position: Position;
  3210. direction: LONGINT;
  3211. type: SyntaxTree.Type;
  3212. arrayType: SyntaxTree.ArrayType;
  3213. expression: SyntaxTree.Expression;
  3214. name: SyntaxTree.Identifier;
  3215. parameter: SyntaxTree.Parameter;
  3216. BEGIN
  3217. IF Trace THEN
  3218. S("PortDeclaration")
  3219. END;
  3220. position := symbol.position;
  3221. IF Optional(Scanner.In) THEN
  3222. direction := SyntaxTree.InPort;
  3223. ELSIF Optional(Scanner.Out) THEN
  3224. direction := SyntaxTree.OutPort;
  3225. ELSE
  3226. Error(position, Basic.InvalidCode, "invalid direction, expected in or out");
  3227. END;
  3228. type := SyntaxTree.NewPortType(position, direction, NIL, parentScope);
  3229. IF Optional(Scanner.LeftBracket) THEN
  3230. expression := Expression();
  3231. arrayType := SyntaxTree.NewArrayType(position, parentScope, SyntaxTree.Static);
  3232. arrayType.SetArrayBase(type);
  3233. arrayType.SetLength(expression);
  3234. type := arrayType;
  3235. Check(Scanner.RightBracket);
  3236. END;
  3237. name := Identifier(position);
  3238. parameter := SyntaxTree.NewParameter(position, cell, name, SyntaxTree.ValueParameter);
  3239. cell.AddParameter(parameter);
  3240. parameter.SetType(type);
  3241. IF Trace THEN
  3242. E("PortDeclaration")
  3243. END;
  3244. END PortDeclaration;
  3245. PROCEDURE PortList(cell: SyntaxTree.CellType; parentScope: SyntaxTree.Scope);
  3246. BEGIN
  3247. IF Trace THEN
  3248. S("PortList")
  3249. END;
  3250. Check(Scanner.LeftParenthesis);
  3251. IF ~Optional(Scanner.RightParenthesis) THEN
  3252. REPEAT
  3253. PortDeclaration(cell, parentScope);
  3254. UNTIL ~Optional(Scanner.Comma);
  3255. Check(Scanner.RightParenthesis);
  3256. END;
  3257. IF Trace THEN
  3258. E("PortList")
  3259. END;
  3260. END PortList;
  3261. (**
  3262. cell-declaration:
  3263. [cell-modifiers] 'cell' identifier ['(' [cell-parameter-list] ')'] cell-body [';']
  3264. cell-body:
  3265. '{' [cell-member-declarations] '}'
  3266. cell-member-declarations:
  3267. cell-member-declaration
  3268. cell-member-declarations cell-member-declaration
  3269. cell-member-declaration:
  3270. constant-declaration
  3271. field-declaration
  3272. method-declaration
  3273. constructor-declaration
  3274. type-declaration
  3275. cellnet-declaration:
  3276. [cell-modifiers] 'cellnet' identifier ['(' [cell-parameter-list] ')'] cell-body [';']
  3277. **)
  3278. PROCEDURE CellMemberDeclaration(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3279. BEGIN
  3280. IF Trace THEN
  3281. S("CellMemberDeclaration")
  3282. END;
  3283. MemberDeclaration(parentScope, parentName);
  3284. IF Trace THEN
  3285. E("CellMemberDeclaration")
  3286. END;
  3287. END CellMemberDeclaration;
  3288. PROCEDURE CellMemberDeclarations(parentScope: SyntaxTree.Scope; parentName: SyntaxTree.Identifier);
  3289. VAR previousScope: SyntaxTree.Scope;
  3290. BEGIN
  3291. IF Trace THEN
  3292. S("CellMemberDeclarations")
  3293. END;
  3294. previousScope := currentScope;
  3295. currentScope := parentScope;
  3296. WHILE ~Peek(Scanner.RightBrace) DO
  3297. CellMemberDeclaration(parentScope, parentName);
  3298. END;
  3299. currentScope := previousScope;
  3300. IF Trace THEN
  3301. E("CellMemberDeclarations")
  3302. END;
  3303. END CellMemberDeclarations;
  3304. PROCEDURE CellDeclaration(
  3305. parentScope: SyntaxTree.Scope;
  3306. modifiers: SET;
  3307. attributes: SyntaxTree.Modifier;
  3308. isCellNet: BOOLEAN);
  3309. VAR name: SyntaxTree.Identifier;
  3310. position: Position;
  3311. access: SET;
  3312. typeDeclaration: SyntaxTree.TypeDeclaration;
  3313. cellScope: SyntaxTree.CellScope;
  3314. cellType: SyntaxTree.CellType;
  3315. previousStatements: SyntaxTree.StatementSequence;
  3316. previousOuter: SyntaxTree.Statement;
  3317. b: BOOLEAN;
  3318. BEGIN
  3319. IF Trace THEN
  3320. S("CellDeclaration")
  3321. END;
  3322. previousStatements := initStatements;
  3323. previousOuter := initOuter;
  3324. (* TODO: Implement initialization of fields *)
  3325. initStatements := NIL;
  3326. initOuter := NIL;
  3327. (* symbol 'cell' already consumed *)
  3328. name := Identifier(position);
  3329. access := IdentifierAccess(modifiers, FALSE);
  3330. typeDeclaration := SyntaxTree.NewTypeDeclaration(position, name);
  3331. CommentSymbol(typeDeclaration);
  3332. cellScope := SyntaxTree.NewCellScope(parentScope);
  3333. cellType := SyntaxTree.NewCellType(position, parentScope, cellScope);
  3334. cellType.IsCellNet(isCellNet);
  3335. cellScope.SetOwnerCell(cellType);
  3336. IF attributes # NIL THEN
  3337. cellType.SetModifiers(attributes);
  3338. END;
  3339. IF Peek(Scanner.LeftParenthesis) THEN
  3340. PortList(cellType, cellScope);
  3341. END;
  3342. EnterInit;
  3343. Check(Scanner.LeftBrace);
  3344. CellMemberDeclarations(cellScope, name);
  3345. Check(Scanner.RightBrace);
  3346. b := Optional(Scanner.Semicolon);
  3347. cellType.SetTypeDeclaration(typeDeclaration);
  3348. typeDeclaration.SetDeclaredType(cellType);
  3349. typeDeclaration.SetAccess(access);
  3350. parentScope.AddTypeDeclaration(typeDeclaration);
  3351. initStatements := previousStatements;
  3352. initOuter := previousOuter;
  3353. IF Trace THEN
  3354. E("CellDeclaration")
  3355. END;
  3356. END CellDeclaration;
  3357. (**
  3358. import-directives:
  3359. import-directive
  3360. import-directives import-directive
  3361. import-directive:
  3362. import-alias-directive
  3363. import-module-directive
  3364. import-alias-directive:
  3365. 'import' identifier '=' module-name ';'
  3366. import-module-directive:
  3367. 'import' module-name ';'
  3368. module-name:
  3369. identifier
  3370. **)
  3371. PROCEDURE ImportDirective(moduleScope: SyntaxTree.ModuleScope);
  3372. VAR alias, name, context: SyntaxTree.Identifier;
  3373. import: SyntaxTree.Import;
  3374. position, idPosition: Position;
  3375. BEGIN
  3376. IF Trace THEN
  3377. S("ImportDirective")
  3378. END;
  3379. (* import symbol already consumed *)
  3380. position := symbol.position;
  3381. alias := Identifier(idPosition);
  3382. IF alias # SyntaxTree.invalidIdentifier THEN
  3383. IF Optional(Scanner.Equal) THEN
  3384. name := Identifier(idPosition);
  3385. ELSE
  3386. name := alias;
  3387. END;
  3388. import := SyntaxTree.NewImport(position, alias, name, TRUE);
  3389. CommentSymbol(import);
  3390. moduleScope.AddImport(import);
  3391. END;
  3392. Check(Scanner.Semicolon);
  3393. IF Trace THEN
  3394. E("ImportDirective");
  3395. END;
  3396. END ImportDirective;
  3397. PROCEDURE ImportDirectives(moduleScope: SyntaxTree.ModuleScope);
  3398. BEGIN
  3399. IF Trace THEN
  3400. S("ImportDirectives")
  3401. END;
  3402. WHILE Optional(Scanner.Import) DO
  3403. ImportDirective(moduleScope);
  3404. END;
  3405. IF Trace THEN
  3406. E("ImportDirectives");
  3407. END;
  3408. END ImportDirectives;
  3409. (**
  3410. compilation-unit:
  3411. 'module' identifier '{' [import-directives] [class-member-declarations] '}' [';']
  3412. 'cellnet' identifier '{' [import-directives] [class-member-declarations] '}' [';']
  3413. **)
  3414. PROCEDURE Module*(): SyntaxTree.Module;
  3415. VAR moduleName, context: SyntaxTree.Identifier;
  3416. module: SyntaxTree.Module;
  3417. position: Position;
  3418. isCellNet: BOOLEAN;
  3419. scannerDiagnostics: Diagnostics.Diagnostics;
  3420. b: BOOLEAN;
  3421. BEGIN
  3422. IF Trace THEN
  3423. S("Module")
  3424. END;
  3425. position := symbol.position;
  3426. (* needed to feed in comment already before module starts: *)
  3427. moduleScope := SyntaxTree.NewModuleScope();
  3428. currentScope := moduleScope;
  3429. isCellNet := Optional(Scanner.Cellnet);
  3430. IF isCellNet OR Mandatory(Scanner.Module) THEN
  3431. moduleName := Identifier(position);
  3432. module := SyntaxTree.NewModule(scanner.source^, position, moduleName, moduleScope, LynxCase);
  3433. IF isCellNet THEN
  3434. module.SetCellNet(TRUE);
  3435. END;
  3436. module.SetType(SyntaxTree.moduleType);
  3437. CommentSymbol(module);
  3438. Check(Scanner.LeftBrace);
  3439. IF Peek(Scanner.Import) THEN
  3440. ImportDirectives(moduleScope)
  3441. END;
  3442. EnterInit;
  3443. ClassMemberDeclarations(moduleScope, moduleName);
  3444. Check(Scanner.RightBrace);
  3445. b := Optional(Scanner.Semicolon);
  3446. IF ~error & ~scanner.error THEN
  3447. (* read ahead to read comments *)
  3448. scannerDiagnostics := NIL;
  3449. scanner.ResetErrorDiagnostics(scannerDiagnostics);
  3450. NextSymbol;
  3451. scanner.ResetErrorDiagnostics(scannerDiagnostics);
  3452. (* do not use Check for not reading after end of module *)
  3453. SetNextInComment(recentComment, module);
  3454. module.SetClosingComment(recentComment);
  3455. recentComment := NIL;
  3456. END;
  3457. END;
  3458. IF Trace THEN
  3459. E("Module")
  3460. END;
  3461. RETURN module
  3462. END Module;
  3463. END Parser; (* Parser *)
  3464. VAR invalidPosition: Position;
  3465. (** parser retrieval **)
  3466. PROCEDURE NewParser*(scanner: Scanner.Scanner; diagnostics: Diagnostics.Diagnostics): Parser;
  3467. VAR parser: Parser;
  3468. BEGIN
  3469. NEW(parser, scanner, diagnostics);
  3470. RETURN parser;
  3471. END NewParser;
  3472. BEGIN
  3473. invalidPosition.start := -1;
  3474. END FoxCSharpParser.