public static object Calculate(Lexem oper, Lexem leftValue, Lexem rightValue, ref LexemType lt) { var t = PickCorrectType(leftValue, rightValue); switch (t) { case TypeCode.Double: lt = LexemType.Number; switch (oper.Content.ToString()) { case "*": return leftValue.ToDouble() * rightValue.ToDouble(); case "/": return leftValue.ToDouble() / rightValue.ToDouble(); case "+": return leftValue.ToDouble() + rightValue.ToDouble(); case "-": return leftValue.ToDouble() - rightValue.ToDouble(); case ">": lt = LexemType.Boolean; return leftValue.ToDouble() > rightValue.ToDouble(); case "<": lt = LexemType.Boolean; return leftValue.ToDouble() < rightValue.ToDouble(); case "!=": lt = LexemType.Boolean; return leftValue.ToDouble() != rightValue.ToDouble(); case "==": lt = LexemType.Boolean; return leftValue.ToDouble() == rightValue.ToDouble(); case ">=": lt = LexemType.Boolean; return leftValue.ToDouble() >= rightValue.ToDouble(); case "<=": lt = LexemType.Boolean; return leftValue.ToDouble() <= rightValue.ToDouble(); case "=": Storage.SetVariableValue(leftValue, rightValue.ToDouble()); if (leftValue.Content is Variable) return (leftValue.Content as Variable).Value; return Storage.GetVariable(leftValue.Content.ToString()); } break; case TypeCode.String: lt = LexemType.String; switch (oper.Content.ToString()) { case "+": return leftValue.ToString() + rightValue.ToString(); case "!=": lt = LexemType.Boolean; return leftValue.ToString() != rightValue.ToString(); case "==": lt = LexemType.Boolean; return leftValue.ToString() == rightValue.ToString(); case "=": Storage.SetVariableValue(leftValue, rightValue.ToString()); if (leftValue.Content is Variable) return (leftValue.Content as Variable).Value; return Storage.GetVariable(leftValue.Content.ToString()); default: throw new SyntaxException("Неверная операция", oper); } case TypeCode.Boolean: lt = LexemType.Boolean; switch (oper.Content.ToString()) { case "||": return leftValue.ToBoolean() || rightValue.ToBoolean(); case "&&": return leftValue.ToBoolean() && rightValue.ToBoolean(); case "==": return leftValue.ToBoolean() == rightValue.ToBoolean(); case "!=": return leftValue.ToBoolean() != rightValue.ToBoolean(); case "=": Storage.SetVariableValue(leftValue, rightValue.ToBoolean()); if (leftValue.Content is Variable) return (leftValue.Content as Variable).Value; return Storage.GetVariable(leftValue.Content.ToString()); default: throw new SyntaxException("Неверная операция", oper); } } throw new SyntaxException("Ошибка вычисления оператора", oper); }
private static TypeCode PickCorrectType(Lexem leftValue, Lexem rightValue) { LexemType lType = leftValue.LexemType, rType = rightValue.LexemType; if (lType == LexemType.Number && rType == LexemType.Number) { return TypeCode.Double; } if (lType == LexemType.String && rType == LexemType.String) { return TypeCode.String; } if (lType == LexemType.Variable && rType == LexemType.Number || lType == LexemType.String && rType == LexemType.Number) { try { leftValue.ToDouble(); return TypeCode.Double; } catch (Exception) { return TypeCode.String; } } if (lType == LexemType.Number && rType == LexemType.Variable || lType == LexemType.Number && rType == LexemType.String) { try { rightValue.ToDouble(); return TypeCode.Double; } catch (Exception) { return TypeCode.String; } } if (lType == LexemType.Variable && rType == LexemType.String || lType == LexemType.String && rType == LexemType.Variable) { return TypeCode.String; } if (lType == LexemType.Variable && rType == LexemType.Boolean || lType == LexemType.Boolean && rType == LexemType.Variable) { return TypeCode.Boolean; } if (lType == LexemType.Boolean && rType == LexemType.Boolean) { return TypeCode.Boolean; } if (lType == LexemType.Variable && rType == LexemType.Variable) { try { leftValue.ToDouble(); return TypeCode.Double; } catch (Exception) { try { leftValue.ToBoolean(); return TypeCode.Boolean; } catch (Exception) { return TypeCode.String; } } } throw new SyntaxException("Не удалось определить общий тип", leftValue); }