/*void Main() { string code = "distanceToDestination * 4 / 0"; var output = Code.ParseStatement(code.Split(' '), null); Console.Write("Expected: "); Console.WriteLine(2 * 4 + 2 * 2); var fn = Code.CreateStatement(code); Console.Write("Actual: "); Console.WriteLine(fn(2)); Console.WriteLine(output); }*/ void Main() { var dictionary = System.IO.File.ReadAllLines(@"example.config") .Select(entry => { var keyAndValue = entry.Split(','); return new KeyValuePair(keyAndValue[0],keyAndValue[1]); }) .Select ( keyAndValue => new KeyValuePair> (keyAndValue.Key, Code.CreateStatement(keyAndValue.Value)) ).ToDictionary(keyAndValue=>keyAndValue.Key, keyAndValue => keyAndValue.Value); dictionary["bus"](2); } enum OperatorType { Variable, Operand, Constant } class EquationPart { public EquationPart LeftOperand; public EquationPart RightOperand; public String Name; public OperatorType OType; public override string ToString() => ToString(0); private string ToString(int indent) { return $@"{Name} : {OType} {LeftOperand.ToString(indent + 1)} {RightOperand.ToString(indent + 1)} "; } } class Code { public static Func GetModifier(string op) { switch (op) { case "*": return Expression.Multiply; case "+": return Expression.Add; case "-": return Expression.Subtract; case "/": return Expression.Divide; } throw new Exception("Operator not recognized"); } public static int OperandPrecedence(string item) { switch (item) { case "+": case "-": return 1; case "*": case "/": return 2; default: return 0; } } public static EquationPart ParseStatement (IEnumerable statement, EquationPart tree) { if (!statement.Any()) { return tree; } var part = statement.First(); switch (OperandPrecedence(part)) { case 2: { var op = new EquationPart { Name = part, OType = OperatorType.Operand, LeftOperand = tree, RightOperand = ParseStatement(statement.Skip(1).Take(1),tree) }; return ParseStatement(statement.Skip(2), op); } case 1: { return new EquationPart { Name = part, OType = OperatorType.Operand, LeftOperand = tree, RightOperand = ParseStatement(statement.Skip(1), null) }; } default: { int result; return ParseStatement(statement.Skip(1), new EquationPart { Name = part, OType = (int.TryParse(part, out result))? OperatorType.Constant : OperatorType.Variable }); } } } public static Func CreateStatement(string statement) { var statementParts = statement.Split(' '); var tree = ParseStatement(statementParts, null); var travelParm = Expression.Parameter(typeof(int), "distanceToDestination"); var mainBody = CreateBody(tree,travelParm); var parameterException = Expression.Parameter(typeof(Exception)); var logCatchException = Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[1] { typeof(string) }), Expression.Call(parameterException, typeof(Exception).GetMethod("ToString")) ); var logCatchStatement = Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[1] { typeof(string) }), Expression.Constant("Configuration statement: " + statement)); var catchBlockCode = Expression.Block(logCatchException, logCatchStatement, Expression.Rethrow(typeof(double))); var catchBlock = Expression.MakeCatchBlock(typeof(Exception), parameterException ,catchBlockCode,null); var tryCatch = Expression.TryCatch(mainBody, catchBlock); return Expression.Lambda>(tryCatch, new ParameterExpression[] {travelParm}).Compile(); } static Expression CreateBody(EquationPart tree, ParameterExpression travelParm) { var body = MakeBody(tree, travelParm); var result = Expression.Variable(typeof(double)); var infinityCondition = CreateInfinityCondition(result); var assign = Expression.Assign(result, body); var write = Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[1] { typeof(double) }), result); return Expression.Block(new ParameterExpression[] { result }, assign, write, infinityCondition ,result); } static Expression CreateInfinityCondition(ParameterExpression resultToCheck) { var test = Expression.Call(typeof(double).GetMethod("IsInfinity", new Type[1] {typeof(double)}), resultToCheck); var trueBlock = Expression.Throw(Expression.Constant(new Exception("Result is infinity"))); return Expression.Condition(test, trueBlock, Expression.Empty()); } public static Expression MakeBody (EquationPart tree, ParameterExpression distance) { if (tree.OType == OperatorType.Operand) { var leftAction = MakeBody(tree.LeftOperand, distance); var rightAction = MakeBody(tree.RightOperand, distance); var action = Code.GetModifier(tree.Name)(Expression.Convert(leftAction, typeof(double)), Expression.Convert(rightAction, typeof(double))); return action; } return (tree.Name == distance.Name) ? (Expression)distance : Expression.Constant(int.Parse(tree.Name), typeof(int)); } }