/// <summary> /// Add the type arguments for generic instances. Go through all type names, and if it is generic, such /// as Hashtable`1, remove the `1. Look in the arguments list and put the list of arguments in between {} /// /// Example: Hashtable{`0}.KeyValuePair /// /// There are some interesting corner cases involving nested types - /// First, generic argument indexes are counted over all types in the nested type hierarchy. /// Therefore, OuterClass`2.InnerClass`2 should resolve as OuterClass{`0,`1}.InnerClass{`2,`3}. /// /// Secondly, it is not required that all generic arguments be made concrete. /// For example, it's possible in IL to define nested generic types OuterClass`2.InnerClass`2 and /// then pass only two generic types in GenericTypeArgs. In such cases, the type should resolve /// as OuterClass{`0,`1}.InnerClass`2. /// </summary> private IEnumerable <string> GetGenericDisplayNames(IList <string> displayNames) { // The most outputs when run on mscorlib are under 50 bytes in length const int SB_CAPACITY = 50; // Index goes outside the for loop because it increments over all type names, not just a specific type name int index = 0; for (int i = 0; i < displayNames.Count; i++) { var displayName = displayNames[i]; int pos = displayName.IndexOf('`'); if (pos <= 0) { StringBuilder returnName = new StringBuilder(displayName, SB_CAPACITY); if (i == displayNames.Count - 1 && GenericTypeArgs.Count > index) { // Even though this is not a generic type, if it's the last type in the displayNames list and // there are left-over generic arguments, we should append them to this name. // This is because it's possible (from IL) to define a non-generic type that accepts generic arguments. // This construction is used by some obfuscators. returnName.Append("{"); returnName.Append(string.Join(",", GenericTypeArgs.GetRange(index, GenericTypeArgs.Count - index))); returnName.Append("}"); index = GenericTypeArgs.Count; } yield return(returnName.ToString()); continue; } // Separate the name from the generic marker and the string after. // The format is: 'StringBefore`10StringAfter' int numGenericArgs; int offsetStringAfterGenericMarker; // This calculates the number of generic arguments in the specific displayName we're looking at in // this iteration of the foreach loop. if (!CalculateGenericArgsOffset(displayName, pos, out numGenericArgs, out offsetStringAfterGenericMarker)) { yield return(displayName); continue; } // It is possible (from IL) to only pass generic type arguments for the outer class in the case of nested generic classes. // In such cases, once we run out of generic arguments, we just return the generic type names without resolving generic arguments. if (index + numGenericArgs > GenericTypeArgs.Count) { yield return(displayName); continue; } // Start with the name up to the generic parameter token var sb = new StringBuilder(displayName, 0, pos, SB_CAPACITY); // Add the generic parameters sb.Append("{"); sb.Append(string.Join(",", GenericTypeArgs.GetRange(index, numGenericArgs))); sb.Append("}"); // Add any part that was after the generic entry if (displayName.Length > offsetStringAfterGenericMarker) { var length = displayName.Length - offsetStringAfterGenericMarker; sb.Append(displayName, offsetStringAfterGenericMarker, length); } yield return(sb.ToString()); // Advance the index in the args list index += numGenericArgs; } }
/// <summary> /// Traduit le jeton en code lisible. /// </summary> /// <returns></returns> public string ToReadableCode() { Func <string, string> getChildrenCode = delegate(string separator) { StringBuilder b = new StringBuilder(); for (int i = 0; i < SubTokens.Count; i++) { b.Append(SubTokens[i].ToReadableCode()); if (i != SubTokens.Count - 1) { b.Append(separator); } } return(b.ToString()); }; Func <string, string> getChildrenCode2 = delegate(string ending) { StringBuilder b = new StringBuilder(); for (int i = 0; i < SubTokens.Count; i++) { b.Append(SubTokens[i].ToReadableCode()); b.Append(ending); } return(b.ToString()); }; switch (TkType) { case ExpressionTokenType.BracketList: return("[" + getChildrenCode(",") + "]"); case ExpressionTokenType.FunctionCall: return(FunctionCallIdentifier.ToReadableCode() + "(" + FunctionCallArgs.ToReadableCode() + ")"); case ExpressionTokenType.GenericType: return(GenericTypeIdentifier.ToReadableCode() + "<" + GenericTypeArgs.ToReadableCode() + ">"); case ExpressionTokenType.ArrayType: return(ArrayTypeIdentifier.ToReadableCode() + "[" + ArrayTypeArgs.ToReadableCode() + "]"); case ExpressionTokenType.List: return(getChildrenCode(" ")); case ExpressionTokenType.ArgList: return(getChildrenCode(",")); case ExpressionTokenType.GenericParametersList: return("<" + getChildrenCode(",") + ">"); case ExpressionTokenType.Name: return(this.Content); case ExpressionTokenType.CodeBlock: return("{ " + getChildrenCode(",") + " }"); case ExpressionTokenType.NamedCodeBlock: return(SubTokens[0].ToReadableCode() + "\n{\n" + Tools.StringUtils.Indent(SubTokens[1].ToReadableCode(), 1) + "\n}"); case ExpressionTokenType.FunctionDeclaration: return(SubTokens[0].ToReadableCode() + "\n{\n" + Tools.StringUtils.Indent(SubTokens[1].ToReadableCode(), 1) + "\n}"); case ExpressionTokenType.NamedGenericCodeBlock: return(NamedGenericCodeBlockIdentifier.ToReadableCode() + "{\n" + Tools.StringUtils.Indent(NamedGenericCodeBlockInstructions.ToReadableCode(), 1) + "\n}"); case ExpressionTokenType.EndOfInstruction: return(this.Content + "\n"); case ExpressionTokenType.InstructionList: return(getChildrenCode2(";\n")); case ExpressionTokenType.ExpressionGroup: if (Operator.IsBinaryOperator) { if (Operator.Content == "=") { return(Operands1.ToReadableCode() + Operator.ToReadableCode() + Operands2.ToReadableCode()); } else { return("(" + Operands1.ToReadableCode() + Operator.ToReadableCode() + Operands2.ToReadableCode() + ")"); } } else { return(Operator.ToReadableCode() + Operands1.ToReadableCode()); } case ExpressionTokenType.NumberLiteral: return(this.Content); case ExpressionTokenType.Operator: return(this.Content); case ExpressionTokenType.Separator: return(this.Content); case ExpressionTokenType.BoolLiteral: return(this.Content); case ExpressionTokenType.StringLiteral: return("\"" + this.Content + "\""); case ExpressionTokenType.Modifier: return(this.Content); default: return("??"); } }
/// <summary> /// Traduit le jeton en code lisible. /// </summary> /// <returns></returns> public string ToXML() { Func <string, string> i = delegate(string str) { return(Tools.StringUtils.Indent(str, 1)); }; Func <string, string, string> inlineencapsulate = delegate(string str, string delim) { return("<" + delim + ">" + str + "</" + delim + ">\n"); }; Func <string, string, string> encapsulate = delegate(string str, string delim) { return("<" + delim + ">\n" + i(str) + "\n</" + delim + ">\n"); }; Func <string, string> getChildrenCode = delegate(string name) { StringBuilder b = new StringBuilder(); b.Append("<" + name + ">\n"); for (int j = 0; j < SubTokens.Count; j++) { b.AppendLine(i(SubTokens[j].ToXML())); } b.Append("</" + name + ">\n"); return(b.ToString()); }; switch (TkType) { case ExpressionTokenType.BracketList: return(getChildrenCode("BracketList")); case ExpressionTokenType.FunctionCall: return("<FunctionCall>\n" + i("<Identifier>\n" + i(FunctionCallIdentifier.ToXML()) + "</Identifier>\n") + i(FunctionCallArgs.ToXML()) + "</FunctionCall>"); case ExpressionTokenType.GenericType: return("<GenericType>\n" + i("<Identifier>\n" + i(GenericTypeIdentifier.ToXML()) + "</Identifier>\n") + i(GenericTypeArgs.ToXML()) + "</GenericType>"); case ExpressionTokenType.ArrayType: return("<ArrayType>\n" + i("<Identifier>\n" + i(ArrayTypeIdentifier.ToXML()) + "</Identifier>\n") + i(ArrayTypeArgs.ToXML()) + "</ArrayType>"); case ExpressionTokenType.NamedCodeBlock: return("<NamedCodeBlock>\n" + i("<Identifier>\n" + i(SubTokens[0].ToXML()) + "</Identifier>\n") + i(SubTokens[1].ToXML()) + "</NamedCodeBlock>"); case ExpressionTokenType.NamedGenericCodeBlock: return("<NamedGenericCodeBlock>\n" + i("<Identifier>\n" + i(NamedGenericCodeBlockIdentifier.ToXML()) + "</Identifier>\n") + i(NamedGenericCodeBlockInstructions.ToXML()) + "</NamedGenericCodeBlock>"); case ExpressionTokenType.FunctionDeclaration: return("<FunctionDeclaration>\n" + i("<FuncName>\n" + i(SubTokens[0].ToXML()) + "</FuncName>\n") + i(SubTokens[1].ToXML()) + "</FunctionDeclaration>"); case ExpressionTokenType.List: return(getChildrenCode("List")); case ExpressionTokenType.ArgList: return(getChildrenCode("ArgList")); case ExpressionTokenType.GenericParametersList: return(getChildrenCode("GenList")); case ExpressionTokenType.Name: return(inlineencapsulate(this.Content, "Name")); case ExpressionTokenType.CodeBlock: return(getChildrenCode("CodeBlock")); case ExpressionTokenType.EndOfInstruction: return(inlineencapsulate(this.Content, "EndOfInstruction")); case ExpressionTokenType.InstructionList: return(getChildrenCode("InstructionList")); case ExpressionTokenType.ExpressionGroup: if (Operator.IsBinaryOperator) { return(encapsulate( encapsulate(Operands1.ToXML(), "Operand1") + Operator.ToXML() + encapsulate(Operands2.ToXML(), "Operand2"), "ExpressionGroup")); } else { return(encapsulate( encapsulate(Operands1.ToXML(), "Operand1") + Operator.ToXML(), "ExpressionGroup")); } case ExpressionTokenType.NumberLiteral: return(inlineencapsulate(this.Content, "NumberLiteral")); case ExpressionTokenType.Operator: return(inlineencapsulate(this.Content, "Operator")); case ExpressionTokenType.Separator: return(inlineencapsulate(this.Content, "Separator")); case ExpressionTokenType.StringLiteral: return(inlineencapsulate(this.Content, "StringLiteral")); case ExpressionTokenType.BoolLiteral: return(inlineencapsulate(this.Content, "BoolLiteral")); case ExpressionTokenType.Modifier: return(inlineencapsulate(this.Content, "Modifier")); default: return("??"); } }
/// <summary> /// Traduit le jeton en "code" lisible. /// </summary> /// <returns></returns> public string ToDebugCode() { Func <string, string> getChildrenCode = delegate(string separator) { StringBuilder b = new StringBuilder(); for (int i = 0; i < SubTokens.Count; i++) { b.Append(SubTokens[i].ToDebugCode()); if (i != SubTokens.Count - 1) { b.Append(separator); } } return(b.ToString()); }; switch (TkType) { case ExpressionTokenType.BracketList: return("l[" + getChildrenCode(",") + "]"); case ExpressionTokenType.FunctionCall: return(FunctionCallIdentifier.ToDebugCode() + ".call(" + FunctionCallArgs.ToDebugCode() + ")"); case ExpressionTokenType.GenericType: return(GenericTypeIdentifier.ToDebugCode() + ".gen<" + GenericTypeArgs.ToDebugCode() + ">"); case ExpressionTokenType.ArrayType: return(ArrayTypeIdentifier.ToDebugCode() + ".arr[" + ArrayTypeArgs.ToDebugCode() + "]"); case ExpressionTokenType.List: return("l:(" + getChildrenCode(" _ ") + ")"); case ExpressionTokenType.ArgList: return("args:(" + getChildrenCode(",") + ")"); case ExpressionTokenType.GenericParametersList: return("l<" + getChildrenCode(",") + ">"); case ExpressionTokenType.Name: return(this.Content); case ExpressionTokenType.CodeBlock: return("{ " + getChildrenCode(",") + "}"); case ExpressionTokenType.FunctionDeclaration: return("decl:" + SubTokens[0].ToDebugCode() + "{\n" + Tools.StringUtils.Indent(SubTokens[1].ToDebugCode(), 1) + "\n}"); case ExpressionTokenType.EndOfInstruction: return("/" + this.Content); case ExpressionTokenType.InstructionList: return("\ninstruction_list:(\n" + getChildrenCode("?;\n") + ")\n"); case ExpressionTokenType.ExpressionGroup: if (Operator.IsBinaryOperator) { return("(" + Operands1.ToDebugCode() + Operator.ToDebugCode() + Operands2.ToDebugCode() + ")"); } else { return(Operator.ToDebugCode() + Operands1.ToDebugCode()); } case ExpressionTokenType.NamedCodeBlock: return("block:" + SubTokens[0].ToDebugCode() + "{\n" + Tools.StringUtils.Indent(SubTokens[1].ToDebugCode(), 1) + "}\n"); case ExpressionTokenType.NamedGenericCodeBlock: return("gen_block:" + NamedGenericCodeBlockIdentifier.ToDebugCode() + "{\n" + Tools.StringUtils.Indent(NamedGenericCodeBlockInstructions.ToDebugCode(), 1) + "}\n"); case ExpressionTokenType.NumberLiteral: return(this.Content); case ExpressionTokenType.Operator: return(this.Content); case ExpressionTokenType.Separator: return("/" + this.Content); case ExpressionTokenType.StringLiteral: return("\"" + this.Content + "\""); case ExpressionTokenType.Modifier: return(this.Content); case ExpressionTokenType.ConditionalStatement: return(this.Content); default: return("??"); } }