Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I've kind of chucked this c# console app together as a bit of a proof of concept. Have a feeling it could be a lot better (that switch statement in GetNode is kind of clunky (it's there coz I hit a blank trying to map a class name to an operator)). Any suggestions on how it could be improved very welcome.</p> <pre><code>using System; class Program { static void Main(string[] args) { string expression = "(((3.5 * 4.5) / (1 + 2)) + 5)"; Console.WriteLine(string.Format("{0} = {1}", expression, new Expression.ExpressionTree(expression).Value)); Console.WriteLine("\nShow's over folks, press a key to exit"); Console.ReadKey(false); } } namespace Expression { // ------------------------------------------------------- abstract class NodeBase { public abstract double Value { get; } } // ------------------------------------------------------- class ValueNode : NodeBase { public ValueNode(double value) { _double = value; } private double _double; public override double Value { get { return _double; } } } // ------------------------------------------------------- abstract class ExpressionNodeBase : NodeBase { protected NodeBase GetNode(string expression) { // Remove parenthesis expression = RemoveParenthesis(expression); // Is expression just a number? double value = 0; if (double.TryParse(expression, out value)) { return new ValueNode(value); } else { int pos = ParseExpression(expression); if (pos &gt; 0) { string leftExpression = expression.Substring(0, pos - 1).Trim(); string rightExpression = expression.Substring(pos).Trim(); switch (expression.Substring(pos - 1, 1)) { case "+": return new Add(leftExpression, rightExpression); case "-": return new Subtract(leftExpression, rightExpression); case "*": return new Multiply(leftExpression, rightExpression); case "/": return new Divide(leftExpression, rightExpression); default: throw new Exception("Unknown operator"); } } else { throw new Exception("Unable to parse expression"); } } } private string RemoveParenthesis(string expression) { if (expression.Contains("(")) { expression = expression.Trim(); int level = 0; int pos = 0; foreach (char token in expression.ToCharArray()) { pos++; switch (token) { case '(': level++; break; case ')': level--; break; } if (level == 0) { break; } } if (level == 0 &amp;&amp; pos == expression.Length) { expression = expression.Substring(1, expression.Length - 2); expression = RemoveParenthesis(expression); } } return expression; } private int ParseExpression(string expression) { int winningLevel = 0; byte winningTokenWeight = 0; int winningPos = 0; int level = 0; int pos = 0; foreach (char token in expression.ToCharArray()) { pos++; switch (token) { case '(': level++; break; case ')': level--; break; } if (level &lt;= winningLevel) { if (OperatorWeight(token) &gt; winningTokenWeight) { winningLevel = level; winningTokenWeight = OperatorWeight(token); winningPos = pos; } } } return winningPos; } private byte OperatorWeight(char value) { switch (value) { case '+': case '-': return 3; case '*': return 2; case '/': return 1; default: return 0; } } } // ------------------------------------------------------- class ExpressionTree : ExpressionNodeBase { protected NodeBase _rootNode; public ExpressionTree(string expression) { _rootNode = GetNode(expression); } public override double Value { get { return _rootNode.Value; } } } // ------------------------------------------------------- abstract class OperatorNodeBase : ExpressionNodeBase { protected NodeBase _leftNode; protected NodeBase _rightNode; public OperatorNodeBase(string leftExpression, string rightExpression) { _leftNode = GetNode(leftExpression); _rightNode = GetNode(rightExpression); } } // ------------------------------------------------------- class Add : OperatorNodeBase { public Add(string leftExpression, string rightExpression) : base(leftExpression, rightExpression) { } public override double Value { get { return _leftNode.Value + _rightNode.Value; } } } // ------------------------------------------------------- class Subtract : OperatorNodeBase { public Subtract(string leftExpression, string rightExpression) : base(leftExpression, rightExpression) { } public override double Value { get { return _leftNode.Value - _rightNode.Value; } } } // ------------------------------------------------------- class Divide : OperatorNodeBase { public Divide(string leftExpression, string rightExpression) : base(leftExpression, rightExpression) { } public override double Value { get { return _leftNode.Value / _rightNode.Value; } } } // ------------------------------------------------------- class Multiply : OperatorNodeBase { public Multiply(string leftExpression, string rightExpression) : base(leftExpression, rightExpression) { } public override double Value { get { return _leftNode.Value * _rightNode.Value; } } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload