using System.Collections.Generic; using System.Globalization; using HeuristicLab.Algorithms.PushGP.Expressions; using HeuristicLab.Algorithms.PushGP.Expressions.Boolean; using HeuristicLab.Algorithms.PushGP.Expressions.Code; using HeuristicLab.Algorithms.PushGP.Expressions.Exec; using HeuristicLab.Algorithms.PushGP.Expressions.Float; using HeuristicLab.Algorithms.PushGP.Expressions.Integer; using HeuristicLab.Algorithms.PushGP.Expressions.Name; namespace HeuristicLab.Algorithms.PushGP { public static class Parser { private static readonly CultureInfo cultureInfo = CultureInfo.CreateSpecificCulture("en-US"); private const string openBrace = "("; private const string closeBrace = ")"; private const char delimiter = ' '; private static readonly char[] symbolTrim = new[] { '\r', '\n' }; public static Expression Parse(string source, int startIndex = 0) { var symbols = source.Split(delimiter); int endIndex; return Parse(symbols, 0, out endIndex); } private static Expression Parse(string[] symbols, int startIndex, out int endIndex) { var expressions = new List(); for (var i = startIndex; i < symbols.Length; i++) { var symbol = symbols[i].TrimEnd(symbolTrim); if (string.IsNullOrWhiteSpace(symbol)) { continue; } if (symbol == openBrace) { var subExpression = Parse(symbols, i + 1, out endIndex); expressions.Insert(0, subExpression); i = endIndex; continue; } else if (symbol == closeBrace) { endIndex = i; return expressions.Count != 0 ? new ExecExpandExpression(expressions.ToArray()) : new CodeNoopExpression() as Expression; } // literal Expression expression; if (TryParseLiteral(symbol, out expression)) { expressions.Insert(0, expression); continue; } // expression OpCode opCode; if (SymbolTable.TryGetOpCode(symbol, out opCode)) { expression = ExpressionFactory.Create(opCode); expressions.Insert(0, expression); continue; } // identifier - custom expression or named literals expressions.Insert(0, new NameDefineXExecExpression(symbol)); } endIndex = symbols.Length - 1; return expressions.Count == 1 ? expressions[0] : new ExecExpandExpression(expressions.ToArray()); } private static bool TryParseLiteral(string word, out Expression expression) { long longValue; if (long.TryParse(word, out longValue)) { expression = new IntegerPushExpression(longValue); return true; } double floatValue; if (double.TryParse(word, NumberStyles.Float, cultureInfo, out floatValue)) { expression = new FloatPushExpression(floatValue); return true; } bool booleanValue; if (bool.TryParse(word, out booleanValue)) { expression = new BooleanPushExpression(booleanValue); return true; } expression = null; return false; } } }