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); }
/// <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); }
/// <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); } }