1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636 |
- MODULE ModuleParser; (** AUTHOR "mb"; PURPOSE "Active Oberon parser for use with ModuleTrees **)
- (**
- * Notes:
- * - The Module node's parent is the module node itself
- *)
- IMPORT
- Strings, Files, Diagnostics, FoxScanner, KernelLog, Texts, TextUtilities;
- CONST
- (* visibilities *)
- Public* = 1;
- PublicRO* = 2;
- Private* = 3;
- (* block modifiers *)
- Exclusive* = 1;
- Active* = 2;
- Safe* = 3;
- Priority* = 4;
- Unchecked* = 5;
- Uncooperative* = 6;
- HasExclusiveBlock* = 7;
- (* procedure modifiers (in addition to block modifiers) *)
- Overwrite* = 8; (* procedure overwrites procedure in superclass *)
- Overwritten* = 9; (* procedure is overwritten in subclass *)
- Interrupt* = 10; (* procedure is an interrupt handler that might be called asynchronously *)
- ExclusiveStr = "EXCLUSIVE";
- ActiveStr = "ACTIVE";
- RealtimeStr = "REALTIME";
- SafeStr = "SAFE";
- PriorityStr = "PRIORITY";
- UncheckedStr = "UNCHECKED";
- UncooperativeStr = "UNCOOPERATIVE";
- NoPAFStr = "NOPAF"; FixedStr = "FIXED"; AlignedStr = "FIXED";
- DynamicStr = "DYNAMIC"; InterruptStr = "INTERRUPT"; PCOffsetStr = "PCOFFSET";
- TYPE
- InfoItem* = OBJECT
- VAR
- name*: Strings.String;
- pos*: LONGINT;
- END InfoItem;
- Node* = OBJECT
- VAR
- parent- : Node;
- PROCEDURE GetModule*() : Module;
- VAR node : Node; module : Module;
- BEGIN
- module := NIL;
- node := SELF;
- WHILE (node # NIL) & (node.parent # node) DO node := node.parent; END;
- IF (node # NIL) THEN
- module := node (Module);
- END;
- RETURN module;
- END GetModule;
- PROCEDURE &Init*(parent : Node);
- BEGIN
- SELF.parent := parent;
- END Init;
- END Node;
- NodeList* = OBJECT(Node);
- VAR
- next*: NodeList;
- END NodeList;
- Import* = OBJECT (NodeList)
- VAR
- ident*, alias*, context*: InfoItem;
- END Import;
- Definition* = OBJECT (NodeList)
- VAR
- ident*: InfoItem;
- refines*: Qualident;
- procs*: ProcHead;
- END Definition;
- Type* = OBJECT(Node)
- VAR
- qualident*: Qualident;
- array*: Array;
- record*: Record;
- pointer*: Pointer;
- object*: Object;
- enum*: Enum;
- cell*: Cell;
- port*: Port;
- procedure*: Procedure;
- END Type;
- Array* = OBJECT(Node)
- VAR
- open*: BOOLEAN;
- len*: InfoItem;
- base*: Type;
- END Array;
- Record* = OBJECT(Node)
- VAR
- super*: Qualident;
- superPtr* : Record;
- fieldList*: FieldDecl;
- END Record;
- FieldDecl* = OBJECT (NodeList)
- VAR
- identList*: IdentList;
- type*: Type;
- END FieldDecl;
- Pointer* = OBJECT(Node)
- VAR
- type*: Type;
- END Pointer;
- Enum* = OBJECT(Node)
- VAR identList*: IdentList;
- END Enum;
- Port*= OBJECT(Node)
- END Port;
- Cell*= OBJECT(Node)
- VAR
- modifiers* : SET;
- declSeq*: DeclSeq;
- bodyPos- : LONGINT;
- formalPars*: FormalPars;
- PROCEDURE FindProcDecl*(CONST name : ARRAY OF CHAR) : ProcDecl;
- VAR procDecl : ProcDecl;
- BEGIN
- IF (declSeq # NIL) THEN
- procDecl := declSeq.FindProcDecl(name);
- ELSE
- procDecl := NIL;
- END;
- RETURN procDecl;
- END FindProcDecl;
- END Cell;
- Object* = OBJECT(Node)
- VAR
- super*, implements*: Qualident;
- superPtr* : Object;
- modifiers* : SET;
- declSeq*: DeclSeq;
- bodyPos- : LONGINT;
- PROCEDURE FindProcDecl*(CONST name : ARRAY OF CHAR) : ProcDecl;
- VAR procDecl : ProcDecl;
- BEGIN
- IF (declSeq # NIL) THEN
- procDecl := declSeq.FindProcDecl(name);
- ELSE
- procDecl := NIL;
- END;
- RETURN procDecl;
- END FindProcDecl;
- END Object;
- Procedure* = OBJECT(Node)
- VAR
- delegate*: BOOLEAN;
- formalPars*: FormalPars;
- END Procedure;
- DeclSeq* = OBJECT (NodeList)
- VAR
- constDecl*: ConstDecl;
- typeDecl*: TypeDecl;
- varDecl*: VarDecl;
- procDecl*: ProcDecl;
- PROCEDURE FindProcDecl*(CONST name : ARRAY OF CHAR) : ProcDecl;
- VAR pd : ProcDecl;
- BEGIN
- pd := procDecl;
- WHILE (pd # NIL) & (pd.head.identDef.ident.name^ # name) DO
- IF (pd.next # NIL) THEN
- pd := pd.next (ProcDecl);
- ELSE
- pd := NIL;
- END;
- END;
- ASSERT((pd = NIL) OR (pd.head.identDef.ident.name^ = name));
- RETURN pd;
- END FindProcDecl;
- PROCEDURE FindTypeDecl*(CONST name : ARRAY OF CHAR) : TypeDecl;
- VAR td : TypeDecl;
- BEGIN
- td := typeDecl;
- WHILE (td # NIL) & (td.identDef.ident.name^ # name) DO
- IF (td.next # NIL) THEN
- td := td.next (TypeDecl);
- ELSE
- td := NIL;
- END;
- END;
- ASSERT((td = NIL) OR (td.identDef.ident.name^ = name));
- RETURN td;
- END FindTypeDecl;
- END DeclSeq;
- ConstDecl* = OBJECT (NodeList)
- VAR
- identDef*: IdentDef;
- constExpr*: Expr;
- expr*: InfoItem;
- END ConstDecl;
- TypeDecl* = OBJECT (NodeList)
- VAR
- identDef*: IdentDef;
- type*: Type;
- END TypeDecl;
- VarDecl* = OBJECT (NodeList)
- VAR
- identList*: IdentList;
- type*: Type;
- END VarDecl;
- ProcDecl* = OBJECT (NodeList)
- VAR
- head*: ProcHead;
- declSeq*: DeclSeq;
- bodyPos- : LONGINT;
- END ProcDecl;
- ProcHead* = OBJECT (NodeList)
- VAR
- sysFlag*: InfoItem;
- constructor*, inline*, operator*: BOOLEAN;
- modifiers* : SET;
- identDef*: IdentDef;
- formalPars*: FormalPars;
- END ProcHead;
- FormalPars* = OBJECT(Node)
- VAR
- fpSectionList*: FPSection;
- returnType*: Type;
- END FormalPars;
- FPSection* = OBJECT (NodeList)
- VAR
- var*, const*: BOOLEAN;
- identList*: IdentList;
- type*: Type;
- END FPSection;
- Expr* = OBJECT (NodeList)
- VAR
- simpleExprL*, simpleExprR*: SimpleExpr;
- relation*: InfoItem;
- END Expr;
- SimpleExpr* = OBJECT (NodeList)
- VAR
- sign*: InfoItem;
- termL*, termR*: Term;
- addOp*: AddOp;
- END SimpleExpr;
- Term* = OBJECT (NodeList)
- VAR
- factorL*, factorR*: Factor;
- mulOp*: MulOp;
- END Term;
- Factor* = OBJECT (NodeList)
- VAR
- designator*: Designator;
- number*, string*, nil*, bool*: InfoItem;
- set*: Element;
- expr*: Expr;
- factor*: Factor;
- END Factor;
- Designator* = OBJECT (NodeList)
- VAR
- qualident*: Qualident;
- ident*, arrowUp*: InfoItem;
- exprList*: Expr;
- END Designator;
- Qualident* = OBJECT (NodeList)
- VAR
- ident*: InfoItem;
- END Qualident;
- Element* = OBJECT (NodeList)
- VAR
- expr*, upToExpr*: Expr;
- END Element;
- MulOp* = OBJECT (NodeList)
- VAR
- op*: InfoItem;
- END MulOp;
- AddOp* = OBJECT (NodeList)
- VAR
- op*: InfoItem;
- END AddOp;
- IdentDef* = OBJECT
- VAR
- ident*: InfoItem;
- vis*: SHORTINT;
- initializer*: InfoItem;
- external*: Strings.String;
- END IdentDef;
- IdentList* = OBJECT (NodeList)
- VAR
- identDef*: IdentDef;
- END IdentList;
- Module* = OBJECT(Node)
- VAR
- ident*, context*: InfoItem;
- importList*: Import;
- modifiers* : SET;
- definitions*: Definition;
- declSeq*: DeclSeq;
- bodyPos- : LONGINT;
- hasError-: BOOLEAN;
- resolved* : BOOLEAN;
- PROCEDURE FindTypeDecl*(CONST name : ARRAY OF CHAR) : TypeDecl;
- VAR typeDecl : TypeDecl;
- BEGIN
- IF (declSeq # NIL) THEN
- typeDecl := declSeq.FindTypeDecl(name);
- ELSE
- typeDecl := NIL;
- END;
- RETURN typeDecl;
- END FindTypeDecl;
- PROCEDURE FindImport*(CONST name : ARRAY OF CHAR) : Import;
- VAR import : Import;
- BEGIN
- import := importList;
- WHILE (import # NIL) & ((import.ident = NIL) OR (import.ident.name^ # name)) DO
- IF (import.next # NIL) THEN
- import := import.next (Import);
- ELSE
- import := NIL;
- END;
- END;
- RETURN import;
- END FindImport;
- END Module;
- Parser = OBJECT
- VAR
- symbol : FoxScanner.Symbol;
- scanner: FoxScanner.Scanner;
- hasError: BOOLEAN;
- PROCEDURE & Init*(scanner: FoxScanner.Scanner);
- BEGIN
- ASSERT(scanner # NIL);
- SELF.scanner := scanner;
- hasError := FALSE;
- END Init;
- PROCEDURE NextSymbol;
- VAR ignore : BOOLEAN;
- BEGIN
- ignore := scanner.GetNextSymbol(symbol);
- WHILE (symbol.token = FoxScanner.Comment) DO ignore := scanner.GetNextSymbol(symbol); END;
- END NextSymbol;
- PROCEDURE ModuleP(VAR module: Module);
- VAR
- modName: FoxScanner.IdentifierString;
- definition: Definition;
- BEGIN
- NextSymbol;
- IF (symbol.token = FoxScanner.Module) OR (symbol.token = FoxScanner.CellNet) THEN
- NEW(module, NIL); module.parent := module;
- NextSymbol;
- IF symbol.token = FoxScanner.Identifier THEN
- NEW(module.ident);
- COPY(symbol.identifierString, modName);
- module.ident.name := Strings.NewString(symbol.identifierString);
- module.ident.pos := symbol.position.start;
- END;
- NextSymbol;
- IF symbol.token = FoxScanner.In THEN
- NextSymbol;
- IF symbol.token = FoxScanner.Identifier THEN
- NEW(module.context);
- module.context.name := Strings.NewString(symbol.identifierString);
- module.context.pos := symbol.position.start;
- END;
- Check (FoxScanner.Identifier);
- END;
- IF symbol.token = FoxScanner.LeftBrace THEN
- WHILE (symbol.token # FoxScanner.Semicolon) & (symbol.token # FoxScanner.EndOfText) DO NextSymbol END;
- END;
- Check(FoxScanner.Semicolon);
- IF symbol.token = FoxScanner.Import THEN
- NEW(module.importList, module);
- ImportListP(module.importList);
- END;
- WHILE symbol.token = FoxScanner.Definition DO
- NEW(definition, module);
- DefinitionP(definition);
- IF module.definitions = NIL THEN module.definitions := definition
- ELSE AppendLast(module.definitions, definition)
- END;
- END;
- IF (symbol.token = FoxScanner.Const) OR (symbol.token = FoxScanner.Type) OR
- (symbol.token = FoxScanner.Var) OR (symbol.token = FoxScanner.Procedure) OR (symbol.token = FoxScanner.Operator) THEN
- NEW(module.declSeq, module);
- DeclSeqP(module.declSeq);
- END;
- IF (symbol.token = FoxScanner.Begin) THEN
- module.bodyPos := symbol.position.start;
- ELSE
- module.bodyPos := 0;
- END;
- BodyP(FALSE, module.modifiers);
- IF (symbol.token = FoxScanner.Identifier) & (symbol.identifierString = modName) THEN
- (* correct *)
- ELSE
- (* maybe missing END or wrong module name *)
- hasError := TRUE;
- KernelLog.String("err3: "); KernelLog.Int(symbol.position.start, 0); KernelLog.Ln;
- END;
- module.hasError := hasError;
- END;
- END ModuleP;
- PROCEDURE ImportListP(import: Import);
- VAR newImport: Import;
- BEGIN
- NextSymbol;
- WHILE symbol.token = FoxScanner.Identifier DO
- NEW(import.ident);
- import.ident.name := Strings.NewString(symbol.identifierString);
- import.ident.pos := symbol.position.start;
- NextSymbol; (* avoids endless loop *)
- IF symbol.token = FoxScanner.Becomes THEN
- NextSymbol;
- IF symbol.token = FoxScanner.Identifier THEN
- NEW(import.alias);
- import.alias.name := Strings.NewString(symbol.identifierString);
- import.alias.pos := symbol.position.start;
- NextSymbol;
- ELSE
- (* Error *)
- hasError := TRUE;
- KernelLog.String("err2: "); KernelLog.Int(symbol.position.start, 0); KernelLog.Ln;
- END;
- END;
- IF symbol.token = FoxScanner.In THEN
- NextSymbol;
- IF symbol.token = FoxScanner.Identifier THEN
- NEW(import.context);
- import.context.name := Strings.NewString(symbol.identifierString);
- import.context.pos := symbol.position.start;
- END;
- Check (FoxScanner.Identifier);
- END;
- IF symbol.token = FoxScanner.Comma THEN
- NextSymbol;
- END;
- NEW(newImport, import.parent);
- import.next := newImport;
- import := newImport;
- END;
- Check(FoxScanner.Semicolon);
- END ImportListP;
- PROCEDURE DefinitionP(definition: Definition);
- VAR
- procHead: ProcHead;
- BEGIN
- IF symbol.token = FoxScanner.Definition THEN
- NextSymbol;
- IF symbol.token = FoxScanner.Identifier THEN
- NEW(definition.ident);
- definition.ident.name := Strings.NewString(symbol.identifierString);
- definition.ident.pos := symbol.position.start;
- NextSymbol;
- END;
- WHILE symbol.token = FoxScanner.Semicolon DO NextSymbol END;
- (*? IF symbol.token = FoxScanner.Refines THEN
- NextSymbol;
- NEW(definition.refines, definition);
- QualidentP(definition.refines);
- END; *)
- WHILE (symbol.token = FoxScanner.Procedure) OR (symbol.token = FoxScanner.Operator) DO
- NEW(procHead, definition);
- NextSymbol;
- ProcHeadP(procHead);
- IF definition.procs = NIL THEN definition.procs := procHead
- ELSE AppendLast(definition.procs, procHead)
- END;
- Check(FoxScanner.Semicolon);
- END;
- Check(FoxScanner.End);
- Check(FoxScanner.Identifier);
- WHILE symbol.token = FoxScanner.Semicolon DO NextSymbol END;
- END;
- END DefinitionP;
- PROCEDURE DeclSeqP(declSeq: DeclSeq);
- VAR
- constDecl: ConstDecl;
- typeDecl: TypeDecl;
- varDecl: VarDecl;
- procDecl: ProcDecl;
- PROCEDURE CheckEndOrSemicolon;
- BEGIN
- IF symbol.token # FoxScanner.End THEN
- REPEAT Check(FoxScanner.Semicolon) UNTIL symbol.token # FoxScanner.Semicolon
- END;
- END CheckEndOrSemicolon;
- BEGIN
- LOOP
- CASE symbol.token OF
- | FoxScanner.Const:
- NextSymbol;
- WHILE symbol.token = FoxScanner.Identifier DO
- NEW(constDecl, declSeq);
- ConstDeclP(constDecl);
- IF declSeq.constDecl = NIL THEN declSeq.constDecl := constDecl;
- ELSE AppendLast(declSeq.constDecl, constDecl);
- END;
- CheckEndOrSemicolon;
- (*Check(FoxScanner.Semicolon);*)
- END;
- | FoxScanner.Type:
- NextSymbol;
- WHILE symbol.token = FoxScanner.Identifier DO
- NEW(typeDecl, declSeq);
- TypeDeclP(typeDecl);
- IF declSeq.typeDecl = NIL THEN declSeq.typeDecl := typeDecl;
- ELSE AppendLast(declSeq.typeDecl, typeDecl);
- END;
- CheckEndOrSemicolon;
- (*Check(FoxScanner.Semicolon);*)
- END;
- | FoxScanner.Var:
- NextSymbol;
- WHILE symbol.token = FoxScanner.Identifier DO
- NEW(varDecl, declSeq);
- VarDeclP(varDecl);
- IF declSeq.varDecl = NIL THEN declSeq.varDecl := varDecl;
- ELSE AppendLast(declSeq.varDecl, varDecl);
- END;
- CheckEndOrSemicolon;
- (*Check(FoxScanner.Semicolon);*)
- END;
- | FoxScanner.Procedure, FoxScanner.Operator:
- WHILE (symbol.token = FoxScanner.Procedure) OR (symbol.token = FoxScanner.Operator) DO
- NextSymbol;
- NEW(procDecl, declSeq);
- ProcDeclP(procDecl);
- IF procDecl.head = NIL THEN
- procDecl := NIL
- ELSE
- IF declSeq.procDecl = NIL THEN declSeq.procDecl := procDecl;
- ELSE AppendLast(declSeq.procDecl, procDecl);
- END;
- END;
- CheckEndOrSemicolon;
- (*Check(FoxScanner.Semicolon);*)
- END;
- ELSE
- EXIT;
- END;
- END;
- END DeclSeqP;
- PROCEDURE ConstDeclP(const: ConstDecl);
- BEGIN
- NEW(const.identDef);
- IdentDefP(const.identDef);
- Check(FoxScanner.Equal);
- (* NEW(const.constExpr);
- ExprP(const.constExpr); *)
- NEW(const.expr);
- ConstExprP(FoxScanner.Semicolon, -1, const.expr);
- END ConstDeclP;
- PROCEDURE TypeDeclP(type: TypeDecl);
- BEGIN
- NEW(type.identDef);
- IdentDefP(type.identDef);
- Check(FoxScanner.Equal);
- NEW(type.type, type);
- TypeP(type.type);
- END TypeDeclP;
- PROCEDURE VarDeclP(var: VarDecl);
- VAR
- identDef: IdentDef;
- identList: IdentList;
-
- PROCEDURE Initializer;
- VAR expr: InfoItem;
- BEGIN
- Check (FoxScanner.Becomes); NEW (expr);
- ConstExprP(FoxScanner.Colon, FoxScanner.Comma, expr);
- END Initializer;
-
- BEGIN
- (*SysFlag;*)
- NEW(var.identList, var);
- NEW(var.identList.identDef);
- IdentDefP(var.identList.identDef);
- SysFlag;
- IF symbol.token = FoxScanner.Becomes THEN Initializer END;
- WHILE symbol.token = FoxScanner.Comma DO
- NextSymbol; (* avoids endless loop *)
- NEW(identDef);
- IdentDefP(identDef);
- SysFlag;
- IF symbol.token = FoxScanner.Becomes THEN Initializer END;
- NEW(identList, var);
- identList.identDef := identDef;
- AppendLast(var.identList, identList);
- END;
- Check(FoxScanner.Colon);
- NEW(var.type, var);
- TypeP(var.type);
- END VarDeclP;
- PROCEDURE ProcDeclP(proc: ProcDecl);
- VAR
- declSeq: DeclSeq;
- BEGIN
- NEW(proc.head, proc);
- ProcHeadP(proc.head);
- IF proc.head.identDef = NIL THEN proc.head := NIL; RETURN END;
- IF proc.head.identDef.external # NIL THEN RETURN END;
- Check(FoxScanner.Semicolon);
- IF (symbol.token = FoxScanner.Const) OR (symbol.token = FoxScanner.Var) OR
- (symbol.token = FoxScanner.Type) OR (symbol.token = FoxScanner.Procedure) OR (symbol.token = FoxScanner.Operator) THEN
- NEW(declSeq, proc);
- DeclSeqP(declSeq);
- IF proc.declSeq = NIL THEN proc.declSeq := declSeq;
- ELSE AppendLast(proc.declSeq, declSeq);
- END;
- END;
- IF (symbol.token = FoxScanner.Begin) THEN
- proc.bodyPos := symbol.position.start;
- ELSE
- proc.bodyPos := 0;
- END;
- BodyP(FALSE, proc.head.modifiers);
- NextSymbol; (* skip ident *)
- END ProcDeclP;
- PROCEDURE ProcHeadP(head: ProcHead);
- VAR forward: BOOLEAN;
- BEGIN
- ProcedureModifierP(head);
- (*SysFlag;*)
- CASE symbol.token OF
- | FoxScanner.Minus: head.inline := TRUE; NextSymbol;
- | FoxScanner.And: head.constructor := TRUE; NextSymbol;
- | FoxScanner.Times: (* ignore *) NextSymbol;
- | FoxScanner.Not: (* ignore *) NextSymbol;
- | FoxScanner.Arrow: (* ignore *) NextSymbol; forward := TRUE;
- | FoxScanner.String: head.operator := TRUE;
- | FoxScanner.Number: IF symbol.numberType = FoxScanner.Character THEN head.operator := TRUE END;
- ELSE
- END;
- NEW(head.identDef);
- IdentDefP(head.identDef);
- OSAIrq; (* tk: Compatibility to OSACompiler*)
- IF symbol.token = FoxScanner.LeftParenthesis THEN
- NEW(head.formalPars, head);
- FormalParsP(head.formalPars);
- END;
- IF forward THEN
- head.identDef := NIL;
- head.formalPars := NIL;
- END;
- END ProcHeadP;
- PROCEDURE SysFlag;
- VAR ignore: InfoItem;
- BEGIN
- IF symbol.token = FoxScanner.LeftBrace THEN
- NextSymbol;
- IF symbol.token # FoxScanner.RightBrace THEN
- LOOP
- Check(FoxScanner.Identifier);
- IF (symbol.token = FoxScanner.LeftParenthesis) THEN
- NextSymbol;
- NEW (ignore);
- ConstExprP (FoxScanner.RightParenthesis, -1, ignore);
- Check (FoxScanner.RightParenthesis);
- ELSIF (symbol.token = FoxScanner.Equal) THEN
- NextSymbol;
- NEW (ignore);
- ConstExprP (FoxScanner.RightBrace, FoxScanner.Comma, ignore);
- END;
- IF symbol.token # FoxScanner.Comma THEN EXIT END;
- NextSymbol;
- END;
- END;
- Check(FoxScanner.RightBrace);
- END;
- END SysFlag;
- (* tk: For OSA Compatibility *)
- PROCEDURE OSAIrq;
- BEGIN
- IF symbol.token = FoxScanner.LeftBracket THEN
- NextSymbol;
- Check(FoxScanner.Number);
- Check(FoxScanner.RightBracket);
- END;
- END OSAIrq;
- PROCEDURE FormalParsP(pars: FormalPars);
- VAR
- fpSection: FPSection;
- BEGIN
- NextSymbol;
- IF (symbol.token = FoxScanner.Var) OR (symbol.token = FoxScanner.Const) OR (symbol.token = FoxScanner.Identifier) THEN
- NEW(pars.fpSectionList, pars);
- FPSectionP(pars.fpSectionList);
- WHILE symbol.token = FoxScanner.Semicolon DO
- NextSymbol; (* avoids endless loop *)
- NEW(fpSection, pars.fpSectionList);
- FPSectionP(fpSection);
- AppendLast(pars.fpSectionList, fpSection);
- END;
- END;
- Check(FoxScanner.RightParenthesis);
- IF symbol.token = FoxScanner.Colon THEN
- NextSymbol;
- SysFlag;
- NEW(pars.returnType, pars);
- TypeP(pars.returnType)
- END;
- END FormalParsP;
- PROCEDURE FPSectionP(fpSection: FPSection);
- VAR
- identList: IdentList; dummy: InfoItem;
- BEGIN
- NEW(dummy);
- IF symbol.token = FoxScanner.Var THEN
- fpSection.var := TRUE;
- NextSymbol;
- ELSIF symbol.token = FoxScanner.Const THEN
- fpSection.const := TRUE;
- NextSymbol;
- END;
- IF symbol.token = FoxScanner.Identifier THEN
- (*StringPool.GetString(scanner.name, name);*)
- NEW(fpSection.identList, fpSection);
- NEW(fpSection.identList.identDef);
- IdentDefP(fpSection.identList.identDef);
- SysFlag;
- (*
- fpSection.identList.ident.name := Strings.NewString(name);
- fpSection.identList.ident.pos := symbol.position.start;
- NextSymbol;
- *)
- IF symbol.token = FoxScanner.Equal THEN NextSymbol; ConstExprP(FoxScanner.Comma, FoxScanner.Colon, dummy) END; (* added for optional parameters *)
- WHILE symbol.token = FoxScanner.Comma DO
- NEW(identList, fpSection.identList);
- NextSymbol;
- NEW(identList.identDef);
- IdentDefP(identList.identDef);
- SysFlag;
- AppendLast(fpSection.identList, identList);
- (*
- IF symbol.token = FoxScanner.Identifier THEN
- StringPool.GetString(scanner.name, name);
- NEW(identDef);
- NEW(identDef.ident);
- identDef.ident.name := Strings.NewString(name);
- identDef.ident.pos := symbol.position.start;
- AppendLast(fpSection.identlist, identDef);
- NextSymbol;
- END;
- *)
- IF symbol.token = FoxScanner.Equal THEN NextSymbol; ConstExprP(FoxScanner.Comma, FoxScanner.Colon, dummy) END; (* added for optional parameters *)
- END;
- Check(FoxScanner.Colon);
- NEW(fpSection.type, fpSection);
- TypeP(fpSection.type);
- END;
- END FPSectionP;
- PROCEDURE TypeP(type: Type);
- BEGIN
- CASE symbol.token OF
- | FoxScanner.Array: NextSymbol; NEW(type.array, type); ArrayP(type.array);
- | FoxScanner.Record: NextSymbol; NEW(type.record, type); RecordP(type.record);
- | FoxScanner.Pointer: NextSymbol; NEW(type.pointer, type); PointerP(type.pointer);
- | FoxScanner.Object: NextSymbol; NEW(type.object, type); ObjectP(type.object);
- | FoxScanner.Port: NextSymbol; NEW(type.port, type); PortP(type.port);
- | FoxScanner.Cell, FoxScanner.CellNet: NextSymbol; NEW(type.cell, type); CellP(type.cell);
- | FoxScanner.Enum: NextSymbol; NEW(type.enum, type); EnumP(type.enum);
- | FoxScanner.Procedure, FoxScanner.Operator: NextSymbol; NEW(type.procedure, type); ProcedureP(type.procedure);
- | FoxScanner.Identifier: NEW(type.qualident, type); QualidentP(type.qualident);
- | FoxScanner.Address, FoxScanner.Size: NEW(type.qualident, type); NEW(type.qualident.ident);
- type.qualident.ident.name := Strings.NewString(symbol.identifierString); type.qualident.ident.pos := symbol.position.start; NextSymbol;
- ELSE
- (* Error *)
- hasError := TRUE; KernelLog.String("err4: "); KernelLog.Int(symbol.position.start, 0); KernelLog.Ln;
- NextSymbol; (* ??? *)
- END;
- END TypeP;
- PROCEDURE ArrayP(array: Array);
- BEGIN
- SysFlag;
- IF symbol.token = FoxScanner.Of THEN
- array.open := TRUE;
- NEW(array.base, array);
- NextSymbol;
- TypeP(array.base);
- ELSE
- NEW(array.len);
- ConstExprP(FoxScanner.Of, FoxScanner.Comma, array.len);
- (*
- SimpleExprP(array.len);
- *)
- IF symbol.token = FoxScanner.Of THEN
- NEW(array.base, array);
- NextSymbol;
- TypeP(array.base);
- ELSIF symbol.token = FoxScanner.Comma THEN
- NEW(array.base, array);
- NEW(array.base.array, array);
- NextSymbol;
- ArrayP(array.base.array)
- ELSE
- (* Error *)
- hasError := TRUE;
- KernelLog.String("err1: "); KernelLog.Int(symbol.position.start, 0); KernelLog.Ln;
- END;
- END;
- END ArrayP;
- PROCEDURE RecordP(record: Record);
- BEGIN
- SysFlag;
- IF symbol.token = FoxScanner.LeftParenthesis THEN
- NextSymbol;
- NEW(record.super, record);
- QualidentP(record.super);
- Check(FoxScanner.RightParenthesis);
- END;
- WHILE symbol.token = FoxScanner.Semicolon DO NextSymbol END;
- IF symbol.token = FoxScanner.Identifier THEN
- NEW(record.fieldList, record);
- FieldListP(record.fieldList);
- END;
- Check(FoxScanner.End);
- END RecordP;
- PROCEDURE FieldListP(fieldList: FieldDecl);
- VAR fieldDecl: FieldDecl;
- BEGIN
- FieldDeclP(fieldList);
- WHILE symbol.token = FoxScanner.Semicolon DO
- NextSymbol;
- NEW(fieldDecl, fieldList);
- FieldDeclP(fieldDecl);
- AppendLast(fieldList, fieldDecl);
- END;
- END FieldListP;
- PROCEDURE FieldDeclP(fieldDecl: FieldDecl);
- VAR
- identDef: IdentDef;
- identList: IdentList;
- BEGIN
- IF symbol.token = FoxScanner.Identifier THEN
- NEW(fieldDecl.identList, fieldDecl);
- NEW(fieldDecl.identList.identDef);
- IdentDefP(fieldDecl.identList.identDef);
- SysFlag;
- WHILE symbol.token = FoxScanner.Comma DO
- NextSymbol;
- NEW(identDef);
- IdentDefP(identDef);
- SysFlag;
- NEW(identList, identList);
- identList.identDef := identDef;
- AppendLast(fieldDecl.identList, identList);
- END;
- Check(FoxScanner.Colon);
- NEW(fieldDecl.type, fieldDecl);
- TypeP(fieldDecl.type);
- END;
- END FieldDeclP;
- PROCEDURE PointerP(pointer: Pointer);
- BEGIN
- SysFlag;
- Check(FoxScanner.To);
- NEW(pointer.type, pointer);
- TypeP(pointer.type);
- END PointerP;
- PROCEDURE EnumP(enum: Enum);
- VAR identDef: IdentDef; identList: IdentList;
- BEGIN
- NEW(enum.identList, enum);
- NEW(enum.identList.identDef);
- IdentDefP(enum.identList.identDef);
- SysFlag;
- WHILE symbol.token = FoxScanner.Comma DO
- NextSymbol; (* avoids endless loop *)
- NEW(identDef);
- IdentDefP(identDef);
- NEW(identList, enum);
- identList.identDef := identDef;
- AppendLast(enum.identList, identList);
- END;
- Check(FoxScanner.End);
- END EnumP;
- PROCEDURE PortP(port: Port);
- BEGIN
- IF (symbol.token = FoxScanner.Out) OR (symbol.token = FoxScanner.In) THEN
- NextSymbol
- END;
- END PortP;
- PROCEDURE ObjectP(object: Object);
- VAR declSeq: DeclSeq;
- pos: LONGINT;
- (*? qualident: Qualident; *)
- BEGIN
- IF (symbol.token = FoxScanner.Semicolon) OR (symbol.token = FoxScanner.RightParenthesis) THEN RETURN END;
- SysFlag;
- IF symbol.token = FoxScanner.LeftParenthesis THEN
- NEW(object.super, object);
- NextSymbol;
- QualidentP(object.super);
- Check(FoxScanner.RightParenthesis);
- END;
- (*? IF symbol.token = FoxScanner.Implements THEN
- NEW(object.implements, object);
- NextSymbol;
- QualidentP(object.implements);
- WHILE symbol.token = FoxScanner.Comma DO
- NEW(qualident, object.implements);
- NextSymbol;
- QualidentP(qualident);
- AppendLast(object.implements, qualident);
- END;
- END; *)
- pos := -1;
- WHILE (symbol.token # FoxScanner.Begin) & (symbol.token # FoxScanner.End) & (symbol.token # FoxScanner.EndOfText) DO
- (* avoid endless-loop *)
- IF pos = symbol.position.start THEN NextSymbol END;
- pos := symbol.position.start;
- NEW(declSeq, object);
- DeclSeqP(declSeq);
- IF object.declSeq = NIL THEN object.declSeq := declSeq;
- ELSE AppendLast(object.declSeq, declSeq);
- END;
- END;
- IF (symbol.token = FoxScanner.Begin) THEN
- object.bodyPos := symbol.position.start;
- ELSE
- object.bodyPos := 0;
- END;
- BodyP(TRUE, object.modifiers);
- IF symbol.token = FoxScanner.Identifier THEN NextSymbol END;
- END ObjectP;
- PROCEDURE CellP(cell: Cell);
- VAR declSeq: DeclSeq;
- pos: LONGINT;
- (*? qualident: Qualident; *)
- BEGIN
- SysFlag;
- IF symbol.token = FoxScanner.LeftParenthesis THEN
- NEW(cell.formalPars, cell);
- FormalParsP(cell.formalPars);
- END;
- pos := -1;
- WHILE (symbol.token # FoxScanner.Begin) & (symbol.token # FoxScanner.End) & (symbol.token # FoxScanner.EndOfText) DO
- (* avoid endless-loop *)
- IF pos = symbol.position.start THEN NextSymbol END;
- pos := symbol.position.start;
- NEW(declSeq, cell);
- DeclSeqP(declSeq);
- IF cell.declSeq = NIL THEN cell.declSeq := declSeq;
- ELSE AppendLast(cell.declSeq, declSeq);
- END;
- END;
- IF (symbol.token = FoxScanner.Begin) THEN
- cell.bodyPos := symbol.position.start;
- ELSE
- cell.bodyPos := 0;
- END;
- BodyP(TRUE, cell.modifiers);
- IF symbol.token = FoxScanner.Identifier THEN NextSymbol END;
- END CellP;
- PROCEDURE ProcedureP(proc: Procedure);
- BEGIN
- SysFlag;
- IF symbol.token = FoxScanner.LeftBrace THEN
- NextSymbol;
- IF symbol.token # FoxScanner.Identifier THEN
- (* Error *)
- ELSIF symbol.identifierString = "DELEGATE" THEN
- proc.delegate := TRUE;
- END;
- NextSymbol;
- Check(FoxScanner.RightBrace);
- END;
- IF symbol.token = FoxScanner.LeftParenthesis THEN
- NEW(proc.formalPars, proc);
- FormalParsP(proc.formalPars);
- END;
- END ProcedureP;
- PROCEDURE ConstExprP(delimiter1, delimiter2: FoxScanner.Token; expr: InfoItem);
- VAR
- exprStr, name: ARRAY 1024 OF CHAR;
- longExprStr : Strings.String; (* for exprStr content lengths > LEN(exprStr) *)
- paren, brace, brak: LONGINT;
- PROCEDURE Add(CONST str: ARRAY OF CHAR);
- VAR len1, len2 : LONGINT;
- BEGIN
- len1 := Strings.Length(exprStr);
- len2 := Strings.Length(str);
- IF (len1 + len2 + 1 > LEN(exprStr)) THEN
- IF (longExprStr = NIL) THEN
- longExprStr := Strings.ConcatToNew(exprStr, str);
- ELSE
- (* assume that this happens almost never *)
- longExprStr := Strings.ConcatToNew(longExprStr^, exprStr);
- longExprStr := Strings.ConcatToNew(longExprStr^, str);
- END;
- exprStr := "";
- ELSE
- Strings.Append(exprStr, str);
- END;
- END Add;
- BEGIN
- expr.pos := symbol.position.start;
- IF (symbol.token = delimiter1) OR (symbol.token = delimiter2) THEN RETURN END;
- REPEAT
- CASE symbol.token OF
- | FoxScanner.LeftParenthesis: INC(paren); Add("(");
- | FoxScanner.RightParenthesis: DEC(paren); Add(")");
- | FoxScanner.LeftBrace: INC(brace); Add("{");
- | FoxScanner.RightBrace: DEC(brace); Add("}");
- | FoxScanner.LeftBracket: INC(brak); Add("[");
- | FoxScanner.RightBracket: DEC(brak); Add("]");
- | FoxScanner.Number: Add(symbol.identifierString);
- | FoxScanner.Nil: Add("NIL");
- | FoxScanner.True: Add("TRUE");
- | FoxScanner.False: Add("FALSE");
- | FoxScanner.Not: Add("~");
- | FoxScanner.Period: Add(".");
- | FoxScanner.Identifier: Add(symbol.identifierString);
- | FoxScanner.Comma: Add(", ");
- | FoxScanner.Plus: Add(" + ");
- | FoxScanner.Minus: Add(" - ");
- | FoxScanner.Times: Add(" * ");
- | FoxScanner.Upto: Add(" .. ");
- | FoxScanner.Equal: Add(" = ");
- | FoxScanner.Unequal: Add(" # ");
- | FoxScanner.Less: Add(" < ");
- | FoxScanner.LessEqual: Add(" <= ");
- | FoxScanner.Greater: Add(" > ");
- | FoxScanner.GreaterEqual: Add(" >= ");
- | FoxScanner.In: Add(" IN ");
- | FoxScanner.Is: Add(" IS ");
- | FoxScanner.Div: Add(" DIV ");
- | FoxScanner.Mod: Add(" MOD ");
- | FoxScanner.Slash: Add(" / ");
- | FoxScanner.And: Add(" & ");
- | FoxScanner.Or: Add(" OR ");
- | FoxScanner.String: name[0] := '"'; name[1] := 0X; Add(name); Add(symbol.string^); Add(name);
- | FoxScanner.Arrow: Add("^");
- ELSE
- (* error *)
- hasError := TRUE;
- END;
- NextSymbol;
- (* urgh, what an ugly condition ... *)
- UNTIL (((symbol.token = delimiter1) OR (symbol.token = delimiter2)) & (paren = 0) & (brace = 0) & (brak = 0)) OR (symbol.token = FoxScanner.EndOfText);
- IF (longExprStr = NIL) THEN
- expr.name := Strings.NewString(exprStr);
- ELSE
- expr.name := Strings.ConcatToNew(longExprStr^, exprStr);
- END;
- END ConstExprP;
- PROCEDURE BlockModifierP(allowBody : BOOLEAN; VAR modifiers : SET);
- VAR ignore : InfoItem;
- BEGIN
- modifiers := {};
- IF symbol.token = FoxScanner.LeftBrace THEN
- NextSymbol;
- LOOP
- IF symbol.token = FoxScanner.Identifier THEN
- IF symbol.identifierString = ExclusiveStr THEN
- modifiers := modifiers + {Exclusive};
- NextSymbol;
- ELSIF allowBody & (symbol.identifierString = ActiveStr) THEN
- modifiers := modifiers + {Active};
- NextSymbol
- ELSIF allowBody & (symbol.identifierString = RealtimeStr) THEN
- NextSymbol;
- ELSIF allowBody & (symbol.identifierString = SafeStr) THEN
- modifiers := modifiers + {Safe};
- NextSymbol
- ELSIF allowBody & (symbol.identifierString = PriorityStr) THEN
- modifiers := modifiers + {Priority};
- NextSymbol;
- IF symbol.token = FoxScanner.LeftParenthesis THEN
- NextSymbol;
- NEW(ignore);
- ConstExprP(FoxScanner.RightParenthesis, -1, ignore);
- Check(FoxScanner.RightParenthesis);
- END;
- ELSIF symbol.identifierString = UncheckedStr THEN
- modifiers := modifiers + {Unchecked};
- NextSymbol;
- ELSIF symbol.identifierString = UncooperativeStr THEN
- modifiers := modifiers + {Uncooperative};
- NextSymbol;
- ELSE
- Error(symbol.position.start); NextSymbol (* skip the ident, probably a typo *)
- END;
- END;
- IF symbol.token # FoxScanner.Comma THEN EXIT END;
- NextSymbol
- END;
- Check(FoxScanner.RightBrace);
- END;
- END BlockModifierP;
- PROCEDURE ProcedureModifierP(procHead: ProcHead);
- VAR
- value: LONGINT; ignore: InfoItem;
- BEGIN
- IF symbol.token = FoxScanner.LeftBrace THEN
- NextSymbol;
- IF symbol.token # FoxScanner.RightBrace THEN
- LOOP
- IF symbol.token = FoxScanner.Identifier THEN
- IF symbol.identifierString = InterruptStr THEN NextSymbol; procHead.modifiers := procHead.modifiers + {Interrupt}
- ELSE NextSymbol;
- END;
- ELSE Error(symbol.position.start); NextSymbol; (* skip the ident, probably a typo *)
- END;
- IF (symbol.token = FoxScanner.LeftParenthesis) THEN
- NextSymbol;
- NEW (ignore);
- ConstExprP (FoxScanner.RightParenthesis, -1, ignore);
- Check (FoxScanner.RightParenthesis);
- ELSIF (symbol.token = FoxScanner.Equal) THEN
- NextSymbol;
- NEW (ignore);
- ConstExprP (FoxScanner.Comma, FoxScanner.RightBrace, ignore);
- END;
- IF symbol.token # FoxScanner.Comma THEN EXIT END;
- NextSymbol;
- END
- END;
- Check(FoxScanner.RightBrace)
- END
- END ProcedureModifierP;
- PROCEDURE ModifierValueP(VAR value: LONGINT);
- BEGIN
- IF symbol.token = FoxScanner.Equal THEN
- NextSymbol; Check(FoxScanner.Number); value := symbol.integer
- ELSIF symbol.token = FoxScanner.LeftParenthesis THEN
- NextSymbol; Check(FoxScanner.Number); value := symbol.integer; Check(FoxScanner.RightParenthesis)
- ELSE
- Error(symbol.position.start); NextSymbol
- END
- END ModifierValueP;
- PROCEDURE BodyP(allowBody : BOOLEAN; VAR modifiers : SET);
- VAR end, lastToken: LONGINT; m : SET; first : BOOLEAN;
- BEGIN
- IF symbol.token = FoxScanner.Begin THEN
- end := 1;
- first := TRUE;
- REPEAT
- lastToken := symbol.token;
- NextSymbol;
- IF (lastToken = FoxScanner.Begin) & (symbol.token = FoxScanner.LeftBrace) THEN
- BlockModifierP(allowBody, m);
- IF first THEN
- allowBody := FALSE;
- modifiers := m;
- ELSE
- IF m * {Exclusive} # {} THEN
- modifiers := modifiers + {HasExclusiveBlock};
- END;
- END;
- END;
- first := FALSE;
- CASE symbol.token OF
- | FoxScanner.Begin: INC(end);
- | FoxScanner.If, FoxScanner.Case, FoxScanner.While, FoxScanner.For, FoxScanner.Loop, FoxScanner.With: INC(end);
- | FoxScanner.Code:
- REPEAT NextSymbol UNTIL (symbol.token = FoxScanner.End) OR (symbol.token = FoxScanner.EndOfText);
- NextSymbol;
- | FoxScanner.End: DEC(end);
- ELSE
- END;
- UNTIL (end = 0) OR (symbol.token = FoxScanner.EndOfText);
- ELSIF symbol.token = FoxScanner.Code THEN
- REPEAT NextSymbol UNTIL (symbol.token = FoxScanner.End) OR (symbol.token = FoxScanner.EndOfText);
- END;
- NextSymbol;
- END BodyP;
- PROCEDURE QualidentP(qualident: Qualident);
- VAR
- name : ARRAY 64 OF CHAR;
- pos: LONGINT;
- BEGIN
- IF symbol.token = FoxScanner.Identifier THEN
- COPY(symbol.identifierString, name);
- pos := symbol.position.start;
- NextSymbol;
- IF symbol.token = FoxScanner.Period THEN
- NextSymbol;
- IF symbol.token = FoxScanner.Identifier THEN
- Strings.Append(name, ".");
- Strings.Concat(name, symbol.identifierString, name);
- NextSymbol;
- END;
- END;
- NEW(qualident.ident);
- qualident.ident.name := Strings.NewString(name);
- qualident.ident.pos := pos;
- END;
- END QualidentP;
- PROCEDURE IdentDefP(identDef: IdentDef);
- BEGIN
- IF (symbol.token = FoxScanner.Identifier) OR (symbol.token = FoxScanner.Number) & (symbol.numberType = FoxScanner.Character) THEN
- NEW(identDef.ident);
- identDef.ident.name := Strings.NewString(symbol.identifierString);
- identDef.ident.pos := symbol.position.start;
- ELSIF (symbol.token = FoxScanner.String) THEN
- NEW(identDef.ident);
- identDef.ident.name := Strings.NewString(symbol.string^);
- identDef.ident.pos := symbol.position.start;
- END;
- NextSymbol;
- IF symbol.token = FoxScanner.Times THEN
- identDef.vis := Public;
- NextSymbol;
- ELSIF symbol.token = FoxScanner.Minus THEN
- identDef.vis := PublicRO;
- NextSymbol;
- ELSE
- identDef.vis := Private;
- END;
- identDef.external := NIL;
- IF symbol.token = FoxScanner.Becomes THEN
- NextSymbol;
- NEW(identDef.initializer);
- ConstExprP(FoxScanner.Colon, FoxScanner.Comma, identDef.initializer);
- ELSIF symbol.token = FoxScanner.Extern THEN
- NextSymbol;
- identDef.external := Strings.NewString(symbol.string^);
- Check(FoxScanner.String);
- TRACE (identDef.external^);
- END;
- END IdentDefP;
- PROCEDURE Check(token: FoxScanner.Token);
- BEGIN
- IF symbol.token = token THEN
- (* correct *)
- ELSE
- (* error *)
- KernelLog.String("******* Check error ********** ");
- KernelLog.Int(symbol.position.start, 0);
- KernelLog.Ln;
- hasError := TRUE;
- (*HALT(33);*)
- END;
- NextSymbol;
- END Check;
- PROCEDURE Error(pos : LONGINT);
- BEGIN
- KernelLog.String("ModuleParser: Error at pos "); KernelLog.Int(pos, 0); KernelLog.Ln;
- END Error;
- END Parser;
- ListEntry = POINTER TO RECORD
- module : Module;
- next : ListEntry;
- END;
- ModuleCache = OBJECT
- VAR
- head : ListEntry; (* private *)
- nofModules : LONGINT;
- PROCEDURE Add(module : Module);
- VAR entry : ListEntry;
- BEGIN {EXCLUSIVE}
- ASSERT((module # NIL) & (module.ident.name # NIL));
- entry := FindEntry(module.ident.name^);
- IF (entry = NIL) THEN
- NEW(entry);
- entry.next := head.next;
- head.next := entry;
- module.resolved := FALSE;
- INC(nofModules);
- END;
- entry.module := module;
- END Add;
- PROCEDURE Get(CONST moduleName : ARRAY OF CHAR) : Module;
- VAR module : Module; entry : ListEntry;
- BEGIN {EXCLUSIVE}
- entry := FindEntry(moduleName);
- IF (entry # NIL) THEN
- module := entry.module;
- ELSE
- module := NIL;
- END;
- RETURN module;
- END Get;
- PROCEDURE Enumerate(enumerator : EnumeratorProc);
- VAR entry : ListEntry;
- BEGIN
- ASSERT(enumerator # NIL);
- entry := head.next;
- WHILE (entry # NIL) DO
- enumerator(entry.module, SELF);
- entry := entry.next;
- END;
- END Enumerate;
- PROCEDURE FindEntry(CONST moduleName : ARRAY OF CHAR) : ListEntry; (* private *)
- VAR entry : ListEntry;
- BEGIN
- entry := head.next;
- WHILE (entry # NIL) & (entry.module.ident.name^ # moduleName) DO entry := entry.next; END;
- RETURN entry;
- END FindEntry;
- PROCEDURE &Init; (* private *)
- BEGIN
- NEW(head); head.module := NIL; head.next := NIL;
- nofModules := 0;
- END Init;
- END ModuleCache;
- EnumeratorProc = PROCEDURE {DELEGATE} (module : Module; cache : ModuleCache);
- PROCEDURE AppendLast(head, node: NodeList);
- VAR n: NodeList;
- BEGIN
- IF head = NIL THEN RETURN END;
- n := head;
- WHILE n.next # NIL DO
- n := n.next;
- END;
- n.next := node;
- END AppendLast;
- PROCEDURE SplitName*(CONST name : ARRAY OF CHAR; VAR moduleName, typeName : ARRAY OF CHAR);
- VAR i, j : LONGINT;
- BEGIN
- IF Strings.ContainsChar(name, ".", FALSE) THEN
- i := 0;
- WHILE (i < LEN(name)) & (name[i] # ".") DO moduleName[i] := name[i]; INC(i); END;
- moduleName[i] := 0X;
- INC(i); (* skip "." *)
- j := 0;
- WHILE (i < LEN(name)) & (name[i] # 0X) DO typeName[j] := name[i]; INC(i); INC(j); END;
- typeName[j] := 0X;
- ELSE
- COPY("", moduleName);
- COPY(name, typeName);
- END;
- END SplitName;
- PROCEDURE FindType(CONST name : ARRAY OF CHAR; type : LONGINT; definitionModule : Module; cache : ModuleCache) : TypeDecl;
- VAR
- module : Module; import : Import; typeDecl : TypeDecl;
- moduleName, importName, typeName : ARRAY 256 OF CHAR;
- context : ARRAY 32 OF CHAR;
- filename : Files.FileName;
- PROCEDURE FileExists(CONST filename : ARRAY OF CHAR) : BOOLEAN;
- VAR file : Files.File;
- BEGIN
- file := Files.Old(filename);
- RETURN (file # NIL);
- END FileExists;
- PROCEDURE GenerateFilename(CONST prefix, context, moduleName, fileExtension: ARRAY OF CHAR) : Files.FileName;
- VAR filename : Files.FileName;
- BEGIN
- COPY(prefix, filename);
- IF (context # "") THEN Strings.Append(filename, context); Strings.Append(filename, "."); END;
- Strings.Append(filename, moduleName); Strings.Append(filename, fileExtension);
- RETURN filename;
- END GenerateFilename;
- (* Simple heuristics that tries to find the filename of a given module name *)
- PROCEDURE FindCorrectFilename(CONST context, moduleName : ARRAY OF CHAR) : Files.FileName;
- VAR filename : Files.FileName;
- BEGIN
- filename := GenerateFilename("", context, moduleName, ".Mod");
- IF ~FileExists(filename) THEN
- filename := GenerateFilename("I386.", context, moduleName, ".Mod");
- IF ~FileExists(filename) THEN
- filename := GenerateFilename("Win32.", context, moduleName, ".Mod");
- IF ~FileExists(filename) THEN
- filename := GenerateFilename("Unix.", context, moduleName, ".Mod");
- IF ~FileExists(filename) THEN
- filename := GenerateFilename("Oberon-", context, moduleName, ".Mod");
- IF ~FileExists(filename) THEN
- filename := GenerateFilename("", context, moduleName, ".Mod");
- END;
- END;
- END;
- END;
- END;
- RETURN filename;
- END FindCorrectFilename;
- BEGIN
- ASSERT((definitionModule # NIL) & (cache # NIL));
- SplitName(name, moduleName, typeName);
- import := definitionModule.FindImport(moduleName);
- importName := "";
- IF (import # NIL) THEN
- IF (import.context # NIL) THEN
- COPY(import.context.name^, context);
- ELSIF (definitionModule.context # NIL) THEN
- COPY(definitionModule.context.name^, context);
- ELSE
- COPY("", context);
- END;
- IF (import.alias # NIL) THEN
- Strings.Append(importName, import.alias.name^);
- ELSE
- Strings.Append(importName, import.ident.name^);
- END;
- END;
- IF (importName # "") THEN
- module := cache.Get(importName);
- IF (module = NIL) THEN
- filename := FindCorrectFilename(context, importName);
- module := ParseFile(filename, NIL);
- IF (module # NIL) THEN cache.Add(module); END;
- END;
- ELSE
- module := definitionModule;
- END;
- typeDecl := NIL;
- IF (module # NIL) THEN
- typeDecl := module.FindTypeDecl(typeName);
- IF (typeDecl # NIL) & (type # 3) & (((typeDecl.type.record = NIL) & (type = 0)) OR ((typeDecl.type.object = NIL) & (type = 1)) OR
- (((typeDecl.type.pointer = NIL) OR (typeDecl.type.pointer.type.record = NIL)) & (type = 2))) THEN
- typeDecl := NIL; (* wrong type *)
- END;
- ELSE
- KernelLog.String("Module "); KernelLog.String(moduleName); KernelLog.String(" not found.");
- KernelLog.Ln;
- END;
- RETURN typeDecl;
- END FindType;
- PROCEDURE ResolveTypeHierarchy(module : Module; cache : ModuleCache);
- VAR typeDecl, td : TypeDecl;
- BEGIN
- ASSERT(module # NIL);
- IF ~module.resolved & (module.declSeq # NIL) & (module.declSeq.typeDecl # NIL) THEN
- typeDecl := module.declSeq.typeDecl;
- WHILE (typeDecl # NIL) DO
- IF (typeDecl.type.record # NIL) & (typeDecl.type.record.super # NIL) THEN
- td := FindType(typeDecl.type.record.super.ident.name^, 0, module, cache);
- IF (td # NIL) THEN
- typeDecl.type.record.superPtr := td.type.record;
- END;
- ELSIF (typeDecl.type.pointer # NIL) & (typeDecl.type.pointer.type.record # NIL) & (typeDecl.type.pointer.type.record.super # NIL) THEN
- td := FindType(typeDecl.type.pointer.type.record.super.ident.name^, 2, module, cache);
- IF (td # NIL) THEN
- typeDecl.type.pointer.type.record.superPtr := td.type.pointer.type.record;
- END;
- ELSIF (typeDecl.type.object # NIL) & (typeDecl.type.object.super # NIL) THEN
- td := FindType(typeDecl.type.object.super.ident.name^, 1, module, cache);
- IF (td # NIL) THEN
- typeDecl.type.object.superPtr := td.type.object;
- END;
- END;
- IF (typeDecl.next # NIL) THEN
- typeDecl := typeDecl.next (TypeDecl);
- ELSE
- typeDecl := NIL;
- END;
- END;
- module.resolved := TRUE;
- END;
- END ResolveTypeHierarchy;
- PROCEDURE ResolveMethodOverwrites(module : Module; cache : ModuleCache);
- VAR typeDecl : TypeDecl; method, procDecl : ProcDecl; superClass : Object;
- BEGIN
- IF module.resolved & (module.declSeq # NIL) & (module.declSeq.typeDecl # NIL) THEN
- typeDecl := module.declSeq.typeDecl;
- WHILE (typeDecl # NIL) DO
- IF (typeDecl.type.object # NIL) & (typeDecl.type.object.declSeq # NIL) THEN
- method := typeDecl.type.object.declSeq.procDecl;
- WHILE (method # NIL) DO
- superClass := typeDecl.type.object.superPtr;
- WHILE (superClass # NIL) DO
- procDecl := superClass.FindProcDecl(method.head.identDef.ident.name^);
- IF (procDecl # NIL) THEN
- INCL(procDecl.head.modifiers, Overwritten);
- INCL(method.head.modifiers, Overwrite)
- END;
- superClass := superClass.superPtr;
- END;
- IF (method.next # NIL) THEN
- method := method.next (ProcDecl);
- ELSE
- method := NIL;
- END;
- END;
- END;
- IF (typeDecl.next # NIL) THEN
- typeDecl := typeDecl.next (TypeDecl);
- ELSE
- typeDecl := NIL;
- END;
- END;
- END;
- END ResolveMethodOverwrites;
- PROCEDURE ParseFile*(CONST filename : ARRAY OF CHAR; diagnostics : Diagnostics.Diagnostics) : Module;
- VAR
- module : Module;
- scanner : FoxScanner.Scanner;
- text : Texts.Text; reader : TextUtilities.TextReader;
- format, res : LONGINT;
- BEGIN
- NEW(text);
- TextUtilities.LoadAuto(text, filename, format, res);
- IF (res = 0) THEN
- NEW(reader, text);
- scanner := FoxScanner.NewScanner(filename, reader, 0, diagnostics);
- Parse(scanner, module);
- ELSIF (diagnostics # NIL) THEN
- diagnostics.Error("ModuleParser", Diagnostics.Invalid, Diagnostics.Invalid, "File not found");
- END;
- RETURN module
- END ParseFile;
- (** Parse all modules required to set the Record.superPtr and Object.superPtr fields and set these fields*)
- PROCEDURE SetSuperTypes*(module: Module);
- VAR cache : ModuleCache; nofModules : LONGINT;
- BEGIN
- ASSERT(module # NIL);
- NEW(cache);
- cache.Add(module);
- ResolveTypeHierarchy(module, cache);
- nofModules := -1;
- WHILE (nofModules # cache.nofModules) DO
- nofModules := cache.nofModules;
- cache.Enumerate(ResolveTypeHierarchy);
- END;
- cache.Enumerate(ResolveMethodOverwrites);
- END SetSuperTypes;
- PROCEDURE Parse*(scanner: FoxScanner.Scanner; VAR module: Module);
- VAR parser: Parser;
- BEGIN
- NEW(parser, scanner);
- parser.ModuleP(module);
- END Parse;
- END ModuleParser.
- PC.Compile \s ModuleParser.Mod ~
- Builder.Compile \s ModuleParser.Mod ~
- System.DeleteFiles ModuleParser.Obx ~
- System.Free ModuleParser ~
- Decoder.Decode ModuleParser ~
|