public override AddResult AddTo(CodeFragment to, CodeLexer sr)
        {
            if (Value == "")
            {
                return(AddResult.Ok);
            }
            else if (Value == "var")
            {
                // We're reading a local:
                return(AddResult.Local);
            }
            else if (Value == "for" || Value == "while")
            {
                return(new ForFragment(sr, Value).AddTo(to, sr));
            }
            else if (Value == "switch")
            {
                return(new SwitchFragment(sr).AddTo(to, sr));
            }
            else if (Value == "if")
            {
                return(new IfFragment(sr).AddTo(to, sr));
            }
            else if (Value == "else")
            {
                CodeFragment previous = to.ParentFragment;

                // Parent->prev operation->last object. Should be an IF.

                if (previous == null || ((previous = previous.LastChild) == null) || ((previous = previous.LastChild) == null) || previous.GetType() != typeof(IfFragment))
                {
                    Error("Else can only be applied to an if. E.g. if(){}else{}.");
                }

                IfFragment ifFrag = (IfFragment)previous;

                ifFrag.ApplyElseTo.SetIfFalse(new BracketFragment(sr));

                return(AddResult.Stop);
            }
            else if (Value == "elseif")
            {
                CodeFragment previous = to.ParentFragment;
                // Parent->prev operation->last object. Should be an IF.

                if (previous == null || ((previous = previous.LastChild) == null) || ((previous = previous.LastChild) == null) || previous.GetType() != typeof(IfFragment))
                {
                    Error("Else if can only be applied to an if. E.g. if(){}else if{}..");
                }

                IfFragment ifFrag  = (IfFragment)previous;
                IfFragment newfrag = new IfFragment(sr);

                BracketFragment   bf = new BracketFragment();
                OperationFragment op = new OperationFragment();
                op.AddChild(newfrag);
                bf.AddChild(op);

                ifFrag.ApplyElseTo.SetIfFalse(bf);
                ifFrag.ApplyElseTo = newfrag;

                return(AddResult.Stop);
            }
            else
            {
                return(base.AddTo(to, sr));
            }
        }
		/// <summary>Compiles an operation fragment into an executable operation. The fragment may contain multiple
		/// operators and some may even be the same so the furthest right takes priority; 1+2+3 becomes 1+(2+3).
		/// The compiled fragments are placed back into the same operation fragment. When it's complete, the operation
		/// will only contain one compiled fragment.</summary>
		/// <param name="fragment">The operation fragment to compile.</param>
		/// <param name="parentBlock">The method the operations are compiling into.</param>
		public static void CompileOperators(OperationFragment fragment,CompiledMethod parentBlock){
			CodeFragment child=fragment.FirstChild;
			OperatorFragment highestPriority=null;
			
			while(child!=null){
				
				if(child.GetType()==typeof(OperatorFragment)){
					OperatorFragment thisOperator=(OperatorFragment)child;
					
					// <= below enforces furthest right:
					if(highestPriority==null||highestPriority.Value.Priority<=thisOperator.Value.Priority){
						highestPriority=thisOperator;
					}
					
				}
				
				child=child.NextChild;
			}
			
			if(highestPriority==null){
				return;
			}
			
			CodeFragment left=highestPriority.PreviousChild;
			CodeFragment right=highestPriority.NextChild;
			CodeFragment leftUsed=left;
			CodeFragment rightUsed=right;
			
			if(left==null||left.GetType()==typeof(OperatorFragment)){
				leftUsed=null;
			}else if(!Types.IsCompiled(left)){
				leftUsed=left.Compile(parentBlock);
			}
			
			if(right==null||right.GetType()==typeof(OperatorFragment)){
				rightUsed=null;
			}else if(!Types.IsCompiled(right)){
				rightUsed=right.Compile(parentBlock);
			}
			
			Operation newFragment=highestPriority.Value.ToOperation((CompiledFragment)leftUsed,(CompiledFragment)rightUsed,parentBlock);
			
			if(newFragment==null){
				highestPriority.Error("Error: An operator has been used but with nothing to use it on! (It was a '"+highestPriority.Value.Pattern+"')");
			}
			
			// Replace out Left, Right and the operator itself with the new fragment:
			highestPriority.Remove();
			
			if(left==null){
				newFragment.AddBefore(right);
			}else{
				newFragment.AddAfter(left);
			}
			
			if(rightUsed!=null){
				right.Remove();
			}
			
			if(leftUsed!=null){
				left.Remove();
			}
			
			// And call again to collect the rest:
			CompileOperators(fragment,parentBlock);
		}
예제 #3
0
        /// <summary>Compiles an operation fragment into an executable operation. The fragment may contain multiple
        /// operators and some may even be the same so the furthest right takes priority; 1+2+3 becomes 1+(2+3).
        /// The compiled fragments are placed back into the same operation fragment. When it's complete, the operation
        /// will only contain one compiled fragment.</summary>
        /// <param name="fragment">The operation fragment to compile.</param>
        /// <param name="parentBlock">The method the operations are compiling into.</param>
        public static void CompileOperators(OperationFragment fragment, CompiledMethod parentBlock)
        {
            CodeFragment     child           = fragment.FirstChild;
            OperatorFragment highestPriority = null;

            while (child != null)
            {
                if (child.GetType() == typeof(OperatorFragment))
                {
                    OperatorFragment thisOperator = (OperatorFragment)child;

                    // <= below enforces furthest right:
                    if (highestPriority == null || highestPriority.Value.Priority <= thisOperator.Value.Priority)
                    {
                        highestPriority = thisOperator;
                    }
                }

                child = child.NextChild;
            }

            if (highestPriority == null)
            {
                return;
            }

            CodeFragment left      = highestPriority.PreviousChild;
            CodeFragment right     = highestPriority.NextChild;
            CodeFragment leftUsed  = left;
            CodeFragment rightUsed = right;

            if (left == null || left.GetType() == typeof(OperatorFragment))
            {
                leftUsed = null;
            }
            else if (!Types.IsCompiled(left))
            {
                leftUsed = left.Compile(parentBlock);
            }

            if (right == null || right.GetType() == typeof(OperatorFragment))
            {
                rightUsed = null;
            }
            else if (!Types.IsCompiled(right))
            {
                rightUsed = right.Compile(parentBlock);
            }

            Operation newFragment = highestPriority.Value.ToOperation((CompiledFragment)leftUsed, (CompiledFragment)rightUsed, parentBlock);

            if (newFragment == null)
            {
                highestPriority.Error("Error: An operator has been used but with nothing to use it on! (It was a '" + highestPriority.Value.Pattern + "')");
            }

            // Replace out Left, Right and the operator itself with the new fragment:
            highestPriority.Remove();

            if (left == null)
            {
                newFragment.AddBefore(right);
            }
            else
            {
                newFragment.AddAfter(left);
            }

            if (rightUsed != null)
            {
                right.Remove();
            }

            if (leftUsed != null)
            {
                left.Remove();
            }

            // And call again to collect the rest:
            CompileOperators(fragment, parentBlock);
        }
예제 #4
0
        /// <summary>Compiles a known keyword fragment into the given method.</summary>
        /// <param name="kwd">The known keyword fragment. return, using, break or continue.</param>
        /// <param name="method">The method to compile the fragment into.</param>
        /// <returns>A compiled instruction of the given keyword.</returns>
        public static CompiledFragment Compile(VariableFragment kwd, CompiledMethod method)
        {
            OperationFragment parent = (OperationFragment)kwd.ParentFragment;

            switch (kwd.Value)
            {
            case "return":
                if (kwd.PreviousChild != null)
                {
                    kwd.Error("Return cannot follow other operations. You might have a missing ;.");
                }
                kwd.Remove();
                ReturnOperation returnOperation = new ReturnOperation(method);

                if (parent.FirstChild != null)
                {
                    if ((returnOperation.Input0 = parent.Compile(method)) == null)
                    {
                        return(null);
                    }
                }

                parent.FirstChild = returnOperation;
                return(returnOperation);

            case "typeof":
                if (kwd.PreviousChild != null)
                {
                    kwd.Error("Typeof cannot follow other operations. You might have a missing ;.");
                }
                kwd.Remove();
                TypeofOperation tOperation = new TypeofOperation(method);

                if (parent.FirstChild == null)
                {
                    kwd.Error("typeof command is missing the thing to find the type of.");
                }

                if ((tOperation.Input0 = parent.Compile(method)) == null)
                {
                    return(null);
                }

                parent.FirstChild = tOperation;
                return(tOperation);

            case "using":
                if (kwd.PreviousChild != null)
                {
                    kwd.Error("Using cannot follow other operations. You might be missing a ;.");
                }

                kwd.Remove();

                if (parent.FirstChild != null)
                {
                    method.Script.AddReference(parent.FirstChild);
                }

                return(null);

            case "break":
                kwd.Remove();
                BreakOperation breakOperation = new BreakOperation(method, 1);

                if (parent.FirstChild != null)
                {
                    CompiledFragment cf = parent.Compile(method);

                    if (cf.Value != null && cf.Value.GetType() == typeof(int))
                    {
                        breakOperation.Depth = (int)cf.Value;

                        if (breakOperation.Depth <= 0)
                        {
                            parent.Error("Break operations must be greater than 0 loops.");
                        }
                    }
                    else
                    {
                        parent.Error("Break statements can only be followed by a fixed integer constant, e.g. break 2; or just break;");
                    }
                }

                parent.FirstChild = breakOperation;
                return(breakOperation);

            case "continue":
                kwd.Remove();
                ContinueOperation cOperation = new ContinueOperation(method, 1);

                if (parent.FirstChild != null)
                {
                    CompiledFragment cf = parent.Compile(method);

                    if (cf.Value != null && cf.Value.GetType() == typeof(int))
                    {
                        cOperation.Depth = (int)cf.Value;
                        if (cOperation.Depth <= 0)
                        {
                            parent.Error("Continue operations must be greater than 0 loops.");
                        }
                    }
                    else
                    {
                        parent.Error("Continue statements can only be followed by a fixed integer constant, e.g. continue 2; or just continue;");
                    }
                }

                parent.FirstChild = cOperation;
                return(cOperation);

            default:
                parent.Error("Unrecognised keyword: " + kwd.Value);
                return(null);
            }
        }
		public override AddResult AddTo(CodeFragment to,CodeLexer sr){
			
			if(Value==""){
				return AddResult.Ok;
			}else if(Value=="var"){
				
				// We're reading a local:
				return AddResult.Local;
				
			}else if(Value=="for" || Value=="while"){
				return new ForFragment(sr,Value).AddTo(to,sr);
			}else if(Value=="switch"){
				return new SwitchFragment(sr).AddTo(to,sr);
			}else if(Value=="if"){
				return new IfFragment(sr).AddTo(to,sr);
			}else if(Value=="else"){
				CodeFragment previous=to.ParentFragment;
				
				// Parent->prev operation->last object. Should be an IF.
				
				if(previous==null||((previous=previous.LastChild)==null)||((previous=previous.LastChild)==null)||previous.GetType()!=typeof(IfFragment)){
					Error("Else can only be applied to an if. E.g. if(){}else{}.");
				}
				
				IfFragment ifFrag=(IfFragment)previous;
				
				ifFrag.ApplyElseTo.SetIfFalse(new BracketFragment(sr));
				
				return AddResult.Stop;
			}else if(Value=="elseif"){
				CodeFragment previous=to.ParentFragment;
				// Parent->prev operation->last object. Should be an IF.
				
				if(previous==null||((previous=previous.LastChild)==null)||((previous=previous.LastChild)==null)||previous.GetType()!=typeof(IfFragment)){
					Error("Else if can only be applied to an if. E.g. if(){}else if{}..");
				}
				
				IfFragment ifFrag=(IfFragment)previous;
				IfFragment newfrag=new IfFragment(sr);
				
				 BracketFragment bf=new BracketFragment();
				  OperationFragment op=new OperationFragment();
				  op.AddChild(newfrag);
				 bf.AddChild(op);
				
				ifFrag.ApplyElseTo.SetIfFalse(bf);
				ifFrag.ApplyElseTo=newfrag;
				
				return AddResult.Stop;
				
			}else{
				return base.AddTo(to,sr);
			}
			
		}