123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647 |
- 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, Streams, 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;
- enumeration*: Enumeration;
- 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;
- Enumeration* = OBJECT(Node)
- VAR
- enumeratorList*: ConstDecl;
- END Enumeration;
- 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
- token : FoxScanner.Token;
- scanner: FoxScanner.Scanner;
- hasError: BOOLEAN;
- PROCEDURE & Init*(scanner: FoxScanner.Scanner);
- BEGIN
- ASSERT(scanner # NIL);
- SELF.scanner := scanner;
- hasError := FALSE;
- END Init;
- PROCEDURE NextToken;
- VAR ignore : BOOLEAN;
- BEGIN
- ignore := scanner.GetNextToken(token);
- WHILE (token.symbol = FoxScanner.Comment) DO ignore := scanner.GetNextToken(token); END;
- END NextToken;
- PROCEDURE ModuleP(VAR module: Module);
- VAR
- modName: FoxScanner.IdentifierString;
- definition: Definition;
- BEGIN
- NextToken;
- IF (token.symbol = FoxScanner.Module) OR (token.symbol = FoxScanner.CellNet) THEN
- NEW(module, NIL); module.parent := module;
- NextToken;
- IF token.symbol = FoxScanner.Identifier THEN
- NEW(module.ident);
- COPY(token.identifierString, modName);
- module.ident.name := Strings.NewString(token.identifierString);
- module.ident.pos := token.position.start;
- END;
- NextToken;
- IF token.symbol = FoxScanner.In THEN
- NextToken;
- IF token.symbol = FoxScanner.Identifier THEN
- NEW(module.context);
- module.context.name := Strings.NewString(token.identifierString);
- module.context.pos := token.position.start;
- END;
- Check (FoxScanner.Identifier);
- END;
- IF token.symbol = FoxScanner.LeftBrace THEN
- WHILE (token.symbol # FoxScanner.Semicolon) & (token.symbol # FoxScanner.EndOfText) DO NextToken END;
- END;
- Check(FoxScanner.Semicolon);
- IF token.symbol = FoxScanner.Import THEN
- NEW(module.importList, module);
- ImportListP(module.importList);
- END;
- WHILE token.symbol = FoxScanner.Definition DO
- NEW(definition, module);
- DefinitionP(definition);
- IF module.definitions = NIL THEN module.definitions := definition
- ELSE AppendLast(module.definitions, definition)
- END;
- END;
- IF (token.symbol = FoxScanner.Const) OR (token.symbol = FoxScanner.Type) OR
- (token.symbol = FoxScanner.Var) OR (token.symbol = FoxScanner.Procedure) OR (token.symbol = FoxScanner.Operator) THEN
- NEW(module.declSeq, module);
- DeclSeqP(module.declSeq);
- END;
- IF (token.symbol = FoxScanner.Begin) THEN
- module.bodyPos := token.position.start;
- ELSE
- module.bodyPos := 0;
- END;
- BodyP(FALSE, module.modifiers);
- IF (token.symbol = FoxScanner.Identifier) & (token.identifierString = modName) THEN
- (* correct *)
- ELSE
- (* maybe missing END or wrong module name *)
- hasError := TRUE;
- KernelLog.String("err3: "); KernelLog.Int(token.position.start, 0); KernelLog.Ln;
- END;
- module.hasError := hasError;
- END;
- END ModuleP;
- PROCEDURE ImportListP(import: Import);
- VAR newImport: Import;
- BEGIN
- NextToken;
- WHILE token.symbol = FoxScanner.Identifier DO
- NEW(import.ident);
- import.ident.name := Strings.NewString(token.identifierString);
- import.ident.pos := token.position.start;
- NextToken; (* avoids endless loop *)
- IF token.symbol = FoxScanner.Becomes THEN
- NextToken;
- IF token.symbol = FoxScanner.Identifier THEN
- NEW(import.alias);
- import.alias.name := Strings.NewString(token.identifierString);
- import.alias.pos := token.position.start;
- NextToken;
- ELSE
- (* Error *)
- hasError := TRUE;
- KernelLog.String("err2: "); KernelLog.Int(token.position.start, 0); KernelLog.Ln;
- END;
- END;
- IF token.symbol = FoxScanner.In THEN
- NextToken;
- IF token.symbol = FoxScanner.Identifier THEN
- NEW(import.context);
- import.context.name := Strings.NewString(token.identifierString);
- import.context.pos := token.position.start;
- END;
- Check (FoxScanner.Identifier);
- END;
- IF token.symbol = FoxScanner.Comma THEN
- NextToken;
- 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 token.symbol = FoxScanner.Definition THEN
- NextToken;
- IF token.symbol = FoxScanner.Identifier THEN
- NEW(definition.ident);
- definition.ident.name := Strings.NewString(token.identifierString);
- definition.ident.pos := token.position.start;
- NextToken;
- END;
- WHILE token.symbol = FoxScanner.Semicolon DO NextToken END;
- (*? IF token.symbol = FoxScanner.Refines THEN
- NextToken;
- NEW(definition.refines, definition);
- QualidentP(definition.refines);
- END; *)
- WHILE (token.symbol = FoxScanner.Procedure) OR (token.symbol = FoxScanner.Operator) DO
- NEW(procHead, definition);
- NextToken;
- 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 token.symbol = FoxScanner.Semicolon DO NextToken END;
- END;
- END DefinitionP;
- PROCEDURE DeclSeqP(declSeq: DeclSeq);
- VAR
- constDecl: ConstDecl;
- typeDecl: TypeDecl;
- varDecl: VarDecl;
- procDecl: ProcDecl;
- PROCEDURE CheckEndOrSemicolon;
- BEGIN
- IF token.symbol # FoxScanner.End THEN
- REPEAT Check(FoxScanner.Semicolon) UNTIL token.symbol # FoxScanner.Semicolon
- END;
- END CheckEndOrSemicolon;
- BEGIN
- LOOP
- CASE token.symbol OF
- | FoxScanner.Const:
- NextToken;
- WHILE token.symbol = 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:
- NextToken;
- WHILE token.symbol = 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:
- NextToken;
- WHILE token.symbol = 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 (token.symbol = FoxScanner.Procedure) OR (token.symbol = FoxScanner.Operator) DO
- NextToken;
- 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 token.symbol = FoxScanner.Becomes THEN Initializer END;
- WHILE token.symbol = FoxScanner.Comma DO
- NextToken; (* avoids endless loop *)
- NEW(identDef);
- IdentDefP(identDef);
- SysFlag;
- IF token.symbol = 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 (token.symbol = FoxScanner.Const) OR (token.symbol = FoxScanner.Var) OR
- (token.symbol = FoxScanner.Type) OR (token.symbol = FoxScanner.Procedure) OR (token.symbol = FoxScanner.Operator) THEN
- NEW(declSeq, proc);
- DeclSeqP(declSeq);
- IF proc.declSeq = NIL THEN proc.declSeq := declSeq;
- ELSE AppendLast(proc.declSeq, declSeq);
- END;
- END;
- IF (token.symbol = FoxScanner.Begin) THEN
- proc.bodyPos := token.position.start;
- ELSE
- proc.bodyPos := 0;
- END;
- BodyP(FALSE, proc.head.modifiers);
- NextToken; (* skip ident *)
- END ProcDeclP;
- PROCEDURE ProcHeadP(head: ProcHead);
- VAR forward: BOOLEAN;
- BEGIN
- ProcedureModifierP(head);
- (*SysFlag;*)
- CASE token.symbol OF
- | FoxScanner.Minus: head.inline := TRUE; NextToken;
- | FoxScanner.And: head.constructor := TRUE; NextToken;
- | FoxScanner.Times: (* ignore *) NextToken;
- | FoxScanner.Not: (* ignore *) NextToken;
- | FoxScanner.Arrow: (* ignore *) NextToken; forward := TRUE;
- | FoxScanner.String: head.operator := TRUE;
- | FoxScanner.Number: IF token.numberType = FoxScanner.Character THEN head.operator := TRUE END;
- ELSE
- END;
- NEW(head.identDef);
- IdentDefP(head.identDef);
- OSAIrq; (* tk: Compatibility to OSACompiler*)
- IF token.symbol = 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 token.symbol = FoxScanner.LeftBrace THEN
- NextToken;
- IF token.symbol # FoxScanner.RightBrace THEN
- LOOP
- Check(FoxScanner.Identifier);
- IF (token.symbol = FoxScanner.LeftParenthesis) THEN
- NextToken;
- NEW (ignore);
- ConstExprP (FoxScanner.RightParenthesis, -1, ignore);
- Check (FoxScanner.RightParenthesis);
- ELSIF (token.symbol = FoxScanner.Equal) THEN
- NextToken;
- NEW (ignore);
- ConstExprP (FoxScanner.RightBrace, FoxScanner.Comma, ignore);
- END;
- IF token.symbol # FoxScanner.Comma THEN EXIT END;
- NextToken;
- END;
- END;
- Check(FoxScanner.RightBrace);
- END;
- END SysFlag;
- (* tk: For OSA Compatibility *)
- PROCEDURE OSAIrq;
- BEGIN
- IF token.symbol = FoxScanner.LeftBracket THEN
- NextToken;
- Check(FoxScanner.Number);
- Check(FoxScanner.RightBracket);
- END;
- END OSAIrq;
- PROCEDURE FormalParsP(pars: FormalPars);
- VAR
- fpSection: FPSection;
- BEGIN
- NextToken;
- IF (token.symbol = FoxScanner.Var) OR (token.symbol = FoxScanner.Const) OR (token.symbol = FoxScanner.Identifier) THEN
- NEW(pars.fpSectionList, pars);
- FPSectionP(pars.fpSectionList);
- WHILE token.symbol = FoxScanner.Semicolon DO
- NextToken; (* avoids endless loop *)
- NEW(fpSection, pars.fpSectionList);
- FPSectionP(fpSection);
- AppendLast(pars.fpSectionList, fpSection);
- END;
- END;
- Check(FoxScanner.RightParenthesis);
- IF token.symbol = FoxScanner.Colon THEN
- NextToken;
- SysFlag;
- NEW(pars.returnType, pars);
- TypeP(pars.returnType)
- END;
- END FormalParsP;
- PROCEDURE FPSectionP(fpSection: FPSection);
- VAR
- identList: IdentList; dummy: InfoItem;
- BEGIN
- NEW(dummy);
- IF token.symbol = FoxScanner.Var THEN
- fpSection.var := TRUE;
- NextToken;
- ELSIF token.symbol = FoxScanner.Const THEN
- fpSection.const := TRUE;
- NextToken;
- END;
- IF token.symbol = 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 := token.position.start;
- NextToken;
- *)
- IF token.symbol = FoxScanner.Equal THEN NextToken; ConstExprP(FoxScanner.Comma, FoxScanner.Colon, dummy) END; (* added for optional parameters *)
- WHILE token.symbol = FoxScanner.Comma DO
- NEW(identList, fpSection.identList);
- NextToken;
- NEW(identList.identDef);
- IdentDefP(identList.identDef);
- SysFlag;
- AppendLast(fpSection.identList, identList);
- (*
- IF token.symbol = FoxScanner.Identifier THEN
- StringPool.GetString(scanner.name, name);
- NEW(identDef);
- NEW(identDef.ident);
- identDef.ident.name := Strings.NewString(name);
- identDef.ident.pos := token.position.start;
- AppendLast(fpSection.identlist, identDef);
- NextToken;
- END;
- *)
- IF token.symbol = FoxScanner.Equal THEN NextToken; 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 token.symbol OF
- | FoxScanner.Array: NextToken; NEW(type.array, type); ArrayP(type.array);
- | FoxScanner.Record: NextToken; NEW(type.record, type); RecordP(type.record);
- | FoxScanner.Pointer: NextToken; NEW(type.pointer, type); PointerP(type.pointer);
- | FoxScanner.Object: NextToken; NEW(type.object, type); ObjectP(type.object);
- | FoxScanner.Port: NextToken; NEW(type.port, type); PortP(type.port);
- | FoxScanner.Cell, FoxScanner.CellNet: NextToken; NEW(type.cell, type); CellP(type.cell);
- | FoxScanner.Enum: NextToken; NEW(type.enumeration, type); EnumerationP(type.enumeration);
- | FoxScanner.Procedure, FoxScanner.Operator: NextToken; 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(token.identifierString); type.qualident.ident.pos := token.position.start; NextToken;
- ELSE
- (* Error *)
- hasError := TRUE; KernelLog.String("err4: "); KernelLog.Int(token.position.start, 0); KernelLog.Ln;
- NextToken; (* ??? *)
- END;
- END TypeP;
- PROCEDURE ArrayP(array: Array);
- BEGIN
- SysFlag;
- IF token.symbol = FoxScanner.Of THEN
- array.open := TRUE;
- NEW(array.base, array);
- NextToken;
- TypeP(array.base);
- ELSE
- NEW(array.len);
- ConstExprP(FoxScanner.Of, FoxScanner.Comma, array.len);
- (*
- SimpleExprP(array.len);
- *)
- IF token.symbol = FoxScanner.Of THEN
- NEW(array.base, array);
- NextToken;
- TypeP(array.base);
- ELSIF token.symbol = FoxScanner.Comma THEN
- NEW(array.base, array);
- NEW(array.base.array, array);
- NextToken;
- ArrayP(array.base.array)
- ELSE
- (* Error *)
- hasError := TRUE;
- KernelLog.String("err1: "); KernelLog.Int(token.position.start, 0); KernelLog.Ln;
- END;
- END;
- END ArrayP;
- PROCEDURE RecordP(record: Record);
- BEGIN
- SysFlag;
- IF token.symbol = FoxScanner.LeftParenthesis THEN
- NextToken;
- NEW(record.super, record);
- QualidentP(record.super);
- Check(FoxScanner.RightParenthesis);
- END;
- WHILE token.symbol = FoxScanner.Semicolon DO NextToken END;
- IF token.symbol = 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 token.symbol = FoxScanner.Semicolon DO
- NextToken;
- NEW(fieldDecl, fieldList);
- FieldDeclP(fieldDecl);
- AppendLast(fieldList, fieldDecl);
- END;
- END FieldListP;
- PROCEDURE FieldDeclP(fieldDecl: FieldDecl);
- VAR
- identDef: IdentDef;
- identList: IdentList;
- BEGIN
- IF token.symbol = FoxScanner.Identifier THEN
- NEW(fieldDecl.identList, fieldDecl);
- NEW(fieldDecl.identList.identDef);
- IdentDefP(fieldDecl.identList.identDef);
- SysFlag;
- WHILE token.symbol = FoxScanner.Comma DO
- NextToken;
- 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 EnumerationP(enumeration: Enumeration);
- VAR identDef: IdentDef; enumerator: ConstDecl;
- BEGIN
- NEW(enumerator, enumeration);
- EnumeratorP(enumerator);
- enumeration.enumeratorList := enumerator;
- WHILE token.symbol = FoxScanner.Comma DO
- NextToken; (* avoids endless loop *)
- NEW(enumerator, enumeration);
- EnumeratorP(enumerator);
- AppendLast(enumeration.enumeratorList, enumerator);
- END;
- Check(FoxScanner.End);
- END EnumerationP;
- PROCEDURE EnumeratorP(enumerator: ConstDecl);
- BEGIN
- NEW(enumerator.identDef);
- IdentDefP(enumerator.identDef);
- IF token.symbol = FoxScanner.Equal THEN
- NextToken;
- (* NEW(enumerator.constExpr);
- ExprP(enumerator.constExpr); *)
- NEW(enumerator.expr);
- ConstExprP(FoxScanner.Comma, FoxScanner.End, enumerator.expr);
- END;
- END EnumeratorP;
- PROCEDURE PortP(port: Port);
- BEGIN
- IF (token.symbol = FoxScanner.Out) OR (token.symbol = FoxScanner.In) THEN
- NextToken
- END;
- END PortP;
- PROCEDURE ObjectP(object: Object);
- VAR declSeq: DeclSeq;
- pos: LONGINT;
- (*? qualident: Qualident; *)
- BEGIN
- IF (token.symbol = FoxScanner.Semicolon) OR (token.symbol = FoxScanner.RightParenthesis) THEN RETURN END;
- SysFlag;
- IF token.symbol = FoxScanner.LeftParenthesis THEN
- NEW(object.super, object);
- NextToken;
- QualidentP(object.super);
- Check(FoxScanner.RightParenthesis);
- END;
- (*? IF token.symbol = FoxScanner.Implements THEN
- NEW(object.implements, object);
- NextToken;
- QualidentP(object.implements);
- WHILE token.symbol = FoxScanner.Comma DO
- NEW(qualident, object.implements);
- NextToken;
- QualidentP(qualident);
- AppendLast(object.implements, qualident);
- END;
- END; *)
- pos := -1;
- WHILE (token.symbol # FoxScanner.Begin) & (token.symbol # FoxScanner.End) & (token.symbol # FoxScanner.EndOfText) DO
- (* avoid endless-loop *)
- IF pos = token.position.start THEN NextToken END;
- pos := token.position.start;
- NEW(declSeq, object);
- DeclSeqP(declSeq);
- IF object.declSeq = NIL THEN object.declSeq := declSeq;
- ELSE AppendLast(object.declSeq, declSeq);
- END;
- END;
- IF (token.symbol = FoxScanner.Begin) THEN
- object.bodyPos := token.position.start;
- ELSE
- object.bodyPos := 0;
- END;
- BodyP(TRUE, object.modifiers);
- IF token.symbol = FoxScanner.Identifier THEN NextToken END;
- END ObjectP;
- PROCEDURE CellP(cell: Cell);
- VAR declSeq: DeclSeq;
- pos: LONGINT;
- (*? qualident: Qualident; *)
- BEGIN
- SysFlag;
- IF token.symbol = FoxScanner.LeftParenthesis THEN
- NEW(cell.formalPars, cell);
- FormalParsP(cell.formalPars);
- END;
- pos := -1;
- WHILE (token.symbol # FoxScanner.Begin) & (token.symbol # FoxScanner.End) & (token.symbol # FoxScanner.EndOfText) DO
- (* avoid endless-loop *)
- IF pos = token.position.start THEN NextToken END;
- pos := token.position.start;
- NEW(declSeq, cell);
- DeclSeqP(declSeq);
- IF cell.declSeq = NIL THEN cell.declSeq := declSeq;
- ELSE AppendLast(cell.declSeq, declSeq);
- END;
- END;
- IF (token.symbol = FoxScanner.Begin) THEN
- cell.bodyPos := token.position.start;
- ELSE
- cell.bodyPos := 0;
- END;
- BodyP(TRUE, cell.modifiers);
- IF token.symbol = FoxScanner.Identifier THEN NextToken END;
- END CellP;
- PROCEDURE ProcedureP(proc: Procedure);
- BEGIN
- SysFlag;
- IF token.symbol = FoxScanner.LeftBrace THEN
- NextToken;
- IF token.symbol # FoxScanner.Identifier THEN
- (* Error *)
- ELSIF token.identifierString = "DELEGATE" THEN
- proc.delegate := TRUE;
- END;
- NextToken;
- Check(FoxScanner.RightBrace);
- END;
- IF token.symbol = FoxScanner.LeftParenthesis THEN
- NEW(proc.formalPars, proc);
- FormalParsP(proc.formalPars);
- END;
- END ProcedureP;
- PROCEDURE ConstExprP(delimiter1, delimiter2: FoxScanner.Symbol; 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 := token.position.start;
- IF (token.symbol = delimiter1) OR (token.symbol = delimiter2) THEN RETURN END;
- REPEAT
- CASE token.symbol 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(token.identifierString);
- | FoxScanner.Nil: Add("NIL");
- | FoxScanner.True: Add("TRUE");
- | FoxScanner.False: Add("FALSE");
- | FoxScanner.Not: Add("~");
- | FoxScanner.Period: Add(".");
- | FoxScanner.Identifier: Add(token.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(token.string^); Add(name);
- | FoxScanner.Arrow: Add("^");
- ELSE
- (* error *)
- hasError := TRUE;
- END;
- NextToken;
- (* urgh, what an ugly condition ... *)
- UNTIL (((token.symbol = delimiter1) OR (token.symbol = delimiter2)) & (paren = 0) & (brace = 0) & (brak = 0)) OR (token.symbol = 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 token.symbol = FoxScanner.LeftBrace THEN
- NextToken;
- LOOP
- IF token.symbol = FoxScanner.Identifier THEN
- IF token.identifierString = ExclusiveStr THEN
- modifiers := modifiers + {Exclusive};
- NextToken;
- ELSIF allowBody & (token.identifierString = ActiveStr) THEN
- modifiers := modifiers + {Active};
- NextToken
- ELSIF allowBody & (token.identifierString = RealtimeStr) THEN
- NextToken;
- ELSIF allowBody & (token.identifierString = SafeStr) THEN
- modifiers := modifiers + {Safe};
- NextToken
- ELSIF allowBody & (token.identifierString = PriorityStr) THEN
- modifiers := modifiers + {Priority};
- NextToken;
- IF token.symbol = FoxScanner.LeftParenthesis THEN
- NextToken;
- NEW(ignore);
- ConstExprP(FoxScanner.RightParenthesis, -1, ignore);
- Check(FoxScanner.RightParenthesis);
- END;
- ELSIF token.identifierString = UncheckedStr THEN
- modifiers := modifiers + {Unchecked};
- NextToken;
- ELSIF token.identifierString = UncooperativeStr THEN
- modifiers := modifiers + {Uncooperative};
- NextToken;
- ELSE
- Error(token.position.start); NextToken (* skip the ident, probably a typo *)
- END;
- END;
- IF token.symbol # FoxScanner.Comma THEN EXIT END;
- NextToken
- END;
- Check(FoxScanner.RightBrace);
- END;
- END BlockModifierP;
- PROCEDURE ProcedureModifierP(procHead: ProcHead);
- VAR
- value: LONGINT; ignore: InfoItem;
- BEGIN
- IF token.symbol = FoxScanner.LeftBrace THEN
- NextToken;
- IF token.symbol # FoxScanner.RightBrace THEN
- LOOP
- IF token.symbol = FoxScanner.Identifier THEN
- IF token.identifierString = InterruptStr THEN NextToken; procHead.modifiers := procHead.modifiers + {Interrupt}
- ELSE NextToken;
- END;
- ELSE Error(token.position.start); NextToken; (* skip the ident, probably a typo *)
- END;
- IF (token.symbol = FoxScanner.LeftParenthesis) THEN
- NextToken;
- NEW (ignore);
- ConstExprP (FoxScanner.RightParenthesis, -1, ignore);
- Check (FoxScanner.RightParenthesis);
- ELSIF (token.symbol = FoxScanner.Equal) THEN
- NextToken;
- NEW (ignore);
- ConstExprP (FoxScanner.Comma, FoxScanner.RightBrace, ignore);
- END;
- IF token.symbol # FoxScanner.Comma THEN EXIT END;
- NextToken;
- END
- END;
- Check(FoxScanner.RightBrace)
- END
- END ProcedureModifierP;
- PROCEDURE ModifierValueP(VAR value: LONGINT);
- BEGIN
- IF token.symbol = FoxScanner.Equal THEN
- NextToken; Check(FoxScanner.Number); value := token.integer
- ELSIF token.symbol = FoxScanner.LeftParenthesis THEN
- NextToken; Check(FoxScanner.Number); value := token.integer; Check(FoxScanner.RightParenthesis)
- ELSE
- Error(token.position.start); NextToken
- END
- END ModifierValueP;
- PROCEDURE BodyP(allowBody : BOOLEAN; VAR modifiers : SET);
- VAR end: LONGINT; lastSymbol: FoxScanner.Symbol; m : SET; first : BOOLEAN;
- BEGIN
- IF token.symbol = FoxScanner.Begin THEN
- end := 1;
- first := TRUE;
- REPEAT
- lastSymbol := token.symbol;
- NextToken;
- IF (lastSymbol = FoxScanner.Begin) & (token.symbol = 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 token.symbol OF
- | FoxScanner.Begin: INC(end);
- | FoxScanner.If, FoxScanner.Case, FoxScanner.While, FoxScanner.For, FoxScanner.Loop, FoxScanner.With: INC(end);
- | FoxScanner.Code:
- REPEAT NextToken UNTIL (token.symbol = FoxScanner.End) OR (token.symbol = FoxScanner.EndOfText);
- NextToken;
- | FoxScanner.End: DEC(end);
- ELSE
- END;
- UNTIL (end = 0) OR (token.symbol = FoxScanner.EndOfText);
- ELSIF token.symbol = FoxScanner.Code THEN
- REPEAT NextToken UNTIL (token.symbol = FoxScanner.End) OR (token.symbol = FoxScanner.EndOfText);
- END;
- NextToken;
- END BodyP;
- PROCEDURE QualidentP(qualident: Qualident);
- VAR
- name : ARRAY 64 OF CHAR;
- pos: LONGINT;
- BEGIN
- IF token.symbol = FoxScanner.Identifier THEN
- COPY(token.identifierString, name);
- pos := token.position.start;
- NextToken;
- IF token.symbol = FoxScanner.Period THEN
- NextToken;
- IF token.symbol = FoxScanner.Identifier THEN
- Strings.Append(name, ".");
- Strings.Concat(name, token.identifierString, name);
- NextToken;
- END;
- END;
- NEW(qualident.ident);
- qualident.ident.name := Strings.NewString(name);
- qualident.ident.pos := pos;
- END;
- END QualidentP;
- PROCEDURE IdentDefP(identDef: IdentDef);
- BEGIN
- IF (token.symbol = FoxScanner.Identifier) OR (token.symbol = FoxScanner.Number) & (token.numberType = FoxScanner.Character) THEN
- NEW(identDef.ident);
- identDef.ident.name := Strings.NewString(token.identifierString);
- identDef.ident.pos := token.position.start;
- ELSIF (token.symbol = FoxScanner.String) THEN
- NEW(identDef.ident);
- identDef.ident.name := Strings.NewString(token.string^);
- identDef.ident.pos := token.position.start;
- END;
- NextToken;
- IF token.symbol = FoxScanner.Times THEN
- identDef.vis := Public;
- NextToken;
- ELSIF token.symbol = FoxScanner.Minus THEN
- identDef.vis := PublicRO;
- NextToken;
- ELSE
- identDef.vis := Private;
- END;
- identDef.external := NIL;
- IF token.symbol = FoxScanner.Becomes THEN
- NextToken;
- NEW(identDef.initializer);
- ConstExprP(FoxScanner.Colon, FoxScanner.Comma, identDef.initializer);
- ELSIF token.symbol = FoxScanner.Extern THEN
- NextToken;
- identDef.external := Strings.NewString(token.string^);
- Check(FoxScanner.String);
- TRACE (identDef.external^);
- END;
- END IdentDefP;
- PROCEDURE Check(symbol: FoxScanner.Symbol);
- BEGIN
- IF token.symbol = symbol THEN
- (* correct *)
- ELSE
- (* error *)
- KernelLog.String("******* Check error ********** ");
- KernelLog.Int(token.position.start, 0);
- KernelLog.Ln;
- hasError := TRUE;
- (*HALT(33);*)
- END;
- NextToken;
- 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("Windows.", 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: LONGINT; res : WORD;
- 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", Streams.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 ~
|