I have a lot of problems making this code look more elegant or to reduce its size. The algorithm is mostly copied from the pseudocode of wikipedia page. The difference is I prepare my string with the tokenSplit method.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace YardVer3
{
class Program
{
public class Token
{
public Token()
{
Value = string.Empty;
Info = '?';
Precedence = -1;
}
public Token(string text)
{
Value = text;
}
public string Value;
public char Info; //d - digit f-function r,l - right/left operator e- unHandled
public int Precedence;
}
static void Main(string[] args)
{
string inLine = "3 + 4 × 2 ÷ ( 1 − 5 ) ^ 2 ^ 3";
Token[] lineToken = new Token[inLine.Length];
for (int i = 0; i < lineToken.Length; i++)
{
lineToken[i] = new Token();
}
int tokenIndex = 0;
tokenIndex = tokenSplit(inLine, tokenIndex, lineToken);
//Start of Shunting Yard Algorithm(Referenced by Wikipedia PseudoCode)
Queue<Token> rpnLine = new Queue<Token>();
Stack<Token> opStack = new Stack<Token>();
for (int i = 0; i < tokenIndex; i++)
{
switch (lineToken[i].Info)
{
case 'd':
rpnLine.Enqueue(lineToken[i]);
break;
case 'f':
opStack.Push((lineToken[i]));
break;
case '(':
opStack.Push(new Token("("));
break;
case 'l':
case 'r':
if (opStack.Count>0)
{
Token t = opStack.Peek();
while ( t.Info == 'f' ||
(t.Precedence > lineToken[i].Precedence) ||
(t.Precedence == lineToken[i].Precedence && t.Info == 'l'))
{
rpnLine.Enqueue(opStack.Pop());
t = opStack.Peek();
}
}
opStack.Push(lineToken[i]);
break;
case ')':
while (opStack.Count > 0)
{
if (opStack.Peek().Value != "(")
{
rpnLine.Enqueue(opStack.Pop());
}
else
{
opStack.Pop();
break;
}
}
break;
default:
Console.WriteLine("Problem Accured");
break;
}
}
while (opStack.Count >0)
{
rpnLine.Enqueue(opStack.Pop());
}
Console.WriteLine(inLine);
while (rpnLine.Count > 0)
{
Console.Write(rpnLine.Dequeue().Value);
Console.Write(' ');
}
Console.WriteLine();
}
private static int tokenSplit(string inLine, int tokenIndex, Token[] lineToken)
{
Match digit = Regex.Match(inLine, @"\d+\.?\d*");
Match funct = Regex.Match(inLine, @"[a-zA-Z]+");
for (int i = 0; i < inLine.Length; i++)
{
if (char.IsDigit(inLine[i]))
{
i += digit.Length - 1;
lineToken[tokenIndex].Info = 'd';
lineToken[tokenIndex].Value = digit.Value;
tokenIndex++;
digit = digit.NextMatch();
}
else if (char.IsLetter(inLine[i]))
{
i += funct.Length - 1;
lineToken[tokenIndex].Info = 'f';
lineToken[tokenIndex].Value = funct.Value;
tokenIndex++;
funct = funct.NextMatch();
}
else if (inLine[i] != ' ' && inLine[i] != ',')
{
lineToken[tokenIndex] = tokenInfoFill(inLine[i]);
lineToken[tokenIndex].Value = inLine[i].ToString();
tokenIndex++;
}
}
return tokenIndex;
}
public static Token tokenInfoFill(char c)
{
Token temp = new Token();
switch (c)
{
case '+':
case '-':
case '−':
temp.Precedence = 2;
temp.Info = 'l';
return temp;
case '*':
case '×':
case '/':
case '÷':
temp.Precedence = 3;
temp.Info = 'l';
return temp;
case '^':
temp.Precedence = 4;
temp.Info = 'r';
return temp;
case '(':
case ')':
temp.Precedence = -2;
temp.Info = c;
return temp;
default:
return temp;
}
}
}
}