using System; using System.Collections.Generic; using HeuristicLab.Common; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration { [StorableClass] public abstract class Symbol : DeepCloneable, IEquatable { [Storable] private readonly int stringRepresentationHash; [Storable(AllowOneWay = true)] public string StringRepresentation { get; } protected Symbol(string representation) { StringRepresentation = representation; stringRepresentationHash = representation.GetHashCode(); } protected Symbol(Symbol original, Cloner cloner) : base(original, cloner) { StringRepresentation = original.StringRepresentation; stringRepresentationHash = original.stringRepresentationHash; } [StorableConstructor] protected Symbol(bool deserializing) { } public override string ToString() { return StringRepresentation; } #region IEquatable public static bool operator ==(Symbol s1, Symbol s2) { if (ReferenceEquals(s1, s2)) return true; if (ReferenceEquals(s1, null) || ReferenceEquals(s2, null)) return false; return s1.Equals(s2); } public static bool operator !=(Symbol s1, Symbol s2) { return !(s1 == s2); } public bool Equals(Symbol other) { if (ReferenceEquals(other, null)) return false; if (ReferenceEquals(other, this)) return true; if (this.GetType() != other.GetType()) return false; // Otherwise, this needs to be reimplemented in derived classes. return StringRepresentation == other.StringRepresentation; } public override bool Equals(object obj) { if (ReferenceEquals(obj, null)) return false; if (ReferenceEquals(obj, this)) return true; if (this.GetType() != obj.GetType()) return false; return Equals((Symbol)obj); } public override int GetHashCode() { return stringRepresentationHash; } #endregion } [StorableClass] public class TerminalSymbol : Symbol { public TerminalSymbol(string representation) : base(representation) { } public TerminalSymbol(TerminalSymbol original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new TerminalSymbol(this, cloner); } [StorableConstructor] protected TerminalSymbol(bool deserializing) : base(deserializing) { } } [StorableClass] public class VariableTerminalSymbol : TerminalSymbol { public VariableTerminalSymbol(string representation) : base(representation) { } public VariableTerminalSymbol(VariableTerminalSymbol original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new VariableTerminalSymbol(this, cloner); } [StorableConstructor] protected VariableTerminalSymbol(bool deserializing) : base(deserializing) { } } [StorableClass] public class NonterminalSymbol : Symbol { public NonterminalSymbol(string representation) : base(representation) { } public NonterminalSymbol(NonterminalSymbol original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new NonterminalSymbol(this, cloner); } [StorableConstructor] protected NonterminalSymbol(bool deserializing) : base(deserializing) { } } [StorableClass] public class Production : List, IDeepCloneable { public Production(params Symbol[] symbols) : base(symbols) { } public Production(IEnumerable symbols) : base(symbols) { } [StorableConstructor] protected Production(bool deserializing) { } protected Production(Production original, Cloner cloner) : this(original) { cloner.RegisterClonedObject(original, this); } public IDeepCloneable Clone(Cloner cloner) { return new Production(this, cloner); } public object Clone() { return Clone(new Cloner()); } public override string ToString() { return string.Join(" ", this); } } }