Click here to Skip to main content
13,139,520 members (51,757 online)
Click here to Skip to main content

Stats

43.9K views
2K downloads
17 bookmarked
Posted 1 Oct 2010

Expression Control for TFS Work Items

, 5 Oct 2010
Custom control for TFS Work Items that shows the result of calculating an expression based on the work item fields contents
using System;
using Antlr.Runtime.Tree;
using System.Text;

namespace Evaluant.Calculator.Domain
{
    public abstract class LogicalExpression
    {
        const char BS = '\\';

        private static string extractString(string text)
        {

            StringBuilder sb = new StringBuilder(text);
            int startIndex = 1; // Skip initial quote
            int slashIndex = -1;

            while ((slashIndex = sb.ToString().IndexOf(BS, startIndex)) != -1)
            {
                char escapeType = sb[slashIndex + 1];
                switch (escapeType)
                {
                    case 'u':
                        string hcode = String.Concat(sb[slashIndex + 4], sb[slashIndex + 5]);
                        string lcode = String.Concat(sb[slashIndex + 2], sb[slashIndex + 3]);
                        char unicodeChar = Encoding.Unicode.GetChars(new byte[] { System.Convert.ToByte(hcode, 16), System.Convert.ToByte(lcode, 16) })[0];
                        sb.Remove(slashIndex, 6).Insert(slashIndex, unicodeChar);
                        break;
                    case 'n': sb.Remove(slashIndex, 2).Insert(slashIndex, '\n'); break;
                    case 'r': sb.Remove(slashIndex, 2).Insert(slashIndex, '\r'); break;
                    case 't': sb.Remove(slashIndex, 2).Insert(slashIndex, '\t'); break;
                    case '\'': sb.Remove(slashIndex, 2).Insert(slashIndex, '\''); break;
                    case '\\': sb.Remove(slashIndex, 2).Insert(slashIndex, '\\'); break;
                    default: throw new ApplicationException("Unvalid escape sequence: \\" + escapeType);
                }

                startIndex = slashIndex + 1;

            }

            sb.Remove(0, 1);
            sb.Remove(sb.Length - 1, 1);

            return sb.ToString();
        }

        public static LogicalExpression Create(CommonTree ast)
        {
            if (ast == null)
                throw new ArgumentNullException("tree");

            switch (ast.Type)
            {
                case ECalcParser.STRING:
                    return new Value(extractString(ast.Text), ValueType.String);

                case ECalcParser.INTEGER:
                    return new Value(ast.Text, ValueType.Integer);

                case ECalcParser.BOOLEAN:
                    return new Value(ast.Text, ValueType.Boolean);

                case ECalcParser.DATETIME:
                    return new Value(ast.Text, ValueType.DateTime);

                case ECalcParser.FLOAT:
                    return new Value(ast.Text, ValueType.Float);

                case ECalcParser.NOT:
                    return new UnaryExpression(UnaryExpressionType.Not,
                        Create((CommonTree)ast.GetChild(0)));

                case ECalcParser.NEGATE:
                    return new UnaryExpression(UnaryExpressionType.Negate,
                        Create((CommonTree)ast.GetChild(0)));

                case ECalcParser.MULT:
                    return new BinaryExpresssion(BinaryExpressionType.Times,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.POW:
                    return new BinaryExpresssion(BinaryExpressionType.Pow,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.DIV:
                    return new BinaryExpresssion(BinaryExpressionType.Div,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.MOD:
                    return new BinaryExpresssion(BinaryExpressionType.Modulo,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.PLUS:
                    return new BinaryExpresssion(BinaryExpressionType.Plus,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.MINUS:
                    return new BinaryExpresssion(BinaryExpressionType.Minus,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.LT:
                    return new BinaryExpresssion(BinaryExpressionType.Lesser,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.LTEQ:
                    return new BinaryExpresssion(BinaryExpressionType.LesserOrEqual,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.GT:
                    return new BinaryExpresssion(BinaryExpressionType.Greater,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.GTEQ:
                    return new BinaryExpresssion(BinaryExpressionType.GreaterOrEqual,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.EQUALS:
                    return new BinaryExpresssion(BinaryExpressionType.Equal,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.NOTEQUALS:
                    return new BinaryExpresssion(BinaryExpressionType.NotEqual,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.AND:
                    return new BinaryExpresssion(BinaryExpressionType.And,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcParser.OR:
                    return new BinaryExpresssion(BinaryExpressionType.Or,
                        Create((CommonTree)ast.GetChild(0)),
                        Create((CommonTree)ast.GetChild(1)));

                case ECalcLexer.IDENT:
                    LogicalExpression[] expressions = new LogicalExpression[ast.ChildCount];

                    for (int i = 0; i < ast.ChildCount; i++)
                        expressions[i] = LogicalExpression.Create((CommonTree)ast.GetChild(i));

                    return new Function(ast.Text, expressions);

                case ECalcLexer.PARAM:
                    return new Parameter(((CommonTree)ast.GetChild(0)).Text);

                default:
                    return null;
            }

        }

        public virtual void Accept(LogicalExpressionVisitor visitor)
        {
            visitor.Visit(this);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

konamiman.MSX
Software Developer SunHotels
Spain Spain
Under the secret identity of a C# programmer, a freaky guy who loves MSX computers and japanese culture is hidden. Beware!

You may also be interested in...

Pro
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170915.1 | Last Updated 6 Oct 2010
Article Copyright 2010 by konamiman.MSX
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid