2
0

ModuleParser.Mod 45 KB

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