XamlParser.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Markup / XamlParser.cs / 1305600 / XamlParser.cs

                            /****************************************************************************\ 
*
* File: XamlParser.cs
*
* Purpose:  Class for compiling Xaml. 
*
* History: 
*    6/06/01:    rogerg        Created 
*    5/28/03:    peterost      Ported to wcp
*    10/6/03:    peterost      Reorganized to remove DP - clr distinction 
*
* Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
*
\***************************************************************************/ 

 
using System; 
using System.Xml;
using System.IO; 
using System.Text;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics; 
using System.Reflection;
using System.Globalization; 
using System.Security.Permissions; 
using MS.Utility;
using System.Runtime.InteropServices; 
using MS.Internal;

// Disabling 1634 and 1691:
// In order to avoid generating warnings about unknown message numbers and 
// unknown pragmas when compiling C# source code with the C# compiler,
// you need to disable warnings 1634 and 1691. (Presharp Documentation) 
#pragma warning disable 1634, 1691 

#if PBTCOMPILER 
namespace MS.Internal.Markup
#else

using System.Windows; 

namespace System.Windows.Markup 
#endif 
{
 
    #region enums

    /// 
    /// Parser modes. indicates if the Xaml should be parsed [....] or async. 
    /// currently public so test can set these values.
    ///  
    internal enum XamlParseMode 
    {
        ///  
        /// Not initialized
        /// 
        Uninitialized,
 
        /// 
        /// [....] 
        ///  
        Synchronous,
 
        /// 
        /// Async
        /// 
        Asynchronous, 
    }
 
    #endregion enums 

    ///  
    /// XamlParser class. This class is used internally
    /// 
    internal class XamlParser
    { 
#if PBTCOMPILER
    #region Constructors 
 
        /// 
        /// Constructor that takes a stream and creates an XmlCompatibilityReader on it. 
        /// 
        public XamlParser(
            ParserContext parserContext,
            BamlRecordWriter bamlWriter, 
            Stream xamlStream,
            bool multipleRoots) : this(parserContext, bamlWriter, 
                                        new XmlTextReader(xamlStream, 
                                        multipleRoots ? XmlNodeType.Element : XmlNodeType.Document,
                                        (XmlParserContext)parserContext)                             ) 
        {
        }

        protected XamlParser( 
            ParserContext parserContext,
            BamlRecordWriter bamlWriter, 
            XmlTextReader textReader) : this(parserContext, bamlWriter) 
        {
 
            // When the XML 1.0 specification was authored, security was not a top concern, and as a result DTDs have the
            // unfortunate capability of severe Denial of Service (DoS) attacks, typically through the use of an internal
            // entity expansion technique. In System.Xml V2.0, in order to provide protection against DTD DoS attacks there
            // is the capability of turning off DTD parsing through the use of the ProhibitDtd property. 

            textReader.ProhibitDtd = true; 
 
            XmlCompatibilityReader xcr = new XmlCompatibilityReader(textReader,
                                                                    new IsXmlNamespaceSupportedCallback(IsXmlNamespaceSupported), 
                                                                    _predefinedNamespaces );

            TokenReader = new XamlReaderHelper(this,parserContext,xcr);
        } 

        protected XamlParser( 
            ParserContext parserContext, 
            BamlRecordWriter bamlWriter)
        { 
            _parserContext = parserContext;
            _bamlWriter = bamlWriter;
        }
 

        // Default constructor to aid in subclassing 
        protected XamlParser() 
        {
        } 

#endregion Constructors

    #region PublicMethods 

 
        ///  
        /// Main method to Parse the XAML.
        /// When in synchronous mode the entire file is parsed before 
        /// this method returns.
        /// In asynchronous mode at least the root tag is parsed. This
        /// is necessary for the way binders currently work.
        ///  
        public void Parse()
        { 
            // if parseMode hasn't been set then set it now to synchronous. 
            if (XamlParseMode == XamlParseMode.Uninitialized)
            { 
                XamlParseMode = XamlParseMode.Synchronous;
            }

            _Parse(); 
        }
 
 

        ///  
        /// Main function called by the XamlCompiler on a Compile.
        /// If singleRecordMode is true the Read returns after each item read.
        /// 
        /// True if more nodes to read 

        // !! Review - now that have separate out into XamlReaderHelper 
        // review if still need all the virtuals or the caller of the TokenReader 
        // can dispatch as they feel appropriate.
        public bool ReadXaml(bool singleRecordMode) 
        {
            XamlNode xamlNode = null;
            bool     cleanup = !singleRecordMode;
            bool     done = false; 

            try // What do we do with Exceptions we catch on this thread?. 
            { 

                while (TokenReader.Read(ref xamlNode)) 
                {
                    SetParserAction(xamlNode);

                    if (ParserAction == ParserAction.Normal) 
                    {
                        // If processing of the xaml node determines that we are done, 
                        // then stop now.  This can happen if ProcessXamlNode is 
                        // overridden (such as when processing styles) and the parsed
                        // block is finished, but the overall file is not.  In that 
                        // case exit this parser, but leave everything intact.
                        ProcessXamlNode(xamlNode, ref cleanup, ref done);

                        if (done) 
                        {
                            break; 
                        } 

                        // return here in single record mode since we don't want 
                        // to set the parser loop to Done.
                        if (singleRecordMode)
                        {
                            return true; 
                        }
 
                    } 
                }
 
            }
            catch (Exception e)
            {
                if (CriticalExceptions.IsCriticalException(e)) 
                {
                   throw; 
                } 
                else
                { 
                    if (e is XamlParseException)
                    {
                        throw;
                    } 
                    // If the exception was a XamlParse exception on the other
                    // side of a Reflection Invoke, then just pull up the Parse exception. 
                    if (e is TargetInvocationException &&  e.InnerException is XamlParseException) 
                    {
                        throw e.InnerException; 
                    }

                    int lineNumber = 0;
                    int linePosition = 0; 
                    string newMessage = null;
 
                    if (e is XmlException) 
                    {
                        XmlException xmlEx = (XmlException)e; 
                        lineNumber = xmlEx.LineNumber;
                        linePosition = xmlEx.LinePosition;
                        newMessage = xmlEx.Message;
                    } 
                    else
                    { 
                        // generic exception, If have a xamlNode then use the 
                        // nodes values for the line Numbers.
                        if (null != xamlNode) 
                        {
                            lineNumber = xamlNode.LineNumber;
                            linePosition = xamlNode.LinePosition;
                        } 
                        newMessage = e.Message + " " + SR.Get(SRID.ParserLineAndOffset,
                                                  lineNumber.ToString(CultureInfo.CurrentCulture), 
                                                  linePosition.ToString(CultureInfo.CurrentCulture)); 
                    }
                    XamlParseException parseException = new XamlParseException(newMessage, lineNumber, linePosition, e); 
                    ParseError(parseException);

                    // Recurse on error
                    cleanup = true; 
                    throw parseException;
                } 
            } 
            finally
            { 
                // Perform cleanup only if we encountered a non-recoverable error, or
                // we're finished reading the stream (EndDocument reached in single
                // record mode, or end of stream reached in multi-record mode)
                if (cleanup) 
                {
                    // Close the reader, which will close the underlying stream. 
                    TokenReader.Close(); 
                }
            } 

            return false;
        }
 
       /// 
       /// Big switch to handle all the records. 
       ///  
       ///  Node received from TokenReader to process
       ///  True if end of stream reached and document is 
       ///                        totally finished and should be closed 
       ///  True if done processing and want to exit.  Doesn't
       ///                     necessarily mean document is finished (see cleanup) 
       internal virtual void ProcessXamlNode( 
               XamlNode xamlNode,
           ref bool     cleanup, 
           ref bool     done) 
       {
            switch(xamlNode.TokenType) 
            {
                case XamlNodeType.DocumentStart:
                    XamlDocumentStartNode xamlDocumentStartNode =
                        (XamlDocumentStartNode) xamlNode; 

                    WriteDocumentStart(xamlDocumentStartNode); 
 
                    break;
                case XamlNodeType.DocumentEnd: 
                    XamlDocumentEndNode xamlEndDocumentNode =
                        (XamlDocumentEndNode) xamlNode;
                    cleanup = true;
                    done = true; 
                    WriteDocumentEnd(xamlEndDocumentNode);
 
                    break; 

                case XamlNodeType.ElementStart: 
                    XamlElementStartNode xamlElementNode =
                        (XamlElementStartNode) xamlNode;
                    WriteElementStart(xamlElementNode);
 
                    break;
 
                case XamlNodeType.ElementEnd: 
                    XamlElementEndNode xamlEndElementNode =
                        (XamlElementEndNode) xamlNode; 

                    WriteElementEnd(xamlEndElementNode);

                    break; 
                case XamlNodeType.UnknownTagStart:
                    XamlUnknownTagStartNode xamlUnknownTagStartNode = 
                        (XamlUnknownTagStartNode) xamlNode; 

                    WriteUnknownTagStart(xamlUnknownTagStartNode); 

                    break;
                case XamlNodeType.UnknownTagEnd:
                    XamlUnknownTagEndNode xamlUnknownTagEndNode = 
                        (XamlUnknownTagEndNode) xamlNode;
 
                    WriteUnknownTagEnd(xamlUnknownTagEndNode); 

                    break; 
                case XamlNodeType.XmlnsProperty:

                    XamlXmlnsPropertyNode xamlXmlnsPropertyNode =
                        (XamlXmlnsPropertyNode) xamlNode; 

                    WriteNamespacePrefix(xamlXmlnsPropertyNode); 
 
                    break;
 
                case XamlNodeType.Property:

                    XamlPropertyNode xamlPropertyNode =
                        (XamlPropertyNode) xamlNode; 
                    if (xamlPropertyNode.AttributeUsage == BamlAttributeUsage.RuntimeName)
                    { 
                        _parserContext.XamlTypeMapper.ValidateNames( 
                                            xamlPropertyNode.Value,
                                            xamlPropertyNode.LineNumber, 
                                            xamlPropertyNode.LinePosition);
                    }

                    WriteProperty(xamlPropertyNode); 
                    break;
 
                case XamlNodeType.PropertyWithExtension: 

                    XamlPropertyWithExtensionNode xamlPropertyWithExtensionNode = 
                        (XamlPropertyWithExtensionNode)xamlNode;
                    WritePropertyWithExtension(xamlPropertyWithExtensionNode);
                    break;
 
                case XamlNodeType.PropertyWithType:
 
                    XamlPropertyWithTypeNode xamlPropertyWithTypeNode = 
                        (XamlPropertyWithTypeNode) xamlNode;
                    WritePropertyWithType(xamlPropertyWithTypeNode); 
                    break;

                case XamlNodeType.UnknownAttribute:
                    XamlUnknownAttributeNode xamlUnknownAttributeNode = 
                        (XamlUnknownAttributeNode) xamlNode;
 
                    WriteUnknownAttribute(xamlUnknownAttributeNode); 

                    break; 

                case XamlNodeType.PropertyComplexStart:
                    XamlPropertyComplexStartNode xamlPropertyComplexStartNode =
                        (XamlPropertyComplexStartNode) xamlNode; 
                    WritePropertyComplexStart(xamlPropertyComplexStartNode);
                    break; 
 
                case XamlNodeType.PropertyComplexEnd:
                    XamlPropertyComplexEndNode xamlPropertyComplexEndNode = 
                        (XamlPropertyComplexEndNode) xamlNode;
                    WritePropertyComplexEnd(xamlPropertyComplexEndNode);
                    break;
 
                case XamlNodeType.LiteralContent:
                    XamlLiteralContentNode xamlLiteralContentNode = 
                        (XamlLiteralContentNode) xamlNode; 
                    WriteLiteralContent(xamlLiteralContentNode);
                    break; 

                case XamlNodeType.Text:
                    XamlTextNode xamlTextNode =
                        (XamlTextNode) xamlNode; 
                    WriteText(xamlTextNode);
                    break; 
 
                case XamlNodeType.ClrEvent:
                    XamlClrEventNode xamlClrEventNode = 
                        (XamlClrEventNode) xamlNode;
                    WriteClrEvent(xamlClrEventNode);
                    break;
 

                case XamlNodeType.PropertyArrayStart: 
                    XamlPropertyArrayStartNode xamlPropertyArrayStartNode = 
                        (XamlPropertyArrayStartNode) xamlNode;
                    WritePropertyArrayStart(xamlPropertyArrayStartNode); 
                    break;

                case XamlNodeType.PropertyArrayEnd:
                    XamlPropertyArrayEndNode xamlPropertyArrayEndNode = 
                        (XamlPropertyArrayEndNode) xamlNode;
                    WritePropertyArrayEnd(xamlPropertyArrayEndNode); 
                    break; 

                case XamlNodeType.PropertyIListStart: 
                    XamlPropertyIListStartNode xamlPropertyIListStartNode =
                        (XamlPropertyIListStartNode) xamlNode;
                    WritePropertyIListStart(xamlPropertyIListStartNode);
                    break; 

                case XamlNodeType.PropertyIListEnd: 
                    XamlPropertyIListEndNode xamlPropertyIListEndNode = 
                        (XamlPropertyIListEndNode) xamlNode;
                    WritePropertyIListEnd(xamlPropertyIListEndNode); 
                    break;

                case XamlNodeType.PropertyIDictionaryStart:
                    XamlPropertyIDictionaryStartNode xamlPropertyIDictionaryStartNode = 
                        (XamlPropertyIDictionaryStartNode) xamlNode;
                    WritePropertyIDictionaryStart(xamlPropertyIDictionaryStartNode); 
                    break; 

                case XamlNodeType.PropertyIDictionaryEnd: 
                    XamlPropertyIDictionaryEndNode xamlPropertyIDictionaryEndNode =
                        (XamlPropertyIDictionaryEndNode) xamlNode;
                    WritePropertyIDictionaryEnd(xamlPropertyIDictionaryEndNode);
                    break; 

                case XamlNodeType.DefTag: 
                    XamlDefTagNode xamlDefTagNode = 
                        (XamlDefTagNode) xamlNode;
                    WriteDefTag(xamlDefTagNode); 

                    break;

                case XamlNodeType.DefKeyTypeAttribute: 
                    XamlDefAttributeKeyTypeNode xamlDefAttributeKeyTypeNode =
                        (XamlDefAttributeKeyTypeNode) xamlNode; 
                    WriteDefAttributeKeyType(xamlDefAttributeKeyTypeNode); 
                    break;
 
                case XamlNodeType.DefAttribute:
                    XamlDefAttributeNode xamlDefAttributeNode =
                        (XamlDefAttributeNode) xamlNode;
 
                    if (xamlDefAttributeNode.AttributeUsage == BamlAttributeUsage.RuntimeName)
                    { 
                        _parserContext.XamlTypeMapper.ValidateNames( 
                                            xamlDefAttributeNode.Value,
                                            xamlDefAttributeNode.LineNumber, 
                                            xamlDefAttributeNode.LinePosition);
                    }

                    WriteDefAttributeCore(xamlDefAttributeNode); 
                    break;
 
                case XamlNodeType.PresentationOptionsAttribute: 
                    XamlPresentationOptionsAttributeNode xamlPresentationOptionsAttributeNode =
                        (XamlPresentationOptionsAttributeNode) xamlNode; 
                    WritePresentationOptionsAttribute(xamlPresentationOptionsAttributeNode);
                    break;

                case XamlNodeType.PIMapping: 
                    XamlPIMappingNode xamlPIMappingNode =
                        (XamlPIMappingNode) xamlNode; 
                    WritePIMapping(xamlPIMappingNode); 
                    break;
 
                // The following tokens that are used primarily by the markup compiler
                case XamlNodeType.EndAttributes:
                    XamlEndAttributesNode xamlEndAttributesNode =
                        (XamlEndAttributesNode) xamlNode; 
                    // if first tag and haven't alredy set the ParseMode
                    // set it to synchronous. 
                    if (0 == xamlEndAttributesNode.Depth) 
                    {
                        if (XamlParseMode == XamlParseMode.Uninitialized) 
                        {
                            XamlParseMode = XamlParseMode.Synchronous;
                        }
                    } 
                    WriteEndAttributes(xamlEndAttributesNode);
                    break; 
 
                case XamlNodeType.KeyElementStart:
                    XamlKeyElementStartNode xamlKeyElementStartNode = 
                        (XamlKeyElementStartNode) xamlNode;
                    WriteKeyElementStart(xamlKeyElementStartNode);
                    break;
 
                case XamlNodeType.KeyElementEnd:
                    XamlKeyElementEndNode xamlKeyElementEndNode = 
                        (XamlKeyElementEndNode) xamlNode; 
                    WriteKeyElementEnd(xamlKeyElementEndNode);
                    break; 

                case XamlNodeType.ConstructorParametersEnd:
                    XamlConstructorParametersEndNode xamlConstructorParametersEndNode =
                        (XamlConstructorParametersEndNode) xamlNode; 
                    WriteConstructorParametersEnd(xamlConstructorParametersEndNode);
                    break; 
 
                case XamlNodeType.ConstructorParametersStart:
                    XamlConstructorParametersStartNode xamlConstructorParametersStartNode = 
                        (XamlConstructorParametersStartNode) xamlNode;
                    WriteConstructorParametersStart(xamlConstructorParametersStartNode);
                    break;
 
                case XamlNodeType.ContentProperty:
                    XamlContentPropertyNode xamlContentPropertyNode = 
                        (XamlContentPropertyNode)xamlNode; 
                    WriteContentProperty(xamlContentPropertyNode);
                    break; 

                case XamlNodeType.ConstructorParameterType:
                    XamlConstructorParameterTypeNode xamlConstructorParameterTypeNode =
                        (XamlConstructorParameterTypeNode)xamlNode; 
                    WriteConstructorParameterType(xamlConstructorParameterTypeNode);
                    break; 
                default: 
                    Debug.Assert(false,"Unknown Xaml Token.");
                    break; 
            }

       }
 
#endregion // PublicMethods
 
    #region Virtuals 

        ///  
        /// Called when parsing begins
        /// 
        public virtual void WriteDocumentStart(XamlDocumentStartNode XamlDocumentStartNode)
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WriteDocumentStart(XamlDocumentStartNode); 
            }
        } 

        /// 
        /// Called when parsing ends
        ///  
        public virtual void WriteDocumentEnd(XamlDocumentEndNode xamlEndDocumentNode)
        { 
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteDocumentEnd(xamlEndDocumentNode); 
            }
        }

        ///  
        /// Write Start of an Element, which is a tag of the form /
        ///  
        public virtual void WriteElementStart(XamlElementStartNode xamlElementStartNode) 
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteElementStart(xamlElementStartNode);
            }
        } 

        ///  
        /// Write start of an unknown tag 
        /// 
        public virtual void WriteUnknownTagStart(XamlUnknownTagStartNode xamlUnknownTagStartNode) 
        {
            // The default action for unknown tags is throw an exception.
            ThrowException(SRID.ParserUnknownTag ,
                        xamlUnknownTagStartNode.Value, 
                        xamlUnknownTagStartNode.XmlNamespace,
                        xamlUnknownTagStartNode.LineNumber, 
                        xamlUnknownTagStartNode.LinePosition); 
        }
 
        /// 
        /// Write end of an unknown tag
        /// 
        public virtual void WriteUnknownTagEnd(XamlUnknownTagEndNode xamlUnknownTagEndNode) 
        {
            // The default action for unknown tags is throw an exception.  This should never 
            // get here unless there is a coding error, since it would first hit 
            // WriteUnknownTagStart
            ThrowException(SRID.ParserUnknownTag , 
                        "???",
                        xamlUnknownTagEndNode.LineNumber,
                        xamlUnknownTagEndNode.LinePosition);
        } 

        ///  
        /// Write End Element 
        /// 
        public virtual void WriteElementEnd(XamlElementEndNode xamlElementEndNode) 
        {
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WriteElementEnd(xamlElementEndNode); 
            }
        } 
 
        /// 
        /// Called when parsing hits literal content. 
        /// 
        public virtual void WriteLiteralContent(XamlLiteralContentNode xamlLiteralContentNode)
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteLiteralContent(xamlLiteralContentNode); 
            } 
        }
 
        /// 
        /// Write Start Complex Property, where the tag is of the
        /// form /
        ///  
        public virtual void WritePropertyComplexStart(
            XamlPropertyComplexStartNode xamlPropertyComplexStartNode) 
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WritePropertyComplexStart(xamlPropertyComplexStartNode);
            }
        }
 

 
        ///  
        /// Write End Complex Property
        ///  
        public virtual void WritePropertyComplexEnd(
            XamlPropertyComplexEndNode xamlPropertyComplexEndNode)
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WritePropertyComplexEnd(xamlPropertyComplexEndNode); 
            } 
        }
 
        /// 
        /// Write Start element for a dictionary key section.
        /// 
        public virtual void WriteKeyElementStart( 
            XamlElementStartNode xamlKeyElementStartNode)
        { 
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteKeyElementStart(xamlKeyElementStartNode); 
            }
        }

        ///  
        /// Write End element for a dictionary key section
        ///  
        public virtual void WriteKeyElementEnd( 
            XamlElementEndNode xamlKeyElementEndNode)
        { 
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WriteKeyElementEnd(xamlKeyElementEndNode);
            } 
        }
 
        ///  
        /// Write unknown attribute
        ///  
        public virtual void WriteUnknownAttribute(XamlUnknownAttributeNode xamlUnknownAttributeNode)
        {
            // The default action for unknown attributes is throw an exception.
            ThrowException(SRID.ParserUnknownAttribute , 
                        xamlUnknownAttributeNode.Name,
                        xamlUnknownAttributeNode.XmlNamespace, 
                        xamlUnknownAttributeNode.LineNumber, 
                        xamlUnknownAttributeNode.LinePosition);
        } 

        /// 
        /// Write a Property, which has the form in markup of property="value".
        ///  
        /// 
        /// Note that for DependencyProperties, the assemblyName, TypeFullName, PropIdName 
        /// refer to DependencyProperty field 
        /// that the property was found on. This may be different from the ownerType
        /// of the propId if the property was registered as an alias so if the 
        /// callback is persisting we want to persist the information that the propId
        /// was found on in case the alias is a private or internal field.
        /// 
        public virtual void WriteProperty(XamlPropertyNode xamlPropertyNode) 
        {
            if (BamlRecordWriter != null) 
            { 
                BamlRecordWriter.WriteProperty(xamlPropertyNode);
            } 
        }

        internal void WriteBaseProperty(XamlPropertyNode xamlPropertyNode)
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.BaseWriteProperty(xamlPropertyNode); 
            }
        } 

        /// 
        /// Write a Property, which has the form in markup of property="value".
        ///  
        /// 
        /// Note that for DependencyProperties, the assemblyName, TypeFullName, PropIdName 
        /// refer to DependencyProperty field 
        /// that the property was found on. This may be different from the ownerType
        /// of the propId if the property was registered as an alias so if the 
        /// callback is persisting we want to persist the information that the propId
        /// was found on in case the alias is a private or internal field.
        /// 
        public virtual void WritePropertyWithType(XamlPropertyWithTypeNode xamlPropertyNode) 
        {
            if (BamlRecordWriter != null) 
            { 
                if (xamlPropertyNode.ValueElementType == null)
                { 
                    ThrowException(SRID.ParserNoType,
                                   xamlPropertyNode.ValueTypeFullName,
                                   xamlPropertyNode.LineNumber,
                                   xamlPropertyNode.LinePosition); 
                }
 
                BamlRecordWriter.WritePropertyWithType(xamlPropertyNode); 
            }
        } 

        public virtual void WritePropertyWithExtension(XamlPropertyWithExtensionNode xamlPropertyWithExtensionNode)
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WritePropertyWithExtension(xamlPropertyWithExtensionNode); 
            } 
        }
 

        /// 
        /// Write out Text, currently don't keep track if originally CData or Text
        ///  
        public virtual void WriteText(XamlTextNode xamlTextNode)
        { 
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteText(xamlTextNode); 
            }
        }

 
        /// 
        /// Write a new namespacePrefix to NamespaceURI map 
        ///  
        public virtual void WriteNamespacePrefix(XamlXmlnsPropertyNode xamlXmlnsPropertyNode)
        { 
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WriteNamespacePrefix(xamlXmlnsPropertyNode);
            } 
        }
 
 
        /// 
        /// Xml - Clr namespace mapping 
        /// 
        public virtual void WritePIMapping(XamlPIMappingNode xamlPIMappingNode)
        {
            // The only case when the assembly name can be empty is when there is a local assembly 
            // specified in the Mapping PI, but the compiler extension should have resolved it by
            // now. So if we are still seeing an empty string here that means we in the pure xaml 
            // parsing scenario and should throw. 
            if (xamlPIMappingNode.AssemblyName.Length == 0)
            { 
                ThrowException(SRID.ParserMapPIMissingKey, xamlPIMappingNode.LineNumber, xamlPIMappingNode.LinePosition);
            }

            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WritePIMapping(xamlPIMappingNode); 
            } 
        }
 
        /// 
        /// Write out the Clr event.
        /// 
        public virtual void WriteClrEvent(XamlClrEventNode xamlClrEventNode) 
        {
            // Parser currently doesn't support hooking up Events directly from 
            // XAML so throw an exception. In the compile case this method 
            // is overriden.
 
            if (null == ParserHooks)
            {
                ThrowException(SRID.ParserNoEvents,
                    xamlClrEventNode.LineNumber, 
                    xamlClrEventNode.LinePosition);
            } 
            else if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteClrEvent(xamlClrEventNode); 
            }
        }

        ///  
        /// Write Property Array Start
        ///  
        public virtual void WritePropertyArrayStart(XamlPropertyArrayStartNode xamlPropertyArrayStartNode) 
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WritePropertyArrayStart(xamlPropertyArrayStartNode);
            }
        } 

 
        ///  
        /// Write Property Array End
        ///  
        public virtual void WritePropertyArrayEnd(XamlPropertyArrayEndNode xamlPropertyArrayEndNode)
        {
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WritePropertyArrayEnd(xamlPropertyArrayEndNode);
            } 
        } 

 
        /// 
        /// Write Property IList Start
        /// 
        public virtual void WritePropertyIListStart(XamlPropertyIListStartNode xamlPropertyIListStartNode) 
        {
            if (BamlRecordWriter != null) 
            { 
                BamlRecordWriter.WritePropertyIListStart(xamlPropertyIListStartNode);
            } 
        }


        ///  
        /// Write Property IList End
        ///  
        public virtual void WritePropertyIListEnd(XamlPropertyIListEndNode xamlPropertyIListEndNode) 
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WritePropertyIListEnd(xamlPropertyIListEndNode);
            }
        } 

        ///  
        /// Write Property IDictionary Start 
        /// 
        public virtual void WritePropertyIDictionaryStart(XamlPropertyIDictionaryStartNode xamlPropertyIDictionaryStartNode) 
        {
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WritePropertyIDictionaryStart(xamlPropertyIDictionaryStartNode); 
            }
        } 
 

        ///  
        /// Write Property IDictionary End
        /// 
        public virtual void WritePropertyIDictionaryEnd(XamlPropertyIDictionaryEndNode xamlPropertyIDictionaryEndNode)
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WritePropertyIDictionaryEnd(xamlPropertyIDictionaryEndNode); 
            }
        } 


        /// 
        /// WriteEndAttributes occurs after the last attribute (property, complex property or 
        /// def record) is written.  Note that if there are none of the above, then WriteEndAttributes
        /// is not called for a normal start tag. 
        ///  
        public virtual void WriteEndAttributes(XamlEndAttributesNode xamlEndAttributesNode)
        { 
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WriteEndAttributes(xamlEndAttributesNode);
            } 
        }
 
        ///  
        /// WriteDefTag occurs when a x:Whatever tag is encountered.
        /// Superclasses must interprete this since the base class doesn't understand 
        /// any of them.
        /// 
        public virtual void WriteDefTag(XamlDefTagNode xamlDefTagNode)
        { 
            ThrowException(SRID.ParserDefTag,
                        xamlDefTagNode.Value, 
                        xamlDefTagNode.LineNumber, 
                        xamlDefTagNode.LinePosition);
        } 

        /// 
        /// Write out a key to a dictionary that has been resolved at compile or parse
        /// time to a Type object. 
        /// 
        public virtual void WriteDefAttributeKeyType(XamlDefAttributeKeyTypeNode xamlDefNode) 
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WriteDefAttributeKeyType(xamlDefNode);
            }
        }
 
        /// 
        /// WriteDefAttribute when attributes of the form x:Whatever are encountered 
        ///  
        public virtual void WriteDefAttribute(XamlDefAttributeNode xamlDefAttributeNode)
        { 
            string attributeValue = xamlDefAttributeNode.Value;

            // There are several known def attributes, and these are checked for
            // correctness by running the known type converters. 
            switch(xamlDefAttributeNode.Name)
            { 
               case XamlReaderHelper.DefinitionSynchronousMode: 
                   if (BamlRecordWriter != null)
                   { 
                       if (xamlDefAttributeNode.Value == "Async")
                       {
                           ThrowException(SRID.ParserNoBamlAsync, "Async",
                                      xamlDefAttributeNode.LineNumber, 
                                      xamlDefAttributeNode.LinePosition);
                       } 
                   } 
                   break;
 
               case XamlReaderHelper.DefinitionAsyncRecords:
                    // Update the AsyncRecords and don't store this as a def attribute
                       ThrowException(SRID.ParserNoBamlAsync, xamlDefAttributeNode.Name,
                                      xamlDefAttributeNode.LineNumber, 
                                      xamlDefAttributeNode.LinePosition);
                   break; 
 
                case XamlReaderHelper.DefinitionShared:
                    Boolean.Parse(attributeValue);   // For validation only. 
                    if (BamlRecordWriter != null)
                    {
                        BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode);
                    } 
                    break;
 
                case XamlReaderHelper.DefinitionUid: 
                case XamlReaderHelper.DefinitionRuntimeName:
                    //Error if x:Uid or x:Name are markup extensions 
                    if (MarkupExtensionParser.LooksLikeAMarkupExtension(attributeValue))
                    {
                        string message = SR.Get(SRID.ParserBadUidOrNameME, attributeValue);
                        message += " "; 
                        message += SR.Get(SRID.ParserLineAndOffset,
                                    xamlDefAttributeNode.LineNumber.ToString(CultureInfo.CurrentCulture), 
                                    xamlDefAttributeNode.LinePosition.ToString(CultureInfo.CurrentCulture)); 

                        XamlParseException parseException = new XamlParseException(message, 
                                xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition);

                        throw parseException;
                    } 

                    if (BamlRecordWriter != null) 
                    { 
                        BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode);
                    } 
                    break;

                case XamlReaderHelper.DefinitionName:
                    if (BamlRecordWriter != null) 
                    {
                        BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); 
                    } 
                    break;
 
                default:
                    string errorID;
                        errorID = SRID.ParserUnknownDefAttribute;
                        ThrowException(errorID, 
                                   xamlDefAttributeNode.Name,
                                   xamlDefAttributeNode.LineNumber, 
                                   xamlDefAttributeNode.LinePosition); 
                    break;
            } 
        }

        /// 
        /// Write attributes of the form PresentationOptions:Whatever to Baml 
        /// 
        public virtual void WritePresentationOptionsAttribute(XamlPresentationOptionsAttributeNode xamlPresentationOptionsAttributeNode) 
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WritePresentationOptionsAttribute(xamlPresentationOptionsAttributeNode);
            }
        }
 
        /// 
        /// Write the start of a constructor parameter section 
        ///  
        public virtual void WriteConstructorParametersStart(XamlConstructorParametersStartNode xamlConstructorParametersStartNode)
        { 
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WriteConstructorParametersStart(xamlConstructorParametersStartNode);
            } 
        }
 
        public virtual void WriteContentProperty(XamlContentPropertyNode xamlContentPropertyNode) 
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteContentProperty(xamlContentPropertyNode);
            }
        } 

        ///  
        /// Write the constructor parameter record where the parameter is a compile time 
        /// resolved Type object.
        ///  
        public virtual void WriteConstructorParameterType(
             XamlConstructorParameterTypeNode xamlConstructorParameterTypeNode)
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteConstructorParameterType(xamlConstructorParameterTypeNode); 
            } 
        }
 
        /// 
        /// Write the end of a constructor parameter section
        /// 
        public virtual void WriteConstructorParametersEnd(XamlConstructorParametersEndNode xamlConstructorParametersEndNode) 
        {
            if (BamlRecordWriter != null) 
            { 
                BamlRecordWriter.WriteConstructorParametersEnd(xamlConstructorParametersEndNode);
            } 
        }

        /// 
        /// Can be used by ac to return the type of the element if a class attribute is 
        /// present. If want to override default Type because of class= attribute can do so here.
        /// Should leave the XmlReader positioned at the Element so if read attributes 
        /// to determine type need to call XmlReader.MoveToElement() 
        /// 
        public virtual bool GetElementType( 
                XmlReader  reader,
                string     localName,
                string     namespaceUri,
            ref string     assemblyName, 
            ref string     typeFullName,
            ref Type       baseType, 
            ref Type       serializerType) 
        {
            bool result = false; 

            assemblyName   = string.Empty;
            typeFullName   = string.Empty;
            serializerType = null; 
            baseType       = null;
 
            // if no namespaceURI or local name don't bother 
            if (null == namespaceUri || null == localName)
            { 
                return false;
            }

            TypeAndSerializer typeAndSerializer = 
                XamlTypeMapper.GetTypeAndSerializer(namespaceUri, localName, null);
 
            if (typeAndSerializer != null && 
                typeAndSerializer.ObjectType != null)
            { 
                serializerType = typeAndSerializer.SerializerType;
                baseType = typeAndSerializer.ObjectType;
                typeFullName = baseType.FullName;
                assemblyName = baseType.Assembly.FullName; 
                result = true;
 
                Debug.Assert(null != assemblyName, "assembly name returned from GetBaseElement is null"); 
                Debug.Assert(null != typeFullName, "Type name returned from GetBaseElement is null");
            } 

            return result;
        }
 

#endregion Virtuals 
 

        ///  
        /// Write a Connector Id for compiler.
        /// 
        protected internal void WriteConnectionId(Int32 connectionId)
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WriteConnectionId(connectionId); 
            }
        } 

        /// 
        /// A def attribute was encountered.  Perform synchonous mode checking
        /// prior to calling the virtual that may be overridden. 
        /// 
        void WriteDefAttributeCore(XamlDefAttributeNode xamlDefAttributeNode) 
        { 

            string attributeValue = xamlDefAttributeNode.Value; 

            switch(xamlDefAttributeNode.Name)
            {
                case  XamlReaderHelper.DefinitionSynchronousMode: 
                    XamlParseMode documentParseMode = XamlParseMode.Synchronous;
 
                    if (attributeValue.Equals("Async")) 
                    {
                        documentParseMode = XamlParseMode.Asynchronous; 
                    }
                    else if (attributeValue.Equals("[....]"))
                    {
                        documentParseMode = XamlParseMode.Synchronous; 
                    }
                    else 
                    { 
                        ThrowException(SRID.ParserBadSyncMode,
                               xamlDefAttributeNode.LineNumber, 
                               xamlDefAttributeNode.LinePosition );
                    }

                    // if we haven't initialized the the parseMode yet set it 
                    if (XamlParseMode == XamlParseMode.Uninitialized)
                    { 
                        // todo: for now hardcode the string. when finalized 
                        // should add a TypeConverter.
                        XamlParseMode = documentParseMode; 

                    }
                    break;
                default: 
                    break;
            } 
 
            WriteDefAttribute(xamlDefAttributeNode);
        } 

    #region Methods

        // virtuals to override the default implementation. used by the compiler 
        // for internal virtuals review why not public as the others?
 
        // Used when an exception is thrown.The default action is to shutdown the parser 
        // and throw the exception.
        internal virtual void ParseError(XamlParseException e) 
        {
        }

        ///  
        /// Called when the parse was cancelled by the user.
        ///  
        internal virtual void  ParseCancelled() 
        {
        } 

        /// 
        ///  called when the parse has been completed successfully.
        ///  
        internal virtual void ParseCompleted()
        { 
        } 

 

        /// 
        ///  Default parsing is to synchronously read all the xaml nodes
        ///  until done. 
        /// 
        internal virtual void _Parse() 
        { 

            ReadXaml(false /* want to parse the entire thing */); 

        }

 
        /// 
        /// If there are ParserHooks, call it with the current xamlNode and perform 
        /// as directed by the callback. 
        /// 
        private void SetParserAction(XamlNode xamlNode) 
        {
            // if no ParserHooks then process as normal
            if (null == ParserHooks)
            { 
                ParserAction = ParserAction.Normal;
                return; 
            } 

            // if ParserHooks want to skip the current node and its children, 
            // check for end of scope where it asked to be skipped.
            if (ParserAction == ParserAction.Skip)
            {
                if (xamlNode.Depth <= SkipActionDepthCount && 
                    xamlNode.TokenType == SkipActionToken)
                { 
                    // We found the end token at the correct depth.  Reset the depth count 
                    // so that in the next call we won't skip calling the ParserHooks.  Don't
                    // reset the ParserAction since we want to skip this end token. 
                    SkipActionDepthCount = -1;
                    SkipActionToken = XamlNodeType.Unknown;
                    return;
                } 
                else if (SkipActionDepthCount >= 0)
                { 
                    return; 
                }
            } 

            // If we get to here, the ParserHooks want to be called.
            ParserAction = ParserHooks.LoadNode(xamlNode);
 
            // if the ParserHooks want to skip the current node and its children then
            // set the callback depth so that we'll know when to start processing again. 
            if (ParserAction == ParserAction.Skip) 
            {
                // For tokens with no scope (eg = attributes), don't set the depth so 
                // that we will only skip once
                Debug.Assert(SkipActionDepthCount == -1);
                int tokenIndex = ((IList)XamlNode.ScopeStartTokens).IndexOf(xamlNode.TokenType);
                if (tokenIndex != -1) 
                {
                    SkipActionDepthCount = xamlNode.Depth; 
                    SkipActionToken = XamlNode.ScopeEndTokens[tokenIndex]; 
                }
            } 
        }


 
        // Return true if the passed namespace is known, meaning that it maps
        // to a set of assemblies and clr namespaces 
        internal bool IsXmlNamespaceSupported(string xmlNamespace, out string newXmlNamespace) 
        {
            newXmlNamespace = null; 

            if (xmlNamespace.StartsWith(XamlReaderHelper.MappingProtocol, StringComparison.Ordinal))
            {
                return true; 
            }
            else if (xmlNamespace == XamlReaderHelper.PresentationOptionsNamespaceURI) 
            { 
                // PresentationOptions is expected to be marked as 'ignorable' in most Xaml
                // so that other Xaml parsers don't have to interpret it, but this parser 
                // does handle it to support it's Freeze attribute.
                return true;
            }
            else 
            {
                return XamlTypeMapper.IsXmlNamespaceKnown(xmlNamespace, out newXmlNamespace) || 
                    TokenReader.IsXmlDataIsland(); 
            }
        } 
#endregion Methods

    #region Properties
 
        /// 
        /// TokenReader that is being used. 
        ///  
        internal XamlReaderHelper TokenReader
        { 
            get { return _xamlTokenReader; }
            set { _xamlTokenReader = value; }
        }
 
        /// 
        ///  ParserHooks implementation that any parse time callbacks 
        ///  should be called on. 
        /// 
        internal  ParserHooks ParserHooks 
        {
            get { return _parserHooks; }
            set { _parserHooks = value; }
        } 

        // Set the depth count for how deep we are within 
        // a ParserAction.Skip reference. 
        int SkipActionDepthCount
        { 
            get { return _skipActionDepthCount; }
            set {  _skipActionDepthCount = value; }
        }
 
        // Set and get the token to watch for when skipping a
        // section of a xaml file 
        XamlNodeType SkipActionToken 
        {
            get { return _skipActionToken; } 
            set {  _skipActionToken = value; }
        }

        // set the operation mode of the parser as determined 
        // by attached ParserHooks
        ParserAction ParserAction 
        { 
            get { return _parserAction; }
            set {  _parserAction = value; } 
        }

        /// 
        /// Instance of the XamlTypeMapper 
        /// 
        internal XamlTypeMapper XamlTypeMapper 
        { 
            get { return _parserContext.XamlTypeMapper; }
        } 

        /// 
        /// Instance of the BamlMapTable
        ///  
        internal BamlMapTable MapTable
        { 
            get { return _parserContext.MapTable; } 
        }
 
        /// 
        /// BamlRecordWriter being used by the Parser
        /// 
        public BamlRecordWriter BamlRecordWriter 
        {
            get { return _bamlWriter; } 
            set 
            {
                Debug.Assert(null == _bamlWriter || null == value, "XamlParser already had a bamlWriter"); 
                _bamlWriter = value;
            }
        }
 
        /// 
        ///  ParseMode the Parser is in. 
        ///  
        internal XamlParseMode XamlParseMode
        { 
            get { return _xamlParseMode; }
            set { _xamlParseMode = value; }
        }
 
        /// 
        ///  Parser context 
        ///  
        internal ParserContext ParserContext
        { 
            get { return _parserContext; }
            set { _parserContext = value; }
        }
 
        internal virtual bool CanResolveLocalAssemblies()
        { 
            return false; 
        }
 
        // Used to determine if strict or loose parsing rules should be enforced.  The TokenReader
        // does some validations that are difficult for the XamlParser to do and in strict parsing
        // mode the TokenReader should throw exceptions of standard Xaml rules are violated.
        internal virtual bool StrictParsing 
        {
            get { return true; } 
        } 

 
#endregion Properties

    #region Data
 

 
 
        // private Data
 
        XamlReaderHelper             _xamlTokenReader;

        ParserContext                _parserContext; // todo, need this for the XamlTypeMapper/resolver.
 
        XamlParseMode                _xamlParseMode;
        BamlRecordWriter             _bamlWriter; 
 
        // ParserHooks related
        ParserHooks                  _parserHooks; 
        ParserAction                 _parserAction = ParserAction.Normal;
        int                          _skipActionDepthCount = -1; // skip mode depth count.
        XamlNodeType                 _skipActionToken = XamlNodeType.Unknown;
 
        static private string []     _predefinedNamespaces = new string [3] {
            XamlReaderHelper.DefinitionNamespaceURI, 
            XamlReaderHelper.DefaultNamespaceURI, 
            XamlReaderHelper.DefinitionMetroNamespaceURI
        }; 
    #endregion Data

#endif
 
        // helper method called to throw an exception.
        // todo: update exception with lineNumbers from Node. 
        internal static void ThrowException(string id, int lineNumber, int linePosition) 
        {
            string message = SR.Get(id); 
            ThrowExceptionWithLine(message, lineNumber, linePosition);
        }

        // helper method called to throw an exception. 
        internal static void ThrowException(string id, string value, int lineNumber, int linePosition)
        { 
            string message = SR.Get(id, value); 
            ThrowExceptionWithLine(message, lineNumber, linePosition);
        } 

        // helper method called to throw an exception.
        internal static void ThrowException(string id, string value1, string value2, int lineNumber, int linePosition)
        { 
            string message = SR.Get(id, value1, value2);
            ThrowExceptionWithLine(message, lineNumber, linePosition); 
        } 

        internal static void ThrowException(string id, string value1, string value2, string value3, int lineNumber, int linePosition) 
        {
            string message = SR.Get(id, value1, value2, value3);
            ThrowExceptionWithLine(message, lineNumber, linePosition);
        } 

        internal static void ThrowException(string id, string value1, string value2, string value3, string value4, int lineNumber, int linePosition) 
        { 
            string message = SR.Get(id, value1, value2, value3, value4);
            ThrowExceptionWithLine(message, lineNumber, linePosition); 
        }

        private static void ThrowExceptionWithLine(string message, int lineNumber, int linePosition)
        { 
            message += " ";
            message += SR.Get(SRID.ParserLineAndOffset, 
                                    lineNumber.ToString(CultureInfo.CurrentCulture), 
                                    linePosition.ToString(CultureInfo.CurrentCulture));
 
            XamlParseException parseException = new XamlParseException(message,
                lineNumber, linePosition);

 
            throw parseException;
        } 
 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
/****************************************************************************\ 
*
* File: XamlParser.cs
*
* Purpose:  Class for compiling Xaml. 
*
* History: 
*    6/06/01:    rogerg        Created 
*    5/28/03:    peterost      Ported to wcp
*    10/6/03:    peterost      Reorganized to remove DP - clr distinction 
*
* Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
*
\***************************************************************************/ 

 
using System; 
using System.Xml;
using System.IO; 
using System.Text;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics; 
using System.Reflection;
using System.Globalization; 
using System.Security.Permissions; 
using MS.Utility;
using System.Runtime.InteropServices; 
using MS.Internal;

// Disabling 1634 and 1691:
// In order to avoid generating warnings about unknown message numbers and 
// unknown pragmas when compiling C# source code with the C# compiler,
// you need to disable warnings 1634 and 1691. (Presharp Documentation) 
#pragma warning disable 1634, 1691 

#if PBTCOMPILER 
namespace MS.Internal.Markup
#else

using System.Windows; 

namespace System.Windows.Markup 
#endif 
{
 
    #region enums

    /// 
    /// Parser modes. indicates if the Xaml should be parsed [....] or async. 
    /// currently public so test can set these values.
    ///  
    internal enum XamlParseMode 
    {
        ///  
        /// Not initialized
        /// 
        Uninitialized,
 
        /// 
        /// [....] 
        ///  
        Synchronous,
 
        /// 
        /// Async
        /// 
        Asynchronous, 
    }
 
    #endregion enums 

    ///  
    /// XamlParser class. This class is used internally
    /// 
    internal class XamlParser
    { 
#if PBTCOMPILER
    #region Constructors 
 
        /// 
        /// Constructor that takes a stream and creates an XmlCompatibilityReader on it. 
        /// 
        public XamlParser(
            ParserContext parserContext,
            BamlRecordWriter bamlWriter, 
            Stream xamlStream,
            bool multipleRoots) : this(parserContext, bamlWriter, 
                                        new XmlTextReader(xamlStream, 
                                        multipleRoots ? XmlNodeType.Element : XmlNodeType.Document,
                                        (XmlParserContext)parserContext)                             ) 
        {
        }

        protected XamlParser( 
            ParserContext parserContext,
            BamlRecordWriter bamlWriter, 
            XmlTextReader textReader) : this(parserContext, bamlWriter) 
        {
 
            // When the XML 1.0 specification was authored, security was not a top concern, and as a result DTDs have the
            // unfortunate capability of severe Denial of Service (DoS) attacks, typically through the use of an internal
            // entity expansion technique. In System.Xml V2.0, in order to provide protection against DTD DoS attacks there
            // is the capability of turning off DTD parsing through the use of the ProhibitDtd property. 

            textReader.ProhibitDtd = true; 
 
            XmlCompatibilityReader xcr = new XmlCompatibilityReader(textReader,
                                                                    new IsXmlNamespaceSupportedCallback(IsXmlNamespaceSupported), 
                                                                    _predefinedNamespaces );

            TokenReader = new XamlReaderHelper(this,parserContext,xcr);
        } 

        protected XamlParser( 
            ParserContext parserContext, 
            BamlRecordWriter bamlWriter)
        { 
            _parserContext = parserContext;
            _bamlWriter = bamlWriter;
        }
 

        // Default constructor to aid in subclassing 
        protected XamlParser() 
        {
        } 

#endregion Constructors

    #region PublicMethods 

 
        ///  
        /// Main method to Parse the XAML.
        /// When in synchronous mode the entire file is parsed before 
        /// this method returns.
        /// In asynchronous mode at least the root tag is parsed. This
        /// is necessary for the way binders currently work.
        ///  
        public void Parse()
        { 
            // if parseMode hasn't been set then set it now to synchronous. 
            if (XamlParseMode == XamlParseMode.Uninitialized)
            { 
                XamlParseMode = XamlParseMode.Synchronous;
            }

            _Parse(); 
        }
 
 

        ///  
        /// Main function called by the XamlCompiler on a Compile.
        /// If singleRecordMode is true the Read returns after each item read.
        /// 
        /// True if more nodes to read 

        // !! Review - now that have separate out into XamlReaderHelper 
        // review if still need all the virtuals or the caller of the TokenReader 
        // can dispatch as they feel appropriate.
        public bool ReadXaml(bool singleRecordMode) 
        {
            XamlNode xamlNode = null;
            bool     cleanup = !singleRecordMode;
            bool     done = false; 

            try // What do we do with Exceptions we catch on this thread?. 
            { 

                while (TokenReader.Read(ref xamlNode)) 
                {
                    SetParserAction(xamlNode);

                    if (ParserAction == ParserAction.Normal) 
                    {
                        // If processing of the xaml node determines that we are done, 
                        // then stop now.  This can happen if ProcessXamlNode is 
                        // overridden (such as when processing styles) and the parsed
                        // block is finished, but the overall file is not.  In that 
                        // case exit this parser, but leave everything intact.
                        ProcessXamlNode(xamlNode, ref cleanup, ref done);

                        if (done) 
                        {
                            break; 
                        } 

                        // return here in single record mode since we don't want 
                        // to set the parser loop to Done.
                        if (singleRecordMode)
                        {
                            return true; 
                        }
 
                    } 
                }
 
            }
            catch (Exception e)
            {
                if (CriticalExceptions.IsCriticalException(e)) 
                {
                   throw; 
                } 
                else
                { 
                    if (e is XamlParseException)
                    {
                        throw;
                    } 
                    // If the exception was a XamlParse exception on the other
                    // side of a Reflection Invoke, then just pull up the Parse exception. 
                    if (e is TargetInvocationException &&  e.InnerException is XamlParseException) 
                    {
                        throw e.InnerException; 
                    }

                    int lineNumber = 0;
                    int linePosition = 0; 
                    string newMessage = null;
 
                    if (e is XmlException) 
                    {
                        XmlException xmlEx = (XmlException)e; 
                        lineNumber = xmlEx.LineNumber;
                        linePosition = xmlEx.LinePosition;
                        newMessage = xmlEx.Message;
                    } 
                    else
                    { 
                        // generic exception, If have a xamlNode then use the 
                        // nodes values for the line Numbers.
                        if (null != xamlNode) 
                        {
                            lineNumber = xamlNode.LineNumber;
                            linePosition = xamlNode.LinePosition;
                        } 
                        newMessage = e.Message + " " + SR.Get(SRID.ParserLineAndOffset,
                                                  lineNumber.ToString(CultureInfo.CurrentCulture), 
                                                  linePosition.ToString(CultureInfo.CurrentCulture)); 
                    }
                    XamlParseException parseException = new XamlParseException(newMessage, lineNumber, linePosition, e); 
                    ParseError(parseException);

                    // Recurse on error
                    cleanup = true; 
                    throw parseException;
                } 
            } 
            finally
            { 
                // Perform cleanup only if we encountered a non-recoverable error, or
                // we're finished reading the stream (EndDocument reached in single
                // record mode, or end of stream reached in multi-record mode)
                if (cleanup) 
                {
                    // Close the reader, which will close the underlying stream. 
                    TokenReader.Close(); 
                }
            } 

            return false;
        }
 
       /// 
       /// Big switch to handle all the records. 
       ///  
       ///  Node received from TokenReader to process
       ///  True if end of stream reached and document is 
       ///                        totally finished and should be closed 
       ///  True if done processing and want to exit.  Doesn't
       ///                     necessarily mean document is finished (see cleanup) 
       internal virtual void ProcessXamlNode( 
               XamlNode xamlNode,
           ref bool     cleanup, 
           ref bool     done) 
       {
            switch(xamlNode.TokenType) 
            {
                case XamlNodeType.DocumentStart:
                    XamlDocumentStartNode xamlDocumentStartNode =
                        (XamlDocumentStartNode) xamlNode; 

                    WriteDocumentStart(xamlDocumentStartNode); 
 
                    break;
                case XamlNodeType.DocumentEnd: 
                    XamlDocumentEndNode xamlEndDocumentNode =
                        (XamlDocumentEndNode) xamlNode;
                    cleanup = true;
                    done = true; 
                    WriteDocumentEnd(xamlEndDocumentNode);
 
                    break; 

                case XamlNodeType.ElementStart: 
                    XamlElementStartNode xamlElementNode =
                        (XamlElementStartNode) xamlNode;
                    WriteElementStart(xamlElementNode);
 
                    break;
 
                case XamlNodeType.ElementEnd: 
                    XamlElementEndNode xamlEndElementNode =
                        (XamlElementEndNode) xamlNode; 

                    WriteElementEnd(xamlEndElementNode);

                    break; 
                case XamlNodeType.UnknownTagStart:
                    XamlUnknownTagStartNode xamlUnknownTagStartNode = 
                        (XamlUnknownTagStartNode) xamlNode; 

                    WriteUnknownTagStart(xamlUnknownTagStartNode); 

                    break;
                case XamlNodeType.UnknownTagEnd:
                    XamlUnknownTagEndNode xamlUnknownTagEndNode = 
                        (XamlUnknownTagEndNode) xamlNode;
 
                    WriteUnknownTagEnd(xamlUnknownTagEndNode); 

                    break; 
                case XamlNodeType.XmlnsProperty:

                    XamlXmlnsPropertyNode xamlXmlnsPropertyNode =
                        (XamlXmlnsPropertyNode) xamlNode; 

                    WriteNamespacePrefix(xamlXmlnsPropertyNode); 
 
                    break;
 
                case XamlNodeType.Property:

                    XamlPropertyNode xamlPropertyNode =
                        (XamlPropertyNode) xamlNode; 
                    if (xamlPropertyNode.AttributeUsage == BamlAttributeUsage.RuntimeName)
                    { 
                        _parserContext.XamlTypeMapper.ValidateNames( 
                                            xamlPropertyNode.Value,
                                            xamlPropertyNode.LineNumber, 
                                            xamlPropertyNode.LinePosition);
                    }

                    WriteProperty(xamlPropertyNode); 
                    break;
 
                case XamlNodeType.PropertyWithExtension: 

                    XamlPropertyWithExtensionNode xamlPropertyWithExtensionNode = 
                        (XamlPropertyWithExtensionNode)xamlNode;
                    WritePropertyWithExtension(xamlPropertyWithExtensionNode);
                    break;
 
                case XamlNodeType.PropertyWithType:
 
                    XamlPropertyWithTypeNode xamlPropertyWithTypeNode = 
                        (XamlPropertyWithTypeNode) xamlNode;
                    WritePropertyWithType(xamlPropertyWithTypeNode); 
                    break;

                case XamlNodeType.UnknownAttribute:
                    XamlUnknownAttributeNode xamlUnknownAttributeNode = 
                        (XamlUnknownAttributeNode) xamlNode;
 
                    WriteUnknownAttribute(xamlUnknownAttributeNode); 

                    break; 

                case XamlNodeType.PropertyComplexStart:
                    XamlPropertyComplexStartNode xamlPropertyComplexStartNode =
                        (XamlPropertyComplexStartNode) xamlNode; 
                    WritePropertyComplexStart(xamlPropertyComplexStartNode);
                    break; 
 
                case XamlNodeType.PropertyComplexEnd:
                    XamlPropertyComplexEndNode xamlPropertyComplexEndNode = 
                        (XamlPropertyComplexEndNode) xamlNode;
                    WritePropertyComplexEnd(xamlPropertyComplexEndNode);
                    break;
 
                case XamlNodeType.LiteralContent:
                    XamlLiteralContentNode xamlLiteralContentNode = 
                        (XamlLiteralContentNode) xamlNode; 
                    WriteLiteralContent(xamlLiteralContentNode);
                    break; 

                case XamlNodeType.Text:
                    XamlTextNode xamlTextNode =
                        (XamlTextNode) xamlNode; 
                    WriteText(xamlTextNode);
                    break; 
 
                case XamlNodeType.ClrEvent:
                    XamlClrEventNode xamlClrEventNode = 
                        (XamlClrEventNode) xamlNode;
                    WriteClrEvent(xamlClrEventNode);
                    break;
 

                case XamlNodeType.PropertyArrayStart: 
                    XamlPropertyArrayStartNode xamlPropertyArrayStartNode = 
                        (XamlPropertyArrayStartNode) xamlNode;
                    WritePropertyArrayStart(xamlPropertyArrayStartNode); 
                    break;

                case XamlNodeType.PropertyArrayEnd:
                    XamlPropertyArrayEndNode xamlPropertyArrayEndNode = 
                        (XamlPropertyArrayEndNode) xamlNode;
                    WritePropertyArrayEnd(xamlPropertyArrayEndNode); 
                    break; 

                case XamlNodeType.PropertyIListStart: 
                    XamlPropertyIListStartNode xamlPropertyIListStartNode =
                        (XamlPropertyIListStartNode) xamlNode;
                    WritePropertyIListStart(xamlPropertyIListStartNode);
                    break; 

                case XamlNodeType.PropertyIListEnd: 
                    XamlPropertyIListEndNode xamlPropertyIListEndNode = 
                        (XamlPropertyIListEndNode) xamlNode;
                    WritePropertyIListEnd(xamlPropertyIListEndNode); 
                    break;

                case XamlNodeType.PropertyIDictionaryStart:
                    XamlPropertyIDictionaryStartNode xamlPropertyIDictionaryStartNode = 
                        (XamlPropertyIDictionaryStartNode) xamlNode;
                    WritePropertyIDictionaryStart(xamlPropertyIDictionaryStartNode); 
                    break; 

                case XamlNodeType.PropertyIDictionaryEnd: 
                    XamlPropertyIDictionaryEndNode xamlPropertyIDictionaryEndNode =
                        (XamlPropertyIDictionaryEndNode) xamlNode;
                    WritePropertyIDictionaryEnd(xamlPropertyIDictionaryEndNode);
                    break; 

                case XamlNodeType.DefTag: 
                    XamlDefTagNode xamlDefTagNode = 
                        (XamlDefTagNode) xamlNode;
                    WriteDefTag(xamlDefTagNode); 

                    break;

                case XamlNodeType.DefKeyTypeAttribute: 
                    XamlDefAttributeKeyTypeNode xamlDefAttributeKeyTypeNode =
                        (XamlDefAttributeKeyTypeNode) xamlNode; 
                    WriteDefAttributeKeyType(xamlDefAttributeKeyTypeNode); 
                    break;
 
                case XamlNodeType.DefAttribute:
                    XamlDefAttributeNode xamlDefAttributeNode =
                        (XamlDefAttributeNode) xamlNode;
 
                    if (xamlDefAttributeNode.AttributeUsage == BamlAttributeUsage.RuntimeName)
                    { 
                        _parserContext.XamlTypeMapper.ValidateNames( 
                                            xamlDefAttributeNode.Value,
                                            xamlDefAttributeNode.LineNumber, 
                                            xamlDefAttributeNode.LinePosition);
                    }

                    WriteDefAttributeCore(xamlDefAttributeNode); 
                    break;
 
                case XamlNodeType.PresentationOptionsAttribute: 
                    XamlPresentationOptionsAttributeNode xamlPresentationOptionsAttributeNode =
                        (XamlPresentationOptionsAttributeNode) xamlNode; 
                    WritePresentationOptionsAttribute(xamlPresentationOptionsAttributeNode);
                    break;

                case XamlNodeType.PIMapping: 
                    XamlPIMappingNode xamlPIMappingNode =
                        (XamlPIMappingNode) xamlNode; 
                    WritePIMapping(xamlPIMappingNode); 
                    break;
 
                // The following tokens that are used primarily by the markup compiler
                case XamlNodeType.EndAttributes:
                    XamlEndAttributesNode xamlEndAttributesNode =
                        (XamlEndAttributesNode) xamlNode; 
                    // if first tag and haven't alredy set the ParseMode
                    // set it to synchronous. 
                    if (0 == xamlEndAttributesNode.Depth) 
                    {
                        if (XamlParseMode == XamlParseMode.Uninitialized) 
                        {
                            XamlParseMode = XamlParseMode.Synchronous;
                        }
                    } 
                    WriteEndAttributes(xamlEndAttributesNode);
                    break; 
 
                case XamlNodeType.KeyElementStart:
                    XamlKeyElementStartNode xamlKeyElementStartNode = 
                        (XamlKeyElementStartNode) xamlNode;
                    WriteKeyElementStart(xamlKeyElementStartNode);
                    break;
 
                case XamlNodeType.KeyElementEnd:
                    XamlKeyElementEndNode xamlKeyElementEndNode = 
                        (XamlKeyElementEndNode) xamlNode; 
                    WriteKeyElementEnd(xamlKeyElementEndNode);
                    break; 

                case XamlNodeType.ConstructorParametersEnd:
                    XamlConstructorParametersEndNode xamlConstructorParametersEndNode =
                        (XamlConstructorParametersEndNode) xamlNode; 
                    WriteConstructorParametersEnd(xamlConstructorParametersEndNode);
                    break; 
 
                case XamlNodeType.ConstructorParametersStart:
                    XamlConstructorParametersStartNode xamlConstructorParametersStartNode = 
                        (XamlConstructorParametersStartNode) xamlNode;
                    WriteConstructorParametersStart(xamlConstructorParametersStartNode);
                    break;
 
                case XamlNodeType.ContentProperty:
                    XamlContentPropertyNode xamlContentPropertyNode = 
                        (XamlContentPropertyNode)xamlNode; 
                    WriteContentProperty(xamlContentPropertyNode);
                    break; 

                case XamlNodeType.ConstructorParameterType:
                    XamlConstructorParameterTypeNode xamlConstructorParameterTypeNode =
                        (XamlConstructorParameterTypeNode)xamlNode; 
                    WriteConstructorParameterType(xamlConstructorParameterTypeNode);
                    break; 
                default: 
                    Debug.Assert(false,"Unknown Xaml Token.");
                    break; 
            }

       }
 
#endregion // PublicMethods
 
    #region Virtuals 

        ///  
        /// Called when parsing begins
        /// 
        public virtual void WriteDocumentStart(XamlDocumentStartNode XamlDocumentStartNode)
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WriteDocumentStart(XamlDocumentStartNode); 
            }
        } 

        /// 
        /// Called when parsing ends
        ///  
        public virtual void WriteDocumentEnd(XamlDocumentEndNode xamlEndDocumentNode)
        { 
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteDocumentEnd(xamlEndDocumentNode); 
            }
        }

        ///  
        /// Write Start of an Element, which is a tag of the form /
        ///  
        public virtual void WriteElementStart(XamlElementStartNode xamlElementStartNode) 
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteElementStart(xamlElementStartNode);
            }
        } 

        ///  
        /// Write start of an unknown tag 
        /// 
        public virtual void WriteUnknownTagStart(XamlUnknownTagStartNode xamlUnknownTagStartNode) 
        {
            // The default action for unknown tags is throw an exception.
            ThrowException(SRID.ParserUnknownTag ,
                        xamlUnknownTagStartNode.Value, 
                        xamlUnknownTagStartNode.XmlNamespace,
                        xamlUnknownTagStartNode.LineNumber, 
                        xamlUnknownTagStartNode.LinePosition); 
        }
 
        /// 
        /// Write end of an unknown tag
        /// 
        public virtual void WriteUnknownTagEnd(XamlUnknownTagEndNode xamlUnknownTagEndNode) 
        {
            // The default action for unknown tags is throw an exception.  This should never 
            // get here unless there is a coding error, since it would first hit 
            // WriteUnknownTagStart
            ThrowException(SRID.ParserUnknownTag , 
                        "???",
                        xamlUnknownTagEndNode.LineNumber,
                        xamlUnknownTagEndNode.LinePosition);
        } 

        ///  
        /// Write End Element 
        /// 
        public virtual void WriteElementEnd(XamlElementEndNode xamlElementEndNode) 
        {
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WriteElementEnd(xamlElementEndNode); 
            }
        } 
 
        /// 
        /// Called when parsing hits literal content. 
        /// 
        public virtual void WriteLiteralContent(XamlLiteralContentNode xamlLiteralContentNode)
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteLiteralContent(xamlLiteralContentNode); 
            } 
        }
 
        /// 
        /// Write Start Complex Property, where the tag is of the
        /// form /
        ///  
        public virtual void WritePropertyComplexStart(
            XamlPropertyComplexStartNode xamlPropertyComplexStartNode) 
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WritePropertyComplexStart(xamlPropertyComplexStartNode);
            }
        }
 

 
        ///  
        /// Write End Complex Property
        ///  
        public virtual void WritePropertyComplexEnd(
            XamlPropertyComplexEndNode xamlPropertyComplexEndNode)
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WritePropertyComplexEnd(xamlPropertyComplexEndNode); 
            } 
        }
 
        /// 
        /// Write Start element for a dictionary key section.
        /// 
        public virtual void WriteKeyElementStart( 
            XamlElementStartNode xamlKeyElementStartNode)
        { 
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteKeyElementStart(xamlKeyElementStartNode); 
            }
        }

        ///  
        /// Write End element for a dictionary key section
        ///  
        public virtual void WriteKeyElementEnd( 
            XamlElementEndNode xamlKeyElementEndNode)
        { 
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WriteKeyElementEnd(xamlKeyElementEndNode);
            } 
        }
 
        ///  
        /// Write unknown attribute
        ///  
        public virtual void WriteUnknownAttribute(XamlUnknownAttributeNode xamlUnknownAttributeNode)
        {
            // The default action for unknown attributes is throw an exception.
            ThrowException(SRID.ParserUnknownAttribute , 
                        xamlUnknownAttributeNode.Name,
                        xamlUnknownAttributeNode.XmlNamespace, 
                        xamlUnknownAttributeNode.LineNumber, 
                        xamlUnknownAttributeNode.LinePosition);
        } 

        /// 
        /// Write a Property, which has the form in markup of property="value".
        ///  
        /// 
        /// Note that for DependencyProperties, the assemblyName, TypeFullName, PropIdName 
        /// refer to DependencyProperty field 
        /// that the property was found on. This may be different from the ownerType
        /// of the propId if the property was registered as an alias so if the 
        /// callback is persisting we want to persist the information that the propId
        /// was found on in case the alias is a private or internal field.
        /// 
        public virtual void WriteProperty(XamlPropertyNode xamlPropertyNode) 
        {
            if (BamlRecordWriter != null) 
            { 
                BamlRecordWriter.WriteProperty(xamlPropertyNode);
            } 
        }

        internal void WriteBaseProperty(XamlPropertyNode xamlPropertyNode)
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.BaseWriteProperty(xamlPropertyNode); 
            }
        } 

        /// 
        /// Write a Property, which has the form in markup of property="value".
        ///  
        /// 
        /// Note that for DependencyProperties, the assemblyName, TypeFullName, PropIdName 
        /// refer to DependencyProperty field 
        /// that the property was found on. This may be different from the ownerType
        /// of the propId if the property was registered as an alias so if the 
        /// callback is persisting we want to persist the information that the propId
        /// was found on in case the alias is a private or internal field.
        /// 
        public virtual void WritePropertyWithType(XamlPropertyWithTypeNode xamlPropertyNode) 
        {
            if (BamlRecordWriter != null) 
            { 
                if (xamlPropertyNode.ValueElementType == null)
                { 
                    ThrowException(SRID.ParserNoType,
                                   xamlPropertyNode.ValueTypeFullName,
                                   xamlPropertyNode.LineNumber,
                                   xamlPropertyNode.LinePosition); 
                }
 
                BamlRecordWriter.WritePropertyWithType(xamlPropertyNode); 
            }
        } 

        public virtual void WritePropertyWithExtension(XamlPropertyWithExtensionNode xamlPropertyWithExtensionNode)
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WritePropertyWithExtension(xamlPropertyWithExtensionNode); 
            } 
        }
 

        /// 
        /// Write out Text, currently don't keep track if originally CData or Text
        ///  
        public virtual void WriteText(XamlTextNode xamlTextNode)
        { 
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteText(xamlTextNode); 
            }
        }

 
        /// 
        /// Write a new namespacePrefix to NamespaceURI map 
        ///  
        public virtual void WriteNamespacePrefix(XamlXmlnsPropertyNode xamlXmlnsPropertyNode)
        { 
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WriteNamespacePrefix(xamlXmlnsPropertyNode);
            } 
        }
 
 
        /// 
        /// Xml - Clr namespace mapping 
        /// 
        public virtual void WritePIMapping(XamlPIMappingNode xamlPIMappingNode)
        {
            // The only case when the assembly name can be empty is when there is a local assembly 
            // specified in the Mapping PI, but the compiler extension should have resolved it by
            // now. So if we are still seeing an empty string here that means we in the pure xaml 
            // parsing scenario and should throw. 
            if (xamlPIMappingNode.AssemblyName.Length == 0)
            { 
                ThrowException(SRID.ParserMapPIMissingKey, xamlPIMappingNode.LineNumber, xamlPIMappingNode.LinePosition);
            }

            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WritePIMapping(xamlPIMappingNode); 
            } 
        }
 
        /// 
        /// Write out the Clr event.
        /// 
        public virtual void WriteClrEvent(XamlClrEventNode xamlClrEventNode) 
        {
            // Parser currently doesn't support hooking up Events directly from 
            // XAML so throw an exception. In the compile case this method 
            // is overriden.
 
            if (null == ParserHooks)
            {
                ThrowException(SRID.ParserNoEvents,
                    xamlClrEventNode.LineNumber, 
                    xamlClrEventNode.LinePosition);
            } 
            else if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteClrEvent(xamlClrEventNode); 
            }
        }

        ///  
        /// Write Property Array Start
        ///  
        public virtual void WritePropertyArrayStart(XamlPropertyArrayStartNode xamlPropertyArrayStartNode) 
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WritePropertyArrayStart(xamlPropertyArrayStartNode);
            }
        } 

 
        ///  
        /// Write Property Array End
        ///  
        public virtual void WritePropertyArrayEnd(XamlPropertyArrayEndNode xamlPropertyArrayEndNode)
        {
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WritePropertyArrayEnd(xamlPropertyArrayEndNode);
            } 
        } 

 
        /// 
        /// Write Property IList Start
        /// 
        public virtual void WritePropertyIListStart(XamlPropertyIListStartNode xamlPropertyIListStartNode) 
        {
            if (BamlRecordWriter != null) 
            { 
                BamlRecordWriter.WritePropertyIListStart(xamlPropertyIListStartNode);
            } 
        }


        ///  
        /// Write Property IList End
        ///  
        public virtual void WritePropertyIListEnd(XamlPropertyIListEndNode xamlPropertyIListEndNode) 
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WritePropertyIListEnd(xamlPropertyIListEndNode);
            }
        } 

        ///  
        /// Write Property IDictionary Start 
        /// 
        public virtual void WritePropertyIDictionaryStart(XamlPropertyIDictionaryStartNode xamlPropertyIDictionaryStartNode) 
        {
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WritePropertyIDictionaryStart(xamlPropertyIDictionaryStartNode); 
            }
        } 
 

        ///  
        /// Write Property IDictionary End
        /// 
        public virtual void WritePropertyIDictionaryEnd(XamlPropertyIDictionaryEndNode xamlPropertyIDictionaryEndNode)
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WritePropertyIDictionaryEnd(xamlPropertyIDictionaryEndNode); 
            }
        } 


        /// 
        /// WriteEndAttributes occurs after the last attribute (property, complex property or 
        /// def record) is written.  Note that if there are none of the above, then WriteEndAttributes
        /// is not called for a normal start tag. 
        ///  
        public virtual void WriteEndAttributes(XamlEndAttributesNode xamlEndAttributesNode)
        { 
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WriteEndAttributes(xamlEndAttributesNode);
            } 
        }
 
        ///  
        /// WriteDefTag occurs when a x:Whatever tag is encountered.
        /// Superclasses must interprete this since the base class doesn't understand 
        /// any of them.
        /// 
        public virtual void WriteDefTag(XamlDefTagNode xamlDefTagNode)
        { 
            ThrowException(SRID.ParserDefTag,
                        xamlDefTagNode.Value, 
                        xamlDefTagNode.LineNumber, 
                        xamlDefTagNode.LinePosition);
        } 

        /// 
        /// Write out a key to a dictionary that has been resolved at compile or parse
        /// time to a Type object. 
        /// 
        public virtual void WriteDefAttributeKeyType(XamlDefAttributeKeyTypeNode xamlDefNode) 
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WriteDefAttributeKeyType(xamlDefNode);
            }
        }
 
        /// 
        /// WriteDefAttribute when attributes of the form x:Whatever are encountered 
        ///  
        public virtual void WriteDefAttribute(XamlDefAttributeNode xamlDefAttributeNode)
        { 
            string attributeValue = xamlDefAttributeNode.Value;

            // There are several known def attributes, and these are checked for
            // correctness by running the known type converters. 
            switch(xamlDefAttributeNode.Name)
            { 
               case XamlReaderHelper.DefinitionSynchronousMode: 
                   if (BamlRecordWriter != null)
                   { 
                       if (xamlDefAttributeNode.Value == "Async")
                       {
                           ThrowException(SRID.ParserNoBamlAsync, "Async",
                                      xamlDefAttributeNode.LineNumber, 
                                      xamlDefAttributeNode.LinePosition);
                       } 
                   } 
                   break;
 
               case XamlReaderHelper.DefinitionAsyncRecords:
                    // Update the AsyncRecords and don't store this as a def attribute
                       ThrowException(SRID.ParserNoBamlAsync, xamlDefAttributeNode.Name,
                                      xamlDefAttributeNode.LineNumber, 
                                      xamlDefAttributeNode.LinePosition);
                   break; 
 
                case XamlReaderHelper.DefinitionShared:
                    Boolean.Parse(attributeValue);   // For validation only. 
                    if (BamlRecordWriter != null)
                    {
                        BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode);
                    } 
                    break;
 
                case XamlReaderHelper.DefinitionUid: 
                case XamlReaderHelper.DefinitionRuntimeName:
                    //Error if x:Uid or x:Name are markup extensions 
                    if (MarkupExtensionParser.LooksLikeAMarkupExtension(attributeValue))
                    {
                        string message = SR.Get(SRID.ParserBadUidOrNameME, attributeValue);
                        message += " "; 
                        message += SR.Get(SRID.ParserLineAndOffset,
                                    xamlDefAttributeNode.LineNumber.ToString(CultureInfo.CurrentCulture), 
                                    xamlDefAttributeNode.LinePosition.ToString(CultureInfo.CurrentCulture)); 

                        XamlParseException parseException = new XamlParseException(message, 
                                xamlDefAttributeNode.LineNumber, xamlDefAttributeNode.LinePosition);

                        throw parseException;
                    } 

                    if (BamlRecordWriter != null) 
                    { 
                        BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode);
                    } 
                    break;

                case XamlReaderHelper.DefinitionName:
                    if (BamlRecordWriter != null) 
                    {
                        BamlRecordWriter.WriteDefAttribute(xamlDefAttributeNode); 
                    } 
                    break;
 
                default:
                    string errorID;
                        errorID = SRID.ParserUnknownDefAttribute;
                        ThrowException(errorID, 
                                   xamlDefAttributeNode.Name,
                                   xamlDefAttributeNode.LineNumber, 
                                   xamlDefAttributeNode.LinePosition); 
                    break;
            } 
        }

        /// 
        /// Write attributes of the form PresentationOptions:Whatever to Baml 
        /// 
        public virtual void WritePresentationOptionsAttribute(XamlPresentationOptionsAttributeNode xamlPresentationOptionsAttributeNode) 
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WritePresentationOptionsAttribute(xamlPresentationOptionsAttributeNode);
            }
        }
 
        /// 
        /// Write the start of a constructor parameter section 
        ///  
        public virtual void WriteConstructorParametersStart(XamlConstructorParametersStartNode xamlConstructorParametersStartNode)
        { 
            if (BamlRecordWriter != null)
            {
                BamlRecordWriter.WriteConstructorParametersStart(xamlConstructorParametersStartNode);
            } 
        }
 
        public virtual void WriteContentProperty(XamlContentPropertyNode xamlContentPropertyNode) 
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteContentProperty(xamlContentPropertyNode);
            }
        } 

        ///  
        /// Write the constructor parameter record where the parameter is a compile time 
        /// resolved Type object.
        ///  
        public virtual void WriteConstructorParameterType(
             XamlConstructorParameterTypeNode xamlConstructorParameterTypeNode)
        {
            if (BamlRecordWriter != null) 
            {
                BamlRecordWriter.WriteConstructorParameterType(xamlConstructorParameterTypeNode); 
            } 
        }
 
        /// 
        /// Write the end of a constructor parameter section
        /// 
        public virtual void WriteConstructorParametersEnd(XamlConstructorParametersEndNode xamlConstructorParametersEndNode) 
        {
            if (BamlRecordWriter != null) 
            { 
                BamlRecordWriter.WriteConstructorParametersEnd(xamlConstructorParametersEndNode);
            } 
        }

        /// 
        /// Can be used by ac to return the type of the element if a class attribute is 
        /// present. If want to override default Type because of class= attribute can do so here.
        /// Should leave the XmlReader positioned at the Element so if read attributes 
        /// to determine type need to call XmlReader.MoveToElement() 
        /// 
        public virtual bool GetElementType( 
                XmlReader  reader,
                string     localName,
                string     namespaceUri,
            ref string     assemblyName, 
            ref string     typeFullName,
            ref Type       baseType, 
            ref Type       serializerType) 
        {
            bool result = false; 

            assemblyName   = string.Empty;
            typeFullName   = string.Empty;
            serializerType = null; 
            baseType       = null;
 
            // if no namespaceURI or local name don't bother 
            if (null == namespaceUri || null == localName)
            { 
                return false;
            }

            TypeAndSerializer typeAndSerializer = 
                XamlTypeMapper.GetTypeAndSerializer(namespaceUri, localName, null);
 
            if (typeAndSerializer != null && 
                typeAndSerializer.ObjectType != null)
            { 
                serializerType = typeAndSerializer.SerializerType;
                baseType = typeAndSerializer.ObjectType;
                typeFullName = baseType.FullName;
                assemblyName = baseType.Assembly.FullName; 
                result = true;
 
                Debug.Assert(null != assemblyName, "assembly name returned from GetBaseElement is null"); 
                Debug.Assert(null != typeFullName, "Type name returned from GetBaseElement is null");
            } 

            return result;
        }
 

#endregion Virtuals 
 

        ///  
        /// Write a Connector Id for compiler.
        /// 
        protected internal void WriteConnectionId(Int32 connectionId)
        { 
            if (BamlRecordWriter != null)
            { 
                BamlRecordWriter.WriteConnectionId(connectionId); 
            }
        } 

        /// 
        /// A def attribute was encountered.  Perform synchonous mode checking
        /// prior to calling the virtual that may be overridden. 
        /// 
        void WriteDefAttributeCore(XamlDefAttributeNode xamlDefAttributeNode) 
        { 

            string attributeValue = xamlDefAttributeNode.Value; 

            switch(xamlDefAttributeNode.Name)
            {
                case  XamlReaderHelper.DefinitionSynchronousMode: 
                    XamlParseMode documentParseMode = XamlParseMode.Synchronous;
 
                    if (attributeValue.Equals("Async")) 
                    {
                        documentParseMode = XamlParseMode.Asynchronous; 
                    }
                    else if (attributeValue.Equals("[....]"))
                    {
                        documentParseMode = XamlParseMode.Synchronous; 
                    }
                    else 
                    { 
                        ThrowException(SRID.ParserBadSyncMode,
                               xamlDefAttributeNode.LineNumber, 
                               xamlDefAttributeNode.LinePosition );
                    }

                    // if we haven't initialized the the parseMode yet set it 
                    if (XamlParseMode == XamlParseMode.Uninitialized)
                    { 
                        // todo: for now hardcode the string. when finalized 
                        // should add a TypeConverter.
                        XamlParseMode = documentParseMode; 

                    }
                    break;
                default: 
                    break;
            } 
 
            WriteDefAttribute(xamlDefAttributeNode);
        } 

    #region Methods

        // virtuals to override the default implementation. used by the compiler 
        // for internal virtuals review why not public as the others?
 
        // Used when an exception is thrown.The default action is to shutdown the parser 
        // and throw the exception.
        internal virtual void ParseError(XamlParseException e) 
        {
        }

        ///  
        /// Called when the parse was cancelled by the user.
        ///  
        internal virtual void  ParseCancelled() 
        {
        } 

        /// 
        ///  called when the parse has been completed successfully.
        ///  
        internal virtual void ParseCompleted()
        { 
        } 

 

        /// 
        ///  Default parsing is to synchronously read all the xaml nodes
        ///  until done. 
        /// 
        internal virtual void _Parse() 
        { 

            ReadXaml(false /* want to parse the entire thing */); 

        }

 
        /// 
        /// If there are ParserHooks, call it with the current xamlNode and perform 
        /// as directed by the callback. 
        /// 
        private void SetParserAction(XamlNode xamlNode) 
        {
            // if no ParserHooks then process as normal
            if (null == ParserHooks)
            { 
                ParserAction = ParserAction.Normal;
                return; 
            } 

            // if ParserHooks want to skip the current node and its children, 
            // check for end of scope where it asked to be skipped.
            if (ParserAction == ParserAction.Skip)
            {
                if (xamlNode.Depth <= SkipActionDepthCount && 
                    xamlNode.TokenType == SkipActionToken)
                { 
                    // We found the end token at the correct depth.  Reset the depth count 
                    // so that in the next call we won't skip calling the ParserHooks.  Don't
                    // reset the ParserAction since we want to skip this end token. 
                    SkipActionDepthCount = -1;
                    SkipActionToken = XamlNodeType.Unknown;
                    return;
                } 
                else if (SkipActionDepthCount >= 0)
                { 
                    return; 
                }
            } 

            // If we get to here, the ParserHooks want to be called.
            ParserAction = ParserHooks.LoadNode(xamlNode);
 
            // if the ParserHooks want to skip the current node and its children then
            // set the callback depth so that we'll know when to start processing again. 
            if (ParserAction == ParserAction.Skip) 
            {
                // For tokens with no scope (eg = attributes), don't set the depth so 
                // that we will only skip once
                Debug.Assert(SkipActionDepthCount == -1);
                int tokenIndex = ((IList)XamlNode.ScopeStartTokens).IndexOf(xamlNode.TokenType);
                if (tokenIndex != -1) 
                {
                    SkipActionDepthCount = xamlNode.Depth; 
                    SkipActionToken = XamlNode.ScopeEndTokens[tokenIndex]; 
                }
            } 
        }


 
        // Return true if the passed namespace is known, meaning that it maps
        // to a set of assemblies and clr namespaces 
        internal bool IsXmlNamespaceSupported(string xmlNamespace, out string newXmlNamespace) 
        {
            newXmlNamespace = null; 

            if (xmlNamespace.StartsWith(XamlReaderHelper.MappingProtocol, StringComparison.Ordinal))
            {
                return true; 
            }
            else if (xmlNamespace == XamlReaderHelper.PresentationOptionsNamespaceURI) 
            { 
                // PresentationOptions is expected to be marked as 'ignorable' in most Xaml
                // so that other Xaml parsers don't have to interpret it, but this parser 
                // does handle it to support it's Freeze attribute.
                return true;
            }
            else 
            {
                return XamlTypeMapper.IsXmlNamespaceKnown(xmlNamespace, out newXmlNamespace) || 
                    TokenReader.IsXmlDataIsland(); 
            }
        } 
#endregion Methods

    #region Properties
 
        /// 
        /// TokenReader that is being used. 
        ///  
        internal XamlReaderHelper TokenReader
        { 
            get { return _xamlTokenReader; }
            set { _xamlTokenReader = value; }
        }
 
        /// 
        ///  ParserHooks implementation that any parse time callbacks 
        ///  should be called on. 
        /// 
        internal  ParserHooks ParserHooks 
        {
            get { return _parserHooks; }
            set { _parserHooks = value; }
        } 

        // Set the depth count for how deep we are within 
        // a ParserAction.Skip reference. 
        int SkipActionDepthCount
        { 
            get { return _skipActionDepthCount; }
            set {  _skipActionDepthCount = value; }
        }
 
        // Set and get the token to watch for when skipping a
        // section of a xaml file 
        XamlNodeType SkipActionToken 
        {
            get { return _skipActionToken; } 
            set {  _skipActionToken = value; }
        }

        // set the operation mode of the parser as determined 
        // by attached ParserHooks
        ParserAction ParserAction 
        { 
            get { return _parserAction; }
            set {  _parserAction = value; } 
        }

        /// 
        /// Instance of the XamlTypeMapper 
        /// 
        internal XamlTypeMapper XamlTypeMapper 
        { 
            get { return _parserContext.XamlTypeMapper; }
        } 

        /// 
        /// Instance of the BamlMapTable
        ///  
        internal BamlMapTable MapTable
        { 
            get { return _parserContext.MapTable; } 
        }
 
        /// 
        /// BamlRecordWriter being used by the Parser
        /// 
        public BamlRecordWriter BamlRecordWriter 
        {
            get { return _bamlWriter; } 
            set 
            {
                Debug.Assert(null == _bamlWriter || null == value, "XamlParser already had a bamlWriter"); 
                _bamlWriter = value;
            }
        }
 
        /// 
        ///  ParseMode the Parser is in. 
        ///  
        internal XamlParseMode XamlParseMode
        { 
            get { return _xamlParseMode; }
            set { _xamlParseMode = value; }
        }
 
        /// 
        ///  Parser context 
        ///  
        internal ParserContext ParserContext
        { 
            get { return _parserContext; }
            set { _parserContext = value; }
        }
 
        internal virtual bool CanResolveLocalAssemblies()
        { 
            return false; 
        }
 
        // Used to determine if strict or loose parsing rules should be enforced.  The TokenReader
        // does some validations that are difficult for the XamlParser to do and in strict parsing
        // mode the TokenReader should throw exceptions of standard Xaml rules are violated.
        internal virtual bool StrictParsing 
        {
            get { return true; } 
        } 

 
#endregion Properties

    #region Data
 

 
 
        // private Data
 
        XamlReaderHelper             _xamlTokenReader;

        ParserContext                _parserContext; // todo, need this for the XamlTypeMapper/resolver.
 
        XamlParseMode                _xamlParseMode;
        BamlRecordWriter             _bamlWriter; 
 
        // ParserHooks related
        ParserHooks                  _parserHooks; 
        ParserAction                 _parserAction = ParserAction.Normal;
        int                          _skipActionDepthCount = -1; // skip mode depth count.
        XamlNodeType                 _skipActionToken = XamlNodeType.Unknown;
 
        static private string []     _predefinedNamespaces = new string [3] {
            XamlReaderHelper.DefinitionNamespaceURI, 
            XamlReaderHelper.DefaultNamespaceURI, 
            XamlReaderHelper.DefinitionMetroNamespaceURI
        }; 
    #endregion Data

#endif
 
        // helper method called to throw an exception.
        // todo: update exception with lineNumbers from Node. 
        internal static void ThrowException(string id, int lineNumber, int linePosition) 
        {
            string message = SR.Get(id); 
            ThrowExceptionWithLine(message, lineNumber, linePosition);
        }

        // helper method called to throw an exception. 
        internal static void ThrowException(string id, string value, int lineNumber, int linePosition)
        { 
            string message = SR.Get(id, value); 
            ThrowExceptionWithLine(message, lineNumber, linePosition);
        } 

        // helper method called to throw an exception.
        internal static void ThrowException(string id, string value1, string value2, int lineNumber, int linePosition)
        { 
            string message = SR.Get(id, value1, value2);
            ThrowExceptionWithLine(message, lineNumber, linePosition); 
        } 

        internal static void ThrowException(string id, string value1, string value2, string value3, int lineNumber, int linePosition) 
        {
            string message = SR.Get(id, value1, value2, value3);
            ThrowExceptionWithLine(message, lineNumber, linePosition);
        } 

        internal static void ThrowException(string id, string value1, string value2, string value3, string value4, int lineNumber, int linePosition) 
        { 
            string message = SR.Get(id, value1, value2, value3, value4);
            ThrowExceptionWithLine(message, lineNumber, linePosition); 
        }

        private static void ThrowExceptionWithLine(string message, int lineNumber, int linePosition)
        { 
            message += " ";
            message += SR.Get(SRID.ParserLineAndOffset, 
                                    lineNumber.ToString(CultureInfo.CurrentCulture), 
                                    linePosition.ToString(CultureInfo.CurrentCulture));
 
            XamlParseException parseException = new XamlParseException(message,
                lineNumber, linePosition);

 
            throw parseException;
        } 
 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK