예제 #1
0
파일: Parser.cs 프로젝트: qunyanm/boogie
	void StmtList(out StmtList/*!*/ stmtList) {
		Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); List<BigBlock/*!*/> bigblocks = new List<BigBlock/*!*/>();
		/* built-up state for the current BigBlock: */
		IToken startToken = null;  string currentLabel = null;
		List<Cmd> cs = null;  /* invariant: startToken != null ==> cs != null */
		/* temporary variables: */
		IToken label;  Cmd c;  BigBlock b;
		StructuredCmd ec = null;  StructuredCmd/*!*/ ecn;
		TransferCmd tc = null;  TransferCmd/*!*/ tcn;
		
		while (StartOf(7)) {
			if (StartOf(8)) {
				LabelOrCmd(out c, out label);
				if (c != null) {
				 // LabelOrCmd read a Cmd
				 Contract.Assert(label == null);
				 if (startToken == null) { startToken = c.tok;  cs = new List<Cmd>(); }
				 Contract.Assert(cs != null);
				 cs.Add(c);
				} else {
				 // LabelOrCmd read a label
				 Contract.Assert(label != null);
				 if (startToken != null) {
				   Contract.Assert(cs != null);
				   // dump the built-up state into a BigBlock
				   b = new BigBlock(startToken, currentLabel, cs, null, null);
				   bigblocks.Add(b);
				   cs = null;
				 }
				 startToken = label;
				 currentLabel = label.val;
				 cs = new List<Cmd>();
				}
				
			} else if (la.kind == 41 || la.kind == 43 || la.kind == 46) {
				StructuredCmd(out ecn);
				ec = ecn;
				if (startToken == null) { startToken = ec.tok;  cs = new List<Cmd>(); }
				Contract.Assert(cs != null);
				b = new BigBlock(startToken, currentLabel, cs, ec, null);
				bigblocks.Add(b);
				startToken = null;  currentLabel = null;  cs = null;
				
			} else {
				TransferCmd(out tcn);
				tc = tcn;
				if (startToken == null) { startToken = tc.tok;  cs = new List<Cmd>(); }
				Contract.Assert(cs != null);
				b = new BigBlock(startToken, currentLabel, cs, null, tc);
				bigblocks.Add(b);
				startToken = null;  currentLabel = null;  cs = null;
				
			}
		}
		Expect(29);
		IToken/*!*/ endCurly = t;
		if (startToken == null && bigblocks.Count == 0) {
		 startToken = t;  cs = new List<Cmd>();
		}
		if (startToken != null) {
		 Contract.Assert(cs != null);
		 b = new BigBlock(startToken, currentLabel, cs, null, null);
		 bigblocks.Add(b);
		}
		
		stmtList = new StmtList(bigblocks, endCurly);
		
	}
예제 #2
0
 TransferCmd GotoSuccessor(IToken tok, BigBlock b)
 {
     Contract.Requires(b != null);
       Contract.Requires(tok != null);
       Contract.Ensures(Contract.Result<TransferCmd>() != null);
       if (b.successorBigBlock != null) {
     return new GotoCmd(tok, new List<String> { b.successorBigBlock.LabelName });
       } else {
     return new ReturnCmd(tok);
       }
 }
예제 #3
0
        void RecordSuccessors(StmtList stmtList, BigBlock successor)
        {
            Contract.Requires(stmtList != null);
              for (int i = stmtList.BigBlocks.Count; 0 <= --i; ) {
            BigBlock big = stmtList.BigBlocks[i];
            big.successorBigBlock = successor;

            if (big.ec is WhileCmd) {
              WhileCmd wcmd = (WhileCmd)big.ec;
              RecordSuccessors(wcmd.Body, successor);
            } else {
              for (IfCmd ifcmd = big.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
            RecordSuccessors(ifcmd.thn, successor);
            if (ifcmd.elseBlock != null) {
              RecordSuccessors(ifcmd.elseBlock, successor);
            }
              }
            }

            successor = big;
              }
        }
예제 #4
0
        void CheckLegalLabels(StmtList stmtList, StmtList parentContext, BigBlock parentBigBlock)
        {
            Contract.Requires(stmtList != null);
              Contract.Requires((parentContext == null) == (parentBigBlock == null));
              Contract.Requires(stmtList.ParentContext == null);  // it hasn't been set yet
              //modifies stmtList.*;
              Contract.Ensures(stmtList.ParentContext == parentContext);
              stmtList.ParentContext = parentContext;
              stmtList.ParentBigBlock = parentBigBlock;

              // record the labels declared in this StmtList
              foreach (BigBlock b in stmtList.BigBlocks) {
            if (b.LabelName != null) {
              string n = b.LabelName;
              if (n.StartsWith(prefix)) {
            if (prefix.Length < n.Length && n[prefix.Length] == '0') {
              prefix += "1";
            } else {
              prefix += "0";
            }
              }
              stmtList.Labels.Add(b.LabelName);
            }
              }

              // check that labels in this and nested StmtList's are legal
              foreach (BigBlock b in stmtList.BigBlocks) {
            // goto's must reference blocks in enclosing blocks
            if (b.tc is GotoCmd) {
              GotoCmd g = (GotoCmd)b.tc;
              foreach (string/*!*/ lbl in cce.NonNull(g.labelNames)) {
            Contract.Assert(lbl != null);
            /*
            bool found = false;
            for (StmtList sl = stmtList; sl != null; sl = sl.ParentContext) {
              if (sl.Labels.Contains(lbl)) {
                found = true;
                break;
              }
            }
            if (!found) {
              this.errorHandler.SemErr(g.tok, "Error: goto label '" + lbl + "' is undefined or out of reach");
            }
            */
            if (!allLabels.Contains(lbl)) {
              this.errorHandler.SemErr(g.tok, "Error: goto label '" + lbl + "' is undefined");
            }
              }
            }

            // break labels must refer to an enclosing while statement
            else if (b.ec is BreakCmd) {
              BreakCmd bcmd = (BreakCmd)b.ec;
              Contract.Assert(bcmd.BreakEnclosure == null);  // it hasn't been initialized yet
              bool found = false;
              for (StmtList sl = stmtList; sl.ParentBigBlock != null; sl = sl.ParentContext) {
            cce.LoopInvariant(sl != null);
            BigBlock bb = sl.ParentBigBlock;

            if (bcmd.Label == null) {
              // a label-less break statement breaks out of the innermost enclosing while statement
              if (bb.ec is WhileCmd) {
                bcmd.BreakEnclosure = bb;
                found = true;
                break;
              }
            } else if (bcmd.Label == bb.LabelName) {
              // a break statement with a label can break out of both if statements and while statements
              if (bb.simpleCmds.Count == 0) {
                // this is a good target:  the label refers to the if/while statement
                bcmd.BreakEnclosure = bb;
              } else {
                // the label of bb refers to the first statement of bb, which in which case is a simple statement, not an if/while statement
                this.errorHandler.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
              }
              found = true;  // don't look any further, since we've found a matching label
              break;
            }
              }
              if (!found) {
            if (bcmd.Label == null) {
              this.errorHandler.SemErr(bcmd.tok, "Error: break statement is not inside a loop");
            } else {
              this.errorHandler.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
            }
              }
            }

            // recurse
            else if (b.ec is WhileCmd) {
              WhileCmd wcmd = (WhileCmd)b.ec;
              CheckLegalLabels(wcmd.Body, stmtList, b);
            } else {
              for (IfCmd ifcmd = b.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
            CheckLegalLabels(ifcmd.thn, stmtList, b);
            if (ifcmd.elseBlock != null) {
              CheckLegalLabels(ifcmd.elseBlock, stmtList, b);
            }
              }
            }
              }
        }