namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions { using System; using System.Linq; using Attributes; using Interpreter; using Stack; [PushExpression(StackTypes.String, "STRING.FROMINTEGER", StackTypes.Integer)] public class StringFromIntegerExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.IntegerStack.IsEmpty) return false; var value = interpreter.IntegerStack.Pop(); interpreter.StringStack.Push(value.ToString()); return true; } } [PushExpression(StackTypes.String, "STRING.FROMFLOAT", StackTypes.Float)] public class StringFromFloatExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.FloatStack.IsEmpty) return false; var value = interpreter.FloatStack.Pop(); interpreter.StringStack.Push(value.ToString()); return true; } } [PushExpression(StackTypes.String, "STRING.FROMBOOLEAN", StackTypes.Boolean)] public class StringFromBooleanExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.BooleanStack.IsEmpty) return false; var value = interpreter.BooleanStack.Pop(); interpreter.StringStack.Push(value.ToString()); return true; } } [PushExpression(StackTypes.String, "STRING.FROMCHAR", StackTypes.Char)] public class StringFromCharExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.CharStack.IsEmpty) return false; var value = interpreter.CharStack.Pop(); interpreter.StringStack.Push(value.ToString()); return true; } } [PushExpression(StackTypes.String, "STRING.CONCAT")] public class StringConcatExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.Count < 2 || interpreter.StringStack.Top.Length + interpreter.StringStack.ReverseElementAt(1).Length >= interpreter.Configuration.MaxStringLength) return false; var str = interpreter.StringStack.Pop(); interpreter.StringStack.SetTop(str + interpreter.StringStack.Top); return true; } } /// /// Conj char onto string /// [PushExpression(StackTypes.String, "STRING.CONJCHAR", StackTypes.Char)] public class StringConjCharExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.CharStack.IsEmpty || interpreter.StringStack.Top.Length + 1 >= interpreter.Configuration.MaxStringLength) return false; var c = interpreter.CharStack.Pop(); interpreter.StringStack.SetTop(interpreter.StringStack.Top + c); return true; } } [PushExpression(StackTypes.String, "STRING.TAKE", StackTypes.Integer)] public class StringTakeExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.IntegerStack.IsEmpty) return false; var value = interpreter.IntegerStack.Pop(); if (value < 0) { return true; } var str = interpreter.StringStack.Top; if (str.Length > 0) { value = Math.Min(str.Length - 1, value); interpreter.StringStack.SetTop(str.Substring(0, (int)value)); } return true; } } [PushExpression(StackTypes.String, "STRING.SUBSTRING", StackTypes.Integer)] public class StringSubstringExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.IntegerStack.Count < 2) return false; var str = interpreter.StringStack.Top; var values = interpreter.IntegerStack.Pop(2); var first = Math.Min(str.Length - 1, Math.Max(values[0], 0)); var second = Math.Min(str.Length - 1, Math.Max(values[1], first)); var length = second - first; if (length > 0) interpreter.StringStack.SetTop(str.Substring((int)first, (int)length)); return true; } } [PushExpression(StackTypes.String, "STRING.FIRST")] public class StringFirstExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.StringStack.Top.Length == 0) return false; interpreter.StringStack.SetTop(interpreter.StringStack.Top[0].ToString()); return true; } } [PushExpression(StackTypes.String, "STRING.LAST")] public class StringLastExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.StringStack.Top.Length == 0) return false; var str = interpreter.StringStack.Top; var c = str[str.Length - 1].ToString(); interpreter.StringStack.SetTop(c); return true; } } [PushExpression(StackTypes.String, "STRING.NTH", StackTypes.Integer)] public class StringNthExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.IntegerStack.IsEmpty || interpreter.StringStack.Top.Length == 0) return false; var str = interpreter.StringStack.Top; var index = str.Length == 1 ? 0 : (int)Math.Abs(interpreter.IntegerStack.Pop() % (str.Length - 1)); var c = str[index].ToString(); interpreter.StringStack.SetTop(c); return true; } } [PushExpression(StackTypes.String, "STRING.REST")] public class StringRestExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.StringStack.Top.Length == 0) return false; var str = interpreter.StringStack.Top; interpreter.StringStack.SetTop(str.Length == 1 ? string.Empty : str.Substring(1, str.Length - 1)); return true; } } [PushExpression(StackTypes.String, "STRING.BUTLAST")] public class StringButLastExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.StringStack.Top.Length == 0) return false; var str = interpreter.StringStack.Top; interpreter.StringStack.SetTop(str.Length == 1 ? string.Empty : str.Substring(0, str.Length - 1)); return true; } } [PushExpression(StackTypes.String, "STRING.LENGTH", StackTypes.Integer)] public class StringLengthExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty) return false; var str = interpreter.StringStack.Pop(); interpreter.IntegerStack.Push(str.Length); return true; } } [PushExpression(StackTypes.String, "STRING.REVERSE")] public class StringReverseExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty) return false; interpreter.StringStack.SetTop(interpreter.StringStack.Top.Reverse().ToString()); return true; } } [PushExpression(StackTypes.String, "STRING.PARSETOCHARS")] public class StringParseToCharsExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty) return false; if (interpreter.StringStack.Top.Length == 0) { interpreter.StringStack.Pop(); return true; } var str = interpreter.StringStack.Top; interpreter.StringStack.SetTop(str[0].ToString()); if (str.Length > 1) { var chars = new string[str.Length - 1]; for (var i = 0; i < str.Length - 1; i++) { chars[i] = str[i + 1].ToString(); } interpreter.StringStack.Push(chars); } return true; } } [PushExpression(StackTypes.String, "STRING.SPLIT")] public class StringSplitExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty) return false; var words = interpreter.StringStack.Top.Trim().Split(); if (words.Length == 0) return false; interpreter.StringStack.SetTop(words[0]); if (words.Length > 1) interpreter.StringStack.Push(words, 1); return true; } } /// /// True if top string is empty /// [PushExpression(StackTypes.String, "STRING.EMPTYSTRING", StackTypes.Boolean)] public class StringEmptyStringExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty) return false; var str = interpreter.StringStack.Pop(); interpreter.BooleanStack.Push(str.Length == 0); return true; } } /// /// True if top string is a substring of second string; false otherwise /// [PushExpression(StackTypes.String, "STRING.CONTAINS", StackTypes.Boolean)] public class StringContainsExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.Count < 2) return false; var strings = interpreter.StringStack.Pop(2); interpreter.BooleanStack.Push(strings[0].IndexOf(strings[1], StringComparison.Ordinal) >= 0); return true; } } /// /// True if the top char is in the top string /// [PushExpression(StackTypes.String, "STRING.CONTAINSCHAR", StackTypes.Boolean | StackTypes.Char)] public class StringContainsCharExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.CharStack.IsEmpty) return false; var str = interpreter.StringStack.Pop(); var c = interpreter.CharStack.Pop(); interpreter.BooleanStack.Push(str.IndexOf(c) >= 0); return true; } } /// /// Puts on the integer stack the index of the top char in the top string /// [PushExpression(StackTypes.String, "STRING.INDEXOFCHAR", StackTypes.Integer | StackTypes.Char)] public class StringIndexOfCharExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.CharStack.IsEmpty) return false; var str = interpreter.StringStack.Pop(); var c = interpreter.CharStack.Pop(); interpreter.IntegerStack.Push(str.IndexOf(c)); return true; } } /// /// The number of times the top char is in the top string /// [PushExpression(StackTypes.String, "STRING.OCCURENCESOFCHAR", StackTypes.Integer | StackTypes.Char)] public class StringOccurrencesOfCharExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.CharStack.IsEmpty) return false; var str = interpreter.StringStack.Pop(); var c = interpreter.CharStack.Pop(); var count = 0; for (var i = 0; i < str.Length; i++) if (str[i] == c) count++; interpreter.IntegerStack.Push(count); return true; } } /// /// In third string on stack, replaces second string with first string /// [PushExpression(StackTypes.String, "STRING.REPLACE")] public class StringReplaceExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.Count < 3) return false; var strings = interpreter.StringStack.Pop(2); if (strings[0].Length == 0 || strings[1].Length == 0) interpreter.StringStack.SetTop(strings[0]); else { var result = strings[0].Replace(strings[1], interpreter.StringStack.Top); interpreter.StringStack.SetTop(result); } return true; } } /// /// In third string on stack, replaces first occurence of second string with first string /// [PushExpression(StackTypes.String, "STRING.REPLACEFIRST")] public class StringReplaceLastExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.Count < 3) return false; var strings = interpreter.StringStack.Pop(2); var pos = strings[0].IndexOf(strings[1], StringComparison.Ordinal); if (pos < 0) return true; var result = strings[0].Substring(0, pos) + interpreter.StringStack.Top + strings[0].Substring(pos + strings[1].Length); interpreter.StringStack.SetTop(result); return true; } } /// /// In top string on stack, replaces all occurences of second char with first char /// [PushExpression(StackTypes.String, "STRING.REPLACECHAR", StackTypes.Char)] public class StringReplaceCharExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.CharStack.Count < 2) return false; var chars = interpreter.CharStack.Pop(2); var result = interpreter.StringStack.Top.Replace(chars[0], chars[1]); interpreter.StringStack.SetTop(result); return true; } } /// /// In top string on stack, replaces first occurence of second char with first char /// [PushExpression(StackTypes.String, "STRING.REPLACEFIRSTCHAR", StackTypes.Char)] public class StringReplaceLastCharExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.CharStack.Count < 2) return false; var str = interpreter.StringStack.Top; var chars = interpreter.CharStack.Pop(2); var pos = interpreter.StringStack.Top.IndexOf(chars[0]); if (pos < 0) return true; var result = str.Substring(0, pos) + chars[1] + str.Substring(Math.Min(pos + 2, str.Length - 1)); interpreter.StringStack.SetTop(result); return true; } } /// /// In top string on stack, remove all occurences of char /// [PushExpression(StackTypes.String, "STRING.REMOVECHAR", StackTypes.Char)] public class StringRemoveCharExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.CharStack.IsEmpty) return false; var c = interpreter.CharStack.Pop(); var result = interpreter.StringStack.Top.Trim(c); interpreter.StringStack.SetTop(result); return true; } } /// /// Returns a function that sets char at index in string /// [PushExpression(StackTypes.String, "STRING.SETCHAR", StackTypes.Char | StackTypes.Integer)] public class StringSetCharExpression : StatelessExpression { public override bool Eval(IInternalPushInterpreter interpreter) { if (interpreter.StringStack.IsEmpty || interpreter.CharStack.IsEmpty || interpreter.IntegerStack.IsEmpty) return false; var str = interpreter.StringStack.Top; var i = (int)interpreter.IntegerStack.Pop(); var c = interpreter.CharStack.Pop(); if (str.Length == 0) { interpreter.StringStack.Pop(); return true; } var pos = str.Length == 1 ? 0 : Math.Abs(i) % (str.Length - 1); var result = str.Substring(0, pos) + c + str.Substring(Math.Min(pos + 2, str.Length - 1)); interpreter.StringStack.SetTop(result); return true; } } }