123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305 |
- MODULE TFAOParser; (** AUTHOR "tf"; PURPOSE "Parser for AO --> CI"; *)
- IMPORT
- S := BimboScanner, TS := TFTypeSys, Texts, TextUtilities, Files, Strings, KernelLog, Streams, TFDumpTS, Commands, Kernel, TFCheck;
- TYPE
- Parser*= OBJECT
- VAR s : S.Scanner;
- m* : TS.Module;
- pos : LONGINT;
- comments : TS.Comments;
- lastStatement : TS.Statement;
- (* add the comment to the currents tructure *)
- PROCEDURE CommentToStructure;
- VAR str : Strings.String;
- comment : TS.Comment;
- BEGIN
- ASSERT(s.commentStr # NIL);
- str := s.commentStr.GetString();
- IF str # NIL THEN
- comment := TS.AddComment(comments, str^);
- StorePos(comment.pos)
- END
- END CommentToStructure;
- PROCEDURE Next;
- VAR lpos : LONGINT;
- BEGIN
- s.Next;
- lpos := s.pos;
- WHILE (s.sym = S.comment) OR (s.sym = S.newLine) DO
- IF (s.sym = S.comment) THEN CommentToStructure
- ELSIF s.sym = S.newLine THEN
- IF (comments # NIL) & (lastStatement # NIL) THEN lastStatement.postComment := comments; comments := NIL END;
- lastStatement := NIL;
- END;
- s.Next
- END;
- lpos := s.pos;
- ASSERT((s.sym = S.eof) OR (s.pos > pos)); (* Assert progress *)
- pos := s.pos;
- END Next;
- PROCEDURE StorePos(VAR pos : TS.Position);
- BEGIN
- pos.valid := TRUE;
- pos.a := s.lastpos; pos.b := s.curpos - 1
- END StorePos;
- PROCEDURE Error(CONST str : ARRAY OF CHAR);
- BEGIN
- KernelLog.Ln;
- KernelLog.String("pos= "); KernelLog.Int(s.pos, 0); KernelLog.String(" "); KernelLog.String(str);
- KernelLog.Ln;
- (* HALT(123456); *)
- END Error;
- PROCEDURE Warn(CONST str : ARRAY OF CHAR);
- BEGIN
- KernelLog.Ln;
- KernelLog.String("pos= "); KernelLog.Int(s.pos, 0); KernelLog.String(" "); KernelLog.String(str);
- KernelLog.Ln;
- END Warn;
- PROCEDURE Eat(sym : LONGINT);
- VAR t, str : ARRAY 32 OF CHAR;
- BEGIN
- IF s.sym = sym THEN Next;
- ELSE
- str := "sym = "; Strings.IntToStr(sym, t); Strings.Append(str, t); Strings.Append(str, " expected");
- Error(str)
- END
- END Eat;
- PROCEDURE ImportList;
- VAR
- imp : TS.Import;
- BEGIN
- Next;
- WHILE s.sym = S.ident DO
- NEW(imp);
- imp.name := Strings.NewString(s.str);
- StorePos(imp.pos);
- Next;
- IF s.sym = S.in THEN (* ignore package *)
- Next;
- imp.package := Strings.NewString(s.str);
- Eat(S.ident);
- imp.import := imp.name
- ELSIF s.sym = S.becomes THEN
- Next;
- IF s.sym = S.ident THEN
- imp.import := Strings.NewString(s.str);
- Next;
- IF s.sym = S.in THEN (* ignore package *)
- Next;
- imp.package := Strings.NewString(s.str);
- Eat(S.ident)
- END
- ELSE
- Error("Name of imported module expected")
- END;
- ELSE
- imp.import := imp.name
- END;
- m.scope.elements.Add(imp);
- IF s.sym = S.comma THEN Next END;
- END;
- Eat(S.semicolon);
- END ImportList;
- PROCEDURE ProcedureType(scope : TS.Scope) : TS.ProcedureType;
- VAR proc : TS.ProcedureType;
- BEGIN
- NEW(proc);
- SysFlag;
- IF s.sym = S.lbrace THEN
- Next;
- IF s.sym # S.ident THEN
- (* Error *)
- ELSIF s.str = "DELEGATE" THEN
- proc.delegate := TRUE;
- END;
- Next;
- Eat(S.rbrace);
- END;
- IF s.sym = S.lparen THEN
- proc.signature := ProcSignature(scope);
- END;
- RETURN proc
- END ProcedureType;
- (* *)
- PROCEDURE Type(scope : TS.Scope; CONST name : ARRAY OF CHAR) : TS.Type;
- VAR type : TS.Type; ident : TS.Ident; str : ARRAY 8 OF CHAR;
- BEGIN
- NEW(type);
- type.container := scope;
- CASE s.sym OF
- | S.array: Next; type.kind := TS.TArray; NEW(type.array); Array(type.array, scope);
- | S.record: Next; type.kind := TS.TRecord; NEW(type.record); Record(type.record, scope);
- | S.pointer: Next; type.kind := TS.TPointer; NEW(type.pointer); type.pointer := Pointer(scope);
- | S.object: Next; type.kind := TS.TObject; type.object := Object(name);
- (* Handle the ANY case *)
- IF type.object = NIL THEN
- type.kind := TS.TAlias;
- NEW(ident); str := "OBJECT"; ident.name := TS.s.AddString(str); type.qualident := ident
- END;
- | S.procedure: Next; type.kind := TS.TProcedure; type.procedure := ProcedureType(scope);
- | S.ident: type.kind := TS.TAlias; type.qualident := Designator();
- ELSE
- (* Error *)
- Error("Illegal Type");
- Next (* ??? *)
- END;
- RETURN type
- END Type;
- PROCEDURE Pointer(scope : TS.Scope) : TS.Pointer;
- VAR p : TS.Pointer;
- BEGIN
- SysFlag;
- Eat(S.to);
- NEW(p);
- p.type := Type(scope, "");
- RETURN p
- END Pointer;
- PROCEDURE DeclSeq(declarations: TS.Scope);
- VAR
- ol : TS.ObjectList;
- i, j : LONGINT;
- PROCEDURE CheckEndOrSemicolon;
- BEGIN
- IF s.sym # S.end THEN
- REPEAT Eat(S.semicolon) UNTIL s.sym # S.semicolon
- END
- END CheckEndOrSemicolon;
- BEGIN
- LOOP
- CASE s.sym OF
- | S.const:
- Next;
- WHILE s.sym = S.ident DO
- declarations.Add(ConstDecl());
- CheckEndOrSemicolon()
- END;
- | S.type:
- Next;
- WHILE s.sym = S.ident DO
- declarations.Add(TypeDecl(declarations));
- CheckEndOrSemicolon();
- END;
- | S.var:
- Next;
- WHILE s.sym = S.ident DO
- ol := VarDecl(declarations);
- FOR i := 0 TO ol.nofObjs - 1 DO
- ol.objs[i](TS.Var).varNr := i;
- declarations.Add(ol.objs[i](TS.Var))
- END;
- CheckEndOrSemicolon();
- END;
- | S.procedure:
- WHILE s.sym = S.procedure DO
- Next;
- declarations.Add(ProcDecl(declarations));
- CheckEndOrSemicolon();
- END;
- ELSE
- EXIT;
- END;
- END;
- j := 0;
- FOR i := 0 TO declarations.elements.nofObjs - 1 DO
- IF declarations.elements.objs[i] IS TS.Var THEN
- declarations.elements.objs[i](TS.Var).varNr := j;
- INC(j)
- END
- END
- END DeclSeq;
- PROCEDURE ConstDecl() : TS.Const;
- VAR c : TS.Const;
- BEGIN
- IF s.sym # S.ident THEN Error("Ident expect") END;
- NEW(c); c.name := Strings.NewString(s.str);
- StorePos(c.pos);
- Next;
- c.exportState := VisibilityModifier();
- Eat(S.eql);
- c.expression := Expression();
- RETURN c
- END ConstDecl;
- PROCEDURE TypeDecl(scope : TS.Scope) : TS.TypeDecl;
- VAR t : TS.TypeDecl;
- BEGIN
- IF s.sym # S.ident THEN Error("Ident expect") END;
- NEW(t); StorePos(t.pos); t.name := Strings.NewString(s.str);
- Next;
- t.exportState := VisibilityModifier();
- Eat(S.eql);
- t.type := Type(scope, t.name^);
- RETURN t
- END TypeDecl;
- PROCEDURE VarDecl(scope : TS.Scope) : TS.ObjectList;
- VAR
- ol : TS.ObjectList;
- v : TS.Var;
- t : TS.Type;
- i : LONGINT;
- BEGIN
- NEW(ol);
- IF s.sym # S.ident THEN Error("Ident expect") END;
- NEW(v); StorePos(v.pos); v.name := Strings.NewString(s.str); ol.Add(v);
- Next;
- v.exportState := VisibilityModifier();
- IF s.sym = S.lbrace THEN BlockAttributes; Eat(S.rbrace) END;
- SysFlag;
- WHILE s.sym = S.comma DO
- Next;
- IF s.sym # S.ident THEN Error("Ident expect") END;
- NEW(v); StorePos(v.pos); v.name := Strings.NewString(s.str); ol.Add(v);
- Next;
- v.exportState := VisibilityModifier();
- IF s.sym = S.lbrace THEN BlockAttributes; Eat(S.rbrace) END;
- SysFlag;
- END;
- Eat(S.colon);
- t := Type(scope, v.name^);
- FOR i := 0 TO ol.nofObjs - 1 DO ol.objs[i](TS.Var).type := t END;
- RETURN ol
- END VarDecl;
- PROCEDURE Object(CONST name : ARRAY OF CHAR) : TS.Class;
- VAR
- pos: LONGINT;
- qualident: TS.Designator;
- class : TS.Class;
- body : TS.Statement;
- BEGIN
- NEW(class);
- NEW(class.scope);
- class.name := Strings.NewString(name);
- class.container := m.scope;
- class.scope.parent := m.scope;
- class.scope.owner := class;
- IF (s.sym = S.semicolon) OR (s.sym = S.rparen) THEN RETURN NIL END;
- SysFlag;
- IF s.sym = S.lparen THEN
- Next;
- class.scope.superQualident := Designator();
- Eat(S.rparen);
- END;
- IF (s.sym = S.semicolon) THEN Eat(S.semicolon); Warn("Superfluous Semicolon") END;
- IF s.sym = S.implements THEN
- Next;
- qualident := Designator();
- WHILE s.sym = S.comma DO
- Next;
- qualident := Designator();
- END;
- END;
- IF (s.sym # S.begin) & (s.sym # S.end) & (s.sym # S.eof) THEN
- (* (* avoid endless-loop *)
- IF pos = s.errpos THEN Next END; *)
- pos := s.errpos;
- DeclSeq(class.scope)
- END;
- IF s.sym = S.begin THEN
- Next;
- IF s.sym = S.lbrace THEN BlockAttributes; Eat(S.rbrace) END;
- body := StatementSequence();
- class.scope.ownerBody := body
- END;
- Eat(S.end);
- StorePos(class.altPos);
- IF s.sym = S.ident THEN
- IF s.str # name THEN Error("object name does not match") END;
- Next
- END;
- RETURN class
- END Object;
- PROCEDURE BlockAttributes;
- VAR q : TS.Designator;
- BEGIN
- Next;
- IF s.sym # S.rbrace THEN
- q := Designator();
- WHILE s.sym = S.comma DO
- Next;
- q := Designator()
- END
- END;
- END BlockAttributes;
- PROCEDURE Set(): TS.Set;
- VAR set : TS.Set;
- cr, f: TS.SetRange;
- BEGIN
- NEW(set);
- IF s.sym # S.rbrace THEN
- REPEAT
- IF s.sym= S.comma THEN Next END;
- IF f = NIL THEN NEW(f); cr := f ELSE NEW(cr.next); cr := cr.next END;
- cr.a := Expression();
- IF s.sym = S.upto THEN
- Next; cr.b := Expression();
- END;
- UNTIL s.sym # S.comma;
- set.setRanges := f
- ELSE
- (* empty set *)
- END;
- RETURN set
- END Set;
- PROCEDURE Factor():TS.Expression;
- VAR sym, pos : LONGINT;
- ex : TS.Expression;
- BEGIN
- sym := s.sym; pos := s.pos;
- CASE s.sym OF
- |S.number : ex := TS.PrimitiveExpressionInt(s.intval); Next;
- |S.string: ex := TS.PrimitiveExpressionString(s.str); Next;
- |S.nil : ex := TS.PrimitiveExpressionNIL(); Next
- |S.true: ex := TS.PrimitiveExpressionBool(TRUE); Next
- |S.false: ex := TS.PrimitiveExpressionBool(FALSE); Next
- |S.lbrace: Next; ex := TS.PrimitiveExpressionSet(Set()); Eat(S.rbrace);
- |S.lparen: Next; ex := Expression(); Eat(S.rparen)
- |S.not: Next; ex := TS.UnaryExpression(TS.OpInvert, Factor());
- |S.ident: ex := TS.CreateDesignatorExpression(Designator());
- ELSE
- Error("Unexpected Symbol");
- END;
- (* ASSERT(ex # NIL); *)
- RETURN ex
- END Factor;
- PROCEDURE Term() : TS.Expression;
- VAR exa, exb : TS.Expression;
- op : LONGINT;
- pos : LONGINT;
- BEGIN
- pos := s.pos;
- exa := Factor();
- WHILE (s.sym >= S.times) & (s.sym <= S.and) DO
- CASE s.sym OF
- |S.times : op := TS.OpMul;
- |S.slash : op := TS.OpDiv;
- |S.div : op := TS.OpIntDiv;
- |S.mod : op := TS.OpMod;
- |S.and : op := TS.OpAnd;
- END;
- Next;
- exb := Factor();
- exa := TS.BinaryExpression(op, exa, exb);
- END;
- (* ASSERT(exa # NIL); *)
- RETURN exa;
- END Term;
- PROCEDURE SimpleExpression() : TS.Expression;
- VAR exa, exb : TS.Expression;
- op : LONGINT;
- neg : BOOLEAN;
- BEGIN
- neg := (s.sym = S.minus);
- IF (s.sym = S.plus) OR (s.sym = S.minus) THEN Next END;
- exa := Term();
- IF neg THEN exa := TS.UnaryExpression(TS.OpNegate, exa) END;
- WHILE (s.sym >= S.plus) & (s.sym <= S.or) DO
- CASE s.sym OF
- |S.plus : op := TS.OpAdd;
- |S.minus : op := TS.OpSub;
- |S.or : op := TS.OpOr;
- END;
- Next;
- exb := Term();
- exa := TS.BinaryExpression(op, exa, exb)
- END;
- (*ASSERT(exa # NIL); *)
- RETURN exa
- END SimpleExpression;
- PROCEDURE Expression () : TS.Expression;
- VAR exa, exb : TS.Expression;
- op : LONGINT;
- BEGIN
- exa := SimpleExpression();
- IF (s.sym >= S.eql) & (s.sym <= S.is) THEN
- CASE s.sym OF
- |S.eql : op := TS.OpEql;
- |S.neq : op := TS.OpNeq;
- |S.lss : op := TS.OpLss;
- |S.leq : op := TS.OpLeq;
- |S.gtr : op := TS.OpGtr;
- |S.geq : op := TS.OpGeq;
- |S.in : op := TS.OpIn;
- |S.is : op := TS.OpIs;
- END;
- Next;
- exb := SimpleExpression();
- exa := TS.BinaryExpression(op, exa, exb)
- END;
- (* ASSERT(exa # NIL); *)
- RETURN exa
- END Expression;
- PROCEDURE ExpressionList():TS.ExpressionList;
- VAR f, c : TS.ExpressionList;
- BEGIN
- NEW(f);
- f.expression := Expression();
- c := f;
- WHILE (s.sym = S.comma) DO
- Next;
- NEW(c.next);
- c := c.next;
- c.expression := Expression()
- END;
- RETURN f
- END ExpressionList;
- PROCEDURE Designator () : TS.Designator;
- VAR f, c : TS.Designator;
- parameters : TS.ActualParameters;
- index : TS.Index;
- newIdent : TS.Ident;
- deref : TS.Dereference;
- BEGIN
- NEW(newIdent); StorePos(newIdent.pos);
- newIdent.name := TS.s.AddString(s.str); (* Strings.NewString(s.str); *)
- f := newIdent; c := f;
- Next;
- WHILE (s.sym = S.lbrak) OR (s.sym = S.period) OR (s.sym = S.lparen) OR (s.sym = S.lparen) OR (s.sym = S.arrow) DO
- CASE s.sym OF
- | S.lbrak : Next; NEW(index); index.expressionList := ExpressionList(); c.next := index; c := c.next; Eat(S.rbrak);
- | S.period : Next; NEW(newIdent); StorePos(newIdent.pos);
- newIdent.name := TS.s.AddString(s.str); (*Strings.NewString(s.str);*) c.next := newIdent; c := c.next; Next;
- | S.arrow: NEW(deref); c.next := deref; c := c.next; Next;
- | S.lparen : Next; NEW(parameters);
- IF s.sym # S.rparen THEN parameters.expressionList := ExpressionList() ELSE parameters.expressionList := NIL END;
- c.next := parameters; c := c.next;
- Eat(S.rparen);
- END
- END;
- RETURN f
- END Designator;
- PROCEDURE IFStatement() : TS.IFStatement;
- VAR f, c, if : TS.IFStatement;
- BEGIN
- f := NIL;
- REPEAT
- Next;
- NEW(if);
- IF f = NIL THEN f := if; c := f ELSE c.else := if; c := if END;
- if.expression := Expression();
- Eat(S.then);
- if.then := StatementSequence()
- UNTIL s.sym # S.elsif;
- IF s.sym = S.else THEN
- Next;
- c.else := StatementSequence()
- END;
- Eat(S.end);
- IF s.sym = S.semicolon THEN Next END;
- RETURN f
- END IFStatement;
- PROCEDURE Case() : TS.Case;
- VAR
- case : TS.Case;
- f, cr : TS.CaseRange;
- BEGIN
- NEW(case);
- REPEAT
- IF s.sym= S.comma THEN Next END;
- IF f = NIL THEN NEW(f); cr := f ELSE NEW(cr.next); cr := cr.next END;
- cr.a := Expression();
- IF s.sym = S.upto THEN
- Next; cr.b := Expression();
- END;
- UNTIL s.sym # S.comma;
- Eat(S.colon);
- case.caseRanges := f;
- case.statements := StatementSequence();
- RETURN case
- END Case;
- PROCEDURE StatementSequence() : TS.Statement;
- VAR ex, fromEx, toEx, byEx : TS.Expression;
- f, n, sequence : TS.Statement;
- designator, designator2 : TS.Designator;
- fcase, ccase : TS.Case;
- PROCEDURE Add(new : TS.Statement);
- BEGIN
- IF comments # NIL THEN new.preComment := comments; comments := NIL END;
- lastStatement := new;
- IF f = NIL THEN f := new; n := new;
- ELSE n.next := new; n := new
- END
- END Add;
- BEGIN
- WHILE (s.sym # S.end) & (s.sym # S.else) & (s.sym # S.elsif) & (s.sym # S.until) & (s.sym # S.bar) & (s.sym # S.eof) DO
- CASE s.sym OF
- |S.ident :
- designator := Designator();
- IF s.sym = S.becomes THEN Next; ex := Expression();
- Add(TS.CreateAssignment(designator, ex))
- ELSE
- Add( TS.CreateProcedureCall(designator))
- END
- |S.if :
- Add(IFStatement())
- |S.while :
- Next;
- ex := Expression();
- Eat(S.do);
- Add(TS.CreateWhile(ex, StatementSequence()));
- Eat(S.end);
- |S.repeat :
- Next;
- sequence := StatementSequence();
- Eat(S.until);
- Add(TS.CreateRepeat(Expression(), sequence))
- |S.for :
- Next;
- designator := Designator();
- Eat(S.becomes);
- fromEx := Expression(); Eat(S.to); toEx := Expression();
- IF s.sym = S.by THEN
- Next;
- byEx := Expression()
- ELSE byEx := NIL;
- END;
- Eat(S.do);
- sequence := StatementSequence();
- Add(TS.CreateFor(designator, fromEx, toEx, byEx, sequence));
- Eat(S.end)
- |S.loop :
- Next;
- Add(TS.CreateLoop(StatementSequence()));
- Eat(S.end);
- |S.exit :
- Next;
- Add(TS.CreateExit())
- |S.return :
- Next;
- IF s.sym < S.semicolon THEN ex := Expression() ELSE ex := NIL END;
- Add(TS.CreateReturn(ex))
- |S.case :
- Next;
- fcase := NIL; ccase := NIL;
- ex := Expression();
- Eat(S.of);
- WHILE s.sym <= S.bar DO
- IF s.sym = S.bar THEN Next END;
- IF s.sym # S.else THEN
- IF fcase = NIL THEN fcase := Case(); ccase := fcase
- ELSE ccase.next := Case(); ccase := ccase.next
- END
- ELSE
- Warn("Illegal '|' before 'ELSE'")
- END
- END;
- sequence := NIL;
- IF s.sym = S.else THEN
- Next;
- sequence := StatementSequence();
- END;
- Add(TS.CreateCase(ex, fcase, sequence));
- Eat(S.end)
- |S.finally : Next;
- |S.begin : Add(StatementBlock()); Eat(S.end);
- |S.with : Next; designator := Designator(); Eat(S.colon); designator2 := Designator(); Eat(S.do);
- sequence := StatementSequence(); Eat(S.end);
- Add(TS.CreateWith(designator, designator2, sequence))
- |S.passivate : Next; Eat(S.lparen); ex := Expression(); Eat(S.rparen); Add(TS.CreateAwait(ex))
- |S.semicolon : Next; Warn("Superfluous Semicolon")
- ELSE
- (* not yet handled *)
- KernelLog.String("s.pos= "); KernelLog.Int(s.pos, 0); KernelLog.Ln;
- KernelLog.String("s.sym= "); KernelLog.Int(s.sym, 0); KernelLog.Ln;
- (* synchronize to end of current statement sequence *)
- WHILE (s.sym # S.eof) & (s.sym # S.end) & (s.sym # S.else) & (s.sym # S.elsif) & (s.sym # S.until) & (s.sym # S.bar) DO Next END;
- END;
- IF s.sym = S.semicolon THEN Next END;
- END;
- Add(TS.NewEmptyStatement());
- ASSERT(f # NIL);
- RETURN f
- END StatementSequence;
- PROCEDURE StatementBlock() : TS.StatementBlock;
- VAR block : TS.StatementBlock;
- BEGIN
- Eat(S.begin);
- IF s.sym = S.lbrace THEN BlockAttributes; Eat(S.rbrace) END;
- NEW(block);
- block.statements := StatementSequence();
- RETURN block
- END StatementBlock;
- PROCEDURE Body() : TS.StatementBlock;
- VAR b : TS.StatementBlock;
- BEGIN
- IF s.sym = S.begin THEN
- b := StatementBlock();
- ELSIF s.sym = S.code THEN
- (* skip assembler *)
- WHILE (s.sym # S.eof) & (s.sym # S.end) DO Next END;
- END;
- RETURN b
- END Body;
- PROCEDURE SysFlag;
- BEGIN
- (* System flag *)
- IF s.sym = S.lbrak THEN
- Next;
- Eat(S.ident);
- Eat(S.rbrak);
- END;
- END SysFlag;
- PROCEDURE VisibilityModifier() : SET;
- VAR state : SET;
- BEGIN
- state := {};
- IF (s.sym = S.times) OR (s.sym = S.minus) THEN
- IF (s.sym = S.times) THEN INCL(state, TS.ExportReadWrite) END;
- IF (s.sym = S.minus) THEN INCL(state, TS.ExportReadOnly) END;
- Next
- END;
- RETURN state
- END VisibilityModifier;
- PROCEDURE Array(array: TS.Array; scope : TS.Scope);
- BEGIN
- (* SysFlag; *)
- IF s.sym = S.lbrak THEN (* skip over open array *)
- REPEAT
- Next;
- IF s.sym = S.times THEN Eat(S.times)
- ELSIF s.sym = S.question THEN Eat(S.question)
- ELSE Error("* or ? expected")
- END;
- UNTIL s.sym # S.comma;
- Eat(S.rbrak);
- IF s.sym = S.of THEN
- Next;
- array.base := Type(scope, "");
- END
- ELSE
- IF s.sym = S.of THEN
- array.open := TRUE;
- Next;
- array.base := Type(scope, "")
- ELSE
- array.expression := Expression();
- IF s.sym = S.of THEN
- Next;
- array.base := Type(scope, "");
- ELSIF s.sym = S.comma THEN
- NEW(array.base);
- array.base.kind := TS.TArray;
- NEW(array.base.array);
- Next;
- Array(array.base.array, scope)
- ELSE
- Error("Illegal Array Definition")
- END
- END
- END
- END Array;
- PROCEDURE Record(record: TS.Record; scope : TS.Scope);
- VAR i : LONGINT;
- debug : TS.NamedObject;
- BEGIN
- SysFlag;
- NEW(record.scope);
- record.scope.parent := scope;
- NEW(debug); debug.name := Strings.NewString("RECORD");
- record.scope.owner := debug;
- IF s.sym = S.lparen THEN
- Next;
- record.scope.superQualident := Designator();
- Eat(S.rparen);
- END;
- WHILE s.sym = S.semicolon DO Next END;
- IF s.sym = S.ident THEN
- record.scope.elements := FieldList(record.scope);
- FOR i := 0 TO record.scope.elements.nofObjs - 1 DO
- record.scope.elements.objs[i].container := record.scope
- END;
- END;
- Eat(S.end);
- END Record;
- PROCEDURE FieldList(scope : TS.Scope) : TS.ObjectList;
- VAR fieldList, t : TS.ObjectList; i : LONGINT;
- BEGIN
- NEW(fieldList);
- t := FieldDecl(scope);
- FOR i := 0 TO t.nofObjs - 1 DO fieldList.Add(t.objs[i]) END;
- WHILE s.sym = S.semicolon DO
- Next;
- t := FieldDecl(scope);
- FOR i := 0 TO t.nofObjs - 1 DO fieldList.Add(t.objs[i]) END;
- END;
- RETURN fieldList
- END FieldList;
- PROCEDURE FieldDecl(scope : TS.Scope) : TS.ObjectList;
- VAR
- var : TS.Var;
- t : TS.Type;
- i : LONGINT;
- ol : TS.ObjectList;
- BEGIN
- NEW(ol);
- IF s.sym = S.ident THEN
- NEW(var);
- var.name := Strings.NewString(s.str);
- StorePos(var.pos); ol.Add(var);
- Next;
- var.exportState := VisibilityModifier();
- IF s.sym = S.lbrace THEN BlockAttributes; Eat(S.rbrace) END;
- SysFlag;
- WHILE s.sym = S.comma DO
- Next;
- NEW(var);
- var.name := Strings.NewString(s.str);
- StorePos(var.pos); ol.Add(var);
- Next;
- var.exportState := VisibilityModifier();
- IF s.sym = S.lbrace THEN BlockAttributes; Eat(S.rbrace) END;
- SysFlag
- END;
- Eat(S.colon);
- t := Type(scope, var.name^);
- (* only now the type is known *)
- FOR i := 0 TO ol.nofObjs - 1 DO
- ol.objs[i](TS.Var).type := t
- END
- END;
- RETURN ol
- END FieldDecl;
- (* *)
- PROCEDURE FPSection(scope : TS.Scope) : TS.ObjectList;
- VAR
- var : TS.Var;
- t : TS.Type;
- i : LONGINT;
- ol : TS.ObjectList;
- isConst : BOOLEAN;
- isVar : BOOLEAN;
- BEGIN
- NEW(ol);
- isConst := FALSE; isVar := FALSE;
- IF s.sym = S.var THEN
- (* VAR parameter section *)
- isVar := TRUE;
- Next
- ELSIF s.sym = S.const THEN
- (* CONST parameter section *)
- isConst := TRUE;
- Next
- END;
- IF s.sym = S.ident THEN
- NEW(var);
- StorePos(var.pos);
- var.name := Strings.NewString(s.str);
- IF isConst THEN INCL(var.parameterType, TS.IsConstParam)
- ELSIF isVar THEN INCL(var.parameterType, TS.IsVarParam)
- END;
- ol.Add(var);
- Next;
- WHILE s.sym = S.comma DO
- Next;
- NEW(var);
- StorePos(var.pos);
- var.name := Strings.NewString(s.str);
- ol.Add(var);
- Next
- END;
- Eat(S.colon);
- t := Type(scope, "");
- (* only now the type is known *)
- FOR i := 0 TO ol.nofObjs - 1 DO
- ol.objs[i](TS.Var).type := t
- END
- END;
- RETURN ol
- END FPSection;
- PROCEDURE ProcSignature(scope : TS.Scope) : TS.ProcedureSignature;
- VAR ps : TS.ProcedureSignature;
- ol : TS.ObjectList;
- i : LONGINT;
- BEGIN
- NEW(ps);
- Next;
- IF (s.sym = S.var) OR (s.sym = S.const) OR (s.sym = S.ident) THEN
- ps.params := FPSection(scope);
- WHILE s.sym = S.semicolon DO
- Next; (* avoids endless loop *)
- ol := FPSection(scope);
- FOR i := 0 TO ol.nofObjs - 1 DO ps.params.Add(ol.objs[i]) END;
- END;
- FOR i := 0 TO ps.params.nofObjs - 1 DO
- ps.params.objs[i](TS.Var).varNr := i;
- INCL(ps.params.objs[i](TS.Var).parameterType, TS.IsParam)
- END
- END;
- Eat(S.rparen);
- IF s.sym = S.colon THEN
- Next;
- ps.return := Type(scope, "")
- END;
- RETURN ps
- END ProcSignature;
- PROCEDURE ProcDecl(currentScope : TS.Scope) : TS.ProcDecl;
- VAR pd : TS.ProcDecl; forward : BOOLEAN;
- name : ARRAY 64 OF CHAR;
- i : LONGINT;
- BEGIN
- NEW(pd);
- IF comments # NIL THEN pd.preComment := comments; comments := NIL END;
- forward := FALSE;
- SysFlag;
- CASE s.sym OF
- | S.minus: (*inline := TRUE;*) Next
- | S.and: (* constructor := TRUE;*) Next
- | S.times: (* ignore *) Next
- | S.arrow: forward := TRUE; Next
- | S.string: (*operator := TRUE;*)
- | S.number: (*IF s.numtyp = S.char THEN (* operator := TRUE *)END;*)
- ELSE
- END;
- IF s.sym = S.lbrace THEN BlockAttributes; Eat(S.rbrace) END;
- (* procedure name *)
- pd.name := Strings.NewString(s.str);
- StorePos(pd.pos);
- COPY(pd.name^, name);
- IF pd.name^="" THEN HALT(9999) END;
- Next;
- (* visibility modifier *)
- pd.exportState := VisibilityModifier();
- NEW(pd.scope) ;
- pd.scope.parent := currentScope;
- pd.scope.owner := pd;
- IF s.sym = S.lparen THEN
- pd.signature := ProcSignature(currentScope);
- (* update container *)
- IF pd.signature.params # NIL THEN
- FOR i := 0 TO pd.signature.params.nofObjs - 1 DO pd.signature.params.objs[i].container := pd.scope END;
- END;
- pd.scope.params := pd.signature.params
- END;
- IF ~forward THEN
- Eat(S.semicolon);
- IF (s.sym = S.const) OR (s.sym = S.var) OR (s.sym = S.type) OR (s.sym = S.procedure) THEN
- DeclSeq(pd.scope)
- END;
-
- pd.scope.ownerBody := Body();
- Eat(S.end);
- StorePos(pd.altPos);
- IF s.str # pd.name^ THEN
- Error("Procedure-name does not match")
- END;
- Next;
- END;
- (* KernelLog.String("P:"); KernelLog.String(s.str); KernelLog.Ln; *)
- RETURN pd
- END ProcDecl;
- PROCEDURE Definition;
- VAR ps : TS.ProcedureSignature; q : TS.Designator;
- BEGIN
- IF s.sym = S.definition THEN
- Next;
- IF s.sym = S.ident THEN
- Next
- ELSE Error("Definition name expected")
- END;
- WHILE s.sym = S.semicolon DO Next END;
- IF s.sym = S.refines THEN Next;
- q := Designator()
- END;
- WHILE s.sym = S.procedure DO
- Next;
- ps := ProcSignature(m.scope);
- Eat(S.semicolon);
- END;
- Eat(S.end);
- Eat(S.ident);
- WHILE s.sym = S.semicolon DO Next END;
- END;
- END Definition;
- PROCEDURE Module;
- VAR body : TS.Statement;
- BEGIN
- IF s.sym = S.module THEN
- Next;
- (* read module name *)
- IF s.sym = S.ident THEN
- NEW(m);
- (* attach pre-comments *)
- IF comments # NIL THEN
- m.preComment := comments; comments := NIL
- END;
-
- NEW(m.scope);
- m.scope.parent := Universe;
- m.scope.owner := m;
- StorePos(m.pos);
- m.name := Strings.NewString(s.str);
- (* skip module options *)
- Next;
- IF s.sym = S.lbrace THEN
- WHILE (s.sym # S.semicolon) & (s.sym # S.eof) DO Next END;
- END;
- (* read (and ignore) package *)
- IF s.sym = S.in THEN
- Next;
- m.package := Strings.NewString(s.str);
- Eat(S.ident)
- END;
- Eat(S.semicolon);
- IF s.sym = S.import THEN
- (* attach pre-comments *)
- IF comments # NIL THEN
- m.postComment := comments; comments := NIL
- END;
- ImportList
- END;
- WHILE s.sym = S.definition DO Definition END;
- IF (s.sym = S.const) OR (s.sym = S.type) OR (s.sym = S.var) OR (s.sym = S.procedure) THEN
- DeclSeq(m.scope)
- END;
- IF s.sym = S.begin THEN
- Next;
- IF s.sym = S.lbrace THEN BlockAttributes; Eat(S.rbrace) END;
- body := StatementSequence();
- m.scope.ownerBody := body;
- END;
- Eat(S.end);
- StorePos(m.altPos);
- IF (s.sym = S.ident) & (s.str = m.name^) THEN
- (* correct *)
- Next;
- ELSE
- (* maybe missing END or wrong module name *)
- Error("END missing or wrong module name")
- END;
- Eat(S.period);
- ELSE
- Error("name expected");
- END;
- END;
- END Module;
- PROCEDURE Parse*(s : S.Scanner);
- BEGIN
- SELF.s := s;
- Next; (* establish one look ahead *)
- Module;
- END Parse;
- END Parser;
- FileListEntry = POINTER TO RECORD
- filename : ARRAY 128 OF CHAR;
- next : FileListEntry;
- END;
- SymbolCreator = OBJECT
- VAR filename : ARRAY 128 OF CHAR;
- BEGIN {ACTIVE}
- IncWorker;
- WHILE GetTask(filename) DO
- MakeSymbolFile(filename);
- END;
- DecWorker
- END SymbolCreator;
- VAR Universe* : TS.Scope;
- System : TS.Module;
- release : TS.ObjectList;
- fileList : FileListEntry;
- nofWorkers : LONGINT;
- PROCEDURE GetTask(VAR filename : ARRAY OF CHAR) : BOOLEAN;
- BEGIN {EXCLUSIVE}
- IF fileList # NIL THEN
- COPY(fileList.filename, filename); fileList := fileList.next;
- RETURN TRUE
- ELSE RETURN FALSE
- END
- END GetTask;
- PROCEDURE AddTask(CONST filename : ARRAY OF CHAR);
- VAR fl : FileListEntry;
- BEGIN {EXCLUSIVE}
- NEW(fl);
- COPY(filename, fl.filename);
- fl.next := fileList; fileList := fl;
- END AddTask;
- PROCEDURE IncWorker;
- BEGIN {EXCLUSIVE}
- INC(nofWorkers);
- END IncWorker;
- PROCEDURE DecWorker;
- BEGIN {EXCLUSIVE}
- DEC(nofWorkers);
- END DecWorker;
- PROCEDURE ScanModule*(CONST filename : ARRAY OF CHAR; dump : BOOLEAN; VAR m : TS.Module);
- VAR t : Texts.Text; res : WORD; format: LONGINT;
- s : S.Scanner;
- p : Parser;
- BEGIN
- NEW(t);
- TextUtilities.LoadAuto(t, filename, format, res);
- IF res # 0 THEN
- KernelLog.String(filename); KernelLog.String(" not found"); KernelLog.Ln;
- RETURN
- END;
- s := S.InitWithText(t, 0);
- NEW(p); p.Parse(s);
- m := p.m;
- IF dump THEN
- IF p.m # NIL THEN
- TFDumpTS.Open(p.m.name^);
- TFDumpTS.DumpM(p.m)
- END
- END
- END ScanModule;
- PROCEDURE ScanForModules;
- VAR
- e : Files.Enumerator;
- name : ARRAY 256 OF CHAR; flags : SET; time, date, size : LONGINT;
- module : TS.Module;
- i : LONGINT;
- t0, t1 : LONGINT;
- BEGIN
- NEW(release);
- NEW(e);
- e.Open("d:/release/*.Mod", {});
- i := 0;
- t0 := Kernel.GetTicks();
- WHILE e.HasMoreEntries() DO
- IF e.GetEntry(name, flags, time, date, size) THEN
- KernelLog.String(name); KernelLog.Ln;
- ScanModule(name, FALSE, module);
- TS.WriteSymbolFile(module);
- (* IF module # NIL THEN
- TFCheck.CheckDeclarations(module.scope);
- END; *)
- (* IF module # NIL THEN release.Add(module); INC(i) END; *)
- END
- END;
- t1 := Kernel.GetTicks();
- KernelLog.String("Finished "); KernelLog.Int(i, 0); KernelLog.String(" modules loaded"); KernelLog.Ln;
- KernelLog.String("t1-t0= "); KernelLog.Int(t1-t0, 0); KernelLog.Ln;
- KernelLog.Int((t1-t0) DIV 60000, 0); KernelLog.String("m"); KernelLog.Int(((t1-t0) DIV 1000) MOD 60, 0); KernelLog.String("s"); KernelLog.Ln;
- END ScanForModules;
- PROCEDURE Test*(par : Commands.Context) ;
- VAR
- name :ARRAY 256 OF CHAR;
- sr : Streams.Reader;
- t0, t1 : LONGINT;
- module : TS.Module;
- BEGIN
- sr := par.arg;
- sr.String(name);
- KernelLog.String("Parsing "); KernelLog.String(name);
- t0 := Kernel.GetTicks();
- ScanModule(name, TRUE, module);
- IF module # NIL THEN
- TFCheck.CheckDeclarations(module.scope);
- END;
- t1 := Kernel.GetTicks();
- KernelLog.String("t1-t0= "); KernelLog.Int(t1-t0, 0); KernelLog.Ln;
- KernelLog.String(" done.");
- END Test;
- PROCEDURE MakeSymbolFile(CONST filename : ARRAY OF CHAR);
- VAR module : TS.Module;
- BEGIN
- KernelLog.String(filename); KernelLog.Ln;
- ScanModule(filename, FALSE, module);
- IF module # NIL THEN
- module.filename := Strings.NewString(filename);
- TS.WriteSymbolFile(module)
- END
- END MakeSymbolFile;
- PROCEDURE MakeSymbolFiles*(par : Commands.Context) ;
- CONST NofSymbolCreators = 4;
- VAR e : Files.Enumerator;
- path, name, exclude : ARRAY 256 OF CHAR; flags : SET; time, date, size : LONGINT;
- sr : Streams.Reader;
- i : LONGINT;
- t0, t1 : LONGINT;
- symbolCreators : ARRAY NofSymbolCreators OF SymbolCreator;
- BEGIN
- sr := par.arg;
- sr.String(path); sr.SkipWhitespace();
- sr.String(exclude);
- IF (path # "") & ~Strings.EndsWith("/", path) THEN Strings.Append(path, "/") END;
- Strings.Append(path, "*.Mod");
- KernelLog.String(path); KernelLog.Ln;
- IF exclude # "" THEN
- KernelLog.String("Excluding "); KernelLog.String(exclude); KernelLog.Ln;
- END;
- NEW(e);
- e.Open(path, {});
- i := 0;
- t0 := Kernel.GetTicks();
- KernelLog.String("Processing ... "); KernelLog.Ln;
- WHILE e.HasMoreEntries() DO
- IF e.GetEntry(name, flags, time, date, size) THEN
- IF (exclude = "") OR ~Strings.Match(exclude, name) THEN
- AddTask(name);
- INC(i)
- ELSE
- KernelLog.String("Excluding "); KernelLog.String(name); KernelLog.Ln;
- END
- END
- END;
- KernelLog.Int(i, 0); KernelLog.String(" modules queued for processing"); KernelLog.Ln;
- FOR i := 0 TO NofSymbolCreators - 1 DO NEW(symbolCreators[i]) END;
- BEGIN {EXCLUSIVE}
- AWAIT((fileList = NIL) & (nofWorkers = 0));
- END;
- t1 := Kernel.GetTicks();
- KernelLog.Int((t1-t0) DIV 60000, 0); KernelLog.String("m"); KernelLog.Int(((t1-t0) DIV 1000) MOD 60, 0); KernelLog.String("s"); KernelLog.Ln;
- END MakeSymbolFiles;
- PROCEDURE MakeSym*(par : Commands.Context) ;
- VAR
- name :ARRAY 256 OF CHAR;
- sr : Streams.Reader;
- t0, t1 : LONGINT;
- module : TS.Module;
- BEGIN
- sr := par.arg;
- sr.String(name);
- KernelLog.String("Parsing "); KernelLog.String(name);
- t0 := Kernel.GetTicks();
- ScanModule(name, TRUE, module);
- IF module # NIL THEN
- (* TFCheck.CheckDeclarations(module.scope); *)
- TS.WriteSymbolFile(module);
- END;
- t1 := Kernel.GetTicks();
- KernelLog.String("t1-t0= "); KernelLog.Int(t1-t0, 0); KernelLog.Ln;
- KernelLog.String(" done.");
- END MakeSym;
- PROCEDURE AddStandardProc(scope : TS.Scope; CONST name : ARRAY OF CHAR);
- VAR p : TS.ProcDecl;
- BEGIN
- NEW(p); p.name := Strings.NewString(name);
- scope.Add(p)
- END AddStandardProc;
- PROCEDURE AddBasicType(scope : TS.Scope; CONST name : ARRAY OF CHAR; type : LONGINT);
- VAR t : TS.TypeDecl;
- BEGIN
- NEW(t); t.name := Strings.NewString(name);
- NEW(t.type); t.type.kind := TS.TBasic; t.type.basicType := type;
- scope.Add(t)
- END AddBasicType;
- BEGIN
- NEW(Universe);
- Universe.parent := NIL;
- NEW(System); System.name := Strings.NewString("SYSTEM");
- NEW(System.scope);
- AddBasicType(System.scope, "ADDRESS", TS.BasicInt32);
- AddBasicType(System.scope, "SIZE", TS.BasicInt32);
- TS.ns.AddModule(System);
- AddStandardProc(Universe, "NEW");
- AddStandardProc(Universe, "LEN");
- AddStandardProc(Universe, "COPY");
- AddStandardProc(Universe, "ASSERT");
- AddStandardProc(Universe, "HALT");
- AddStandardProc(Universe, "INC");
- AddStandardProc(Universe, "DEC");
- AddStandardProc(Universe, "INCL");
- AddStandardProc(Universe, "EXCL");
- AddStandardProc(Universe, "CHR");
- AddStandardProc(Universe, "ORD");
- AddStandardProc(Universe, "LONG");
- AddStandardProc(Universe, "SHORT");
- AddStandardProc(Universe, "ENTIER");
- AddStandardProc(Universe, "ASH");
- AddBasicType(Universe, "BOOLEAN", TS.BasicBoolean);
- AddBasicType(Universe, "ANY", TS.BasicInt32);
- AddBasicType(Universe, "PTR", TS.BasicInt32);
- AddBasicType(Universe, "SHORTINT", TS.BasicInt8);
- AddBasicType(Universe, "INTEGER", TS.BasicInt16);
- AddBasicType(Universe, "LONGINT", TS.BasicInt32);
- AddBasicType(Universe, "SET", TS.BasicInt32);
- AddBasicType(Universe, "HUGEINT", TS.BasicInt64);
- AddBasicType(Universe, "CHAR", TS.BasicChar8);
- AddBasicType(Universe, "REAL", TS.BasicReal32);
- AddBasicType(Universe, "LONGREAL", TS.BasicReal64);
- AddBasicType(Universe, "STRING", TS.BasicString);
- END TFAOParser.
|