Archive

Posts Tagged ‘Tokeniser’

Simple Calculation Parser

March 26, 2011 2 comments

Doesnt support brackets yet. Ill add that later.

using System;
using System.Collections.Generic;
using System.IO;

namespace MathsCalcReader
{
    public class Program
    {
        static void Main()
        {
            Interpretor interpretor = new Interpretor("123 + 5 + 3 - 100");
            Console.WriteLine(interpretor.CalculateMathsExpression());
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }

    public class Interpretor
    {
        private readonly string _expression;
        private Queue<Token> _tokens;

        public Interpretor(string expression)
        {
            _expression = expression;
            _tokens = new Queue<Token>();
        }

        public int CalculateMathsExpression()
        {
            StringReader reader = new StringReader(_expression);

            while (reader.Peek() != -1)
            {
                char c = (char)reader.Read();
                if (Char.IsWhiteSpace(c)) continue;
                if (Char.IsDigit(c))
                {
                    AddDigits(reader, c);
                }
                else if (c == '+' || c == '-' || c == '/' || c == '*')
                {
                    AddOperator(c);
                }
            }

            return AccumulateTotal();
        }

        private int AccumulateTotal()
        {
            int total = 0;
            bool firstrun = true;

            while(_tokens.Count != 0)
            {
                if(firstrun)
                {
                    var op1 = _tokens.Dequeue();
                    var op = _tokens.Dequeue();
                    var op2 = _tokens.Dequeue();
                    total += op.Operator.Calc((int)op1.Value, (int)op2.Value);
                    firstrun = false;
                    continue;
                }
                var aop = _tokens.Dequeue();
                var aop2 = _tokens.Dequeue();
                total = aop.Operator.Calc(total, (int)aop2.Value);
            }
            return total;
        }

        private void AddDigits(StringReader reader, char c)
        {
            string temp = c.ToString();
            char p = (char)reader.Peek();
            if (Char.IsDigit(p))
            {
                p = (char)reader.Read();
                while (Char.IsDigit(p))
                {
                    temp += p;
                    p = (char)reader.Read();
                }
            }
            _tokens.Enqueue(new Token(Convert.ToInt32(temp)));
        }

        private void AddOperator(char c)
        {
            switch (c)
            {
                case '+':
                    _tokens.Enqueue(new Token(MathOperator.Addition));
                    break;
                case '-':
                    _tokens.Enqueue(new Token(MathOperator.Subtraction));
                    break;
                case '*':
                    _tokens.Enqueue(new Token(MathOperator.Multiplication));
                    break;
                case '/':
                    _tokens.Enqueue(new Token(MathOperator.Division));
                    break;
            }
        }
    }

    public class MathOperator
    {
        public Func<int, int, int> Calc;
        public char Value { get; private set; }
        public MathOperator(char value, Func<int,int,int> calc)
        {
            Calc = calc;
            Value = value;
        }

        public static MathOperator Addition = new MathOperator('+',(a,b) => a + b);
        public static MathOperator Subtraction = new MathOperator('-',(a,b) => a - b);
        public static MathOperator Multiplication = new MathOperator('*',(a,b) => a * b);
        public static MathOperator Division = new MathOperator('/', (a,b) => a / b);
    }

    public class Token
    {
        public int? Value { get; set; }
        public MathOperator Operator { get; set; }

        public Token(int value)
        {
            Value = value;
        }

        public Token(MathOperator op)
        {
            Operator = op;
        }
    }
}

Advertisements