using System.Collections.Generic;
None, Literal, Separator, Operator
public TokenType Type { get; set; }
public string Value { get; set; }
public double Calculate(string expression) {
var tokens = Parse(expression);
foreach (var token in tokens) {
Console.WriteLine($"{token.Type} [{token.Value}]");
private LinkedList<Token> Parse(string expression) {
var tokens = new LinkedList<Token>();
var token = (Token) null;
while ((token = GetToken(expression, ref index)) != null) {
private Token GetToken(string expression, ref int begin) {
var previousType = TokenType.None;
var token = (Token) null;
if (begin >= (expression.Length)) {
while (Char.IsWhiteSpace(expression[begin])) {
previousType = GetTokenType(expression[begin]);
for (int index = begin; index < expression.Length; ++index) {
char character = expression[index];
if (Char.IsWhiteSpace(character)) {
var tokenType = GetTokenType(character);
if (tokenType != previousType) {
Value = expression.Substring(begin, (end - begin))
private TokenType GetTokenType(char character) {
if (Char.IsDigit(character)) {
return TokenType.Literal;
} else if ((character == '(') || (character == ')')) {
return TokenType.Separator;
} else if ((character == '+') || (character == '-') || (character == '*') || (character == '/')) {
return TokenType.Operator;
throw new ArgumentException($"The expression has an invalid string value: [{character}].");
private LinkedListNode<Token> GetNextToken(LinkedList<Token> tokens, string operatorV) {
for (var iterator = tokens.First; iterator != null; iterator = iterator.Next) {
var current = iterator.Value;
var previous = iterator.Previous?.Value;
var next = iterator.Next?.Value;
if (((current.Type == TokenType.Operator) || (current.Value == operatorV))
&& ((previous != null) && (previous.Type == TokenType.Literal) || (previous.Value == operatorV))
&& ((next != null) && (next.Type == TokenType.Literal) || (next.Value == operatorV))) {
private Token Evaluate(Token operandA, Token operandB, Token operatorC) {
int valueA = int.Parse(operandA.Value);
int valueB = int.Parse(operandB.Value);
switch (operatorC.Value) {
return new Token() { Type = TokenType.Literal, Value = (valueA + valueB).ToString() };
return new Token() { Type = TokenType.Literal, Value = (valueA - valueB).ToString() };
return new Token() { Type = TokenType.Literal, Value = (valueA * valueB).ToString() };
return new Token() { Type = TokenType.Literal, Value = (valueA / valueB).ToString() };
throw new ArgumentException($"The expression has an invalid operands: [{valueA} {operatorC.Value} {valueB}].");
private static void Test(string expression) {
var calculator = new SimpleCalculator();
var result = calculator.Calculate(expression);
Console.WriteLine($"{expression} : {result}");
public static void Main() {
} catch (ArgumentException e) {
Console.WriteLine(e.ToString());