XmlParser.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Speech / Src / Internal / SrgsParser / XmlParser.cs / 1 / XmlParser.cs

                            //  
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//
// Description: 
//      The Srgs xml parser parse takes as input an xml reader and the IElementFactory
//      interface. With this virtualization scheme, the srgs parser do not create 
//      directly Srgs elements. Instead methods on a set of interfaces for each 
//      Srgs Element creates the element themselve. The underlying implementation
//      for each elements is different for the SrgsDocument class and the Srgs 
//      Compiler.
//
//      Interface definition for the IElement
// History: 
//		6/1/2004	jeanfp		Created
//----------------------------------------------------------------------------using System; 
 
using System;
using System.Globalization; 
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml; 
using System.Collections;
using System.Collections.Generic; 
using System.Speech.Recognition.SrgsGrammar; 

#pragma warning disable 1634, 1691 // Allows suppression of certain PreSharp messages. 
#pragma warning disable 56524 // The _reader and  and _xmlReader are not created in this module and should not be disposed

// Remove all the check for null or empty warnings
#pragma warning disable 56507 

namespace System.Speech.Internal.SrgsParser 
{ 
    internal class XmlParser : ISrgsParser
    { 
        //*******************************************************************
        //
        // Constructors
        // 
        //*******************************************************************
 
        #region Constructors 

        internal XmlParser (XmlReader reader, Uri uri) 
        {
            _reader = reader;
            _xmlTextReader = reader as XmlTextReader;
 
            // Try to guess the Uri
            if (uri == null) 
            { 
                // Keep a reference to the filename and XmlTextReader if it is one.
                if (_xmlTextReader != null && _xmlTextReader.BaseURI.Length > 0) 
                {
                    try
                    {
                        uri = new Uri (_xmlTextReader.BaseURI); 
                    }
#pragma warning disable 56502 // Remove the empty catch statements warnings 
                    catch (UriFormatException) 
                    {
                    } 
#pragma warning restore 56502
                }
            }
 
            // Saves the path to the file and the file name
            if (uri != null) 
            { 
                // Saves the full path to the file
                _filename = !uri.IsAbsoluteUri || !uri.IsFile ? uri.OriginalString : uri.LocalPath; 

                // Saves the filename without the path
                int iPosSlash = _filename.LastIndexOfAny (_SlashBackSlash);
                _shortFilename = iPosSlash >= 0 ? _filename.Substring (iPosSlash + 1) : _filename; 
            }
        } 
 
        #endregion
 
        //*******************************************************************
        //
        // Internal Methods
        // 
        //********************************************************************
 
        #region Internal Methods 

        // Initializes the object from a stream containg SRGS in XML 
        public void Parse ()
        {
            try
            { 
                bool isGrammarElementFound = false;
 
 
                while (_reader.Read ())
                { 
                    // Ignore XmlDeclaration, ProcessingInstruction, Comment, DocumentType, Entity, Notation.
                    if (_reader.NodeType == XmlNodeType.Element && _reader.LocalName == "grammar")
                    {
                        if (_reader.NamespaceURI != srgsNamespace) 
                        {
                            ThrowSrgsException (SRID.InvalidSrgsNamespace); 
                        } 

                        if (isGrammarElementFound) 
                        {
                            ThrowSrgsException (SRID.GrammarDefTwice);
                        }
                        else 
                        {
                            ParseGrammar (_reader, _parser.Grammar); 
                            isGrammarElementFound = true; 
                        }
                    } 
                }

                if (!isGrammarElementFound)
                { 
                    ThrowSrgsException (SRID.InvalidSrgs);
                } 
            } 
            catch (XmlException eXml)
            { 
                _parser.RemoveAllRules ();
                ThrowSrgsExceptionWithPosition (_filename, _reader, SR.Get (SRID.InvalidXmlFormat), eXml);
            }
            catch (FormatException e) 
            {
                // Adds a placeholder for the rule. 
                // Once all the rules and scripts are read, the placeholder will be replaced with the proper rule. 
                _parser.RemoveAllRules ();
                ThrowSrgsExceptionWithPosition (_filename, _reader, e.Message, e.InnerException); 
            }
            catch
            {
                // clear all the rules 
                _parser.RemoveAllRules ();
                throw; 
            } 
        }
 
        /// 
        /// Break the string into individual tokens and ParseToken() each individual token.
        ///
        /// Token string is a sequence of 0 or more white space delimited tokens. 
        /// Tokens may also be delimited by double quotes.  In these cases, the double
        /// quotes token must be surrounded by white space or string boundary. 
        ///  
        /// Parent element
        ///  
        /// 
        /// 
        /// 
        ///  
        internal static void ParseText (IElement parent, string sChars, string pronunciation, string display, float reqConfidence, CreateTokenCallback createTokens)
        { 
            sChars = sChars.Trim (Helpers._achTrimChars); 

            char [] achToken = sChars.ToCharArray (); 
            int iTokenEnd = 0;
            int cChars = sChars.Length;

            for (int i = 0; i < achToken.Length; i = iTokenEnd + 1) 
            {
                if (achToken [i] == ' ')                            // Skip white spaces 
                { 
                    iTokenEnd = i;
                    continue; 
                }

                // Find the next token
                if (achToken [i] == '"') 
                {
                    // Quoted string.  Find end of quoted string. 
                    iTokenEnd = ++i; 
                    while ((iTokenEnd < cChars) && (achToken [iTokenEnd] != '"'))
                    { 
                        iTokenEnd++;
                    }

                    if (iTokenEnd >= cChars || achToken [iTokenEnd] != '"') 
                    {
                        // Cannot find matching double quote. 
                        // "Invalid double-quoted string." 
                        XmlParser.ThrowSrgsException (SRID.InvalidQuotedString);
                    } 

                    if (iTokenEnd + 1 != cChars && achToken [iTokenEnd + 1] != ' ')
                    {
                        // Quoted token not surrounded by whitespace."); 
                        // "Invalid double-quoted string."
                        XmlParser.ThrowSrgsException (SRID.InvalidQuotedString); 
                    } 
                }
                else 
                {
                    // Regular token.  Find next white space character or end of string
                    iTokenEnd = i + 1;
                    while ((iTokenEnd < cChars) && achToken [iTokenEnd] != ' ') 
                    {
                        iTokenEnd++; 
                    } 
                }
 
                string sToken = sChars.Substring (i, iTokenEnd - i);
                if (sToken.IndexOf ('"') != -1)
                {
                    // "The token string is not allowed to contain double quote character." 
                    XmlParser.ThrowSrgsException (SRID.InvalidTokenString);
                } 
 
                // Parse the token.
                if (createTokens != null) 
                {
                    createTokens (parent, sToken, pronunciation, display, reqConfidence);
                }
            } 
        }
 
        ///  
        /// Throws an Exception with the error specified by the resource ID.
        /// Add the line and column number if the XmlReader is a TextReader 
        /// 
        /// 
        /// 
        internal static void ThrowSrgsException (SRID id, params object [] args) 
        {
            throw new FormatException (SR.Get (id, args)); 
        } 

        ///  
        /// Throws an Exception with the error specified by the resource ID.
        /// Add the line and column number if the XmlReader is a TextReader
        /// 
        ///  
        /// 
        ///  
        ///  
        internal static void ThrowSrgsExceptionWithPosition (string filename, XmlReader xmlReader, string sError, Exception innerException)
        { 
            // Add the line and column number if the XmlReader is a XmlTextReader
            XmlTextReader xmlTextReader = xmlReader as XmlTextReader;
            if (xmlTextReader != null)
            { 
                string sLine = SR.Get (SRID.Line);
                string sPosition = SR.Get (SRID.Position); 
                int line = xmlTextReader.LineNumber; 
                int position = xmlTextReader.LinePosition;
                if (filename == null) 
                {
                    sError += string.Format (CultureInfo.InvariantCulture, " [{0}={1}, {2}={3}]", sLine, line, sPosition, position);
                }
                else 
                {
                    sError = string.Format (CultureInfo.InvariantCulture, "{0}({1},{2}): error : {3}", filename, line, position, sError); 
                } 
            }
            throw new FormatException (sError, innerException); 
        }

        #endregion
 
        //*******************************************************************
        // 
        // Internal Properties 
        //
        //******************************************************************** 

        #region Internal Methods

        // Inmplementation of the internal interface ISrgsParser 
        public IElementFactory ElementFactory
        { 
            set 
            {
                _parser = value; 
            }
        }

        #endregion 

        //******************************************************************** 
        // 
        // Internal fields
        // 
        //*******************************************************************

        #region Internal fields
 
        internal const string emptyNamespace = "";
 
        internal const string xmlNamespace = "http://www.w3.org/XML/1998/namespace"; 

        internal const string srgsNamespace = "http://www.w3.org/2001/06/grammar"; 

        internal const string sapiNamespace = "http://schemas.microsoft.com/Speech/2002/06/SRGSExtensions";

        #endregion 

        //******************************************************************** 
        // 
        // Private Type
        // 
        //*******************************************************************

        #region Private Type
 
        // Must be a class to be used with generics
        [Serializable] 
        internal class ForwardReference 
        {
            internal ForwardReference (string name, string value) 
            {
                _name = name;
                _value = value;
            } 

            internal string _name; 
            internal string _value; 
        }
        #endregion 

        //*******************************************************************
        //
        // Private Methods 
        //
        //******************************************************************* 
 
        #region Private Methods
 
        // The perf gain using .Lengh == 0 other  readability is not worth it fixing this FxCop issue
        private void ParseGrammar (XmlReader reader, IGrammar grammar)
        {
            string sAlphabet = null; 
#if !NO_STG
            string sLanguage = null; 
            string sNamespace = null; 
#endif
            string sVersion = null; 
            GrammarType grammarType = GrammarType.VoiceGrammar;

            // Process attributes.
            while (reader.MoveToNextAttribute ()) 
            {
                bool isInvalidAttribute = false; 
 
                switch (reader.NamespaceURI)
                { 
                    case emptyNamespace:
                        switch (reader.LocalName)
                        {
                            case "root": 
                                if (grammar.Root == null)
                                { 
                                    grammar.Root = reader.Value; 
                                }
                                else 
                                {
                                    ThrowSrgsException (SRID.RootRuleAlreadyDefined);
                                }
                                break; 

                            case "version": 
                                CheckForDuplicates (ref sVersion, reader); 
                                if (sVersion != "1.0")
                                { 
                                    ThrowSrgsException (SRID.InvalidVersion);
                                }

                                break; 

                            case "tag-format": 
                                switch (reader.Value) 
                                {
                                    case "semantics/1.0": 
                                        grammar.TagFormat = SrgsTagFormat.W3cV1;
                                        _hasTagFormat = true;
                                        break;
 
#if SPEECHSERVER
                                    case "semantics/1.0-literals": 
                                        grammar.TagFormat = SrgsTagFormat.W3cV1; 
                                        _w3c_literal = _hasTagFormat = true;
                                        break; 
#endif
                                    case "semantics-ms/1.0":
                                        grammar.TagFormat = SrgsTagFormat.MssV1;
                                        _hasTagFormat = true; 
                                        break;
 
                                    case "properties-ms/1.0": 
                                        grammar.TagFormat = SrgsTagFormat.KeyValuePairs;
                                        _hasTagFormat = true; 
                                        break;

                                    case "":
                                        break; 

                                    default: 
                                        ThrowSrgsException (SRID.InvalidTagFormat); 
                                        break;
                                } 
                                break;

                            case "mode":
                                switch (reader.Value) 
                                {
                                    case "voice": 
                                        grammar.Mode = GrammarType.VoiceGrammar; 
                                        break;
 
                                    case "dtmf":
                                        grammarType = grammar.Mode = GrammarType.DtmfGrammar;
                                        break;
 
                                    default:
                                        ThrowSrgsException (SRID.InvalidGrammarMode); 
                                        break; 
                                }
                                break; 

                            default:
                                isInvalidAttribute = true;
                                break; 
                        }
                        break; 
 
                    case xmlNamespace:
                        switch (reader.LocalName) 
                        {
                            case "lang":
                                string language = reader.Value;
                                try 
                                {
                                    grammar.Culture = _langId = new CultureInfo (language); 
                                } 
                                catch (ArgumentException)
                                { 
                                    // Special case for "es-us", create a new CultureInfo based on attributes of spanish
                                    // and english
                                    if (string.Compare ("es-us", language, StringComparison.OrdinalIgnoreCase) == 0)
                                    { 
                                        Helpers.CombineCulture ("es-ES", "en-US", new CultureInfo ("es"), 0x540A);
                                        grammar.Culture = _langId = new CultureInfo (language); 
                                    } 
                                    else
                                    { 
                                        // Unknown Culture info, fall back to the base culture.
                                        int pos = reader.Value.IndexOf ("-", StringComparison.Ordinal);
                                        if (pos > 0)
                                        { 
                                            grammar.Culture = _langId = new CultureInfo (reader.Value.Substring (0, pos));
                                        } 
                                        else 
                                        {
                                            throw; 
                                        }
                                    }
                                }
                                break; 

                            case "base": 
                                grammar.XmlBase = new Uri (reader.Value); 
                                break;
                        } 
                        break;

                    case sapiNamespace:
                        switch (reader.LocalName) 
                        {
                            case "alphabet": 
                                CheckForDuplicates (ref sAlphabet, reader); 
                                switch (sAlphabet)
                                { 
                                    case "ipa":
                                        grammar.PhoneticAlphabet = AlphabetType.Ipa;
                                        break;
 
                                    case "sapi":
                                    case "x-sapi": 
                                    case "x-microsoft-sapi": 
                                        grammar.PhoneticAlphabet = AlphabetType.Sapi;
                                        break; 

                                    case "ups":
                                    case "x-ups":
                                    case "x-microsoft-ups": 
                                        grammar.PhoneticAlphabet = AlphabetType.Ups;
                                        break; 
 
                                    default:
                                        ThrowSrgsException (SRID.UnsupportedPhoneticAlphabet, reader.Value); 
                                        break;
                                }
                                break;
 
#if !NO_STG
                            case "language": 
                                CheckForDuplicates (ref sLanguage, reader); 
                                if (sLanguage == "C#" || sLanguage == "VB.Net")
                                { 
                                    grammar.Language = sLanguage;
                                }
                                else
                                { 
                                    ThrowSrgsException (SRID.UnsupportedLanguage, reader.Value);
                                } 
                                break; 

                            case "namespace": 
                                CheckForDuplicates (ref sNamespace, reader);
                                if (string.IsNullOrEmpty (sNamespace))
                                {
                                    ThrowSrgsException (SRID.NoName1, "namespace"); 
                                }
                                grammar.Namespace = sNamespace; 
                                break; 

                            case "codebehind": 
                                if (reader.Value.Length == 0)
                                {
                                    ThrowSrgsException (SRID.NoName1, "codebehind");
                                } 
                                grammar.CodeBehind.Add (reader.Value);
                                break; 
 
                            case "debug":
                                bool f; 
                                if (bool.TryParse (reader.Value, out f))
                                {
                                    grammar.Debug = f;
                                } 
                                break;
#endif 
                            default: 
                                isInvalidAttribute = true;
                                break; 
                        }
                        break;
                }
                if (isInvalidAttribute) 
                {
                    ThrowSrgsException (SRID.InvalidGrammarAttribute, reader.Name); 
                } 
            }
 
            // The version attribute is required  for the grammar element
            if (sVersion == null)
            {
                ThrowSrgsException (SRID.MissingRequiredAttribute, "version", "grammar"); 
            }
 
            // The langId is require for voice grammars 
            if (_langId == null)
            { 
                if (grammarType == GrammarType.VoiceGrammar)
                {
                    ThrowSrgsException (SRID.MissingRequiredAttribute, "xml:lang", "grammar");
                } 
                else
                { 
                    _langId = CultureInfo.CurrentUICulture; 
                }
            } 

            // Process child elements.
            ProcessRulesAndScriptsNodes (reader, grammar);
 
            // Validate all the scripts elements
            ValidateScripts (); 
 
#if !NO_STG
            // Add all the scripts to the rules 
            foreach (ForwardReference script in _scripts)
            {
                _parser.AddScript (grammar, script._name, script._value);
            } 
#endif
            // Finish all initialisation - should check for the Root and the all 
            // rules are defined 
            grammar.PostParse (null);
 
        }

        // The perf gain using .Lengh == 0 other  readability is not worth it fixing this FxCop issue
        private IRule ParseRule (IGrammar grammar, XmlReader reader) 
        {
            string id = null; 
            string scope = null; 
            string dynamic = null;
            RulePublic publicRule = RulePublic.NotSet; 
            RuleDynamic ruleDynamic = RuleDynamic.NotSet;

#if !NO_STG
            string sBaseClass = null; 
            string sInit = null;
            string sParse = null; 
            string sError = null; 
            string sRecognition = null;
#endif 

            while (reader.MoveToNextAttribute ())
            {
                bool isInvalidAttribute = false; 

                switch (reader.NamespaceURI) 
                { 
                    case emptyNamespace:
                        switch (reader.LocalName) 
                        {
                            case "id":
                                CheckForDuplicates (ref id, reader);
                                break; 

                            case "scope": 
                                CheckForDuplicates (ref scope, reader); 
                                switch (scope)
                                { 
                                    case "private":
                                        publicRule = RulePublic.False;
                                        break;
 
                                    case "public":
                                        publicRule = RulePublic.True; 
                                        break; 

                                    default: 
                                        ThrowSrgsException (SRID.InvalidRuleScope);
                                        break;
                                }
                                break; 

                            default: 
                                isInvalidAttribute = true; 
                                break;
                        } 
                        break;

                    case sapiNamespace:
                        switch (reader.LocalName) 
                        {
                            case "dynamic": 
                                CheckForDuplicates (ref dynamic, reader); 
                                switch (dynamic)
                                { 
                                    case "true":
                                        ruleDynamic = RuleDynamic.True;
                                        break;
 
                                    case "false":
                                        ruleDynamic = RuleDynamic.False; 
                                        break; 

                                    default: 
                                        ThrowSrgsException (SRID.InvalidDynamicSetting);
                                        break;
                                }
                                break; 

#if !NO_STG 
                            case "baseclass": 
                                CheckForDuplicates (ref sBaseClass, reader);
                                if (string.IsNullOrEmpty (sBaseClass)) 
                                {
                                    ThrowSrgsException (SRID.NoName1, "baseclass");
                                }
                                break; 

                            case "onInit": 
                                CheckForDuplicates (ref sInit, reader); 
                                sInit = reader.Value;
                                break; 

                            case "onParse":
                                CheckForDuplicates (ref sParse, reader);
                                sParse = reader.Value; 
                                break;
 
                            case "onError": 
                                CheckForDuplicates (ref sError, reader);
                                sError = reader.Value; 
                                break;

                            case "onRecognition":
                                CheckForDuplicates (ref sRecognition, reader); 
                                break;
#endif 
                            default: 
                                isInvalidAttribute = true;
                                break; 
                        }
                        break;
                }
                if (isInvalidAttribute) 
                {
                    ThrowSrgsException (SRID.InvalidRuleAttribute, reader.Name); 
                } 
            }
 
            if (string.IsNullOrEmpty (id))
            {
                ThrowSrgsException (SRID.NoRuleId);
            } 

#if !NO_STG 
            if (sInit != null && publicRule != RulePublic.True) 
            {
                XmlParser.ThrowSrgsException (SRID.OnInitOnPublicRule, "OnInit", id); 
            }

            if (sRecognition != null && publicRule != RulePublic.True)
            { 
                XmlParser.ThrowSrgsException (SRID.OnInitOnPublicRule, "OnRecognition", id);
            } 
 
            ValidateRuleId (id);
 
            bool hasScript = sInit != null || sParse != null || sError != null || sRecognition != null;
            IRule rule = grammar.CreateRule (id, publicRule, ruleDynamic, hasScript);

            if (!string.IsNullOrEmpty (sInit)) 
            {
                rule.CreateScript (grammar, id, sInit, RuleMethodScript.onInit); 
            } 

            if (!string.IsNullOrEmpty (sParse)) 
            {
                rule.CreateScript (grammar, id, sParse, RuleMethodScript.onParse);
            }
 
            if (!string.IsNullOrEmpty (sError))
            { 
                rule.CreateScript (grammar, id, sError, RuleMethodScript.onError); 
            }
 
            if (!string.IsNullOrEmpty (sRecognition))
            {
                rule.CreateScript (grammar, id, sRecognition, RuleMethodScript.onRecognition);
            } 

            rule.BaseClass = sBaseClass; 
#else 
            ValidateRuleId (id);
 
            IRule rule = grammar.CreateRule (id, publicRule, ruleDynamic, false);
#endif
            _rules.Add (id);
 
            if (!ProcessChildNodes (reader, rule, rule, "rule"))
            { 
                if (ruleDynamic != RuleDynamic.True) 
                {
                    ThrowSrgsException (SRID.InvalidEmptyRule, "rule", id); 
                }
            }
            return rule;
        } 

        // The perf gain using .Lengh == 0 other  readability is not worth it fixing this FxCop issue 
        private IRuleRef ParseRuleRef (IElement parent, XmlReader reader) 
        {
            IRuleRef ruleRef = null; 

            string sAlias = null;
            string sParams = null;
            string uri = null; 

            while (reader.MoveToNextAttribute ()) 
            { 
                bool isInvalidAttribute = false;
 
                switch (reader.NamespaceURI)
                {
                    case emptyNamespace:
                        switch (reader.LocalName) 
                        {
                            case "uri": 
                                // Check that the uri pointed to in the ruleref does not point this file 
                                // in srgs.xml: ... = 0) 
            {
                ThrowSrgsException (SRID.InvalidTokenString);
            }
 
            return _parser.CreateToken (parent, content, sPronunciation, sDisplay, reqConfidence);
        } 
 
        /// 
        /// Break the string into individual tokens and ParseToken() each individual token. 
        ///
        /// Token string is a sequence of 0 or more white space delimited tokens.
        /// Tokens may also be delimited by double quotes.  In these cases, the double
        /// quotes token must be surrounded by white space or string boundary. 
        /// 
        /// Parent element 
        ///  
        /// 
        ///  
        /// 
        private void ParseText (IElement parent, string sChars, string pronunciation, string display, float reqConfidence)
        {
            System.Diagnostics.Debug.Assert ((parent != null) && (!string.IsNullOrEmpty (sChars))); 

            ParseText (parent, sChars, pronunciation, display, reqConfidence, new CreateTokenCallback (_parser.CreateToken)); 
        } 

        private IElement ParseTag (IElement parent, XmlReader reader) 
        {
            string content = GetTagContent (parent, reader);

            //Return an empty tag if the content is empty 
            if (string.IsNullOrEmpty (content))
            { 
                return _parser.CreateSemanticTag (parent); 
            }
 
            if (_parser.Grammar.TagFormat != SrgsTagFormat.KeyValuePairs)
            {
                ISemanticTag semanticTag = _parser.CreateSemanticTag (parent);
 
#if SPEECHSERVER
                // For semantic interpretation literal, surround the content of the tag bu "out=" 
                if (_w3c_literal) 
                {
                    content = string.Format (CultureInfo.InvariantCulture, "out=\"{0}\";", content); 
                }
#endif
                semanticTag.Content (parent, content, 0);
                return semanticTag; 
            }
 
            System.Diagnostics.Debug.Assert (_parser.Grammar.TagFormat == SrgsTagFormat.KeyValuePairs); 

            IPropertyTag propertyTag = _parser.CreatePropertyTag (parent); ; 
            string name;
            object value;
            ParsePropertyTag (content, out name, out value);
            propertyTag.NameValue (parent, name, value); 
            return propertyTag;
        } 
 
        private string GetTagContent (IElement parent, XmlReader reader)
        { 
            // A tag format must be specified in the grammar header
            if (!_hasTagFormat)
            {
                ThrowSrgsException (SRID.MissingTagFormat); 
            }
 
            while (reader.MoveToNextAttribute ()) 
            {
                bool isInvalidAttribute = false; 

                switch (reader.NamespaceURI)
                {
                    case emptyNamespace: 
                    case sapiNamespace:
                        isInvalidAttribute = true; 
                        break; 
                }
                if (isInvalidAttribute) 
                {
                    ThrowSrgsException (SRID.InvalidTagAttribute, reader.Name);
                }
            } 

            return GetStringContent (reader).Trim (Helpers._achTrimChars); 
        } 

        ///  
        /// Parse the lexicon Element
        ///
        /// Attributes:
        ///     uri: required 
        ///     type: optional
        ///  
        ///  
        private static void ParseLexicon (XmlReader reader)
        { 
            bool isInvalidAttribute = false;
            bool fFoundUri = false;

            while (reader.MoveToNextAttribute ()) 
            {
                switch (reader.LocalName) 
                { 
                    case "uri":
                        fFoundUri = true; 
                        break;

                    case "type":
                        break; 

                    default: 
                        isInvalidAttribute = true; 
                        break;
                } 

                if (isInvalidAttribute)
                {
                    ThrowSrgsException (SRID.InvalidLexiconAttribute, reader.Name); 
                }
            } 
 
            if (!fFoundUri)
            { 
                ThrowSrgsException (SRID.MissingRequiredAttribute, "uri", "lexicon");
            }
            //
 
        }
 
        ///  
        /// Parse the Meta Element
        /// 
        /// Attributes:
        ///     name and http-equiv: one or the other but not bothsd
        ///     content: required
        ///  
        /// 
        private static void ParseMeta (XmlReader reader) 
        { 
            bool fFoundContent = false;
            bool fFoundNameOrEquiv = false; 
            bool isInvalidAttribute = false;

            while (reader.MoveToNextAttribute ())
            { 
                switch (reader.LocalName)
                { 
                    case "name": 
                    case "http-equiv":
                        if (fFoundNameOrEquiv) 
                        {
                            ThrowSrgsException (SRID.MetaNameHTTPEquiv);
                        }
                        fFoundNameOrEquiv = true; 
                        break;
 
                    case "content": 
                        isInvalidAttribute = fFoundContent;
                        fFoundContent = true; 
                        break;

                    default:
                        isInvalidAttribute = true; 
                        break;
                } 
 
                if (isInvalidAttribute)
                { 
                    ThrowSrgsException (SRID.InvalidMetaAttribute, reader.Name);
                }
            }
 
            if (!fFoundContent)
            { 
                ThrowSrgsException (SRID.MissingRequiredAttribute, "content", "meta"); 
            }
            if (!fFoundNameOrEquiv) 
            {
                ThrowSrgsException (SRID.MissingRequiredAttribute, "name or http-equiv", "meta");
            }
        } 

#if !NO_STG 
 
        private void ParseScript (XmlReader reader, IGrammar grammar)
        { 
            int line = _filename != null ? _xmlTextReader.LineNumber : -1;
            string sRule = null;

            while (reader.MoveToNextAttribute ()) 
            {
                switch (reader.NamespaceURI) 
                { 
                    case emptyNamespace:
                        ThrowSrgsException (SRID.InvalidScriptAttribute); 
                        break;

                    case sapiNamespace:
                        switch (reader.LocalName) 
                        {
                            case "rule": 
                                if (string.IsNullOrEmpty (sRule)) 
                                {
                                    sRule = reader.Value; 
                                }
                                else
                                {
                                    ThrowSrgsException (SRID.RuleAttributeDefinedMultipeTimes); 
                                }
                                break; 
 
                            default:
                                ThrowSrgsException (SRID.InvalidScriptAttribute); 
                                break;
                        }
                        break;
                } 
            }
            // if no rule or method defined - add the content to the generic _scrip 
            if (string.IsNullOrEmpty (sRule)) 
            {
                _parser.AddScript (grammar, GetStringContent (reader), _filename, line); 
            }
            else
            {
                // Adds a placeholder for the rule. 
                // Once all the rules and scripts are read, the placeholder will be replaced with the proper rule.
                _scripts.Add (new ForwardReference (sRule, _parser.AddScript (grammar, sRule, GetStringContent (reader), _filename, line))); 
            } 
        }
 
        static private void ParseAssemblyReference (XmlReader reader, IGrammar grammar)
        {
            while (reader.MoveToNextAttribute ())
            { 
                switch (reader.NamespaceURI)
                { 
                    case emptyNamespace: 
                        ThrowSrgsException (SRID.InvalidScriptAttribute);
                        break; 

                    case sapiNamespace:
                        switch (reader.LocalName)
                        { 
                            case "assembly":
                                grammar.AssemblyReferences.Add (reader.Value); 
                                break; 

                            default: 
                                ThrowSrgsException (SRID.InvalidAssemblyReferenceAttribute);
                                break;
                        }
                        break; 
                }
            } 
        } 

        static private void ParseImportNamespace (XmlReader reader, IGrammar grammar) 
        {
            while (reader.MoveToNextAttribute ())
            {
                switch (reader.NamespaceURI) 
                {
                    case emptyNamespace: 
                        ThrowSrgsException (SRID.InvalidScriptAttribute); 
                        break;
 
                    case sapiNamespace:
                        switch (reader.LocalName)
                        {
                            case "namespace": 
                                grammar.ImportNamespaces.Add (reader.Value);
                                break; 
 
                            default:
                                ThrowSrgsException (SRID.InvalidImportNamespaceAttribute); 
                                break;
                        }
                        break;
                } 
            }
        } 
#endif 

        private bool ProcessChildNodes (XmlReader reader, IElement parent, IRule rule, string parentName) 
        {
            bool fFirstElement = true;

            // Create a list of name value tags for this scope 
            List tags = null;
 
            reader.MoveToElement ();                                 // Move to containing parent of attributes 
            if (!reader.IsEmptyElement)
            { 
                reader.Read ();                                      // Move to first child parent
                while (reader.NodeType != XmlNodeType.EndElement)   // Process each child parent while not at end parent
                {
                    bool isInvalidNode = false; 

                    if (reader.NodeType == XmlNodeType.Element) 
                    { 
                        // Null if no children are allowed
                        if (parent == null) 
                        {
                            ThrowSrgsException (SRID.InvalidNotEmptyElement, parentName);
                        }
 
                        IElement child = null;
                        switch (reader.NamespaceURI) 
                        { 
                            case srgsNamespace:
 
                                switch (reader.LocalName)
                                {
                                    case "example":
                                        if (!(parent is IRule) || !fFirstElement) 
                                        {
                                            ThrowSrgsException (SRID.InvalidExampleOrdering); 
                                        } 
                                        else
                                        { 
                                            reader.Skip ();
                                            continue;
                                        }
 
                                        break;
 
                                    case "ruleref": 
                                        child = ParseRuleRef (parent, reader);
                                        break; 

                                    case "one-of":
                                        child = ParseOneOf (parent, rule, reader);
                                        break; 

                                    case "item": 
                                        child = ParseItem (parent, rule, reader); 
                                        break;
 
                                    case "token":
                                        child = ParseToken (parent, reader);
                                        break;
 
                                    case "tag":
                                        child = ParseTag (parent, reader); 
                                        IPropertyTag tag = child as IPropertyTag; 
                                        if (tag != null)
                                        { 
                                            // The tag list is delayed as it might not be necessary
                                            if (tags == null)
                                            {
                                                tags = new List (); 
                                            }
                                            tags.Add (tag); 
                                        } 
                                        break;
 
                                    case "rule":
                                    default:
                                        isInvalidNode = true;
                                        break; 
                                }
                                break; 
 
                            case sapiNamespace:
                                switch (reader.LocalName) 
                                {
                                    case "subset":
                                        if ((parent is IRule) || (parent is IItem))
                                        { 
                                            child = ParseSubset (parent, reader);
                                        } 
                                        else 
                                        {
                                            isInvalidNode = true; 
                                        }
                                        break;

                                    default: 
                                        isInvalidNode = true;
                                        break; 
                                } 
                                break;
 
                            default:
                                reader.Skip ();                      // Skip over parents in unknown namespaces
                                break;
                        } 
                        isInvalidNode = ParseChildNodeElement (parent, isInvalidNode, child);
                        fFirstElement = false; 
                    } 
                    else if (reader.NodeType == XmlNodeType.Text || reader.NodeType == XmlNodeType.CDATA)
                    { 
                        // Null if no children are allowed
                        if (parent == null)
                        {
                            ThrowSrgsException (SRID.InvalidNotEmptyElement, parentName); 
                        }
 
                        isInvalidNode = ParseChildNodeText (reader, parent); 
                        fFirstElement = false;
                    } 
                    else
                    {
                        reader.Skip ();                              // Skip over non-parent/text node types
                    } 

                    if (isInvalidNode) 
                    { 
                        ThrowSrgsException (SRID.InvalidElement, reader.Name);
                    } 
                }
            }

            reader.Read ();                                          // Move to next sibling 

            // Generate the tags for this scope 
            if (tags != null) 
            {
                foreach (IPropertyTag tag in tags) 
                {
                    tag.PostParse (parent);
                }
            } 
            return !fFirstElement;
        } 
 
        private bool ParseChildNodeText (XmlReader reader, IElement parent)
        { 
            bool isInvalidNode = false;
            string content = reader.Value;

            // Create the SrgsElement for the text 
            IElementText srgsText = _parser.CreateText (parent, content);
 
            // Split it in pieces 
            ParseText (parent, content, null, null, -1f);
 
            // if the parent is a one of, then the children must be an Item
            if (parent is IOneOf)
            {
                isInvalidNode = true; 
            }
            else 
            { 
                IRule parentRule = parent as IRule;
                if (parentRule != null) 
                {
                    _parser.AddElement (parentRule, srgsText);
                }
                else 
                {
                    IItem parentItem = parent as IItem; 
                    if (parentItem != null) 
                    {
                        _parser.AddElement (parentItem, srgsText); 
                    }
                    else
                    {
                        isInvalidNode = true; 
                    }
                } 
            } 

            reader.Read (); 
            return isInvalidNode;
        }

        private bool ParseChildNodeElement (IElement parent, bool isInvalidNode, IElement child) 
        {
            // The child parent has not been processed yet 
            if (child != null) 
            {
                // if the parent is a one of, then the children must be an Item 
                IOneOf parentOneOf = parent as IOneOf;
                if (parentOneOf != null)
                {
                    IItem childItem = child as IItem; 
                    if (childItem != null)
                    { 
                        _parser.AddItem (parentOneOf, childItem); 
                    }
                    else 
                    {
                        isInvalidNode = true;
                    }
                } 
                else
                { 
                    IRule parentRule = parent as IRule; 
                    if (parentRule != null)
                    { 
                        _parser.AddElement (parentRule, child);
                    }
                    else
                    { 
                        IItem parentItem = parent as IItem;
                        if (parentItem != null) 
                        { 
                            _parser.AddElement (parentItem, child);
                        } 
                        else
                        {
                            isInvalidNode = true;
                        } 
                    }
                } 
            } 

            return isInvalidNode; 
        }

        private void ProcessRulesAndScriptsNodes (XmlReader reader, IGrammar grammar)
        { 
            bool fProcessedRules = false;
 
            // Move to containing element of attributes 
            reader.MoveToElement ();
            if (!reader.IsEmptyElement) 
            {
                // Move to first child element
                reader.Read ();
 
                // Process each child element while not at end element
                while (reader.NodeType != XmlNodeType.EndElement) 
                { 
                    bool isInvalidNode = false;
 
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        switch (reader.NamespaceURI)
                        { 
                            case srgsNamespace:
                                switch (reader.LocalName) 
                                { 
                                    case "lexicon":
                                        if (fProcessedRules) 
                                        {
                                            ThrowSrgsException (SRID.InvalidGrammarOrdering);
                                        }
                                        ParseLexicon (reader); 
                                        break;
 
                                    case "meta": 
                                        if (fProcessedRules)
                                        { 
                                            ThrowSrgsException (SRID.InvalidGrammarOrdering);
                                        }
                                        ParseMeta (reader);
                                        break; 

                                    case "metadata": 
                                        if (fProcessedRules) 
                                        {
                                            ThrowSrgsException (SRID.InvalidGrammarOrdering); 
                                        }
                                        reader.Skip ();
                                        break;
 
                                    case "rule":
                                        IRule rule = ParseRule (grammar, reader); 
                                        rule.PostParse (grammar); 
                                        fProcessedRules = true;
                                        break; 

                                    case "tag":
                                        if (fProcessedRules || _hasTagFormat && grammar.TagFormat != SrgsTagFormat.W3cV1)
                                        { 
                                            ThrowSrgsException (SRID.InvalidGrammarOrdering);
                                        } 
                                        grammar.GlobalTags.Add (GetTagContent (grammar, reader)); 
                                        break;
 
                                    default:
                                        isInvalidNode = true;
                                        break;
                                } 
                                break;
 
                            case sapiNamespace: 
                                switch (reader.LocalName)
                                { 
#if !NO_STG
                                    case "script":
                                        ParseScript (reader, grammar);
                                        fProcessedRules = true; 
                                        break;
 
                                    case "assemblyReference": 
                                        ParseAssemblyReference (reader, grammar);
                                        fProcessedRules = true; 
                                        break;

                                    case "importNamespace":
                                        ParseImportNamespace (reader, grammar); 
                                        fProcessedRules = true;
                                        break; 
#endif 
                                    default:
                                        isInvalidNode = true; 
                                        break;
                                }
                                break;
 
                            default:
                                // Skip over elements in unknown namespaces 
                                reader.Skip (); 
                                break;
                        } 
                    }
                    else
                    {
                        if (reader.NodeType == XmlNodeType.Text) 
                        {
                            ThrowSrgsException (SRID.InvalidElement, "text"); 
                        } 
                        // Skip over non-element/text node types
                        reader.Skip (); 
                    }

                    if (isInvalidNode)
                    { 
                        ThrowSrgsException (SRID.InvalidElement, reader.Name);
                    } 
                } 
            }
 
            // Move to next sibling
            reader.Read ();
        }
 
        static private string GetStringContent (XmlReader reader)
        { 
            StringBuilder sb = new StringBuilder (); 

            reader.MoveToElement ();                                 // Move to containing element of attributes 
            if (!reader.IsEmptyElement)
            {
                reader.Read ();                                      // Move to first child element
                while (reader.NodeType != XmlNodeType.EndElement)   // Process each child element while not at end element 
                {
                    sb.Append (reader.ReadString ()); 
 
                    bool isInvalidNode = false;
 
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        switch (reader.NamespaceURI)
                        { 
                            case srgsNamespace:
                            case sapiNamespace: 
                                isInvalidNode = true; 
                                break;
 
                            default:
                                reader.Skip ();                      // Skip over elements in unknown namespaces
                                break;
                        } 
                    }
                    else if (reader.NodeType != XmlNodeType.EndElement) 
                    { 
                        reader.Skip ();                              // Skip over non-end element node types
                    } 

                    if (isInvalidNode)
                    {
                        ThrowSrgsException (SRID.InvalidElement, reader.Name); 
                    }
                } 
            } 

            reader.Read ();                                          // Move to next sibling 
            return sb.ToString ();
        }

        /// TODOC <_include file='doc\Tag.uex' path='docs/doc[@for="Tag.RepeatProbability"]/*' /> 
        static void ParsePropertyTag (string sTag, out string name, out object value)
        { 
            // Default value 
            name = null;
            value = string.Empty; 

            // Name=             pszValue = null     vValue = VT_EMPTY
            // Name="string"     pszValue = "string" vValue = VT_EMPTY
            // Name=true         pszValue = null     vValue = VT_BOOL 
            // Name=123          pszValue = null     vValue = VT_I4
            // Name=3.14         pszValue = null     vValue = VT_R8 
            int iEqual = sTag.IndexOf ('='); 

            if (iEqual >= 0) 
            {
                // Set property name
                name = sTag.Substring (0, iEqual).Trim (Helpers._achTrimChars);
                iEqual++; 
            }
            else 
            { 
                iEqual = 0;
            } 

            // Set property value
            int cLenProperty = sTag.Length;
 
            if (iEqual < cLenProperty)
            { 
                if (sTag [iEqual] == '"') 
                {
                    // Name="string" 
                    iEqual++;

                    int iEndQuote = sTag.IndexOf ('"', iEqual + 1);
 
                    if (iEndQuote + 1 != cLenProperty)
                    { 
                        // Invalid string value 
                        XmlParser.ThrowSrgsException (SRID.IncorrectAttributeValue, name, sTag.Substring (iEqual));
                    } 

                    value = sTag.Substring (iEqual, iEndQuote - iEqual);
                }
                else 
                {
                    string sValue = sTag.Substring (iEqual); 
                    int iValue; 

                    if (int.TryParse (sValue, out iValue)) 
                    {
                        // propInfo.pszValue = null
                        // Name=123
                        // propInfo.vValue = VT_I4 
                        value = iValue;
                    } 
                    else 
                    {
                        double flValue; 

                        if (double.TryParse (sValue, out flValue))
                        {
                            // propInfo.pszValue = null 
                            // propInfo.vValue   = VT_R8
                            value = flValue; 
                        } 
                        else
                        { 
                            bool fValue;

                            if (bool.TryParse (sValue, out fValue))
                            { 
                                // Name=true
                                // propInfo.pszValue = null 
                                // propInfo.vValue   = VT_BOOL 
                                value = fValue;
                            } 
                            else
                            {
                                XmlParser.ThrowSrgsException (SRID.InvalidNameValueProperty, name, sValue);
                            } 
                        }
                    } 
                } 
            }
        } 

        /// 
        /// Convert integer range string to MinValue and MaxValue.
        /// For n- format, MaxValue = Int32.MaxValue 
        /// Valid formats: n|n-|n-m     n,m integers
        ///                integer = [whitespace] [+] [0[{x|X}]] [digits] 
        ///  
        /// 
        ///  
        /// 
        static private void SetRepeatValues (string repeat, out int minRepeat, out int maxRepeat)
        {
            minRepeat = maxRepeat = 1; 
            if (!string.IsNullOrEmpty (repeat))
            { 
                int sep = repeat.IndexOf ("-", StringComparison.Ordinal); 

                if (sep < 0) 
                {
                    int minmax = Convert.ToInt32 (repeat, CultureInfo.InvariantCulture);

                    // Limit the range of valid values 
                    if (minmax < 0 || minmax > 255)
                    { 
                        XmlParser.ThrowSrgsException (SRID.MinMaxOutOfRange, minmax, minmax); 
                    }
                    minRepeat = maxRepeat = minmax; 
                }
                else if (0 < sep)
                {
                    minRepeat = Convert.ToInt32 (repeat.Substring (0, sep), CultureInfo.InvariantCulture); 
                    if (sep < (repeat.Length - 1))
                    { 
                        maxRepeat = Convert.ToInt32 (repeat.Substring (sep + 1), CultureInfo.InvariantCulture); 
                    }
                    else 
                    {
                        maxRepeat = System.Int32.MaxValue;
                    }
                    // Limit the range of valid values 
                    if (minRepeat < 0 || minRepeat > 255 || (maxRepeat != System.Int32.MaxValue && (maxRepeat < 0 || maxRepeat > 255)))
                    { 
                        XmlParser.ThrowSrgsException (SRID.MinMaxOutOfRange, minRepeat, maxRepeat); 
                    }
 
                    // Max be greater or equal to min
                    if (minRepeat > maxRepeat)
                    {
                        throw new ArgumentException (SR.Get (SRID.MinGreaterThanMax)); 
                    }
                } 
                else 
                {
                    ThrowSrgsException (SRID.InvalidItemRepeatAttribute, repeat); 
                }
            }
            else
            { 
                ThrowSrgsException (SRID.InvalidItemAttribute2);
            } 
        } 

        private static void CheckForDuplicates (ref string dest, XmlReader reader) 
        {
            if (!string.IsNullOrEmpty (dest))
            {
                StringBuilder attribute = new StringBuilder (reader.LocalName); 
                if (reader.NamespaceURI.Length > 0)
                { 
                    attribute.Append (reader.NamespaceURI); 
                    attribute.Append (":");
                } 
                XmlParser.ThrowSrgsException (SRID.InvalidAttributeDefinedTwice, reader.Value, attribute);
            }
            dest = reader.Value;
        } 

        // Throws exception if the specified Rule does not have a valid Id. 
        static internal void ValidateRuleId (string id) 
        {
            Helpers.ThrowIfEmptyOrNull (id, "id"); 

            if (!XmlReader.IsName (id) || (id == "NULL") || (id == "VOID") || (id == "GARBAGE") || (id.IndexOfAny (_invalidRuleIdChars) != -1))
            {
                XmlParser.ThrowSrgsException (SRID.InvalidRuleId, id); 
            }
        } 
 
        private void ValidateRulerefNotPointingToSelf (string uri)
        { 
            // Check that the uri pointed to in the ruleref does not point this file
            // in srgs.xml: ... 
            if (_filename != null) 
            {
                if (uri.IndexOf (_shortFilename, StringComparison.Ordinal) == 0 && (uri.Length > _shortFilename.Length && uri [_shortFilename.Length] == '#' || uri.Length == _shortFilename.Length)) 
                { 
                    ThrowSrgsException (SRID.InvalidRuleRefSelf);
                } 
            }
        }

        private void ValidateScripts () 
        {
#if !NO_STG 
            // Check that the rule and methods are defined for a script 
            foreach (ForwardReference script in _scripts)
            { 
                if (!_rules.Contains (script._name))
                {
                    ThrowSrgsException (SRID.InvalidScriptDefinition, script._name);
                } 
            }
#endif 
            // Validate for unique rule names 
            List ruleNames = new List ();
 
            foreach (string rule in _rules)
            {
                if (ruleNames.Contains (rule))
                { 
                    XmlParser.ThrowSrgsException (SRID.RuleAttributeDefinedMultipeTimes, rule);
                } 
 
                ruleNames.Add (rule);
            } 
        }

        #endregion
 
        //********************************************************************
        // 
        // Private Fields 
        //
        //******************************************************************* 

        #region Private Fields

        private IElementFactory _parser; 

        // Avoid to do a cast many times 
        private XmlReader _reader; 

        // Avoid to do a cast many times 
        private XmlTextReader _xmlTextReader;

        // Save the filename
        private string _filename; 

        // Save the filename without the path 
        private string _shortFilename; 

        // Language Id for this grammar 
        private CultureInfo _langId;

        // Has the Grammar element a FormatTag
        private bool _hasTagFormat; 

#if SPEECHSERVER 
        // Has the Grammar element a FormatTag 
        private bool _w3c_literal;
#endif 
        // All defined rules
        List _rules = new List ();

#if !NO_STG 
        List _scripts = new List ();
#endif 
 
        static private readonly char [] _invalidRuleIdChars = new char [] { '.', ':', '-', '#' };
 
        static private readonly char [] _SlashBackSlash = new char [] { '\\', '/' };

        #endregion
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//  
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//
// Description: 
//      The Srgs xml parser parse takes as input an xml reader and the IElementFactory
//      interface. With this virtualization scheme, the srgs parser do not create 
//      directly Srgs elements. Instead methods on a set of interfaces for each 
//      Srgs Element creates the element themselve. The underlying implementation
//      for each elements is different for the SrgsDocument class and the Srgs 
//      Compiler.
//
//      Interface definition for the IElement
// History: 
//		6/1/2004	jeanfp		Created
//----------------------------------------------------------------------------using System; 
 
using System;
using System.Globalization; 
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml; 
using System.Collections;
using System.Collections.Generic; 
using System.Speech.Recognition.SrgsGrammar; 

#pragma warning disable 1634, 1691 // Allows suppression of certain PreSharp messages. 
#pragma warning disable 56524 // The _reader and  and _xmlReader are not created in this module and should not be disposed

// Remove all the check for null or empty warnings
#pragma warning disable 56507 

namespace System.Speech.Internal.SrgsParser 
{ 
    internal class XmlParser : ISrgsParser
    { 
        //*******************************************************************
        //
        // Constructors
        // 
        //*******************************************************************
 
        #region Constructors 

        internal XmlParser (XmlReader reader, Uri uri) 
        {
            _reader = reader;
            _xmlTextReader = reader as XmlTextReader;
 
            // Try to guess the Uri
            if (uri == null) 
            { 
                // Keep a reference to the filename and XmlTextReader if it is one.
                if (_xmlTextReader != null && _xmlTextReader.BaseURI.Length > 0) 
                {
                    try
                    {
                        uri = new Uri (_xmlTextReader.BaseURI); 
                    }
#pragma warning disable 56502 // Remove the empty catch statements warnings 
                    catch (UriFormatException) 
                    {
                    } 
#pragma warning restore 56502
                }
            }
 
            // Saves the path to the file and the file name
            if (uri != null) 
            { 
                // Saves the full path to the file
                _filename = !uri.IsAbsoluteUri || !uri.IsFile ? uri.OriginalString : uri.LocalPath; 

                // Saves the filename without the path
                int iPosSlash = _filename.LastIndexOfAny (_SlashBackSlash);
                _shortFilename = iPosSlash >= 0 ? _filename.Substring (iPosSlash + 1) : _filename; 
            }
        } 
 
        #endregion
 
        //*******************************************************************
        //
        // Internal Methods
        // 
        //********************************************************************
 
        #region Internal Methods 

        // Initializes the object from a stream containg SRGS in XML 
        public void Parse ()
        {
            try
            { 
                bool isGrammarElementFound = false;
 
 
                while (_reader.Read ())
                { 
                    // Ignore XmlDeclaration, ProcessingInstruction, Comment, DocumentType, Entity, Notation.
                    if (_reader.NodeType == XmlNodeType.Element && _reader.LocalName == "grammar")
                    {
                        if (_reader.NamespaceURI != srgsNamespace) 
                        {
                            ThrowSrgsException (SRID.InvalidSrgsNamespace); 
                        } 

                        if (isGrammarElementFound) 
                        {
                            ThrowSrgsException (SRID.GrammarDefTwice);
                        }
                        else 
                        {
                            ParseGrammar (_reader, _parser.Grammar); 
                            isGrammarElementFound = true; 
                        }
                    } 
                }

                if (!isGrammarElementFound)
                { 
                    ThrowSrgsException (SRID.InvalidSrgs);
                } 
            } 
            catch (XmlException eXml)
            { 
                _parser.RemoveAllRules ();
                ThrowSrgsExceptionWithPosition (_filename, _reader, SR.Get (SRID.InvalidXmlFormat), eXml);
            }
            catch (FormatException e) 
            {
                // Adds a placeholder for the rule. 
                // Once all the rules and scripts are read, the placeholder will be replaced with the proper rule. 
                _parser.RemoveAllRules ();
                ThrowSrgsExceptionWithPosition (_filename, _reader, e.Message, e.InnerException); 
            }
            catch
            {
                // clear all the rules 
                _parser.RemoveAllRules ();
                throw; 
            } 
        }
 
        /// 
        /// Break the string into individual tokens and ParseToken() each individual token.
        ///
        /// Token string is a sequence of 0 or more white space delimited tokens. 
        /// Tokens may also be delimited by double quotes.  In these cases, the double
        /// quotes token must be surrounded by white space or string boundary. 
        ///  
        /// Parent element
        ///  
        /// 
        /// 
        /// 
        ///  
        internal static void ParseText (IElement parent, string sChars, string pronunciation, string display, float reqConfidence, CreateTokenCallback createTokens)
        { 
            sChars = sChars.Trim (Helpers._achTrimChars); 

            char [] achToken = sChars.ToCharArray (); 
            int iTokenEnd = 0;
            int cChars = sChars.Length;

            for (int i = 0; i < achToken.Length; i = iTokenEnd + 1) 
            {
                if (achToken [i] == ' ')                            // Skip white spaces 
                { 
                    iTokenEnd = i;
                    continue; 
                }

                // Find the next token
                if (achToken [i] == '"') 
                {
                    // Quoted string.  Find end of quoted string. 
                    iTokenEnd = ++i; 
                    while ((iTokenEnd < cChars) && (achToken [iTokenEnd] != '"'))
                    { 
                        iTokenEnd++;
                    }

                    if (iTokenEnd >= cChars || achToken [iTokenEnd] != '"') 
                    {
                        // Cannot find matching double quote. 
                        // "Invalid double-quoted string." 
                        XmlParser.ThrowSrgsException (SRID.InvalidQuotedString);
                    } 

                    if (iTokenEnd + 1 != cChars && achToken [iTokenEnd + 1] != ' ')
                    {
                        // Quoted token not surrounded by whitespace."); 
                        // "Invalid double-quoted string."
                        XmlParser.ThrowSrgsException (SRID.InvalidQuotedString); 
                    } 
                }
                else 
                {
                    // Regular token.  Find next white space character or end of string
                    iTokenEnd = i + 1;
                    while ((iTokenEnd < cChars) && achToken [iTokenEnd] != ' ') 
                    {
                        iTokenEnd++; 
                    } 
                }
 
                string sToken = sChars.Substring (i, iTokenEnd - i);
                if (sToken.IndexOf ('"') != -1)
                {
                    // "The token string is not allowed to contain double quote character." 
                    XmlParser.ThrowSrgsException (SRID.InvalidTokenString);
                } 
 
                // Parse the token.
                if (createTokens != null) 
                {
                    createTokens (parent, sToken, pronunciation, display, reqConfidence);
                }
            } 
        }
 
        ///  
        /// Throws an Exception with the error specified by the resource ID.
        /// Add the line and column number if the XmlReader is a TextReader 
        /// 
        /// 
        /// 
        internal static void ThrowSrgsException (SRID id, params object [] args) 
        {
            throw new FormatException (SR.Get (id, args)); 
        } 

        ///  
        /// Throws an Exception with the error specified by the resource ID.
        /// Add the line and column number if the XmlReader is a TextReader
        /// 
        ///  
        /// 
        ///  
        ///  
        internal static void ThrowSrgsExceptionWithPosition (string filename, XmlReader xmlReader, string sError, Exception innerException)
        { 
            // Add the line and column number if the XmlReader is a XmlTextReader
            XmlTextReader xmlTextReader = xmlReader as XmlTextReader;
            if (xmlTextReader != null)
            { 
                string sLine = SR.Get (SRID.Line);
                string sPosition = SR.Get (SRID.Position); 
                int line = xmlTextReader.LineNumber; 
                int position = xmlTextReader.LinePosition;
                if (filename == null) 
                {
                    sError += string.Format (CultureInfo.InvariantCulture, " [{0}={1}, {2}={3}]", sLine, line, sPosition, position);
                }
                else 
                {
                    sError = string.Format (CultureInfo.InvariantCulture, "{0}({1},{2}): error : {3}", filename, line, position, sError); 
                } 
            }
            throw new FormatException (sError, innerException); 
        }

        #endregion
 
        //*******************************************************************
        // 
        // Internal Properties 
        //
        //******************************************************************** 

        #region Internal Methods

        // Inmplementation of the internal interface ISrgsParser 
        public IElementFactory ElementFactory
        { 
            set 
            {
                _parser = value; 
            }
        }

        #endregion 

        //******************************************************************** 
        // 
        // Internal fields
        // 
        //*******************************************************************

        #region Internal fields
 
        internal const string emptyNamespace = "";
 
        internal const string xmlNamespace = "http://www.w3.org/XML/1998/namespace"; 

        internal const string srgsNamespace = "http://www.w3.org/2001/06/grammar"; 

        internal const string sapiNamespace = "http://schemas.microsoft.com/Speech/2002/06/SRGSExtensions";

        #endregion 

        //******************************************************************** 
        // 
        // Private Type
        // 
        //*******************************************************************

        #region Private Type
 
        // Must be a class to be used with generics
        [Serializable] 
        internal class ForwardReference 
        {
            internal ForwardReference (string name, string value) 
            {
                _name = name;
                _value = value;
            } 

            internal string _name; 
            internal string _value; 
        }
        #endregion 

        //*******************************************************************
        //
        // Private Methods 
        //
        //******************************************************************* 
 
        #region Private Methods
 
        // The perf gain using .Lengh == 0 other  readability is not worth it fixing this FxCop issue
        private void ParseGrammar (XmlReader reader, IGrammar grammar)
        {
            string sAlphabet = null; 
#if !NO_STG
            string sLanguage = null; 
            string sNamespace = null; 
#endif
            string sVersion = null; 
            GrammarType grammarType = GrammarType.VoiceGrammar;

            // Process attributes.
            while (reader.MoveToNextAttribute ()) 
            {
                bool isInvalidAttribute = false; 
 
                switch (reader.NamespaceURI)
                { 
                    case emptyNamespace:
                        switch (reader.LocalName)
                        {
                            case "root": 
                                if (grammar.Root == null)
                                { 
                                    grammar.Root = reader.Value; 
                                }
                                else 
                                {
                                    ThrowSrgsException (SRID.RootRuleAlreadyDefined);
                                }
                                break; 

                            case "version": 
                                CheckForDuplicates (ref sVersion, reader); 
                                if (sVersion != "1.0")
                                { 
                                    ThrowSrgsException (SRID.InvalidVersion);
                                }

                                break; 

                            case "tag-format": 
                                switch (reader.Value) 
                                {
                                    case "semantics/1.0": 
                                        grammar.TagFormat = SrgsTagFormat.W3cV1;
                                        _hasTagFormat = true;
                                        break;
 
#if SPEECHSERVER
                                    case "semantics/1.0-literals": 
                                        grammar.TagFormat = SrgsTagFormat.W3cV1; 
                                        _w3c_literal = _hasTagFormat = true;
                                        break; 
#endif
                                    case "semantics-ms/1.0":
                                        grammar.TagFormat = SrgsTagFormat.MssV1;
                                        _hasTagFormat = true; 
                                        break;
 
                                    case "properties-ms/1.0": 
                                        grammar.TagFormat = SrgsTagFormat.KeyValuePairs;
                                        _hasTagFormat = true; 
                                        break;

                                    case "":
                                        break; 

                                    default: 
                                        ThrowSrgsException (SRID.InvalidTagFormat); 
                                        break;
                                } 
                                break;

                            case "mode":
                                switch (reader.Value) 
                                {
                                    case "voice": 
                                        grammar.Mode = GrammarType.VoiceGrammar; 
                                        break;
 
                                    case "dtmf":
                                        grammarType = grammar.Mode = GrammarType.DtmfGrammar;
                                        break;
 
                                    default:
                                        ThrowSrgsException (SRID.InvalidGrammarMode); 
                                        break; 
                                }
                                break; 

                            default:
                                isInvalidAttribute = true;
                                break; 
                        }
                        break; 
 
                    case xmlNamespace:
                        switch (reader.LocalName) 
                        {
                            case "lang":
                                string language = reader.Value;
                                try 
                                {
                                    grammar.Culture = _langId = new CultureInfo (language); 
                                } 
                                catch (ArgumentException)
                                { 
                                    // Special case for "es-us", create a new CultureInfo based on attributes of spanish
                                    // and english
                                    if (string.Compare ("es-us", language, StringComparison.OrdinalIgnoreCase) == 0)
                                    { 
                                        Helpers.CombineCulture ("es-ES", "en-US", new CultureInfo ("es"), 0x540A);
                                        grammar.Culture = _langId = new CultureInfo (language); 
                                    } 
                                    else
                                    { 
                                        // Unknown Culture info, fall back to the base culture.
                                        int pos = reader.Value.IndexOf ("-", StringComparison.Ordinal);
                                        if (pos > 0)
                                        { 
                                            grammar.Culture = _langId = new CultureInfo (reader.Value.Substring (0, pos));
                                        } 
                                        else 
                                        {
                                            throw; 
                                        }
                                    }
                                }
                                break; 

                            case "base": 
                                grammar.XmlBase = new Uri (reader.Value); 
                                break;
                        } 
                        break;

                    case sapiNamespace:
                        switch (reader.LocalName) 
                        {
                            case "alphabet": 
                                CheckForDuplicates (ref sAlphabet, reader); 
                                switch (sAlphabet)
                                { 
                                    case "ipa":
                                        grammar.PhoneticAlphabet = AlphabetType.Ipa;
                                        break;
 
                                    case "sapi":
                                    case "x-sapi": 
                                    case "x-microsoft-sapi": 
                                        grammar.PhoneticAlphabet = AlphabetType.Sapi;
                                        break; 

                                    case "ups":
                                    case "x-ups":
                                    case "x-microsoft-ups": 
                                        grammar.PhoneticAlphabet = AlphabetType.Ups;
                                        break; 
 
                                    default:
                                        ThrowSrgsException (SRID.UnsupportedPhoneticAlphabet, reader.Value); 
                                        break;
                                }
                                break;
 
#if !NO_STG
                            case "language": 
                                CheckForDuplicates (ref sLanguage, reader); 
                                if (sLanguage == "C#" || sLanguage == "VB.Net")
                                { 
                                    grammar.Language = sLanguage;
                                }
                                else
                                { 
                                    ThrowSrgsException (SRID.UnsupportedLanguage, reader.Value);
                                } 
                                break; 

                            case "namespace": 
                                CheckForDuplicates (ref sNamespace, reader);
                                if (string.IsNullOrEmpty (sNamespace))
                                {
                                    ThrowSrgsException (SRID.NoName1, "namespace"); 
                                }
                                grammar.Namespace = sNamespace; 
                                break; 

                            case "codebehind": 
                                if (reader.Value.Length == 0)
                                {
                                    ThrowSrgsException (SRID.NoName1, "codebehind");
                                } 
                                grammar.CodeBehind.Add (reader.Value);
                                break; 
 
                            case "debug":
                                bool f; 
                                if (bool.TryParse (reader.Value, out f))
                                {
                                    grammar.Debug = f;
                                } 
                                break;
#endif 
                            default: 
                                isInvalidAttribute = true;
                                break; 
                        }
                        break;
                }
                if (isInvalidAttribute) 
                {
                    ThrowSrgsException (SRID.InvalidGrammarAttribute, reader.Name); 
                } 
            }
 
            // The version attribute is required  for the grammar element
            if (sVersion == null)
            {
                ThrowSrgsException (SRID.MissingRequiredAttribute, "version", "grammar"); 
            }
 
            // The langId is require for voice grammars 
            if (_langId == null)
            { 
                if (grammarType == GrammarType.VoiceGrammar)
                {
                    ThrowSrgsException (SRID.MissingRequiredAttribute, "xml:lang", "grammar");
                } 
                else
                { 
                    _langId = CultureInfo.CurrentUICulture; 
                }
            } 

            // Process child elements.
            ProcessRulesAndScriptsNodes (reader, grammar);
 
            // Validate all the scripts elements
            ValidateScripts (); 
 
#if !NO_STG
            // Add all the scripts to the rules 
            foreach (ForwardReference script in _scripts)
            {
                _parser.AddScript (grammar, script._name, script._value);
            } 
#endif
            // Finish all initialisation - should check for the Root and the all 
            // rules are defined 
            grammar.PostParse (null);
 
        }

        // The perf gain using .Lengh == 0 other  readability is not worth it fixing this FxCop issue
        private IRule ParseRule (IGrammar grammar, XmlReader reader) 
        {
            string id = null; 
            string scope = null; 
            string dynamic = null;
            RulePublic publicRule = RulePublic.NotSet; 
            RuleDynamic ruleDynamic = RuleDynamic.NotSet;

#if !NO_STG
            string sBaseClass = null; 
            string sInit = null;
            string sParse = null; 
            string sError = null; 
            string sRecognition = null;
#endif 

            while (reader.MoveToNextAttribute ())
            {
                bool isInvalidAttribute = false; 

                switch (reader.NamespaceURI) 
                { 
                    case emptyNamespace:
                        switch (reader.LocalName) 
                        {
                            case "id":
                                CheckForDuplicates (ref id, reader);
                                break; 

                            case "scope": 
                                CheckForDuplicates (ref scope, reader); 
                                switch (scope)
                                { 
                                    case "private":
                                        publicRule = RulePublic.False;
                                        break;
 
                                    case "public":
                                        publicRule = RulePublic.True; 
                                        break; 

                                    default: 
                                        ThrowSrgsException (SRID.InvalidRuleScope);
                                        break;
                                }
                                break; 

                            default: 
                                isInvalidAttribute = true; 
                                break;
                        } 
                        break;

                    case sapiNamespace:
                        switch (reader.LocalName) 
                        {
                            case "dynamic": 
                                CheckForDuplicates (ref dynamic, reader); 
                                switch (dynamic)
                                { 
                                    case "true":
                                        ruleDynamic = RuleDynamic.True;
                                        break;
 
                                    case "false":
                                        ruleDynamic = RuleDynamic.False; 
                                        break; 

                                    default: 
                                        ThrowSrgsException (SRID.InvalidDynamicSetting);
                                        break;
                                }
                                break; 

#if !NO_STG 
                            case "baseclass": 
                                CheckForDuplicates (ref sBaseClass, reader);
                                if (string.IsNullOrEmpty (sBaseClass)) 
                                {
                                    ThrowSrgsException (SRID.NoName1, "baseclass");
                                }
                                break; 

                            case "onInit": 
                                CheckForDuplicates (ref sInit, reader); 
                                sInit = reader.Value;
                                break; 

                            case "onParse":
                                CheckForDuplicates (ref sParse, reader);
                                sParse = reader.Value; 
                                break;
 
                            case "onError": 
                                CheckForDuplicates (ref sError, reader);
                                sError = reader.Value; 
                                break;

                            case "onRecognition":
                                CheckForDuplicates (ref sRecognition, reader); 
                                break;
#endif 
                            default: 
                                isInvalidAttribute = true;
                                break; 
                        }
                        break;
                }
                if (isInvalidAttribute) 
                {
                    ThrowSrgsException (SRID.InvalidRuleAttribute, reader.Name); 
                } 
            }
 
            if (string.IsNullOrEmpty (id))
            {
                ThrowSrgsException (SRID.NoRuleId);
            } 

#if !NO_STG 
            if (sInit != null && publicRule != RulePublic.True) 
            {
                XmlParser.ThrowSrgsException (SRID.OnInitOnPublicRule, "OnInit", id); 
            }

            if (sRecognition != null && publicRule != RulePublic.True)
            { 
                XmlParser.ThrowSrgsException (SRID.OnInitOnPublicRule, "OnRecognition", id);
            } 
 
            ValidateRuleId (id);
 
            bool hasScript = sInit != null || sParse != null || sError != null || sRecognition != null;
            IRule rule = grammar.CreateRule (id, publicRule, ruleDynamic, hasScript);

            if (!string.IsNullOrEmpty (sInit)) 
            {
                rule.CreateScript (grammar, id, sInit, RuleMethodScript.onInit); 
            } 

            if (!string.IsNullOrEmpty (sParse)) 
            {
                rule.CreateScript (grammar, id, sParse, RuleMethodScript.onParse);
            }
 
            if (!string.IsNullOrEmpty (sError))
            { 
                rule.CreateScript (grammar, id, sError, RuleMethodScript.onError); 
            }
 
            if (!string.IsNullOrEmpty (sRecognition))
            {
                rule.CreateScript (grammar, id, sRecognition, RuleMethodScript.onRecognition);
            } 

            rule.BaseClass = sBaseClass; 
#else 
            ValidateRuleId (id);
 
            IRule rule = grammar.CreateRule (id, publicRule, ruleDynamic, false);
#endif
            _rules.Add (id);
 
            if (!ProcessChildNodes (reader, rule, rule, "rule"))
            { 
                if (ruleDynamic != RuleDynamic.True) 
                {
                    ThrowSrgsException (SRID.InvalidEmptyRule, "rule", id); 
                }
            }
            return rule;
        } 

        // The perf gain using .Lengh == 0 other  readability is not worth it fixing this FxCop issue 
        private IRuleRef ParseRuleRef (IElement parent, XmlReader reader) 
        {
            IRuleRef ruleRef = null; 

            string sAlias = null;
            string sParams = null;
            string uri = null; 

            while (reader.MoveToNextAttribute ()) 
            { 
                bool isInvalidAttribute = false;
 
                switch (reader.NamespaceURI)
                {
                    case emptyNamespace:
                        switch (reader.LocalName) 
                        {
                            case "uri": 
                                // Check that the uri pointed to in the ruleref does not point this file 
                                // in srgs.xml: ... = 0) 
            {
                ThrowSrgsException (SRID.InvalidTokenString);
            }
 
            return _parser.CreateToken (parent, content, sPronunciation, sDisplay, reqConfidence);
        } 
 
        /// 
        /// Break the string into individual tokens and ParseToken() each individual token. 
        ///
        /// Token string is a sequence of 0 or more white space delimited tokens.
        /// Tokens may also be delimited by double quotes.  In these cases, the double
        /// quotes token must be surrounded by white space or string boundary. 
        /// 
        /// Parent element 
        ///  
        /// 
        ///  
        /// 
        private void ParseText (IElement parent, string sChars, string pronunciation, string display, float reqConfidence)
        {
            System.Diagnostics.Debug.Assert ((parent != null) && (!string.IsNullOrEmpty (sChars))); 

            ParseText (parent, sChars, pronunciation, display, reqConfidence, new CreateTokenCallback (_parser.CreateToken)); 
        } 

        private IElement ParseTag (IElement parent, XmlReader reader) 
        {
            string content = GetTagContent (parent, reader);

            //Return an empty tag if the content is empty 
            if (string.IsNullOrEmpty (content))
            { 
                return _parser.CreateSemanticTag (parent); 
            }
 
            if (_parser.Grammar.TagFormat != SrgsTagFormat.KeyValuePairs)
            {
                ISemanticTag semanticTag = _parser.CreateSemanticTag (parent);
 
#if SPEECHSERVER
                // For semantic interpretation literal, surround the content of the tag bu "out=" 
                if (_w3c_literal) 
                {
                    content = string.Format (CultureInfo.InvariantCulture, "out=\"{0}\";", content); 
                }
#endif
                semanticTag.Content (parent, content, 0);
                return semanticTag; 
            }
 
            System.Diagnostics.Debug.Assert (_parser.Grammar.TagFormat == SrgsTagFormat.KeyValuePairs); 

            IPropertyTag propertyTag = _parser.CreatePropertyTag (parent); ; 
            string name;
            object value;
            ParsePropertyTag (content, out name, out value);
            propertyTag.NameValue (parent, name, value); 
            return propertyTag;
        } 
 
        private string GetTagContent (IElement parent, XmlReader reader)
        { 
            // A tag format must be specified in the grammar header
            if (!_hasTagFormat)
            {
                ThrowSrgsException (SRID.MissingTagFormat); 
            }
 
            while (reader.MoveToNextAttribute ()) 
            {
                bool isInvalidAttribute = false; 

                switch (reader.NamespaceURI)
                {
                    case emptyNamespace: 
                    case sapiNamespace:
                        isInvalidAttribute = true; 
                        break; 
                }
                if (isInvalidAttribute) 
                {
                    ThrowSrgsException (SRID.InvalidTagAttribute, reader.Name);
                }
            } 

            return GetStringContent (reader).Trim (Helpers._achTrimChars); 
        } 

        ///  
        /// Parse the lexicon Element
        ///
        /// Attributes:
        ///     uri: required 
        ///     type: optional
        ///  
        ///  
        private static void ParseLexicon (XmlReader reader)
        { 
            bool isInvalidAttribute = false;
            bool fFoundUri = false;

            while (reader.MoveToNextAttribute ()) 
            {
                switch (reader.LocalName) 
                { 
                    case "uri":
                        fFoundUri = true; 
                        break;

                    case "type":
                        break; 

                    default: 
                        isInvalidAttribute = true; 
                        break;
                } 

                if (isInvalidAttribute)
                {
                    ThrowSrgsException (SRID.InvalidLexiconAttribute, reader.Name); 
                }
            } 
 
            if (!fFoundUri)
            { 
                ThrowSrgsException (SRID.MissingRequiredAttribute, "uri", "lexicon");
            }
            //
 
        }
 
        ///  
        /// Parse the Meta Element
        /// 
        /// Attributes:
        ///     name and http-equiv: one or the other but not bothsd
        ///     content: required
        ///  
        /// 
        private static void ParseMeta (XmlReader reader) 
        { 
            bool fFoundContent = false;
            bool fFoundNameOrEquiv = false; 
            bool isInvalidAttribute = false;

            while (reader.MoveToNextAttribute ())
            { 
                switch (reader.LocalName)
                { 
                    case "name": 
                    case "http-equiv":
                        if (fFoundNameOrEquiv) 
                        {
                            ThrowSrgsException (SRID.MetaNameHTTPEquiv);
                        }
                        fFoundNameOrEquiv = true; 
                        break;
 
                    case "content": 
                        isInvalidAttribute = fFoundContent;
                        fFoundContent = true; 
                        break;

                    default:
                        isInvalidAttribute = true; 
                        break;
                } 
 
                if (isInvalidAttribute)
                { 
                    ThrowSrgsException (SRID.InvalidMetaAttribute, reader.Name);
                }
            }
 
            if (!fFoundContent)
            { 
                ThrowSrgsException (SRID.MissingRequiredAttribute, "content", "meta"); 
            }
            if (!fFoundNameOrEquiv) 
            {
                ThrowSrgsException (SRID.MissingRequiredAttribute, "name or http-equiv", "meta");
            }
        } 

#if !NO_STG 
 
        private void ParseScript (XmlReader reader, IGrammar grammar)
        { 
            int line = _filename != null ? _xmlTextReader.LineNumber : -1;
            string sRule = null;

            while (reader.MoveToNextAttribute ()) 
            {
                switch (reader.NamespaceURI) 
                { 
                    case emptyNamespace:
                        ThrowSrgsException (SRID.InvalidScriptAttribute); 
                        break;

                    case sapiNamespace:
                        switch (reader.LocalName) 
                        {
                            case "rule": 
                                if (string.IsNullOrEmpty (sRule)) 
                                {
                                    sRule = reader.Value; 
                                }
                                else
                                {
                                    ThrowSrgsException (SRID.RuleAttributeDefinedMultipeTimes); 
                                }
                                break; 
 
                            default:
                                ThrowSrgsException (SRID.InvalidScriptAttribute); 
                                break;
                        }
                        break;
                } 
            }
            // if no rule or method defined - add the content to the generic _scrip 
            if (string.IsNullOrEmpty (sRule)) 
            {
                _parser.AddScript (grammar, GetStringContent (reader), _filename, line); 
            }
            else
            {
                // Adds a placeholder for the rule. 
                // Once all the rules and scripts are read, the placeholder will be replaced with the proper rule.
                _scripts.Add (new ForwardReference (sRule, _parser.AddScript (grammar, sRule, GetStringContent (reader), _filename, line))); 
            } 
        }
 
        static private void ParseAssemblyReference (XmlReader reader, IGrammar grammar)
        {
            while (reader.MoveToNextAttribute ())
            { 
                switch (reader.NamespaceURI)
                { 
                    case emptyNamespace: 
                        ThrowSrgsException (SRID.InvalidScriptAttribute);
                        break; 

                    case sapiNamespace:
                        switch (reader.LocalName)
                        { 
                            case "assembly":
                                grammar.AssemblyReferences.Add (reader.Value); 
                                break; 

                            default: 
                                ThrowSrgsException (SRID.InvalidAssemblyReferenceAttribute);
                                break;
                        }
                        break; 
                }
            } 
        } 

        static private void ParseImportNamespace (XmlReader reader, IGrammar grammar) 
        {
            while (reader.MoveToNextAttribute ())
            {
                switch (reader.NamespaceURI) 
                {
                    case emptyNamespace: 
                        ThrowSrgsException (SRID.InvalidScriptAttribute); 
                        break;
 
                    case sapiNamespace:
                        switch (reader.LocalName)
                        {
                            case "namespace": 
                                grammar.ImportNamespaces.Add (reader.Value);
                                break; 
 
                            default:
                                ThrowSrgsException (SRID.InvalidImportNamespaceAttribute); 
                                break;
                        }
                        break;
                } 
            }
        } 
#endif 

        private bool ProcessChildNodes (XmlReader reader, IElement parent, IRule rule, string parentName) 
        {
            bool fFirstElement = true;

            // Create a list of name value tags for this scope 
            List tags = null;
 
            reader.MoveToElement ();                                 // Move to containing parent of attributes 
            if (!reader.IsEmptyElement)
            { 
                reader.Read ();                                      // Move to first child parent
                while (reader.NodeType != XmlNodeType.EndElement)   // Process each child parent while not at end parent
                {
                    bool isInvalidNode = false; 

                    if (reader.NodeType == XmlNodeType.Element) 
                    { 
                        // Null if no children are allowed
                        if (parent == null) 
                        {
                            ThrowSrgsException (SRID.InvalidNotEmptyElement, parentName);
                        }
 
                        IElement child = null;
                        switch (reader.NamespaceURI) 
                        { 
                            case srgsNamespace:
 
                                switch (reader.LocalName)
                                {
                                    case "example":
                                        if (!(parent is IRule) || !fFirstElement) 
                                        {
                                            ThrowSrgsException (SRID.InvalidExampleOrdering); 
                                        } 
                                        else
                                        { 
                                            reader.Skip ();
                                            continue;
                                        }
 
                                        break;
 
                                    case "ruleref": 
                                        child = ParseRuleRef (parent, reader);
                                        break; 

                                    case "one-of":
                                        child = ParseOneOf (parent, rule, reader);
                                        break; 

                                    case "item": 
                                        child = ParseItem (parent, rule, reader); 
                                        break;
 
                                    case "token":
                                        child = ParseToken (parent, reader);
                                        break;
 
                                    case "tag":
                                        child = ParseTag (parent, reader); 
                                        IPropertyTag tag = child as IPropertyTag; 
                                        if (tag != null)
                                        { 
                                            // The tag list is delayed as it might not be necessary
                                            if (tags == null)
                                            {
                                                tags = new List (); 
                                            }
                                            tags.Add (tag); 
                                        } 
                                        break;
 
                                    case "rule":
                                    default:
                                        isInvalidNode = true;
                                        break; 
                                }
                                break; 
 
                            case sapiNamespace:
                                switch (reader.LocalName) 
                                {
                                    case "subset":
                                        if ((parent is IRule) || (parent is IItem))
                                        { 
                                            child = ParseSubset (parent, reader);
                                        } 
                                        else 
                                        {
                                            isInvalidNode = true; 
                                        }
                                        break;

                                    default: 
                                        isInvalidNode = true;
                                        break; 
                                } 
                                break;
 
                            default:
                                reader.Skip ();                      // Skip over parents in unknown namespaces
                                break;
                        } 
                        isInvalidNode = ParseChildNodeElement (parent, isInvalidNode, child);
                        fFirstElement = false; 
                    } 
                    else if (reader.NodeType == XmlNodeType.Text || reader.NodeType == XmlNodeType.CDATA)
                    { 
                        // Null if no children are allowed
                        if (parent == null)
                        {
                            ThrowSrgsException (SRID.InvalidNotEmptyElement, parentName); 
                        }
 
                        isInvalidNode = ParseChildNodeText (reader, parent); 
                        fFirstElement = false;
                    } 
                    else
                    {
                        reader.Skip ();                              // Skip over non-parent/text node types
                    } 

                    if (isInvalidNode) 
                    { 
                        ThrowSrgsException (SRID.InvalidElement, reader.Name);
                    } 
                }
            }

            reader.Read ();                                          // Move to next sibling 

            // Generate the tags for this scope 
            if (tags != null) 
            {
                foreach (IPropertyTag tag in tags) 
                {
                    tag.PostParse (parent);
                }
            } 
            return !fFirstElement;
        } 
 
        private bool ParseChildNodeText (XmlReader reader, IElement parent)
        { 
            bool isInvalidNode = false;
            string content = reader.Value;

            // Create the SrgsElement for the text 
            IElementText srgsText = _parser.CreateText (parent, content);
 
            // Split it in pieces 
            ParseText (parent, content, null, null, -1f);
 
            // if the parent is a one of, then the children must be an Item
            if (parent is IOneOf)
            {
                isInvalidNode = true; 
            }
            else 
            { 
                IRule parentRule = parent as IRule;
                if (parentRule != null) 
                {
                    _parser.AddElement (parentRule, srgsText);
                }
                else 
                {
                    IItem parentItem = parent as IItem; 
                    if (parentItem != null) 
                    {
                        _parser.AddElement (parentItem, srgsText); 
                    }
                    else
                    {
                        isInvalidNode = true; 
                    }
                } 
            } 

            reader.Read (); 
            return isInvalidNode;
        }

        private bool ParseChildNodeElement (IElement parent, bool isInvalidNode, IElement child) 
        {
            // The child parent has not been processed yet 
            if (child != null) 
            {
                // if the parent is a one of, then the children must be an Item 
                IOneOf parentOneOf = parent as IOneOf;
                if (parentOneOf != null)
                {
                    IItem childItem = child as IItem; 
                    if (childItem != null)
                    { 
                        _parser.AddItem (parentOneOf, childItem); 
                    }
                    else 
                    {
                        isInvalidNode = true;
                    }
                } 
                else
                { 
                    IRule parentRule = parent as IRule; 
                    if (parentRule != null)
                    { 
                        _parser.AddElement (parentRule, child);
                    }
                    else
                    { 
                        IItem parentItem = parent as IItem;
                        if (parentItem != null) 
                        { 
                            _parser.AddElement (parentItem, child);
                        } 
                        else
                        {
                            isInvalidNode = true;
                        } 
                    }
                } 
            } 

            return isInvalidNode; 
        }

        private void ProcessRulesAndScriptsNodes (XmlReader reader, IGrammar grammar)
        { 
            bool fProcessedRules = false;
 
            // Move to containing element of attributes 
            reader.MoveToElement ();
            if (!reader.IsEmptyElement) 
            {
                // Move to first child element
                reader.Read ();
 
                // Process each child element while not at end element
                while (reader.NodeType != XmlNodeType.EndElement) 
                { 
                    bool isInvalidNode = false;
 
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        switch (reader.NamespaceURI)
                        { 
                            case srgsNamespace:
                                switch (reader.LocalName) 
                                { 
                                    case "lexicon":
                                        if (fProcessedRules) 
                                        {
                                            ThrowSrgsException (SRID.InvalidGrammarOrdering);
                                        }
                                        ParseLexicon (reader); 
                                        break;
 
                                    case "meta": 
                                        if (fProcessedRules)
                                        { 
                                            ThrowSrgsException (SRID.InvalidGrammarOrdering);
                                        }
                                        ParseMeta (reader);
                                        break; 

                                    case "metadata": 
                                        if (fProcessedRules) 
                                        {
                                            ThrowSrgsException (SRID.InvalidGrammarOrdering); 
                                        }
                                        reader.Skip ();
                                        break;
 
                                    case "rule":
                                        IRule rule = ParseRule (grammar, reader); 
                                        rule.PostParse (grammar); 
                                        fProcessedRules = true;
                                        break; 

                                    case "tag":
                                        if (fProcessedRules || _hasTagFormat && grammar.TagFormat != SrgsTagFormat.W3cV1)
                                        { 
                                            ThrowSrgsException (SRID.InvalidGrammarOrdering);
                                        } 
                                        grammar.GlobalTags.Add (GetTagContent (grammar, reader)); 
                                        break;
 
                                    default:
                                        isInvalidNode = true;
                                        break;
                                } 
                                break;
 
                            case sapiNamespace: 
                                switch (reader.LocalName)
                                { 
#if !NO_STG
                                    case "script":
                                        ParseScript (reader, grammar);
                                        fProcessedRules = true; 
                                        break;
 
                                    case "assemblyReference": 
                                        ParseAssemblyReference (reader, grammar);
                                        fProcessedRules = true; 
                                        break;

                                    case "importNamespace":
                                        ParseImportNamespace (reader, grammar); 
                                        fProcessedRules = true;
                                        break; 
#endif 
                                    default:
                                        isInvalidNode = true; 
                                        break;
                                }
                                break;
 
                            default:
                                // Skip over elements in unknown namespaces 
                                reader.Skip (); 
                                break;
                        } 
                    }
                    else
                    {
                        if (reader.NodeType == XmlNodeType.Text) 
                        {
                            ThrowSrgsException (SRID.InvalidElement, "text"); 
                        } 
                        // Skip over non-element/text node types
                        reader.Skip (); 
                    }

                    if (isInvalidNode)
                    { 
                        ThrowSrgsException (SRID.InvalidElement, reader.Name);
                    } 
                } 
            }
 
            // Move to next sibling
            reader.Read ();
        }
 
        static private string GetStringContent (XmlReader reader)
        { 
            StringBuilder sb = new StringBuilder (); 

            reader.MoveToElement ();                                 // Move to containing element of attributes 
            if (!reader.IsEmptyElement)
            {
                reader.Read ();                                      // Move to first child element
                while (reader.NodeType != XmlNodeType.EndElement)   // Process each child element while not at end element 
                {
                    sb.Append (reader.ReadString ()); 
 
                    bool isInvalidNode = false;
 
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        switch (reader.NamespaceURI)
                        { 
                            case srgsNamespace:
                            case sapiNamespace: 
                                isInvalidNode = true; 
                                break;
 
                            default:
                                reader.Skip ();                      // Skip over elements in unknown namespaces
                                break;
                        } 
                    }
                    else if (reader.NodeType != XmlNodeType.EndElement) 
                    { 
                        reader.Skip ();                              // Skip over non-end element node types
                    } 

                    if (isInvalidNode)
                    {
                        ThrowSrgsException (SRID.InvalidElement, reader.Name); 
                    }
                } 
            } 

            reader.Read ();                                          // Move to next sibling 
            return sb.ToString ();
        }

        /// TODOC <_include file='doc\Tag.uex' path='docs/doc[@for="Tag.RepeatProbability"]/*' /> 
        static void ParsePropertyTag (string sTag, out string name, out object value)
        { 
            // Default value 
            name = null;
            value = string.Empty; 

            // Name=             pszValue = null     vValue = VT_EMPTY
            // Name="string"     pszValue = "string" vValue = VT_EMPTY
            // Name=true         pszValue = null     vValue = VT_BOOL 
            // Name=123          pszValue = null     vValue = VT_I4
            // Name=3.14         pszValue = null     vValue = VT_R8 
            int iEqual = sTag.IndexOf ('='); 

            if (iEqual >= 0) 
            {
                // Set property name
                name = sTag.Substring (0, iEqual).Trim (Helpers._achTrimChars);
                iEqual++; 
            }
            else 
            { 
                iEqual = 0;
            } 

            // Set property value
            int cLenProperty = sTag.Length;
 
            if (iEqual < cLenProperty)
            { 
                if (sTag [iEqual] == '"') 
                {
                    // Name="string" 
                    iEqual++;

                    int iEndQuote = sTag.IndexOf ('"', iEqual + 1);
 
                    if (iEndQuote + 1 != cLenProperty)
                    { 
                        // Invalid string value 
                        XmlParser.ThrowSrgsException (SRID.IncorrectAttributeValue, name, sTag.Substring (iEqual));
                    } 

                    value = sTag.Substring (iEqual, iEndQuote - iEqual);
                }
                else 
                {
                    string sValue = sTag.Substring (iEqual); 
                    int iValue; 

                    if (int.TryParse (sValue, out iValue)) 
                    {
                        // propInfo.pszValue = null
                        // Name=123
                        // propInfo.vValue = VT_I4 
                        value = iValue;
                    } 
                    else 
                    {
                        double flValue; 

                        if (double.TryParse (sValue, out flValue))
                        {
                            // propInfo.pszValue = null 
                            // propInfo.vValue   = VT_R8
                            value = flValue; 
                        } 
                        else
                        { 
                            bool fValue;

                            if (bool.TryParse (sValue, out fValue))
                            { 
                                // Name=true
                                // propInfo.pszValue = null 
                                // propInfo.vValue   = VT_BOOL 
                                value = fValue;
                            } 
                            else
                            {
                                XmlParser.ThrowSrgsException (SRID.InvalidNameValueProperty, name, sValue);
                            } 
                        }
                    } 
                } 
            }
        } 

        /// 
        /// Convert integer range string to MinValue and MaxValue.
        /// For n- format, MaxValue = Int32.MaxValue 
        /// Valid formats: n|n-|n-m     n,m integers
        ///                integer = [whitespace] [+] [0[{x|X}]] [digits] 
        ///  
        /// 
        ///  
        /// 
        static private void SetRepeatValues (string repeat, out int minRepeat, out int maxRepeat)
        {
            minRepeat = maxRepeat = 1; 
            if (!string.IsNullOrEmpty (repeat))
            { 
                int sep = repeat.IndexOf ("-", StringComparison.Ordinal); 

                if (sep < 0) 
                {
                    int minmax = Convert.ToInt32 (repeat, CultureInfo.InvariantCulture);

                    // Limit the range of valid values 
                    if (minmax < 0 || minmax > 255)
                    { 
                        XmlParser.ThrowSrgsException (SRID.MinMaxOutOfRange, minmax, minmax); 
                    }
                    minRepeat = maxRepeat = minmax; 
                }
                else if (0 < sep)
                {
                    minRepeat = Convert.ToInt32 (repeat.Substring (0, sep), CultureInfo.InvariantCulture); 
                    if (sep < (repeat.Length - 1))
                    { 
                        maxRepeat = Convert.ToInt32 (repeat.Substring (sep + 1), CultureInfo.InvariantCulture); 
                    }
                    else 
                    {
                        maxRepeat = System.Int32.MaxValue;
                    }
                    // Limit the range of valid values 
                    if (minRepeat < 0 || minRepeat > 255 || (maxRepeat != System.Int32.MaxValue && (maxRepeat < 0 || maxRepeat > 255)))
                    { 
                        XmlParser.ThrowSrgsException (SRID.MinMaxOutOfRange, minRepeat, maxRepeat); 
                    }
 
                    // Max be greater or equal to min
                    if (minRepeat > maxRepeat)
                    {
                        throw new ArgumentException (SR.Get (SRID.MinGreaterThanMax)); 
                    }
                } 
                else 
                {
                    ThrowSrgsException (SRID.InvalidItemRepeatAttribute, repeat); 
                }
            }
            else
            { 
                ThrowSrgsException (SRID.InvalidItemAttribute2);
            } 
        } 

        private static void CheckForDuplicates (ref string dest, XmlReader reader) 
        {
            if (!string.IsNullOrEmpty (dest))
            {
                StringBuilder attribute = new StringBuilder (reader.LocalName); 
                if (reader.NamespaceURI.Length > 0)
                { 
                    attribute.Append (reader.NamespaceURI); 
                    attribute.Append (":");
                } 
                XmlParser.ThrowSrgsException (SRID.InvalidAttributeDefinedTwice, reader.Value, attribute);
            }
            dest = reader.Value;
        } 

        // Throws exception if the specified Rule does not have a valid Id. 
        static internal void ValidateRuleId (string id) 
        {
            Helpers.ThrowIfEmptyOrNull (id, "id"); 

            if (!XmlReader.IsName (id) || (id == "NULL") || (id == "VOID") || (id == "GARBAGE") || (id.IndexOfAny (_invalidRuleIdChars) != -1))
            {
                XmlParser.ThrowSrgsException (SRID.InvalidRuleId, id); 
            }
        } 
 
        private void ValidateRulerefNotPointingToSelf (string uri)
        { 
            // Check that the uri pointed to in the ruleref does not point this file
            // in srgs.xml: ... 
            if (_filename != null) 
            {
                if (uri.IndexOf (_shortFilename, StringComparison.Ordinal) == 0 && (uri.Length > _shortFilename.Length && uri [_shortFilename.Length] == '#' || uri.Length == _shortFilename.Length)) 
                { 
                    ThrowSrgsException (SRID.InvalidRuleRefSelf);
                } 
            }
        }

        private void ValidateScripts () 
        {
#if !NO_STG 
            // Check that the rule and methods are defined for a script 
            foreach (ForwardReference script in _scripts)
            { 
                if (!_rules.Contains (script._name))
                {
                    ThrowSrgsException (SRID.InvalidScriptDefinition, script._name);
                } 
            }
#endif 
            // Validate for unique rule names 
            List ruleNames = new List ();
 
            foreach (string rule in _rules)
            {
                if (ruleNames.Contains (rule))
                { 
                    XmlParser.ThrowSrgsException (SRID.RuleAttributeDefinedMultipeTimes, rule);
                } 
 
                ruleNames.Add (rule);
            } 
        }

        #endregion
 
        //********************************************************************
        // 
        // Private Fields 
        //
        //******************************************************************* 

        #region Private Fields

        private IElementFactory _parser; 

        // Avoid to do a cast many times 
        private XmlReader _reader; 

        // Avoid to do a cast many times 
        private XmlTextReader _xmlTextReader;

        // Save the filename
        private string _filename; 

        // Save the filename without the path 
        private string _shortFilename; 

        // Language Id for this grammar 
        private CultureInfo _langId;

        // Has the Grammar element a FormatTag
        private bool _hasTagFormat; 

#if SPEECHSERVER 
        // Has the Grammar element a FormatTag 
        private bool _w3c_literal;
#endif 
        // All defined rules
        List _rules = new List ();

#if !NO_STG 
        List _scripts = new List ();
#endif 
 
        static private readonly char [] _invalidRuleIdChars = new char [] { '.', ':', '-', '#' };
 
        static private readonly char [] _SlashBackSlash = new char [] { '\\', '/' };

        #endregion
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

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