using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using JetBrains.Annotations; using UnityEngine; using UnityEngine.Assertions; using UnityEngine.Pool; using UnityEngine.Scripting.APIUpdating; using UnityEngine.Serialization; [assembly: InternalsVisibleTo("Unity.SignalLab.Tests")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.DataBinding.Graph")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.DataBinding.Workflow")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.DataBinding.Tests")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.DataBinding.Tests.Editor")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.DataBuilder.Editor")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.HMI")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.HMI.Editor")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.HMI.DataBinding.Editor")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.HMI.Workflow")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.DataBinding.Editor")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.HMI.Tests")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.HMI.SystemConfigurationGraph")] [assembly: InternalsVisibleTo("UnityEditor.Importer")] [assembly: InternalsVisibleTo("Unity.XWave")] [assembly: InternalsVisibleTo("Unity.XWave.Tests")] [assembly: InternalsVisibleTo("Unity.XWave.Editor")] [assembly: InternalsVisibleTo("Unity.XWave.Editor.Tests")] [assembly: InternalsVisibleTo("Unity.SignalLab")] [assembly: CompilationRelaxations(8)] [assembly: InternalsVisibleTo("Unity.SignalLab.Editor")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.HMI.Tests.Editor")] [assembly: InternalsVisibleTo("Unity.DigitalTwins.DataBinding")] [assembly: InternalsVisibleTo("Unity.Animation.Editor.Tests")] [assembly: InternalsVisibleTo("Unity.Animation.Editor")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: InternalsVisibleTo("UnityEngine")] [assembly: UnityEngineModuleAssembly] [assembly: InternalsVisibleTo("Unity.ShaderGraph.Application.Tests")] [assembly: InternalsVisibleTo("Unity.GraphTools.Foundation.Tests")] [assembly: InternalsVisibleTo("Unity.GraphTools.Foundation.Testing.Editor")] [assembly: InternalsVisibleTo("Unity.GraphTools.Foundation.Editor.Tests")] [assembly: InternalsVisibleTo("Unity.GraphTools.Foundation.Editor.Tests.Performance")] [assembly: InternalsVisibleTo("BlackboardSample")] [assembly: InternalsVisibleTo("ContextSample")] [assembly: InternalsVisibleTo("ImportedGraphEditor")] [assembly: InternalsVisibleTo("RecipesEditor")] [assembly: InternalsVisibleTo("SimpleMathBook")] [assembly: InternalsVisibleTo("VerticalFlow")] [assembly: InternalsVisibleTo("TestSample")] [assembly: InternalsVisibleTo("SharedSample")] [assembly: InternalsVisibleTo("Unity.Animation.StateMachine.Tests")] [assembly: InternalsVisibleTo("Unity.Animation.Hybrid")] [assembly: InternalsVisibleTo("Unity.Animation.Hybrid.Tests")] [assembly: InternalsVisibleTo("Unity.Animation.GameObjectBridge.Tests")] [assembly: InternalsVisibleTo("Unity.SignalLab.Editor.Tests")] [assembly: InternalsVisibleTo("Unity.VisualScripting")] [assembly: InternalsVisibleTo("Unity.VisualScripting.Editor")] [assembly: InternalsVisibleTo("Unity.VisualScripting.Editor.Tests")] [assembly: InternalsVisibleTo("Unity.VisualScripting.Shared")] [assembly: InternalsVisibleTo("Unity.CodelessFoundation")] [assembly: InternalsVisibleTo("Unity.CodelessFoundation.Tests")] [assembly: InternalsVisibleTo("Unity.CodelessFoundation.Editor")] [assembly: InternalsVisibleTo("Unity.CodelessFoundation.Editor.Tests")] [assembly: InternalsVisibleTo("Unity.ShaderGraph.GraphUI")] [assembly: InternalsVisibleTo("Unity.ShaderGraph.Editor")] [assembly: InternalsVisibleTo("Unity.ShaderGraph.Application")] [assembly: InternalsVisibleTo("Unity.ShaderGraph.GraphUI.Tests")] [assembly: InternalsVisibleTo("Unity.ShaderGraph.Editor.Tests")] [assembly: InternalsVisibleTo("Unity.VisualScripting.Tests")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] namespace Unity.GraphToolsFoundation; internal static class IEnumerableExtensions_Internal { internal static int IndexOf_Internal(this IEnumerable source, T element) { if (source is IList list) { return list.IndexOf(element); } int num = 0; foreach (T item in source) { if (object.Equals(item, element)) { return num; } num++; } return -1; } } internal static class StringExtensions_Internal { private static readonly Regex k_CodifyRegex = new Regex("[^a-zA-Z0-9]", RegexOptions.Compiled); internal static string CodifyString_Internal(this string str) { return k_CodifyRegex.Replace(str, "_"); } } internal static class Hash128Extensions { public static Hash128 Generate() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) return Hash128.Compute(Guid.NewGuid().ToByteArray()); } public static (ulong, ulong) ToParts_Internal(this Hash128 hash) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return (hash.u64_0, hash.u64_1); } } [Serializable] [StructLayout(LayoutKind.Explicit)] [Obsolete("Use Hash128 instead")] internal struct SerializableGUID { [FieldOffset(0)] private Hash128 m_Hash128; [FieldOffset(0)] [SerializeField] private ulong m_Value0; [FieldOffset(8)] [SerializeField] private ulong m_Value1; private SerializableGUID(Hash128 hash) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) m_Value0 = 0uL; m_Value1 = 0uL; m_Hash128 = hash; } public static implicit operator Hash128(SerializableGUID sGuid) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return sGuid.m_Hash128; } public static implicit operator SerializableGUID(Hash128 hash) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return new SerializableGUID(hash); } } [Serializable] [MovedFrom(false, "Unity.GraphToolsFoundation", "Unity.GraphTools.Foundation", null)] internal struct EnumValueReference { [SerializeField] private TypeHandle m_EnumType; [SerializeField] private int m_Value; public TypeHandle EnumType { get { return m_EnumType; } set { m_EnumType = value; m_Value = 0; } } public int Value { get { return m_Value; } set { m_Value = value; } } public EnumValueReference(TypeHandle handle) { m_EnumType = handle; m_Value = 0; } public EnumValueReference(Enum e) { m_EnumType = e.GetType().GenerateTypeHandle(); m_Value = Convert.ToInt32(e); } public Enum ValueAsEnum() { return (Enum)Enum.ToObject(m_EnumType.Resolve(), m_Value); } public bool IsValid() { return m_EnumType.IsValid && m_EnumType.Resolve().IsEnum; } } internal static class TypeExtensions { private static readonly Dictionary k_TypeToFriendlyName = new Dictionary { { typeof(string), "String" }, { typeof(object), "System.Object" }, { typeof(bool), "Boolean" }, { typeof(byte), "Byte" }, { typeof(char), "Char" }, { typeof(decimal), "Decimal" }, { typeof(double), "Double" }, { typeof(short), "Short" }, { typeof(int), "Integer" }, { typeof(long), "Long" }, { typeof(sbyte), "SByte" }, { typeof(float), "Float" }, { typeof(ushort), "Unsigned Short" }, { typeof(uint), "Unsigned Integer" }, { typeof(ulong), "Unsigned Long" }, { typeof(void), "Void" }, { typeof(Color), "Color" }, { typeof(Object), "UnityEngine.Object" }, { typeof(Vector2), "Vector 2" }, { typeof(Vector3), "Vector 3" }, { typeof(Vector4), "Vector 4" } }; public static string FriendlyName(this Type type, bool expandGeneric = true) { if (k_TypeToFriendlyName.TryGetValue(type, out var value)) { return value; } value = type.Name; if (type.IsGenericType && expandGeneric) { int num = value.IndexOf('`'); if (num > 0) { value = value.Remove(num); } value += " of "; Type[] genericArguments = type.GetGenericArguments(); for (int i = 0; i < genericArguments.Length; i++) { string text = genericArguments[i].FriendlyName(); value += ((i == 0) ? text : (" and " + text)); } } if (type.IsArray) { return type.GetElementType().FriendlyName() + "[]"; } return value; } public static TypeHandle GenerateTypeHandle(this Type t) { return TypeHandleHelpers.GenerateTypeHandle(t); } } internal class Unknown { private Unknown() { } } internal class MissingPort { private MissingPort() { } } internal class ExecutionFlow { private ExecutionFlow() { } } internal class Subgraph { private Subgraph() { } } [Serializable] [MovedFrom(false, "Unity.GraphToolsFoundation", "Unity.GraphTools.Foundation", null)] [PublicAPI] internal struct TypeHandle : IEquatable, IComparable, ISerializationCallbackReceiver { [SerializeField] [FormerlySerializedAs("Identification")] private string m_Identification; private string m_Name; public static TypeHandle MissingType { get; } public static TypeHandle Unknown { get; } public static TypeHandle ExecutionFlow { get; } public static TypeHandle Subgraph { get; } public static TypeHandle MissingPort { get; } public static TypeHandle Bool { get; } public static TypeHandle Void { get; } public static TypeHandle Char { get; } public static TypeHandle Double { get; } public static TypeHandle Float { get; } public static TypeHandle Int { get; } public static TypeHandle UInt { get; } public static TypeHandle Long { get; } public static TypeHandle Object { get; } public static TypeHandle GameObject { get; } public static TypeHandle String { get; } public static TypeHandle Vector2 { get; } public static TypeHandle Vector3 { get; } public static TypeHandle Vector4 { get; } public static TypeHandle Color { get; } public static TypeHandle Quaternion { get; } public static TypeHandle Texture { get; } public static TypeHandle Texture2D { get; } public static TypeHandle Texture2DArray { get; } public static TypeHandle Texture3D { get; } public bool IsValid => !string.IsNullOrEmpty(m_Identification); internal bool IsCustomTypeHandle_Internal => TypeHandleHelpers.IsCustomTypeHandle_Internal(m_Identification); public string Identification => m_Identification; public string Name => m_Name ?? (m_Name = (IsCustomTypeHandle_Internal ? m_Identification : Resolve().Name)); static TypeHandle() { MissingType = TypeHandleHelpers.GenerateCustomTypeHandle("__MISSINGTYPE"); Unknown = TypeHandleHelpers.GenerateCustomTypeHandle(typeof(Unknown), "__UNKNOWN"); ExecutionFlow = TypeHandleHelpers.GenerateCustomTypeHandle(typeof(ExecutionFlow), "__EXECUTIONFLOW"); Subgraph = TypeHandleHelpers.GenerateCustomTypeHandle(typeof(Subgraph), "__SUBGRAPH"); MissingPort = TypeHandleHelpers.GenerateTypeHandle(typeof(MissingPort)); Bool = TypeHandleHelpers.GenerateTypeHandle(typeof(bool)); Void = TypeHandleHelpers.GenerateTypeHandle(typeof(void)); Char = TypeHandleHelpers.GenerateTypeHandle(typeof(char)); Double = TypeHandleHelpers.GenerateTypeHandle(typeof(double)); Float = TypeHandleHelpers.GenerateTypeHandle(typeof(float)); Int = TypeHandleHelpers.GenerateTypeHandle(typeof(int)); UInt = TypeHandleHelpers.GenerateTypeHandle(typeof(uint)); Long = TypeHandleHelpers.GenerateTypeHandle(typeof(long)); Object = TypeHandleHelpers.GenerateTypeHandle(typeof(object)); GameObject = TypeHandleHelpers.GenerateTypeHandle(typeof(GameObject)); String = TypeHandleHelpers.GenerateTypeHandle(typeof(string)); Vector2 = TypeHandleHelpers.GenerateTypeHandle(typeof(Vector2)); Vector3 = TypeHandleHelpers.GenerateTypeHandle(typeof(Vector3)); Vector4 = TypeHandleHelpers.GenerateTypeHandle(typeof(Vector4)); Color = TypeHandleHelpers.GenerateTypeHandle(typeof(Color)); Quaternion = TypeHandleHelpers.GenerateTypeHandle(typeof(Quaternion)); Texture = TypeHandleHelpers.GenerateTypeHandle(typeof(Texture)); Texture2D = TypeHandleHelpers.GenerateTypeHandle(typeof(Texture2D)); Texture2DArray = TypeHandleHelpers.GenerateTypeHandle(typeof(Texture2DArray)); Texture3D = TypeHandleHelpers.GenerateTypeHandle(typeof(Texture3D)); } internal static TypeHandle Create_Internal(string identification) { return new TypeHandle(identification); } private TypeHandle(string identification) { m_Identification = identification; m_Name = null; } public bool Equals(TypeHandle other) { return string.Equals(m_Identification, other.m_Identification); } public override bool Equals(object obj) { if (obj == null) { return false; } return obj is TypeHandle other && Equals(other); } public override int GetHashCode() { return m_Identification?.GetHashCode() ?? 0; } public override string ToString() { return "TypeName:" + m_Identification; } public static bool operator ==(TypeHandle left, TypeHandle right) { return left.Equals(right); } public static bool operator !=(TypeHandle left, TypeHandle right) { return !left.Equals(right); } public int CompareTo(TypeHandle other) { return string.Compare(m_Identification, other.m_Identification, StringComparison.Ordinal); } public Type Resolve() { return TypeHandleHelpers.ResolveType_Internal(this); } public void OnBeforeSerialize() { } public void OnAfterDeserialize() { m_Name = null; } } internal static class TypeHandleHelpers { private static Regex s_GenericTypeExtractionRegex = new Regex("(?<=\\[\\[)(.*?)(?=\\]\\])"); internal static List<(string, TypeHandle)> customIdToTypeHandle_Internal = new List<(string, TypeHandle)>(); private static List<(string, Type)> s_CustomIdToType = new List<(string, Type)>(); internal static Func GetMovedFromType; private static string Serialize(Type t) { (string, Type) tuple = s_CustomIdToType.Find(((string, Type) e) => e.Item2 == t); (string, Type) tuple2 = tuple; if (tuple2.Item1 != null || tuple2.Item2 != null) { return tuple.Item1; } return t.AssemblyQualifiedName; } private static Type Deserialize(string serializedType) { (string, Type) tuple = s_CustomIdToType.Find(((string, Type) e) => e.Item1 == serializedType); (string, Type) tuple2 = tuple; if (tuple2.Item1 != null || tuple2.Item2 != null) { return tuple.Item2; } return GetTypeFromName_Internal(serializedType); } internal static Type GetTypeFromName_Internal(string assemblyQualifiedName) { Type type = typeof(Unknown); if (!string.IsNullOrEmpty(assemblyQualifiedName)) { Type type2 = Type.GetType(assemblyQualifiedName); if (type2 == null) { assemblyQualifiedName = ExtractAssemblyQualifiedName(assemblyQualifiedName, out var isList); Type type3 = GetMovedFromType?.Invoke(assemblyQualifiedName); if (type3 != null) { type2 = type3; if (isList) { type2 = typeof(List<>).MakeGenericType(type2); } } } type = type2 ?? type; } return type; } private static string ExtractAssemblyQualifiedName(string fullTypeName, out bool isList) { isList = false; if (fullTypeName.StartsWith("System.Collections.Generic.List")) { fullTypeName = s_GenericTypeExtractionRegex.Match(fullTypeName).Value; isList = true; } int num = fullTypeName.IndexOf(", Version="); if (num > 0) { fullTypeName = fullTypeName.Substring(0, num); } fullTypeName = fullTypeName.Replace("+", "/"); return fullTypeName; } internal static Type ResolveType_Internal(TypeHandle th) { return Deserialize(th.Identification); } internal static bool IsCustomTypeHandle_Internal(string id) { return customIdToTypeHandle_Internal.Exists(((string, TypeHandle) e) => e.Item1 == id) && !s_CustomIdToType.Exists(((string, Type) e) => e.Item1 == id); } public static TypeHandle GenerateCustomTypeHandle(string uniqueId) { (string, TypeHandle) tuple = customIdToTypeHandle_Internal.Find(((string, TypeHandle) e) => e.Item1 == uniqueId); (string, TypeHandle) tuple2 = tuple; if (tuple2.Item1 != null || tuple2.Item2 != default(TypeHandle)) { Debug.LogWarning((object)(uniqueId + " is already registered in TypeSerializer")); return tuple.Item2; } TypeHandle typeHandle = TypeHandle.Create_Internal(uniqueId); customIdToTypeHandle_Internal.Add((uniqueId, typeHandle)); return typeHandle; } public static TypeHandle GenerateCustomTypeHandle(Type t, string customUniqueId) { (string, TypeHandle) tuple = customIdToTypeHandle_Internal.Find(((string, TypeHandle) e) => e.Item1 == customUniqueId); (string, TypeHandle) tuple2 = tuple; if (tuple2.Item1 != null || tuple2.Item2 != default(TypeHandle)) { Debug.LogWarning((object)(customUniqueId + " is already registered in TypeSerializer")); return tuple.Item2; } (string, Type) tuple3 = s_CustomIdToType.Find(((string, Type) e) => e.Item2 == t); (string, Type) tuple4 = tuple3; if (tuple4.Item1 != null || tuple4.Item2 != null) { Debug.LogWarning((object)(t.FullName + " is already registered in TypeSerializer")); } TypeHandle typeHandle = TypeHandle.Create_Internal(customUniqueId); customIdToTypeHandle_Internal.Add((customUniqueId, typeHandle)); s_CustomIdToType.Add((customUniqueId, t)); return typeHandle; } public static TypeHandle GenerateTypeHandle() { return GenerateTypeHandle(typeof(T)); } public static TypeHandle GenerateTypeHandle(Type t) { Assert.IsNotNull(t); return TypeHandle.Create_Internal(Serialize(t)); } } internal class TypeMetadata : TypeMetadataBase { private readonly Type m_Type; public override string FriendlyName => TypeHandle.IsCustomTypeHandle_Internal ? TypeHandle.Identification : m_Type.FriendlyName(); public override string Namespace => m_Type.Namespace ?? string.Empty; public override bool IsEnum => m_Type.IsEnum; public override bool IsClass => m_Type.IsClass; public override bool IsValueType => m_Type.IsValueType; public TypeMetadata(TypeHandle typeHandle, Type type) : base(typeHandle) { m_Type = type; } public override bool IsAssignableFrom(TypeMetadataBase metadata) { return metadata.IsAssignableTo(m_Type); } public override bool IsAssignableFrom(Type type) { return m_Type.IsAssignableFrom(type); } public override bool IsAssignableTo(Type t) { return t.IsAssignableFrom(m_Type); } public override bool IsSubclassOf(Type t) { return m_Type.IsSubclassOf(t); } public override bool IsSuperclassOf(Type t) { return t.IsSubclassOf(m_Type); } } internal abstract class TypeMetadataBase { public virtual TypeHandle TypeHandle { get; } public abstract string FriendlyName { get; } public abstract string Namespace { get; } public abstract bool IsEnum { get; } public abstract bool IsClass { get; } public abstract bool IsValueType { get; } protected TypeMetadataBase(TypeHandle typeHandle) { TypeHandle = typeHandle; } public abstract bool IsAssignableFrom(TypeMetadataBase metadata); public abstract bool IsAssignableFrom(Type type); public abstract bool IsAssignableTo(Type type); public abstract bool IsSuperclassOf(Type type); public abstract bool IsSubclassOf(Type type); } internal class TypeMetadataResolver { private readonly ConcurrentDictionary m_MetadataCache = new ConcurrentDictionary(); public virtual TypeMetadataBase Resolve(TypeHandle th) { if (!m_MetadataCache.TryGetValue(th, out var value)) { return m_MetadataCache.GetOrAdd(th, (TypeHandle t) => new TypeMetadata(t, th.Resolve())); } return value; } } internal static class CollectionExtensions { public static bool ContainsReference(this IEnumerable container, T search) where T : class { foreach (T item in container) { if (item == search) { return true; } } return false; } public static List OfTypeToList(this IEnumerable list) { List list2 = new List(); foreach (T2 item2 in list) { if (item2 is T item) { list2.Add(item); } } return list2; } public static IDisposable OfTypeToPooledList(this IEnumerable original, out List filtered) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) PooledObject> val = CollectionPool, T>.Get(ref filtered); foreach (T2 item2 in original) { if (item2 is T item) { filtered.Add(item); } } return (IDisposable)(object)val; } public static IReadOnlyList Cast(this IReadOnlyList list) { if (typeof(T1) == typeof(T2)) { return (IReadOnlyList)list; } List list2 = new List(list.Count); foreach (T1 item2 in list) { if (item2 is T2 item) { list2.Add(item); continue; } throw new InvalidCastException("Cannot cast from type " + typeof(T1).FullName + " to type " + typeof(T2).FullName); } return list2; } } internal abstract class Enumeration : IComparable, IComparable, IEquatable { public string[] ObsoleteNames; public string Name { get; } public int Id { get; } protected Enumeration(int id, string name, string[] obsoleteNames = null) { Id = id; Name = name; ObsoleteNames = obsoleteNames; } public override string ToString() { return Name; } public static IEnumerable GetDeclared() where T : Enumeration { FieldInfo[] fields = typeof(T).GetFields(BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public); return fields.Select((FieldInfo f) => f.GetValue(null)).Cast(); } public static IEnumerable GetAll() where T : TBase where TBase : Enumeration { FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy); return fields.Select((FieldInfo f) => f.GetValue(null)).Cast(); } public bool Equals(Enumeration other) { if ((object)other == null) { return false; } if ((object)this == other) { return true; } if (!Id.Equals(other.Id)) { return false; } return other.GetType().IsInstanceOfType(this) || GetType().IsInstanceOfType(other); } public override bool Equals(object obj) { return Equals((Enumeration)obj); } public override int GetHashCode() { return Id; } public static bool operator ==(Enumeration left, Enumeration right) { return object.Equals(left, right); } public static bool operator !=(Enumeration left, Enumeration right) { return !object.Equals(left, right); } public int CompareTo(Enumeration other) { return ((object)other == null) ? 1 : Id.CompareTo(other.Id); } public int CompareTo(object obj) { if (obj != null && !(obj is Enumeration)) { throw new ArgumentException("Object must be of type Enumeration."); } return CompareTo((Enumeration)obj); } } internal readonly struct BinaryOperation : IOperation_Internal, IExpression { public readonly OperationType Type; public readonly IExpression OperandA; public readonly IExpression OperandB; public BinaryOperation(OperationType type, IExpression operandA, IExpression operandB) { Type = type; OperandA = operandA; OperandB = operandB; } public override string ToString() { return $"({OperandA} {MathExpressionParser.Ops_Internal[Type].Str} {OperandB})"; } } internal readonly struct ExpressionValue : IValue_Internal, IExpression { public readonly float Value; public ExpressionValue(float value) { Value = value; } public override string ToString() { return Value.ToString(CultureInfo.InvariantCulture); } } internal readonly struct FunctionCall : IOperation_Internal, IExpression { public readonly string Id; public readonly List Arguments; public FunctionCall(string id, List arguments) { Id = id; Arguments = arguments; } public override string ToString() { return "#" + Id + "(" + string.Join(", ", Arguments) + ")"; } } internal enum OperationType { Add, Sub, Mul, Div, LeftParens, Plus, Minus, Coma, Mod } internal interface IExpression { } internal interface IOperation_Internal : IExpression { } internal interface IValue_Internal : IExpression { } internal enum Associativity_Internal { None, Left, Right } [Flags] internal enum Token { None = 0, Op = 1, Number = 2, Identifier = 4, LeftParens = 8, RightParens = 0x10, Coma = 0x20 } internal static class MathExpressionParser { internal static readonly Dictionary Ops_Internal = new Dictionary { { OperationType.Add, new Operator_Internal(OperationType.Add, "+", 2, Associativity_Internal.Left) }, { OperationType.Sub, new Operator_Internal(OperationType.Sub, "-", 2, Associativity_Internal.Left) }, { OperationType.Mul, new Operator_Internal(OperationType.Mul, "*", 3, Associativity_Internal.Left) }, { OperationType.Div, new Operator_Internal(OperationType.Div, "/", 3, Associativity_Internal.Left) }, { OperationType.Mod, new Operator_Internal(OperationType.Mod, "%", 3, Associativity_Internal.Left) }, { OperationType.LeftParens, new Operator_Internal(OperationType.LeftParens, "(", 5) }, { OperationType.Minus, new Operator_Internal(OperationType.Minus, "-", 2000, Associativity_Internal.Right, unary: true) } }; public static IExpression Parse(string expressionStr, out string error) { Stack output = new Stack(); Stack opStack = new Stack(); MathExpressionReader_Internal mathExpressionReader_Internal = new MathExpressionReader_Internal(expressionStr); try { mathExpressionReader_Internal.ReadToken(); error = null; return ParseUntil(mathExpressionReader_Internal, opStack, output, Token.None, 0); } catch (Exception ex) { error = ex.Message; return null; } } private static Operator_Internal ReadOperator(string input, bool unary) { return Ops_Internal.Single((KeyValuePair o) => o.Value.Str == input && o.Value.Unary == unary).Value; } private static IExpression ParseUntil(MathExpressionReader_Internal r, Stack opStack, Stack output, Token readUntilToken, int startOpStackSize) { do { switch (r.CurrentTokenType) { case Token.LeftParens: { opStack.Push(Ops_Internal[OperationType.LeftParens]); r.ReadToken(); IExpression item3 = ParseUntil(r, opStack, output, Token.RightParens | Token.Coma, opStack.Count); if (r.CurrentTokenType == Token.Coma) { throw new InvalidDataException("Tuples not supported"); } if (r.CurrentTokenType != Token.RightParens) { throw new InvalidDataException("Mismatched parens, missing a closing parens"); } output.Push(item3); Operator_Internal result2; while (opStack.TryPeek(out result2) && result2.Type != OperationType.LeftParens) { opStack.Pop(); PopOpOperandsAndPushNode(result2); } if (opStack.TryPeek(out var result3) && result3.Type == OperationType.LeftParens) { opStack.Pop(); r.ReadToken(); break; } throw new InvalidDataException("Mismatched parens"); } case Token.RightParens: throw new InvalidDataException("Mismatched parens"); case Token.Op: { bool unary = r.PrevTokenType == Token.Op || r.PrevTokenType == Token.LeftParens || r.PrevTokenType == Token.None; Operator_Internal item2 = ReadOperator(r.CurrentToken, unary); Operator_Internal result; while (opStack.TryPeek(out result) && result.Type != OperationType.LeftParens && result.Type != OperationType.Coma && (result.Precedence > item2.Precedence || (result.Precedence == item2.Precedence && item2.Associativity == Associativity_Internal.Left))) { opStack.Pop(); PopOpOperandsAndPushNode(result); } opStack.Push(item2); r.ReadToken(); break; } case Token.Number: output.Push(new ExpressionValue(float.Parse(r.CurrentToken, CultureInfo.InvariantCulture))); r.ReadToken(); break; case Token.Identifier: { string currentToken = r.CurrentToken; r.ReadToken(); if (r.CurrentTokenType != Token.LeftParens) { output.Push(new Variable(currentToken)); break; } r.ReadToken(); List list = new List(); while (true) { IExpression item = ParseUntil(r, opStack, output, Token.RightParens | Token.Coma, opStack.Count); list.Add(item); if (r.CurrentTokenType == Token.RightParens) { break; } r.ReadToken(); } r.ReadToken(); output.Push(new FunctionCall(currentToken.ToLower(), list)); break; } default: throw new ArgumentOutOfRangeException(r.CurrentTokenType.ToString()); } } while (!readUntilToken.HasFlag(r.CurrentTokenType)); while (opStack.Count > startOpStackSize) { Operator_Internal readBinOp = opStack.Pop(); if (readBinOp.Type == OperationType.LeftParens) { break; } PopOpOperandsAndPushNode(readBinOp); } return output.Pop(); void PopOpOperandsAndPushNode(Operator_Internal operator_Internal) { IExpression expression = output.Pop(); if (operator_Internal.Unary) { output.Push(new UnaryOperation(operator_Internal.Type, expression)); } else { if (output.Count == 0) { throw new InvalidDataException("Missing operand for the " + operator_Internal.Str + " operator in the expression"); } IExpression operandA = output.Pop(); output.Push(new BinaryOperation(operator_Internal.Type, operandA, expression)); } } } } internal class MathExpressionReader_Internal { private readonly string m_Input; private int m_I; public string CurrentToken; public Token CurrentTokenType; public Token PrevTokenType; private bool Done => m_I >= m_Input.Length; private char NextChar => m_Input[m_I]; public MathExpressionReader_Internal(string input) { m_Input = input.Trim(); m_I = 0; } private void SkipWhitespace() { while (!Done && char.IsWhiteSpace(m_Input[m_I])) { m_I++; } } private char ConsumeChar() { return m_Input[m_I++]; } public void ReadToken() { CurrentToken = null; PrevTokenType = CurrentTokenType; CurrentTokenType = Token.None; if (Done) { return; } switch (NextChar) { case '(': ConsumeChar(); CurrentTokenType = Token.LeftParens; break; case ')': ConsumeChar(); CurrentTokenType = Token.RightParens; break; case ',': ConsumeChar(); CurrentTokenType = Token.Coma; break; default: { Operator_Internal desc; if (char.IsDigit(NextChar) || NextCharIsPoint()) { bool flag = false; StringBuilder stringBuilder = new StringBuilder(); do { flag |= NextCharIsPoint(); stringBuilder.Append(ConsumeChar()); } while (!Done && (char.IsDigit(NextChar) || (NextChar == '.' && !flag))); if (!Done && flag && NextCharIsPoint()) { throw new InvalidDataException($"Invalid number: '{stringBuilder}.'"); } CurrentToken = stringBuilder.ToString(); CurrentTokenType = Token.Number; } else if (MatchOp(out desc)) { CurrentToken = desc.Str; CurrentTokenType = Token.Op; for (int i = 0; i < CurrentToken.Length; i++) { ConsumeChar(); } } else { CurrentTokenType = Token.Identifier; StringBuilder stringBuilder2 = new StringBuilder(); Operator_Internal desc2; while (!Done && NextChar != ')' && NextChar != ',' && !MatchOp(out desc2) && !char.IsWhiteSpace(NextChar)) { stringBuilder2.Append(ConsumeChar()); } CurrentToken = stringBuilder2.ToString(); } break; } } SkipWhitespace(); bool MatchOp(out Operator_Internal reference) { using (IEnumerator> enumerator = MathExpressionParser.Ops_Internal.Where((KeyValuePair pair) => m_Input.IndexOf(pair.Value.Str, m_I, StringComparison.Ordinal) == m_I).GetEnumerator()) { if (enumerator.MoveNext()) { reference = enumerator.Current.Value; return true; } } reference = default(Operator_Internal); return false; } bool NextCharIsPoint() { return NextChar == '.'; } } } internal readonly struct Operator_Internal { public readonly OperationType Type; public readonly string Str; public readonly int Precedence; public readonly Associativity_Internal Associativity; public readonly bool Unary; public Operator_Internal(OperationType type, string str, int precedence, Associativity_Internal associativity = Associativity_Internal.None, bool unary = false) { Type = type; Str = str; Precedence = precedence; Associativity = associativity; Unary = unary; } } internal readonly struct UnaryOperation : IOperation_Internal, IExpression { public readonly OperationType Type; public readonly IExpression Operand; public UnaryOperation(OperationType type, IExpression operand) { Type = type; Operand = operand; } public override string ToString() { return $"{MathExpressionParser.Ops_Internal[Type].Str}{Operand}"; } } internal readonly struct Variable : IValue_Internal, IExpression { public readonly string Id; public Variable(string id) { Id = id; } public override string ToString() { return "$" + Id; } } internal static class StringUtilsExtensions { private const char k_NoDelimiter = '\0'; private static readonly char[] k_WordDelimiters = new char[3] { ' ', '-', '_' }; internal static string ToKebabCase_Internal(this string text) { return ConvertCase(text, '-', char.ToLowerInvariant, char.ToLowerInvariant); } private static string ConvertCase(string text, char outputWordDelimiter, Func startOfStringCaseHandler, Func middleStringCaseHandler) { if (text == null) { throw new ArgumentNullException("text"); } StringBuilder stringBuilder = new StringBuilder(); bool flag = true; bool flag2 = true; bool flag3 = true; foreach (char c in text) { if (((IList)k_WordDelimiters).Contains((object?)c)) { if (c == outputWordDelimiter) { stringBuilder.Append(outputWordDelimiter); flag3 = false; } flag2 = true; } else if (!char.IsLetterOrDigit(c)) { flag = true; flag2 = true; } else if (flag2 || char.IsUpper(c)) { if (flag) { stringBuilder.Append(startOfStringCaseHandler(c)); } else { if (flag3 && outputWordDelimiter != 0) { stringBuilder.Append(outputWordDelimiter); } stringBuilder.Append(middleStringCaseHandler(c)); flag3 = true; } flag = false; flag2 = false; } else { stringBuilder.Append(c); } } return stringBuilder.ToString(); } public static string WithUssElement(this string blockName, string elementName) { return blockName + "__" + elementName; } public static string WithUssModifier(this string blockName, string modifier) { return blockName + "--" + modifier; } }