ModuleParser.Mod 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636
  1. MODULE ModuleParser; (** AUTHOR "mb"; PURPOSE "Active Oberon parser for use with ModuleTrees **)
  2. (**
  3. * Notes:
  4. * - The Module node's parent is the module node itself
  5. *)
  6. IMPORT
  7. Strings, Files, Streams, Diagnostics, FoxScanner, KernelLog, Texts, TextUtilities;
  8. CONST
  9. (* visibilities *)
  10. Public* = 1;
  11. PublicRO* = 2;
  12. Private* = 3;
  13. (* block modifiers *)
  14. Exclusive* = 1;
  15. Active* = 2;
  16. Safe* = 3;
  17. Priority* = 4;
  18. Unchecked* = 5;
  19. Uncooperative* = 6;
  20. HasExclusiveBlock* = 7;
  21. (* procedure modifiers (in addition to block modifiers) *)
  22. Overwrite* = 8; (* procedure overwrites procedure in superclass *)
  23. Overwritten* = 9; (* procedure is overwritten in subclass *)
  24. Interrupt* = 10; (* procedure is an interrupt handler that might be called asynchronously *)
  25. ExclusiveStr = "EXCLUSIVE";
  26. ActiveStr = "ACTIVE";
  27. RealtimeStr = "REALTIME";
  28. SafeStr = "SAFE";
  29. PriorityStr = "PRIORITY";
  30. UncheckedStr = "UNCHECKED";
  31. UncooperativeStr = "UNCOOPERATIVE";
  32. NoPAFStr = "NOPAF"; FixedStr = "FIXED"; AlignedStr = "FIXED";
  33. DynamicStr = "DYNAMIC"; InterruptStr = "INTERRUPT"; PCOffsetStr = "PCOFFSET";
  34. TYPE
  35. InfoItem* = OBJECT
  36. VAR
  37. name*: Strings.String;
  38. pos*: LONGINT;
  39. END InfoItem;
  40. Node* = OBJECT
  41. VAR
  42. parent- : Node;
  43. PROCEDURE GetModule*() : Module;
  44. VAR node : Node; module : Module;
  45. BEGIN
  46. module := NIL;
  47. node := SELF;
  48. WHILE (node # NIL) & (node.parent # node) DO node := node.parent; END;
  49. IF (node # NIL) THEN
  50. module := node (Module);
  51. END;
  52. RETURN module;
  53. END GetModule;
  54. PROCEDURE &Init*(parent : Node);
  55. BEGIN
  56. SELF.parent := parent;
  57. END Init;
  58. END Node;
  59. NodeList* = OBJECT(Node);
  60. VAR
  61. next*: NodeList;
  62. END NodeList;
  63. Import* = OBJECT (NodeList)
  64. VAR
  65. ident*, alias*, context*: InfoItem;
  66. END Import;
  67. Definition* = OBJECT (NodeList)
  68. VAR
  69. ident*: InfoItem;
  70. refines*: Qualident;
  71. procs*: ProcHead;
  72. END Definition;
  73. Type* = OBJECT(Node)
  74. VAR
  75. qualident*: Qualident;
  76. array*: Array;
  77. record*: Record;
  78. pointer*: Pointer;
  79. object*: Object;
  80. enum*: Enum;
  81. cell*: Cell;
  82. port*: Port;
  83. procedure*: Procedure;
  84. END Type;
  85. Array* = OBJECT(Node)
  86. VAR
  87. open*: BOOLEAN;
  88. len*: InfoItem;
  89. base*: Type;
  90. END Array;
  91. Record* = OBJECT(Node)
  92. VAR
  93. super*: Qualident;
  94. superPtr* : Record;
  95. fieldList*: FieldDecl;
  96. END Record;
  97. FieldDecl* = OBJECT (NodeList)
  98. VAR
  99. identList*: IdentList;
  100. type*: Type;
  101. END FieldDecl;
  102. Pointer* = OBJECT(Node)
  103. VAR
  104. type*: Type;
  105. END Pointer;
  106. Enum* = OBJECT(Node)
  107. VAR identList*: IdentList;
  108. END Enum;
  109. Port*= OBJECT(Node)
  110. END Port;
  111. Cell*= OBJECT(Node)
  112. VAR
  113. modifiers* : SET;
  114. declSeq*: DeclSeq;
  115. bodyPos- : LONGINT;
  116. formalPars*: FormalPars;
  117. PROCEDURE FindProcDecl*(CONST name : ARRAY OF CHAR) : ProcDecl;
  118. VAR procDecl : ProcDecl;
  119. BEGIN
  120. IF (declSeq # NIL) THEN
  121. procDecl := declSeq.FindProcDecl(name);
  122. ELSE
  123. procDecl := NIL;
  124. END;
  125. RETURN procDecl;
  126. END FindProcDecl;
  127. END Cell;
  128. Object* = OBJECT(Node)
  129. VAR
  130. super*, implements*: Qualident;
  131. superPtr* : Object;
  132. modifiers* : SET;
  133. declSeq*: DeclSeq;
  134. bodyPos- : LONGINT;
  135. PROCEDURE FindProcDecl*(CONST name : ARRAY OF CHAR) : ProcDecl;
  136. VAR procDecl : ProcDecl;
  137. BEGIN
  138. IF (declSeq # NIL) THEN
  139. procDecl := declSeq.FindProcDecl(name);
  140. ELSE
  141. procDecl := NIL;
  142. END;
  143. RETURN procDecl;
  144. END FindProcDecl;
  145. END Object;
  146. Procedure* = OBJECT(Node)
  147. VAR
  148. delegate*: BOOLEAN;
  149. formalPars*: FormalPars;
  150. END Procedure;
  151. DeclSeq* = OBJECT (NodeList)
  152. VAR
  153. constDecl*: ConstDecl;
  154. typeDecl*: TypeDecl;
  155. varDecl*: VarDecl;
  156. procDecl*: ProcDecl;
  157. PROCEDURE FindProcDecl*(CONST name : ARRAY OF CHAR) : ProcDecl;
  158. VAR pd : ProcDecl;
  159. BEGIN
  160. pd := procDecl;
  161. WHILE (pd # NIL) & (pd.head.identDef.ident.name^ # name) DO
  162. IF (pd.next # NIL) THEN
  163. pd := pd.next (ProcDecl);
  164. ELSE
  165. pd := NIL;
  166. END;
  167. END;
  168. ASSERT((pd = NIL) OR (pd.head.identDef.ident.name^ = name));
  169. RETURN pd;
  170. END FindProcDecl;
  171. PROCEDURE FindTypeDecl*(CONST name : ARRAY OF CHAR) : TypeDecl;
  172. VAR td : TypeDecl;
  173. BEGIN
  174. td := typeDecl;
  175. WHILE (td # NIL) & (td.identDef.ident.name^ # name) DO
  176. IF (td.next # NIL) THEN
  177. td := td.next (TypeDecl);
  178. ELSE
  179. td := NIL;
  180. END;
  181. END;
  182. ASSERT((td = NIL) OR (td.identDef.ident.name^ = name));
  183. RETURN td;
  184. END FindTypeDecl;
  185. END DeclSeq;
  186. ConstDecl* = OBJECT (NodeList)
  187. VAR
  188. identDef*: IdentDef;
  189. constExpr*: Expr;
  190. expr*: InfoItem;
  191. END ConstDecl;
  192. TypeDecl* = OBJECT (NodeList)
  193. VAR
  194. identDef*: IdentDef;
  195. type*: Type;
  196. END TypeDecl;
  197. VarDecl* = OBJECT (NodeList)
  198. VAR
  199. identList*: IdentList;
  200. type*: Type;
  201. END VarDecl;
  202. ProcDecl* = OBJECT (NodeList)
  203. VAR
  204. head*: ProcHead;
  205. declSeq*: DeclSeq;
  206. bodyPos- : LONGINT;
  207. END ProcDecl;
  208. ProcHead* = OBJECT (NodeList)
  209. VAR
  210. sysFlag*: InfoItem;
  211. constructor*, inline*, operator*: BOOLEAN;
  212. modifiers* : SET;
  213. identDef*: IdentDef;
  214. formalPars*: FormalPars;
  215. END ProcHead;
  216. FormalPars* = OBJECT(Node)
  217. VAR
  218. fpSectionList*: FPSection;
  219. returnType*: Type;
  220. END FormalPars;
  221. FPSection* = OBJECT (NodeList)
  222. VAR
  223. var*, const*: BOOLEAN;
  224. identList*: IdentList;
  225. type*: Type;
  226. END FPSection;
  227. Expr* = OBJECT (NodeList)
  228. VAR
  229. simpleExprL*, simpleExprR*: SimpleExpr;
  230. relation*: InfoItem;
  231. END Expr;
  232. SimpleExpr* = OBJECT (NodeList)
  233. VAR
  234. sign*: InfoItem;
  235. termL*, termR*: Term;
  236. addOp*: AddOp;
  237. END SimpleExpr;
  238. Term* = OBJECT (NodeList)
  239. VAR
  240. factorL*, factorR*: Factor;
  241. mulOp*: MulOp;
  242. END Term;
  243. Factor* = OBJECT (NodeList)
  244. VAR
  245. designator*: Designator;
  246. number*, string*, nil*, bool*: InfoItem;
  247. set*: Element;
  248. expr*: Expr;
  249. factor*: Factor;
  250. END Factor;
  251. Designator* = OBJECT (NodeList)
  252. VAR
  253. qualident*: Qualident;
  254. ident*, arrowUp*: InfoItem;
  255. exprList*: Expr;
  256. END Designator;
  257. Qualident* = OBJECT (NodeList)
  258. VAR
  259. ident*: InfoItem;
  260. END Qualident;
  261. Element* = OBJECT (NodeList)
  262. VAR
  263. expr*, upToExpr*: Expr;
  264. END Element;
  265. MulOp* = OBJECT (NodeList)
  266. VAR
  267. op*: InfoItem;
  268. END MulOp;
  269. AddOp* = OBJECT (NodeList)
  270. VAR
  271. op*: InfoItem;
  272. END AddOp;
  273. IdentDef* = OBJECT
  274. VAR
  275. ident*: InfoItem;
  276. vis*: SHORTINT;
  277. initializer*: InfoItem;
  278. external*: Strings.String;
  279. END IdentDef;
  280. IdentList* = OBJECT (NodeList)
  281. VAR
  282. identDef*: IdentDef;
  283. END IdentList;
  284. Module* = OBJECT(Node)
  285. VAR
  286. ident*, context*: InfoItem;
  287. importList*: Import;
  288. modifiers* : SET;
  289. definitions*: Definition;
  290. declSeq*: DeclSeq;
  291. bodyPos- : LONGINT;
  292. hasError-: BOOLEAN;
  293. resolved* : BOOLEAN;
  294. PROCEDURE FindTypeDecl*(CONST name : ARRAY OF CHAR) : TypeDecl;
  295. VAR typeDecl : TypeDecl;
  296. BEGIN
  297. IF (declSeq # NIL) THEN
  298. typeDecl := declSeq.FindTypeDecl(name);
  299. ELSE
  300. typeDecl := NIL;
  301. END;
  302. RETURN typeDecl;
  303. END FindTypeDecl;
  304. PROCEDURE FindImport*(CONST name : ARRAY OF CHAR) : Import;
  305. VAR import : Import;
  306. BEGIN
  307. import := importList;
  308. WHILE (import # NIL) & ((import.ident = NIL) OR (import.ident.name^ # name)) DO
  309. IF (import.next # NIL) THEN
  310. import := import.next (Import);
  311. ELSE
  312. import := NIL;
  313. END;
  314. END;
  315. RETURN import;
  316. END FindImport;
  317. END Module;
  318. Parser = OBJECT
  319. VAR
  320. symbol : FoxScanner.Symbol;
  321. scanner: FoxScanner.Scanner;
  322. hasError: BOOLEAN;
  323. PROCEDURE & Init*(scanner: FoxScanner.Scanner);
  324. BEGIN
  325. ASSERT(scanner # NIL);
  326. SELF.scanner := scanner;
  327. hasError := FALSE;
  328. END Init;
  329. PROCEDURE NextSymbol;
  330. VAR ignore : BOOLEAN;
  331. BEGIN
  332. ignore := scanner.GetNextSymbol(symbol);
  333. WHILE (symbol.token = FoxScanner.Comment) DO ignore := scanner.GetNextSymbol(symbol); END;
  334. END NextSymbol;
  335. PROCEDURE ModuleP(VAR module: Module);
  336. VAR
  337. modName: FoxScanner.IdentifierString;
  338. definition: Definition;
  339. BEGIN
  340. NextSymbol;
  341. IF (symbol.token = FoxScanner.Module) OR (symbol.token = FoxScanner.CellNet) THEN
  342. NEW(module, NIL); module.parent := module;
  343. NextSymbol;
  344. IF symbol.token = FoxScanner.Identifier THEN
  345. NEW(module.ident);
  346. COPY(symbol.identifierString, modName);
  347. module.ident.name := Strings.NewString(symbol.identifierString);
  348. module.ident.pos := symbol.position.start;
  349. END;
  350. NextSymbol;
  351. IF symbol.token = FoxScanner.In THEN
  352. NextSymbol;
  353. IF symbol.token = FoxScanner.Identifier THEN
  354. NEW(module.context);
  355. module.context.name := Strings.NewString(symbol.identifierString);
  356. module.context.pos := symbol.position.start;
  357. END;
  358. Check (FoxScanner.Identifier);
  359. END;
  360. IF symbol.token = FoxScanner.LeftBrace THEN
  361. WHILE (symbol.token # FoxScanner.Semicolon) & (symbol.token # FoxScanner.EndOfText) DO NextSymbol END;
  362. END;
  363. Check(FoxScanner.Semicolon);
  364. IF symbol.token = FoxScanner.Import THEN
  365. NEW(module.importList, module);
  366. ImportListP(module.importList);
  367. END;
  368. WHILE symbol.token = FoxScanner.Definition DO
  369. NEW(definition, module);
  370. DefinitionP(definition);
  371. IF module.definitions = NIL THEN module.definitions := definition
  372. ELSE AppendLast(module.definitions, definition)
  373. END;
  374. END;
  375. IF (symbol.token = FoxScanner.Const) OR (symbol.token = FoxScanner.Type) OR
  376. (symbol.token = FoxScanner.Var) OR (symbol.token = FoxScanner.Procedure) OR (symbol.token = FoxScanner.Operator) THEN
  377. NEW(module.declSeq, module);
  378. DeclSeqP(module.declSeq);
  379. END;
  380. IF (symbol.token = FoxScanner.Begin) THEN
  381. module.bodyPos := symbol.position.start;
  382. ELSE
  383. module.bodyPos := 0;
  384. END;
  385. BodyP(FALSE, module.modifiers);
  386. IF (symbol.token = FoxScanner.Identifier) & (symbol.identifierString = modName) THEN
  387. (* correct *)
  388. ELSE
  389. (* maybe missing END or wrong module name *)
  390. hasError := TRUE;
  391. KernelLog.String("err3: "); KernelLog.Int(symbol.position.start, 0); KernelLog.Ln;
  392. END;
  393. module.hasError := hasError;
  394. END;
  395. END ModuleP;
  396. PROCEDURE ImportListP(import: Import);
  397. VAR newImport: Import;
  398. BEGIN
  399. NextSymbol;
  400. WHILE symbol.token = FoxScanner.Identifier DO
  401. NEW(import.ident);
  402. import.ident.name := Strings.NewString(symbol.identifierString);
  403. import.ident.pos := symbol.position.start;
  404. NextSymbol; (* avoids endless loop *)
  405. IF symbol.token = FoxScanner.Becomes THEN
  406. NextSymbol;
  407. IF symbol.token = FoxScanner.Identifier THEN
  408. NEW(import.alias);
  409. import.alias.name := Strings.NewString(symbol.identifierString);
  410. import.alias.pos := symbol.position.start;
  411. NextSymbol;
  412. ELSE
  413. (* Error *)
  414. hasError := TRUE;
  415. KernelLog.String("err2: "); KernelLog.Int(symbol.position.start, 0); KernelLog.Ln;
  416. END;
  417. END;
  418. IF symbol.token = FoxScanner.In THEN
  419. NextSymbol;
  420. IF symbol.token = FoxScanner.Identifier THEN
  421. NEW(import.context);
  422. import.context.name := Strings.NewString(symbol.identifierString);
  423. import.context.pos := symbol.position.start;
  424. END;
  425. Check (FoxScanner.Identifier);
  426. END;
  427. IF symbol.token = FoxScanner.Comma THEN
  428. NextSymbol;
  429. END;
  430. NEW(newImport, import.parent);
  431. import.next := newImport;
  432. import := newImport;
  433. END;
  434. Check(FoxScanner.Semicolon);
  435. END ImportListP;
  436. PROCEDURE DefinitionP(definition: Definition);
  437. VAR
  438. procHead: ProcHead;
  439. BEGIN
  440. IF symbol.token = FoxScanner.Definition THEN
  441. NextSymbol;
  442. IF symbol.token = FoxScanner.Identifier THEN
  443. NEW(definition.ident);
  444. definition.ident.name := Strings.NewString(symbol.identifierString);
  445. definition.ident.pos := symbol.position.start;
  446. NextSymbol;
  447. END;
  448. WHILE symbol.token = FoxScanner.Semicolon DO NextSymbol END;
  449. (*? IF symbol.token = FoxScanner.Refines THEN
  450. NextSymbol;
  451. NEW(definition.refines, definition);
  452. QualidentP(definition.refines);
  453. END; *)
  454. WHILE (symbol.token = FoxScanner.Procedure) OR (symbol.token = FoxScanner.Operator) DO
  455. NEW(procHead, definition);
  456. NextSymbol;
  457. ProcHeadP(procHead);
  458. IF definition.procs = NIL THEN definition.procs := procHead
  459. ELSE AppendLast(definition.procs, procHead)
  460. END;
  461. Check(FoxScanner.Semicolon);
  462. END;
  463. Check(FoxScanner.End);
  464. Check(FoxScanner.Identifier);
  465. WHILE symbol.token = FoxScanner.Semicolon DO NextSymbol END;
  466. END;
  467. END DefinitionP;
  468. PROCEDURE DeclSeqP(declSeq: DeclSeq);
  469. VAR
  470. constDecl: ConstDecl;
  471. typeDecl: TypeDecl;
  472. varDecl: VarDecl;
  473. procDecl: ProcDecl;
  474. PROCEDURE CheckEndOrSemicolon;
  475. BEGIN
  476. IF symbol.token # FoxScanner.End THEN
  477. REPEAT Check(FoxScanner.Semicolon) UNTIL symbol.token # FoxScanner.Semicolon
  478. END;
  479. END CheckEndOrSemicolon;
  480. BEGIN
  481. LOOP
  482. CASE symbol.token OF
  483. | FoxScanner.Const:
  484. NextSymbol;
  485. WHILE symbol.token = FoxScanner.Identifier DO
  486. NEW(constDecl, declSeq);
  487. ConstDeclP(constDecl);
  488. IF declSeq.constDecl = NIL THEN declSeq.constDecl := constDecl;
  489. ELSE AppendLast(declSeq.constDecl, constDecl);
  490. END;
  491. CheckEndOrSemicolon;
  492. (*Check(FoxScanner.Semicolon);*)
  493. END;
  494. | FoxScanner.Type:
  495. NextSymbol;
  496. WHILE symbol.token = FoxScanner.Identifier DO
  497. NEW(typeDecl, declSeq);
  498. TypeDeclP(typeDecl);
  499. IF declSeq.typeDecl = NIL THEN declSeq.typeDecl := typeDecl;
  500. ELSE AppendLast(declSeq.typeDecl, typeDecl);
  501. END;
  502. CheckEndOrSemicolon;
  503. (*Check(FoxScanner.Semicolon);*)
  504. END;
  505. | FoxScanner.Var:
  506. NextSymbol;
  507. WHILE symbol.token = FoxScanner.Identifier DO
  508. NEW(varDecl, declSeq);
  509. VarDeclP(varDecl);
  510. IF declSeq.varDecl = NIL THEN declSeq.varDecl := varDecl;
  511. ELSE AppendLast(declSeq.varDecl, varDecl);
  512. END;
  513. CheckEndOrSemicolon;
  514. (*Check(FoxScanner.Semicolon);*)
  515. END;
  516. | FoxScanner.Procedure, FoxScanner.Operator:
  517. WHILE (symbol.token = FoxScanner.Procedure) OR (symbol.token = FoxScanner.Operator) DO
  518. NextSymbol;
  519. NEW(procDecl, declSeq);
  520. ProcDeclP(procDecl);
  521. IF procDecl.head = NIL THEN
  522. procDecl := NIL
  523. ELSE
  524. IF declSeq.procDecl = NIL THEN declSeq.procDecl := procDecl;
  525. ELSE AppendLast(declSeq.procDecl, procDecl);
  526. END;
  527. END;
  528. CheckEndOrSemicolon;
  529. (*Check(FoxScanner.Semicolon);*)
  530. END;
  531. ELSE
  532. EXIT;
  533. END;
  534. END;
  535. END DeclSeqP;
  536. PROCEDURE ConstDeclP(const: ConstDecl);
  537. BEGIN
  538. NEW(const.identDef);
  539. IdentDefP(const.identDef);
  540. Check(FoxScanner.Equal);
  541. (* NEW(const.constExpr);
  542. ExprP(const.constExpr); *)
  543. NEW(const.expr);
  544. ConstExprP(FoxScanner.Semicolon, -1, const.expr);
  545. END ConstDeclP;
  546. PROCEDURE TypeDeclP(type: TypeDecl);
  547. BEGIN
  548. NEW(type.identDef);
  549. IdentDefP(type.identDef);
  550. Check(FoxScanner.Equal);
  551. NEW(type.type, type);
  552. TypeP(type.type);
  553. END TypeDeclP;
  554. PROCEDURE VarDeclP(var: VarDecl);
  555. VAR
  556. identDef: IdentDef;
  557. identList: IdentList;
  558. PROCEDURE Initializer;
  559. VAR expr: InfoItem;
  560. BEGIN
  561. Check (FoxScanner.Becomes); NEW (expr);
  562. ConstExprP(FoxScanner.Colon, FoxScanner.Comma, expr);
  563. END Initializer;
  564. BEGIN
  565. (*SysFlag;*)
  566. NEW(var.identList, var);
  567. NEW(var.identList.identDef);
  568. IdentDefP(var.identList.identDef);
  569. SysFlag;
  570. IF symbol.token = FoxScanner.Becomes THEN Initializer END;
  571. WHILE symbol.token = FoxScanner.Comma DO
  572. NextSymbol; (* avoids endless loop *)
  573. NEW(identDef);
  574. IdentDefP(identDef);
  575. SysFlag;
  576. IF symbol.token = FoxScanner.Becomes THEN Initializer END;
  577. NEW(identList, var);
  578. identList.identDef := identDef;
  579. AppendLast(var.identList, identList);
  580. END;
  581. Check(FoxScanner.Colon);
  582. NEW(var.type, var);
  583. TypeP(var.type);
  584. END VarDeclP;
  585. PROCEDURE ProcDeclP(proc: ProcDecl);
  586. VAR
  587. declSeq: DeclSeq;
  588. BEGIN
  589. NEW(proc.head, proc);
  590. ProcHeadP(proc.head);
  591. IF proc.head.identDef = NIL THEN proc.head := NIL; RETURN END;
  592. IF proc.head.identDef.external # NIL THEN RETURN END;
  593. Check(FoxScanner.Semicolon);
  594. IF (symbol.token = FoxScanner.Const) OR (symbol.token = FoxScanner.Var) OR
  595. (symbol.token = FoxScanner.Type) OR (symbol.token = FoxScanner.Procedure) OR (symbol.token = FoxScanner.Operator) THEN
  596. NEW(declSeq, proc);
  597. DeclSeqP(declSeq);
  598. IF proc.declSeq = NIL THEN proc.declSeq := declSeq;
  599. ELSE AppendLast(proc.declSeq, declSeq);
  600. END;
  601. END;
  602. IF (symbol.token = FoxScanner.Begin) THEN
  603. proc.bodyPos := symbol.position.start;
  604. ELSE
  605. proc.bodyPos := 0;
  606. END;
  607. BodyP(FALSE, proc.head.modifiers);
  608. NextSymbol; (* skip ident *)
  609. END ProcDeclP;
  610. PROCEDURE ProcHeadP(head: ProcHead);
  611. VAR forward: BOOLEAN;
  612. BEGIN
  613. ProcedureModifierP(head);
  614. (*SysFlag;*)
  615. CASE symbol.token OF
  616. | FoxScanner.Minus: head.inline := TRUE; NextSymbol;
  617. | FoxScanner.And: head.constructor := TRUE; NextSymbol;
  618. | FoxScanner.Times: (* ignore *) NextSymbol;
  619. | FoxScanner.Not: (* ignore *) NextSymbol;
  620. | FoxScanner.Arrow: (* ignore *) NextSymbol; forward := TRUE;
  621. | FoxScanner.String: head.operator := TRUE;
  622. | FoxScanner.Number: IF symbol.numberType = FoxScanner.Character THEN head.operator := TRUE END;
  623. ELSE
  624. END;
  625. NEW(head.identDef);
  626. IdentDefP(head.identDef);
  627. OSAIrq; (* tk: Compatibility to OSACompiler*)
  628. IF symbol.token = FoxScanner.LeftParenthesis THEN
  629. NEW(head.formalPars, head);
  630. FormalParsP(head.formalPars);
  631. END;
  632. IF forward THEN
  633. head.identDef := NIL;
  634. head.formalPars := NIL;
  635. END;
  636. END ProcHeadP;
  637. PROCEDURE SysFlag;
  638. VAR ignore: InfoItem;
  639. BEGIN
  640. IF symbol.token = FoxScanner.LeftBrace THEN
  641. NextSymbol;
  642. IF symbol.token # FoxScanner.RightBrace THEN
  643. LOOP
  644. Check(FoxScanner.Identifier);
  645. IF (symbol.token = FoxScanner.LeftParenthesis) THEN
  646. NextSymbol;
  647. NEW (ignore);
  648. ConstExprP (FoxScanner.RightParenthesis, -1, ignore);
  649. Check (FoxScanner.RightParenthesis);
  650. ELSIF (symbol.token = FoxScanner.Equal) THEN
  651. NextSymbol;
  652. NEW (ignore);
  653. ConstExprP (FoxScanner.RightBrace, FoxScanner.Comma, ignore);
  654. END;
  655. IF symbol.token # FoxScanner.Comma THEN EXIT END;
  656. NextSymbol;
  657. END;
  658. END;
  659. Check(FoxScanner.RightBrace);
  660. END;
  661. END SysFlag;
  662. (* tk: For OSA Compatibility *)
  663. PROCEDURE OSAIrq;
  664. BEGIN
  665. IF symbol.token = FoxScanner.LeftBracket THEN
  666. NextSymbol;
  667. Check(FoxScanner.Number);
  668. Check(FoxScanner.RightBracket);
  669. END;
  670. END OSAIrq;
  671. PROCEDURE FormalParsP(pars: FormalPars);
  672. VAR
  673. fpSection: FPSection;
  674. BEGIN
  675. NextSymbol;
  676. IF (symbol.token = FoxScanner.Var) OR (symbol.token = FoxScanner.Const) OR (symbol.token = FoxScanner.Identifier) THEN
  677. NEW(pars.fpSectionList, pars);
  678. FPSectionP(pars.fpSectionList);
  679. WHILE symbol.token = FoxScanner.Semicolon DO
  680. NextSymbol; (* avoids endless loop *)
  681. NEW(fpSection, pars.fpSectionList);
  682. FPSectionP(fpSection);
  683. AppendLast(pars.fpSectionList, fpSection);
  684. END;
  685. END;
  686. Check(FoxScanner.RightParenthesis);
  687. IF symbol.token = FoxScanner.Colon THEN
  688. NextSymbol;
  689. SysFlag;
  690. NEW(pars.returnType, pars);
  691. TypeP(pars.returnType)
  692. END;
  693. END FormalParsP;
  694. PROCEDURE FPSectionP(fpSection: FPSection);
  695. VAR
  696. identList: IdentList; dummy: InfoItem;
  697. BEGIN
  698. NEW(dummy);
  699. IF symbol.token = FoxScanner.Var THEN
  700. fpSection.var := TRUE;
  701. NextSymbol;
  702. ELSIF symbol.token = FoxScanner.Const THEN
  703. fpSection.const := TRUE;
  704. NextSymbol;
  705. END;
  706. IF symbol.token = FoxScanner.Identifier THEN
  707. (*StringPool.GetString(scanner.name, name);*)
  708. NEW(fpSection.identList, fpSection);
  709. NEW(fpSection.identList.identDef);
  710. IdentDefP(fpSection.identList.identDef);
  711. SysFlag;
  712. (*
  713. fpSection.identList.ident.name := Strings.NewString(name);
  714. fpSection.identList.ident.pos := symbol.position.start;
  715. NextSymbol;
  716. *)
  717. IF symbol.token = FoxScanner.Equal THEN NextSymbol; ConstExprP(FoxScanner.Comma, FoxScanner.Colon, dummy) END; (* added for optional parameters *)
  718. WHILE symbol.token = FoxScanner.Comma DO
  719. NEW(identList, fpSection.identList);
  720. NextSymbol;
  721. NEW(identList.identDef);
  722. IdentDefP(identList.identDef);
  723. SysFlag;
  724. AppendLast(fpSection.identList, identList);
  725. (*
  726. IF symbol.token = FoxScanner.Identifier THEN
  727. StringPool.GetString(scanner.name, name);
  728. NEW(identDef);
  729. NEW(identDef.ident);
  730. identDef.ident.name := Strings.NewString(name);
  731. identDef.ident.pos := symbol.position.start;
  732. AppendLast(fpSection.identlist, identDef);
  733. NextSymbol;
  734. END;
  735. *)
  736. IF symbol.token = FoxScanner.Equal THEN NextSymbol; ConstExprP(FoxScanner.Comma, FoxScanner.Colon, dummy) END; (* added for optional parameters *)
  737. END;
  738. Check(FoxScanner.Colon);
  739. NEW(fpSection.type, fpSection);
  740. TypeP(fpSection.type);
  741. END;
  742. END FPSectionP;
  743. PROCEDURE TypeP(type: Type);
  744. BEGIN
  745. CASE symbol.token OF
  746. | FoxScanner.Array: NextSymbol; NEW(type.array, type); ArrayP(type.array);
  747. | FoxScanner.Record: NextSymbol; NEW(type.record, type); RecordP(type.record);
  748. | FoxScanner.Pointer: NextSymbol; NEW(type.pointer, type); PointerP(type.pointer);
  749. | FoxScanner.Object: NextSymbol; NEW(type.object, type); ObjectP(type.object);
  750. | FoxScanner.Port: NextSymbol; NEW(type.port, type); PortP(type.port);
  751. | FoxScanner.Cell, FoxScanner.CellNet: NextSymbol; NEW(type.cell, type); CellP(type.cell);
  752. | FoxScanner.Enum: NextSymbol; NEW(type.enum, type); EnumP(type.enum);
  753. | FoxScanner.Procedure, FoxScanner.Operator: NextSymbol; NEW(type.procedure, type); ProcedureP(type.procedure);
  754. | FoxScanner.Identifier: NEW(type.qualident, type); QualidentP(type.qualident);
  755. | FoxScanner.Address, FoxScanner.Size: NEW(type.qualident, type); NEW(type.qualident.ident);
  756. type.qualident.ident.name := Strings.NewString(symbol.identifierString); type.qualident.ident.pos := symbol.position.start; NextSymbol;
  757. ELSE
  758. (* Error *)
  759. hasError := TRUE; KernelLog.String("err4: "); KernelLog.Int(symbol.position.start, 0); KernelLog.Ln;
  760. NextSymbol; (* ??? *)
  761. END;
  762. END TypeP;
  763. PROCEDURE ArrayP(array: Array);
  764. BEGIN
  765. SysFlag;
  766. IF symbol.token = FoxScanner.Of THEN
  767. array.open := TRUE;
  768. NEW(array.base, array);
  769. NextSymbol;
  770. TypeP(array.base);
  771. ELSE
  772. NEW(array.len);
  773. ConstExprP(FoxScanner.Of, FoxScanner.Comma, array.len);
  774. (*
  775. SimpleExprP(array.len);
  776. *)
  777. IF symbol.token = FoxScanner.Of THEN
  778. NEW(array.base, array);
  779. NextSymbol;
  780. TypeP(array.base);
  781. ELSIF symbol.token = FoxScanner.Comma THEN
  782. NEW(array.base, array);
  783. NEW(array.base.array, array);
  784. NextSymbol;
  785. ArrayP(array.base.array)
  786. ELSE
  787. (* Error *)
  788. hasError := TRUE;
  789. KernelLog.String("err1: "); KernelLog.Int(symbol.position.start, 0); KernelLog.Ln;
  790. END;
  791. END;
  792. END ArrayP;
  793. PROCEDURE RecordP(record: Record);
  794. BEGIN
  795. SysFlag;
  796. IF symbol.token = FoxScanner.LeftParenthesis THEN
  797. NextSymbol;
  798. NEW(record.super, record);
  799. QualidentP(record.super);
  800. Check(FoxScanner.RightParenthesis);
  801. END;
  802. WHILE symbol.token = FoxScanner.Semicolon DO NextSymbol END;
  803. IF symbol.token = FoxScanner.Identifier THEN
  804. NEW(record.fieldList, record);
  805. FieldListP(record.fieldList);
  806. END;
  807. Check(FoxScanner.End);
  808. END RecordP;
  809. PROCEDURE FieldListP(fieldList: FieldDecl);
  810. VAR fieldDecl: FieldDecl;
  811. BEGIN
  812. FieldDeclP(fieldList);
  813. WHILE symbol.token = FoxScanner.Semicolon DO
  814. NextSymbol;
  815. NEW(fieldDecl, fieldList);
  816. FieldDeclP(fieldDecl);
  817. AppendLast(fieldList, fieldDecl);
  818. END;
  819. END FieldListP;
  820. PROCEDURE FieldDeclP(fieldDecl: FieldDecl);
  821. VAR
  822. identDef: IdentDef;
  823. identList: IdentList;
  824. BEGIN
  825. IF symbol.token = FoxScanner.Identifier THEN
  826. NEW(fieldDecl.identList, fieldDecl);
  827. NEW(fieldDecl.identList.identDef);
  828. IdentDefP(fieldDecl.identList.identDef);
  829. SysFlag;
  830. WHILE symbol.token = FoxScanner.Comma DO
  831. NextSymbol;
  832. NEW(identDef);
  833. IdentDefP(identDef);
  834. SysFlag;
  835. NEW(identList, identList);
  836. identList.identDef := identDef;
  837. AppendLast(fieldDecl.identList, identList);
  838. END;
  839. Check(FoxScanner.Colon);
  840. NEW(fieldDecl.type, fieldDecl);
  841. TypeP(fieldDecl.type);
  842. END;
  843. END FieldDeclP;
  844. PROCEDURE PointerP(pointer: Pointer);
  845. BEGIN
  846. SysFlag;
  847. Check(FoxScanner.To);
  848. NEW(pointer.type, pointer);
  849. TypeP(pointer.type);
  850. END PointerP;
  851. PROCEDURE EnumP(enum: Enum);
  852. VAR identDef: IdentDef; identList: IdentList;
  853. BEGIN
  854. NEW(enum.identList, enum);
  855. NEW(enum.identList.identDef);
  856. IdentDefP(enum.identList.identDef);
  857. SysFlag;
  858. WHILE symbol.token = FoxScanner.Comma DO
  859. NextSymbol; (* avoids endless loop *)
  860. NEW(identDef);
  861. IdentDefP(identDef);
  862. NEW(identList, enum);
  863. identList.identDef := identDef;
  864. AppendLast(enum.identList, identList);
  865. END;
  866. Check(FoxScanner.End);
  867. END EnumP;
  868. PROCEDURE PortP(port: Port);
  869. BEGIN
  870. IF (symbol.token = FoxScanner.Out) OR (symbol.token = FoxScanner.In) THEN
  871. NextSymbol
  872. END;
  873. END PortP;
  874. PROCEDURE ObjectP(object: Object);
  875. VAR declSeq: DeclSeq;
  876. pos: LONGINT;
  877. (*? qualident: Qualident; *)
  878. BEGIN
  879. IF (symbol.token = FoxScanner.Semicolon) OR (symbol.token = FoxScanner.RightParenthesis) THEN RETURN END;
  880. SysFlag;
  881. IF symbol.token = FoxScanner.LeftParenthesis THEN
  882. NEW(object.super, object);
  883. NextSymbol;
  884. QualidentP(object.super);
  885. Check(FoxScanner.RightParenthesis);
  886. END;
  887. (*? IF symbol.token = FoxScanner.Implements THEN
  888. NEW(object.implements, object);
  889. NextSymbol;
  890. QualidentP(object.implements);
  891. WHILE symbol.token = FoxScanner.Comma DO
  892. NEW(qualident, object.implements);
  893. NextSymbol;
  894. QualidentP(qualident);
  895. AppendLast(object.implements, qualident);
  896. END;
  897. END; *)
  898. pos := -1;
  899. WHILE (symbol.token # FoxScanner.Begin) & (symbol.token # FoxScanner.End) & (symbol.token # FoxScanner.EndOfText) DO
  900. (* avoid endless-loop *)
  901. IF pos = symbol.position.start THEN NextSymbol END;
  902. pos := symbol.position.start;
  903. NEW(declSeq, object);
  904. DeclSeqP(declSeq);
  905. IF object.declSeq = NIL THEN object.declSeq := declSeq;
  906. ELSE AppendLast(object.declSeq, declSeq);
  907. END;
  908. END;
  909. IF (symbol.token = FoxScanner.Begin) THEN
  910. object.bodyPos := symbol.position.start;
  911. ELSE
  912. object.bodyPos := 0;
  913. END;
  914. BodyP(TRUE, object.modifiers);
  915. IF symbol.token = FoxScanner.Identifier THEN NextSymbol END;
  916. END ObjectP;
  917. PROCEDURE CellP(cell: Cell);
  918. VAR declSeq: DeclSeq;
  919. pos: LONGINT;
  920. (*? qualident: Qualident; *)
  921. BEGIN
  922. SysFlag;
  923. IF symbol.token = FoxScanner.LeftParenthesis THEN
  924. NEW(cell.formalPars, cell);
  925. FormalParsP(cell.formalPars);
  926. END;
  927. pos := -1;
  928. WHILE (symbol.token # FoxScanner.Begin) & (symbol.token # FoxScanner.End) & (symbol.token # FoxScanner.EndOfText) DO
  929. (* avoid endless-loop *)
  930. IF pos = symbol.position.start THEN NextSymbol END;
  931. pos := symbol.position.start;
  932. NEW(declSeq, cell);
  933. DeclSeqP(declSeq);
  934. IF cell.declSeq = NIL THEN cell.declSeq := declSeq;
  935. ELSE AppendLast(cell.declSeq, declSeq);
  936. END;
  937. END;
  938. IF (symbol.token = FoxScanner.Begin) THEN
  939. cell.bodyPos := symbol.position.start;
  940. ELSE
  941. cell.bodyPos := 0;
  942. END;
  943. BodyP(TRUE, cell.modifiers);
  944. IF symbol.token = FoxScanner.Identifier THEN NextSymbol END;
  945. END CellP;
  946. PROCEDURE ProcedureP(proc: Procedure);
  947. BEGIN
  948. SysFlag;
  949. IF symbol.token = FoxScanner.LeftBrace THEN
  950. NextSymbol;
  951. IF symbol.token # FoxScanner.Identifier THEN
  952. (* Error *)
  953. ELSIF symbol.identifierString = "DELEGATE" THEN
  954. proc.delegate := TRUE;
  955. END;
  956. NextSymbol;
  957. Check(FoxScanner.RightBrace);
  958. END;
  959. IF symbol.token = FoxScanner.LeftParenthesis THEN
  960. NEW(proc.formalPars, proc);
  961. FormalParsP(proc.formalPars);
  962. END;
  963. END ProcedureP;
  964. PROCEDURE ConstExprP(delimiter1, delimiter2: FoxScanner.Token; expr: InfoItem);
  965. VAR
  966. exprStr, name: ARRAY 1024 OF CHAR;
  967. longExprStr : Strings.String; (* for exprStr content lengths > LEN(exprStr) *)
  968. paren, brace, brak: LONGINT;
  969. PROCEDURE Add(CONST str: ARRAY OF CHAR);
  970. VAR len1, len2 : LONGINT;
  971. BEGIN
  972. len1 := Strings.Length(exprStr);
  973. len2 := Strings.Length(str);
  974. IF (len1 + len2 + 1 > LEN(exprStr)) THEN
  975. IF (longExprStr = NIL) THEN
  976. longExprStr := Strings.ConcatToNew(exprStr, str);
  977. ELSE
  978. (* assume that this happens almost never *)
  979. longExprStr := Strings.ConcatToNew(longExprStr^, exprStr);
  980. longExprStr := Strings.ConcatToNew(longExprStr^, str);
  981. END;
  982. exprStr := "";
  983. ELSE
  984. Strings.Append(exprStr, str);
  985. END;
  986. END Add;
  987. BEGIN
  988. expr.pos := symbol.position.start;
  989. IF (symbol.token = delimiter1) OR (symbol.token = delimiter2) THEN RETURN END;
  990. REPEAT
  991. CASE symbol.token OF
  992. | FoxScanner.LeftParenthesis: INC(paren); Add("(");
  993. | FoxScanner.RightParenthesis: DEC(paren); Add(")");
  994. | FoxScanner.LeftBrace: INC(brace); Add("{");
  995. | FoxScanner.RightBrace: DEC(brace); Add("}");
  996. | FoxScanner.LeftBracket: INC(brak); Add("[");
  997. | FoxScanner.RightBracket: DEC(brak); Add("]");
  998. | FoxScanner.Number: Add(symbol.identifierString);
  999. | FoxScanner.Nil: Add("NIL");
  1000. | FoxScanner.True: Add("TRUE");
  1001. | FoxScanner.False: Add("FALSE");
  1002. | FoxScanner.Not: Add("~");
  1003. | FoxScanner.Period: Add(".");
  1004. | FoxScanner.Identifier: Add(symbol.identifierString);
  1005. | FoxScanner.Comma: Add(", ");
  1006. | FoxScanner.Plus: Add(" + ");
  1007. | FoxScanner.Minus: Add(" - ");
  1008. | FoxScanner.Times: Add(" * ");
  1009. | FoxScanner.Upto: Add(" .. ");
  1010. | FoxScanner.Equal: Add(" = ");
  1011. | FoxScanner.Unequal: Add(" # ");
  1012. | FoxScanner.Less: Add(" < ");
  1013. | FoxScanner.LessEqual: Add(" <= ");
  1014. | FoxScanner.Greater: Add(" > ");
  1015. | FoxScanner.GreaterEqual: Add(" >= ");
  1016. | FoxScanner.In: Add(" IN ");
  1017. | FoxScanner.Is: Add(" IS ");
  1018. | FoxScanner.Div: Add(" DIV ");
  1019. | FoxScanner.Mod: Add(" MOD ");
  1020. | FoxScanner.Slash: Add(" / ");
  1021. | FoxScanner.And: Add(" & ");
  1022. | FoxScanner.Or: Add(" OR ");
  1023. | FoxScanner.String: name[0] := '"'; name[1] := 0X; Add(name); Add(symbol.string^); Add(name);
  1024. | FoxScanner.Arrow: Add("^");
  1025. ELSE
  1026. (* error *)
  1027. hasError := TRUE;
  1028. END;
  1029. NextSymbol;
  1030. (* urgh, what an ugly condition ... *)
  1031. UNTIL (((symbol.token = delimiter1) OR (symbol.token = delimiter2)) & (paren = 0) & (brace = 0) & (brak = 0)) OR (symbol.token = FoxScanner.EndOfText);
  1032. IF (longExprStr = NIL) THEN
  1033. expr.name := Strings.NewString(exprStr);
  1034. ELSE
  1035. expr.name := Strings.ConcatToNew(longExprStr^, exprStr);
  1036. END;
  1037. END ConstExprP;
  1038. PROCEDURE BlockModifierP(allowBody : BOOLEAN; VAR modifiers : SET);
  1039. VAR ignore : InfoItem;
  1040. BEGIN
  1041. modifiers := {};
  1042. IF symbol.token = FoxScanner.LeftBrace THEN
  1043. NextSymbol;
  1044. LOOP
  1045. IF symbol.token = FoxScanner.Identifier THEN
  1046. IF symbol.identifierString = ExclusiveStr THEN
  1047. modifiers := modifiers + {Exclusive};
  1048. NextSymbol;
  1049. ELSIF allowBody & (symbol.identifierString = ActiveStr) THEN
  1050. modifiers := modifiers + {Active};
  1051. NextSymbol
  1052. ELSIF allowBody & (symbol.identifierString = RealtimeStr) THEN
  1053. NextSymbol;
  1054. ELSIF allowBody & (symbol.identifierString = SafeStr) THEN
  1055. modifiers := modifiers + {Safe};
  1056. NextSymbol
  1057. ELSIF allowBody & (symbol.identifierString = PriorityStr) THEN
  1058. modifiers := modifiers + {Priority};
  1059. NextSymbol;
  1060. IF symbol.token = FoxScanner.LeftParenthesis THEN
  1061. NextSymbol;
  1062. NEW(ignore);
  1063. ConstExprP(FoxScanner.RightParenthesis, -1, ignore);
  1064. Check(FoxScanner.RightParenthesis);
  1065. END;
  1066. ELSIF symbol.identifierString = UncheckedStr THEN
  1067. modifiers := modifiers + {Unchecked};
  1068. NextSymbol;
  1069. ELSIF symbol.identifierString = UncooperativeStr THEN
  1070. modifiers := modifiers + {Uncooperative};
  1071. NextSymbol;
  1072. ELSE
  1073. Error(symbol.position.start); NextSymbol (* skip the ident, probably a typo *)
  1074. END;
  1075. END;
  1076. IF symbol.token # FoxScanner.Comma THEN EXIT END;
  1077. NextSymbol
  1078. END;
  1079. Check(FoxScanner.RightBrace);
  1080. END;
  1081. END BlockModifierP;
  1082. PROCEDURE ProcedureModifierP(procHead: ProcHead);
  1083. VAR
  1084. value: LONGINT; ignore: InfoItem;
  1085. BEGIN
  1086. IF symbol.token = FoxScanner.LeftBrace THEN
  1087. NextSymbol;
  1088. IF symbol.token # FoxScanner.RightBrace THEN
  1089. LOOP
  1090. IF symbol.token = FoxScanner.Identifier THEN
  1091. IF symbol.identifierString = InterruptStr THEN NextSymbol; procHead.modifiers := procHead.modifiers + {Interrupt}
  1092. ELSE NextSymbol;
  1093. END;
  1094. ELSE Error(symbol.position.start); NextSymbol; (* skip the ident, probably a typo *)
  1095. END;
  1096. IF (symbol.token = FoxScanner.LeftParenthesis) THEN
  1097. NextSymbol;
  1098. NEW (ignore);
  1099. ConstExprP (FoxScanner.RightParenthesis, -1, ignore);
  1100. Check (FoxScanner.RightParenthesis);
  1101. ELSIF (symbol.token = FoxScanner.Equal) THEN
  1102. NextSymbol;
  1103. NEW (ignore);
  1104. ConstExprP (FoxScanner.Comma, FoxScanner.RightBrace, ignore);
  1105. END;
  1106. IF symbol.token # FoxScanner.Comma THEN EXIT END;
  1107. NextSymbol;
  1108. END
  1109. END;
  1110. Check(FoxScanner.RightBrace)
  1111. END
  1112. END ProcedureModifierP;
  1113. PROCEDURE ModifierValueP(VAR value: LONGINT);
  1114. BEGIN
  1115. IF symbol.token = FoxScanner.Equal THEN
  1116. NextSymbol; Check(FoxScanner.Number); value := symbol.integer
  1117. ELSIF symbol.token = FoxScanner.LeftParenthesis THEN
  1118. NextSymbol; Check(FoxScanner.Number); value := symbol.integer; Check(FoxScanner.RightParenthesis)
  1119. ELSE
  1120. Error(symbol.position.start); NextSymbol
  1121. END
  1122. END ModifierValueP;
  1123. PROCEDURE BodyP(allowBody : BOOLEAN; VAR modifiers : SET);
  1124. VAR end, lastToken: LONGINT; m : SET; first : BOOLEAN;
  1125. BEGIN
  1126. IF symbol.token = FoxScanner.Begin THEN
  1127. end := 1;
  1128. first := TRUE;
  1129. REPEAT
  1130. lastToken := symbol.token;
  1131. NextSymbol;
  1132. IF (lastToken = FoxScanner.Begin) & (symbol.token = FoxScanner.LeftBrace) THEN
  1133. BlockModifierP(allowBody, m);
  1134. IF first THEN
  1135. allowBody := FALSE;
  1136. modifiers := m;
  1137. ELSE
  1138. IF m * {Exclusive} # {} THEN
  1139. modifiers := modifiers + {HasExclusiveBlock};
  1140. END;
  1141. END;
  1142. END;
  1143. first := FALSE;
  1144. CASE symbol.token OF
  1145. | FoxScanner.Begin: INC(end);
  1146. | FoxScanner.If, FoxScanner.Case, FoxScanner.While, FoxScanner.For, FoxScanner.Loop, FoxScanner.With: INC(end);
  1147. | FoxScanner.Code:
  1148. REPEAT NextSymbol UNTIL (symbol.token = FoxScanner.End) OR (symbol.token = FoxScanner.EndOfText);
  1149. NextSymbol;
  1150. | FoxScanner.End: DEC(end);
  1151. ELSE
  1152. END;
  1153. UNTIL (end = 0) OR (symbol.token = FoxScanner.EndOfText);
  1154. ELSIF symbol.token = FoxScanner.Code THEN
  1155. REPEAT NextSymbol UNTIL (symbol.token = FoxScanner.End) OR (symbol.token = FoxScanner.EndOfText);
  1156. END;
  1157. NextSymbol;
  1158. END BodyP;
  1159. PROCEDURE QualidentP(qualident: Qualident);
  1160. VAR
  1161. name : ARRAY 64 OF CHAR;
  1162. pos: LONGINT;
  1163. BEGIN
  1164. IF symbol.token = FoxScanner.Identifier THEN
  1165. COPY(symbol.identifierString, name);
  1166. pos := symbol.position.start;
  1167. NextSymbol;
  1168. IF symbol.token = FoxScanner.Period THEN
  1169. NextSymbol;
  1170. IF symbol.token = FoxScanner.Identifier THEN
  1171. Strings.Append(name, ".");
  1172. Strings.Concat(name, symbol.identifierString, name);
  1173. NextSymbol;
  1174. END;
  1175. END;
  1176. NEW(qualident.ident);
  1177. qualident.ident.name := Strings.NewString(name);
  1178. qualident.ident.pos := pos;
  1179. END;
  1180. END QualidentP;
  1181. PROCEDURE IdentDefP(identDef: IdentDef);
  1182. BEGIN
  1183. IF (symbol.token = FoxScanner.Identifier) OR (symbol.token = FoxScanner.Number) & (symbol.numberType = FoxScanner.Character) THEN
  1184. NEW(identDef.ident);
  1185. identDef.ident.name := Strings.NewString(symbol.identifierString);
  1186. identDef.ident.pos := symbol.position.start;
  1187. ELSIF (symbol.token = FoxScanner.String) THEN
  1188. NEW(identDef.ident);
  1189. identDef.ident.name := Strings.NewString(symbol.string^);
  1190. identDef.ident.pos := symbol.position.start;
  1191. END;
  1192. NextSymbol;
  1193. IF symbol.token = FoxScanner.Times THEN
  1194. identDef.vis := Public;
  1195. NextSymbol;
  1196. ELSIF symbol.token = FoxScanner.Minus THEN
  1197. identDef.vis := PublicRO;
  1198. NextSymbol;
  1199. ELSE
  1200. identDef.vis := Private;
  1201. END;
  1202. identDef.external := NIL;
  1203. IF symbol.token = FoxScanner.Becomes THEN
  1204. NextSymbol;
  1205. NEW(identDef.initializer);
  1206. ConstExprP(FoxScanner.Colon, FoxScanner.Comma, identDef.initializer);
  1207. ELSIF symbol.token = FoxScanner.Extern THEN
  1208. NextSymbol;
  1209. identDef.external := Strings.NewString(symbol.string^);
  1210. Check(FoxScanner.String);
  1211. TRACE (identDef.external^);
  1212. END;
  1213. END IdentDefP;
  1214. PROCEDURE Check(token: FoxScanner.Token);
  1215. BEGIN
  1216. IF symbol.token = token THEN
  1217. (* correct *)
  1218. ELSE
  1219. (* error *)
  1220. KernelLog.String("******* Check error ********** ");
  1221. KernelLog.Int(symbol.position.start, 0);
  1222. KernelLog.Ln;
  1223. hasError := TRUE;
  1224. (*HALT(33);*)
  1225. END;
  1226. NextSymbol;
  1227. END Check;
  1228. PROCEDURE Error(pos : LONGINT);
  1229. BEGIN
  1230. KernelLog.String("ModuleParser: Error at pos "); KernelLog.Int(pos, 0); KernelLog.Ln;
  1231. END Error;
  1232. END Parser;
  1233. ListEntry = POINTER TO RECORD
  1234. module : Module;
  1235. next : ListEntry;
  1236. END;
  1237. ModuleCache = OBJECT
  1238. VAR
  1239. head : ListEntry; (* private *)
  1240. nofModules : LONGINT;
  1241. PROCEDURE Add(module : Module);
  1242. VAR entry : ListEntry;
  1243. BEGIN {EXCLUSIVE}
  1244. ASSERT((module # NIL) & (module.ident.name # NIL));
  1245. entry := FindEntry(module.ident.name^);
  1246. IF (entry = NIL) THEN
  1247. NEW(entry);
  1248. entry.next := head.next;
  1249. head.next := entry;
  1250. module.resolved := FALSE;
  1251. INC(nofModules);
  1252. END;
  1253. entry.module := module;
  1254. END Add;
  1255. PROCEDURE Get(CONST moduleName : ARRAY OF CHAR) : Module;
  1256. VAR module : Module; entry : ListEntry;
  1257. BEGIN {EXCLUSIVE}
  1258. entry := FindEntry(moduleName);
  1259. IF (entry # NIL) THEN
  1260. module := entry.module;
  1261. ELSE
  1262. module := NIL;
  1263. END;
  1264. RETURN module;
  1265. END Get;
  1266. PROCEDURE Enumerate(enumerator : EnumeratorProc);
  1267. VAR entry : ListEntry;
  1268. BEGIN
  1269. ASSERT(enumerator # NIL);
  1270. entry := head.next;
  1271. WHILE (entry # NIL) DO
  1272. enumerator(entry.module, SELF);
  1273. entry := entry.next;
  1274. END;
  1275. END Enumerate;
  1276. PROCEDURE FindEntry(CONST moduleName : ARRAY OF CHAR) : ListEntry; (* private *)
  1277. VAR entry : ListEntry;
  1278. BEGIN
  1279. entry := head.next;
  1280. WHILE (entry # NIL) & (entry.module.ident.name^ # moduleName) DO entry := entry.next; END;
  1281. RETURN entry;
  1282. END FindEntry;
  1283. PROCEDURE &Init; (* private *)
  1284. BEGIN
  1285. NEW(head); head.module := NIL; head.next := NIL;
  1286. nofModules := 0;
  1287. END Init;
  1288. END ModuleCache;
  1289. EnumeratorProc = PROCEDURE {DELEGATE} (module : Module; cache : ModuleCache);
  1290. PROCEDURE AppendLast(head, node: NodeList);
  1291. VAR n: NodeList;
  1292. BEGIN
  1293. IF head = NIL THEN RETURN END;
  1294. n := head;
  1295. WHILE n.next # NIL DO
  1296. n := n.next;
  1297. END;
  1298. n.next := node;
  1299. END AppendLast;
  1300. PROCEDURE SplitName*(CONST name : ARRAY OF CHAR; VAR moduleName, typeName : ARRAY OF CHAR);
  1301. VAR i, j : LONGINT;
  1302. BEGIN
  1303. IF Strings.ContainsChar(name, ".", FALSE) THEN
  1304. i := 0;
  1305. WHILE (i < LEN(name)) & (name[i] # ".") DO moduleName[i] := name[i]; INC(i); END;
  1306. moduleName[i] := 0X;
  1307. INC(i); (* skip "." *)
  1308. j := 0;
  1309. WHILE (i < LEN(name)) & (name[i] # 0X) DO typeName[j] := name[i]; INC(i); INC(j); END;
  1310. typeName[j] := 0X;
  1311. ELSE
  1312. COPY("", moduleName);
  1313. COPY(name, typeName);
  1314. END;
  1315. END SplitName;
  1316. PROCEDURE FindType(CONST name : ARRAY OF CHAR; type : LONGINT; definitionModule : Module; cache : ModuleCache) : TypeDecl;
  1317. VAR
  1318. module : Module; import : Import; typeDecl : TypeDecl;
  1319. moduleName, importName, typeName : ARRAY 256 OF CHAR;
  1320. context : ARRAY 32 OF CHAR;
  1321. filename : Files.FileName;
  1322. PROCEDURE FileExists(CONST filename : ARRAY OF CHAR) : BOOLEAN;
  1323. VAR file : Files.File;
  1324. BEGIN
  1325. file := Files.Old(filename);
  1326. RETURN (file # NIL);
  1327. END FileExists;
  1328. PROCEDURE GenerateFilename(CONST prefix, context, moduleName, fileExtension: ARRAY OF CHAR) : Files.FileName;
  1329. VAR filename : Files.FileName;
  1330. BEGIN
  1331. COPY(prefix, filename);
  1332. IF (context # "") THEN Strings.Append(filename, context); Strings.Append(filename, "."); END;
  1333. Strings.Append(filename, moduleName); Strings.Append(filename, fileExtension);
  1334. RETURN filename;
  1335. END GenerateFilename;
  1336. (* Simple heuristics that tries to find the filename of a given module name *)
  1337. PROCEDURE FindCorrectFilename(CONST context, moduleName : ARRAY OF CHAR) : Files.FileName;
  1338. VAR filename : Files.FileName;
  1339. BEGIN
  1340. filename := GenerateFilename("", context, moduleName, ".Mod");
  1341. IF ~FileExists(filename) THEN
  1342. filename := GenerateFilename("I386.", context, moduleName, ".Mod");
  1343. IF ~FileExists(filename) THEN
  1344. filename := GenerateFilename("Windows.", context, moduleName, ".Mod");
  1345. IF ~FileExists(filename) THEN
  1346. filename := GenerateFilename("Unix.", context, moduleName, ".Mod");
  1347. IF ~FileExists(filename) THEN
  1348. filename := GenerateFilename("Oberon-", context, moduleName, ".Mod");
  1349. IF ~FileExists(filename) THEN
  1350. filename := GenerateFilename("", context, moduleName, ".Mod");
  1351. END;
  1352. END;
  1353. END;
  1354. END;
  1355. END;
  1356. RETURN filename;
  1357. END FindCorrectFilename;
  1358. BEGIN
  1359. ASSERT((definitionModule # NIL) & (cache # NIL));
  1360. SplitName(name, moduleName, typeName);
  1361. import := definitionModule.FindImport(moduleName);
  1362. importName := "";
  1363. IF (import # NIL) THEN
  1364. IF (import.context # NIL) THEN
  1365. COPY(import.context.name^, context);
  1366. ELSIF (definitionModule.context # NIL) THEN
  1367. COPY(definitionModule.context.name^, context);
  1368. ELSE
  1369. COPY("", context);
  1370. END;
  1371. IF (import.alias # NIL) THEN
  1372. Strings.Append(importName, import.alias.name^);
  1373. ELSE
  1374. Strings.Append(importName, import.ident.name^);
  1375. END;
  1376. END;
  1377. IF (importName # "") THEN
  1378. module := cache.Get(importName);
  1379. IF (module = NIL) THEN
  1380. filename := FindCorrectFilename(context, importName);
  1381. module := ParseFile(filename, NIL);
  1382. IF (module # NIL) THEN cache.Add(module); END;
  1383. END;
  1384. ELSE
  1385. module := definitionModule;
  1386. END;
  1387. typeDecl := NIL;
  1388. IF (module # NIL) THEN
  1389. typeDecl := module.FindTypeDecl(typeName);
  1390. IF (typeDecl # NIL) & (type # 3) & (((typeDecl.type.record = NIL) & (type = 0)) OR ((typeDecl.type.object = NIL) & (type = 1)) OR
  1391. (((typeDecl.type.pointer = NIL) OR (typeDecl.type.pointer.type.record = NIL)) & (type = 2))) THEN
  1392. typeDecl := NIL; (* wrong type *)
  1393. END;
  1394. ELSE
  1395. KernelLog.String("Module "); KernelLog.String(moduleName); KernelLog.String(" not found.");
  1396. KernelLog.Ln;
  1397. END;
  1398. RETURN typeDecl;
  1399. END FindType;
  1400. PROCEDURE ResolveTypeHierarchy(module : Module; cache : ModuleCache);
  1401. VAR typeDecl, td : TypeDecl;
  1402. BEGIN
  1403. ASSERT(module # NIL);
  1404. IF ~module.resolved & (module.declSeq # NIL) & (module.declSeq.typeDecl # NIL) THEN
  1405. typeDecl := module.declSeq.typeDecl;
  1406. WHILE (typeDecl # NIL) DO
  1407. IF (typeDecl.type.record # NIL) & (typeDecl.type.record.super # NIL) THEN
  1408. td := FindType(typeDecl.type.record.super.ident.name^, 0, module, cache);
  1409. IF (td # NIL) THEN
  1410. typeDecl.type.record.superPtr := td.type.record;
  1411. END;
  1412. ELSIF (typeDecl.type.pointer # NIL) & (typeDecl.type.pointer.type.record # NIL) & (typeDecl.type.pointer.type.record.super # NIL) THEN
  1413. td := FindType(typeDecl.type.pointer.type.record.super.ident.name^, 2, module, cache);
  1414. IF (td # NIL) THEN
  1415. typeDecl.type.pointer.type.record.superPtr := td.type.pointer.type.record;
  1416. END;
  1417. ELSIF (typeDecl.type.object # NIL) & (typeDecl.type.object.super # NIL) THEN
  1418. td := FindType(typeDecl.type.object.super.ident.name^, 1, module, cache);
  1419. IF (td # NIL) THEN
  1420. typeDecl.type.object.superPtr := td.type.object;
  1421. END;
  1422. END;
  1423. IF (typeDecl.next # NIL) THEN
  1424. typeDecl := typeDecl.next (TypeDecl);
  1425. ELSE
  1426. typeDecl := NIL;
  1427. END;
  1428. END;
  1429. module.resolved := TRUE;
  1430. END;
  1431. END ResolveTypeHierarchy;
  1432. PROCEDURE ResolveMethodOverwrites(module : Module; cache : ModuleCache);
  1433. VAR typeDecl : TypeDecl; method, procDecl : ProcDecl; superClass : Object;
  1434. BEGIN
  1435. IF module.resolved & (module.declSeq # NIL) & (module.declSeq.typeDecl # NIL) THEN
  1436. typeDecl := module.declSeq.typeDecl;
  1437. WHILE (typeDecl # NIL) DO
  1438. IF (typeDecl.type.object # NIL) & (typeDecl.type.object.declSeq # NIL) THEN
  1439. method := typeDecl.type.object.declSeq.procDecl;
  1440. WHILE (method # NIL) DO
  1441. superClass := typeDecl.type.object.superPtr;
  1442. WHILE (superClass # NIL) DO
  1443. procDecl := superClass.FindProcDecl(method.head.identDef.ident.name^);
  1444. IF (procDecl # NIL) THEN
  1445. INCL(procDecl.head.modifiers, Overwritten);
  1446. INCL(method.head.modifiers, Overwrite)
  1447. END;
  1448. superClass := superClass.superPtr;
  1449. END;
  1450. IF (method.next # NIL) THEN
  1451. method := method.next (ProcDecl);
  1452. ELSE
  1453. method := NIL;
  1454. END;
  1455. END;
  1456. END;
  1457. IF (typeDecl.next # NIL) THEN
  1458. typeDecl := typeDecl.next (TypeDecl);
  1459. ELSE
  1460. typeDecl := NIL;
  1461. END;
  1462. END;
  1463. END;
  1464. END ResolveMethodOverwrites;
  1465. PROCEDURE ParseFile*(CONST filename : ARRAY OF CHAR; diagnostics : Diagnostics.Diagnostics) : Module;
  1466. VAR
  1467. module : Module;
  1468. scanner : FoxScanner.Scanner;
  1469. text : Texts.Text; reader : TextUtilities.TextReader;
  1470. format, res : LONGINT;
  1471. BEGIN
  1472. NEW(text);
  1473. TextUtilities.LoadAuto(text, filename, format, res);
  1474. IF (res = 0) THEN
  1475. NEW(reader, text);
  1476. scanner := FoxScanner.NewScanner(filename, reader, 0, diagnostics);
  1477. Parse(scanner, module);
  1478. ELSIF (diagnostics # NIL) THEN
  1479. diagnostics.Error("ModuleParser", Streams.Invalid, "File not found");
  1480. END;
  1481. RETURN module
  1482. END ParseFile;
  1483. (** Parse all modules required to set the Record.superPtr and Object.superPtr fields and set these fields*)
  1484. PROCEDURE SetSuperTypes*(module: Module);
  1485. VAR cache : ModuleCache; nofModules : LONGINT;
  1486. BEGIN
  1487. ASSERT(module # NIL);
  1488. NEW(cache);
  1489. cache.Add(module);
  1490. ResolveTypeHierarchy(module, cache);
  1491. nofModules := -1;
  1492. WHILE (nofModules # cache.nofModules) DO
  1493. nofModules := cache.nofModules;
  1494. cache.Enumerate(ResolveTypeHierarchy);
  1495. END;
  1496. cache.Enumerate(ResolveMethodOverwrites);
  1497. END SetSuperTypes;
  1498. PROCEDURE Parse*(scanner: FoxScanner.Scanner; VAR module: Module);
  1499. VAR parser: Parser;
  1500. BEGIN
  1501. NEW(parser, scanner);
  1502. parser.ModuleP(module);
  1503. END Parse;
  1504. END ModuleParser.
  1505. PC.Compile \s ModuleParser.Mod ~
  1506. Builder.Compile \s ModuleParser.Mod ~
  1507. System.DeleteFiles ModuleParser.Obx ~
  1508. System.Free ModuleParser ~
  1509. Decoder.Decode ModuleParser ~