Created
October 11, 2025 11:06
-
-
Save chrdek/9a5ff5ec36426ede97641fac355198d0 to your computer and use it in GitHub Desktop.
Fluent Syntax Calculator in Csharp (2 examples)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| namespace Calc | |
| { | |
| public class FluentCalculator | |
| { | |
| private static readonly int[] Values = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; | |
| private enum OperatorType | |
| { | |
| None, | |
| Plus, | |
| Minus, | |
| Times, | |
| DividedBy | |
| } | |
| private OperatorType lastType; | |
| private double result; | |
| private Stack<double> operandStack; | |
| private Stack<OperatorType> operatorStack; | |
| public FluentCalculator() | |
| { | |
| result = 0; | |
| lastType = OperatorType.None; | |
| operandStack = new Stack<double>(); | |
| operatorStack = new Stack<OperatorType>(); | |
| } | |
| private FluentCalculator ApplyOperator(OperatorType operatorType) | |
| { | |
| while (operatorStack.Count > 0 && Precedence(operatorStack.Peek()) >= Precedence(operatorType)) | |
| { | |
| ProcessStackTop(); | |
| } | |
| operatorStack.Push(operatorType); | |
| return this; | |
| } | |
| private FluentCalculator ApplyValue(double value) | |
| { | |
| operandStack.Push(value); | |
| return this; | |
| } | |
| private void ProcessStackTop() | |
| { | |
| if (operandStack.Count < 2 || operatorStack.Count < 1) | |
| { | |
| // Handle error or throw exception if needed | |
| return; | |
| } | |
| double operand2 = operandStack.Pop(); | |
| double operand1 = operandStack.Pop(); | |
| OperatorType op = operatorStack.Pop(); | |
| double result = PerformOperation(operand1, operand2, op); | |
| operandStack.Push(result); | |
| } | |
| private double PerformOperation(double operand1, double operand2, OperatorType op) | |
| { | |
| switch (op) | |
| { | |
| case OperatorType.Plus: | |
| return operand1 + operand2; | |
| case OperatorType.Minus: | |
| return operand1 - operand2; | |
| case OperatorType.Times: | |
| return operand1 * operand2; | |
| case OperatorType.DividedBy: | |
| if (operand2 != 0) | |
| { | |
| return operand1 / operand2; | |
| } | |
| else | |
| { | |
| // Handle division by zero error or throw exception if needed | |
| return 0; | |
| } | |
| default: | |
| // Handle other cases if necessary | |
| return 0; | |
| } | |
| } | |
| private int Precedence(OperatorType op) | |
| { | |
| switch (op) | |
| { | |
| case OperatorType.Plus: | |
| case OperatorType.Minus: | |
| return 1; | |
| case OperatorType.Times: | |
| case OperatorType.DividedBy: | |
| return 2; | |
| default: | |
| return 0; | |
| } | |
| } | |
| // Methods for numbers and operators (Zero, One, Two, etc.) | |
| public FluentCalculator Zero => ApplyValue(0); | |
| public FluentCalculator One => ApplyValue(1); | |
| public FluentCalculator Two => ApplyValue(2); | |
| public FluentCalculator Three => ApplyValue(3); | |
| public FluentCalculator Four => ApplyValue(4); | |
| public FluentCalculator Five => ApplyValue(5); | |
| public FluentCalculator Six => ApplyValue(6); | |
| public FluentCalculator Seven => ApplyValue(7); | |
| public FluentCalculator Eight => ApplyValue(8); | |
| public FluentCalculator Nine => ApplyValue(9); | |
| public FluentCalculator Ten => ApplyValue(10); | |
| public FluentCalculator Plus => ApplyOperator(OperatorType.Plus); | |
| public FluentCalculator Minus => ApplyOperator(OperatorType.Minus); | |
| public FluentCalculator Times => ApplyOperator(OperatorType.Times); | |
| public FluentCalculator DividedBy => ApplyOperator(OperatorType.DividedBy); | |
| // Result method to retrieve the finalized result | |
| public double Result() | |
| { | |
| while (operatorStack.Count > 0) | |
| { | |
| ProcessStackTop(); | |
| } | |
| return operandStack.Count > 0 ? operandStack.Peek() : 0; | |
| } | |
| // Evaluate method to retrieve the finalized result | |
| public double Evaluate() | |
| { | |
| return Result(); | |
| } | |
| // Implicit conversion operator | |
| public static implicit operator double(FluentCalculator calculator) | |
| { | |
| return calculator.Result(); | |
| } | |
| //Operator Overloads | |
| public static double operator +(FluentCalculator left, double right) | |
| { | |
| left.ApplyValue(right); | |
| return left.Result(); | |
| } | |
| public static double operator *(FluentCalculator left, int right) | |
| { | |
| left.ApplyValue(right); | |
| return left.Result(); | |
| } | |
| // Add other operator overloads as needed | |
| } | |
| } | |
| /***************************************Alternative Approach******************************************************/ | |
| using System; | |
| using System.Collections.Generic; | |
| namespace Calc | |
| { | |
| public class FluentCalculator | |
| { | |
| private static readonly int[] Values = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; | |
| private enum OperatorType | |
| { | |
| None, | |
| Plus, | |
| Minus, | |
| Times, | |
| DividedBy | |
| } | |
| private OperatorType lastType; | |
| private double result; | |
| private Stack<double> operandStack; | |
| private Stack<OperatorType> operatorStack; | |
| public FluentCalculator() | |
| { | |
| result = 0; | |
| lastType = OperatorType.None; | |
| operandStack = new Stack<double>(); | |
| operatorStack = new Stack<OperatorType>(); | |
| } | |
| private FluentCalculator ApplyOperator(OperatorType operatorType) | |
| { | |
| while (operatorStack.Count > 0 && Precedence(operatorStack.Peek()) >= Precedence(operatorType)) | |
| { | |
| ProcessStackTop(); | |
| } | |
| operatorStack.Push(operatorType); | |
| return this; | |
| } | |
| private FluentCalculator ApplyValue(double value) | |
| { | |
| operandStack.Push(value); | |
| return this; | |
| } | |
| private void ProcessStackTop() | |
| { | |
| if (operandStack.Count < 2 || operatorStack.Count < 1) | |
| { | |
| // Handle error or throw exception if needed | |
| return; | |
| } | |
| double operand2 = operandStack.Pop(); | |
| double operand1 = operandStack.Pop(); | |
| OperatorType op = operatorStack.Pop(); | |
| double result = PerformOperation(operand1, operand2, op); | |
| operandStack.Push(result); | |
| } | |
| private double PerformOperation(double operand1, double operand2, OperatorType op) | |
| { | |
| switch (op) | |
| { | |
| case OperatorType.Plus: | |
| return operand1 + operand2; | |
| case OperatorType.Minus: | |
| return operand1 - operand2; | |
| case OperatorType.Times: | |
| return operand1 * operand2; | |
| case OperatorType.DividedBy: | |
| if (operand2 != 0) | |
| { | |
| return operand1 / operand2; | |
| } | |
| else | |
| { | |
| // Handle division by zero error or throw exception if needed | |
| return 0; | |
| } | |
| default: | |
| // Handle other cases if necessary | |
| return 0; | |
| } | |
| } | |
| private int Precedence(OperatorType op) | |
| { | |
| switch (op) | |
| { | |
| case OperatorType.Plus: | |
| case OperatorType.Minus: | |
| return 1; | |
| case OperatorType.Times: | |
| case OperatorType.DividedBy: | |
| return 2; | |
| default: | |
| return 0; | |
| } | |
| } | |
| // Methods for numbers and operators (Zero, One, Two, etc.) | |
| public FluentCalculator Zero => ApplyValue(0); | |
| public FluentCalculator One => ApplyValue(1); | |
| public FluentCalculator Two => ApplyValue(2); | |
| public FluentCalculator Three => ApplyValue(3); | |
| public FluentCalculator Four => ApplyValue(4); | |
| public FluentCalculator Five => ApplyValue(5); | |
| public FluentCalculator Six => ApplyValue(6); | |
| public FluentCalculator Seven => ApplyValue(7); | |
| public FluentCalculator Eight => ApplyValue(8); | |
| public FluentCalculator Nine => ApplyValue(9); | |
| public FluentCalculator Ten => ApplyValue(10); | |
| public FluentCalculator Plus => ApplyOperator(OperatorType.Plus); | |
| public FluentCalculator Minus => ApplyOperator(OperatorType.Minus); | |
| public FluentCalculator Times => ApplyOperator(OperatorType.Times); | |
| public FluentCalculator DividedBy => ApplyOperator(OperatorType.DividedBy); | |
| // Result method to retrieve the finalized result | |
| public double Result() | |
| { | |
| while (operatorStack.Count > 0) | |
| { | |
| ProcessStackTop(); | |
| } | |
| return operandStack.Count > 0 ? operandStack.Peek() : 0; | |
| } | |
| // Evaluate method to retrieve the finalized result | |
| public double Evaluate() | |
| { | |
| return Result(); | |
| } | |
| // Implicit conversion operator | |
| public static implicit operator double(FluentCalculator calculator) | |
| { | |
| return calculator.Result(); | |
| } | |
| //Operator Overloads | |
| /*public static FluentCalculator operator *(FluentCalculator left, int right) | |
| { | |
| left.ApplyValue(right); | |
| return left; | |
| } | |
| public static FluentCalculator operator +(FluentCalculator left, double right) | |
| { | |
| left.ApplyValue(right); | |
| return left; | |
| }*/ | |
| public static double operator +(FluentCalculator left, double right) | |
| { | |
| left.ApplyValue(right); | |
| return left.Result(); | |
| } | |
| public static double operator *(FluentCalculator left, int right) | |
| { | |
| left.ApplyValue(right); | |
| return left.Result(); | |
| } | |
| // Add other operator overloads as needed | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment