public Context From(string source)
        {
            var stream = new ANTLRStringStream(source);
            var lexer = new MessageContractsLexer(stream);

            var tokens = new CommonTokenStream(lexer);

            var parser = new MessageContractsParser(tokens)
                {
                    TreeAdaptor = new CommonTreeAdaptor()
                };

            var program = parser.GetProgram();

            var commonTree = (CommonTree) program.Tree;

            var node = commonTree as CommonErrorNode;

            if (node != null)
            {
                throw new InvalidOperationException(node.ToString());
            }

            var ctx = new Context();
            foreach (var child in commonTree.Children)
            {
                WalkDeclarations(child, ctx);
            }
            return ctx;
        }
        public void WalkDeclarations(object tree, Context context)
        {
            var t = (CommonTree) tree;
            switch (t.Type)
            {
                case MessageContractsLexer.FragmentEntry:
                    var fragmentId = t.GetChild(0).Text;
                    var fragmentType = t.GetChild(1).Text;
                    var fragmentName = t.GetChild(2).Text;
                    context.Fragments[fragmentId] = new Fragment(fragmentType, fragmentName);
                    break;
                case MessageContractsLexer.ModifierDefinition:
                    var modifier = t.GetChild(0).Text;
                    context.CurrentEntity.Modifiers.Remove(modifier);
                    for (int i = 1; i < t.ChildCount; i++)
                    {
                        context.CurrentEntity.Modifiers.Add(modifier, t.GetChild(i).Text);
                    }
                    break;
                case MessageContractsLexer.TypeToken:
                    var name = t.GetChild(0).Text;
                    var block = t.GetChild(1);

                    var modifiers = new List<Modifier>();
                    for (int i = 2; i < t.ChildCount; i++)
                    {
                        var mod = t.GetChild(i).Text;
                        var used = context.CurrentEntity.Modifiers.GetValues(mod);
                        if (null == used || used.Length == 0)
                        {
                            var format = string.Format("Entity '{0}' does not have modifier reference: '{1}'",
                                context.CurrentEntity.Name, mod);
                            throw new InvalidOperationException(format);
                        }
                        foreach (var s in used)
                        {
                            modifiers.Add(new Modifier(mod, s));
                        }
                    }

                    var message = new Message(name, modifiers);
                    if (modifiers.Any())
                    {
                        // only commands and events have modifiers
                        foreach (var member in context.Entities.Peek().FixedMembers)
                        {
                            message.Members.Add(member);
                        }
                    }

                    for (int i = 0; i < block.ChildCount; i++)
                    {
                        message.Members.AddRange(WalkContractMember(block.GetChild(i), context));
                    }

                    context.Contracts.Add(message);
                    context.CurrentEntity.Messages.Add(message);

                    break;

                case MessageContractsLexer.EntityDefinition:
                    var entityName = t.GetChild(0).Text;
                    var entityBlock = t.GetChild(1);

                    var entity = new Entity(entityName);
                    for (int i = 0; i < entityBlock.ChildCount; i++)
                    {
                        entity.FixedMembers.AddRange(WalkContractMember(entityBlock.GetChild(i), context));
                    }

                    context.Entities.Push(entity);

                    break;
                default:
                    throw new InvalidOperationException("Unexpected token: " + t.Text);
            }
        }
        private void WriteContext(CodeWriter writer, Context context)
        {
            foreach (var contract in context.Contracts)
            {
                writer.Write(ClassNameTemplate, contract.Name);

                if (contract.Modifiers.Any())
                {
                    writer.Write(" : {0}", string.Join(", ", contract.Modifiers.Select(s => s.Interface).ToArray()));
                }
                writer.WriteLine();

                writer.WriteLine("{");
                writer.Indent += 1;

                if (contract.Members.Count > 0)
                {
                    WriteMembers(contract, writer);

                    writer.WriteLine();
                    WritePrivateCtor(writer, contract);

                    writer.Write("public {0} (", contract.Name);
                    WriteParameters(contract, writer);
                    writer.WriteLine(")");
                    writer.WriteLine("{");

                    writer.Indent += 1;
                    WriteAssignments(contract, writer);
                    writer.Indent -= 1;

                    writer.WriteLine("}");

                }
                writer.Indent -= 1;
                writer.WriteLine("}");
            }
            foreach (var entity in context.Entities)
            {
                if ((entity.Name ?? "default") == "default")
                    continue;

                GenerateEntityInterface(entity, writer, "?", "public interface I{0}ApplicationService");
                GenerateEntityInterface(entity, writer, "!", "public interface I{0}State");
            }
        }
        static IEnumerable<Member> WalkContractMember(ITree tree, Context context)
        {
            if (tree.Type == MessageContractsLexer.FragmentReference)
            {
                var fragmentId = tree.GetChild(0).Text;

                if (!context.Fragments.ContainsKey(fragmentId))
                {
                    throw new InvalidOperationException(string.Format("Unknown fragment '{0}'", fragmentId));
                }

                var fragment = context.Fragments[fragmentId];
                yield return new Member(fragment.Type, fragment.Name);
                yield break;
            }
            if (tree.Type == MessageContractsLexer.MemberToken)
            {
                var type = tree.GetChild(0).Text;
                var name = tree.GetChild(1).Text;
                if (type == "ref")
                {
                    var match = context.Contracts.Where(c => c.Name == name).ToArray();
                    if (match.Length == 1)
                    {
                        foreach (var member in match[0].Members)
                        {
                            yield return member;
                        }
                        yield break;
                    }
                    throw new InvalidOperationException(string.Format("Unknown include '{0}'", name));
                }
                yield return (new Member(type, name));
                yield break;
            }
            throw new InvalidOperationException("Unexpected token: " + tree.Text);
        }
        public void Generate(Context context, IndentedTextWriter outer)
        {
            var writer = new CodeWriter(outer);
            if (!string.IsNullOrEmpty(Namespace))
            {
                writer.WriteLine("namespace {0}", Namespace);
                writer.WriteLine("{");
            }
            writer.Indent += 1;

            if (!string.IsNullOrEmpty(Region))
            {
                writer.WriteLine("#region {0}", Region);
            }

            WriteContext(writer, context);

            if (!string.IsNullOrEmpty(Region))
            {
                writer.WriteLine("#endregion");
            }

            writer.Indent -= 1;

            if (!string.IsNullOrEmpty(Namespace))
            {
                writer.WriteLine("}");
            }
        }