public override XmlParserState PushChar (char c, IXmlParserContext context, ref string rollback)
		{
			if (context.CurrentStateLength == 0)
				context.StateTag = 0;
			
			if (c == '<') {
				if (context.StateTag == 0) {
					context.StateTag++;
					return null;
				}
			}
			if (context.StateTag > 0) {
				if (CLOSE[context.StateTag] == c) {
					context.StateTag++;
					if (context.StateTag == CLOSE.Length) {
						var el = (XElement) context.Nodes.Pop ();
						var closing = new XClosingTag (new XName ("script"), context.LocationMinus (CLOSE.Length));
						closing.End (context.Location);
						el.Close (closing);
						rollback = string.Empty;
						return Parent;
					}
				} else {
					context.StateTag = 0;
				}
			}
			return null;
		}
		public override XmlParserState PushChar (char c, IXmlParserContext context, ref string rollback)
		{
			var ct = context.Nodes.Peek () as XClosingTag;
			
			if (ct == null) {
				Debug.Assert (context.CurrentStateLength == 1,
					"IncompleteNode must not be an XClosingTag when CurrentStateLength is 1");
				
				ct = new XClosingTag (context.LocationMinus (3)); //3 = </ and the current char
				context.Nodes.Push (ct);
			}
			
			//if tag closed
			if (c == '>') {
				context.Nodes.Pop ();
				
				if (ct.IsNamed) {
					ct.End (context.Location);
					
					// walk up tree of parents looking for matching tag
					int popCount = 0;
					bool found = false;
					foreach (XObject node in context.Nodes) {
						popCount++;
						XElement element = node as XElement;
						if (element != null && element.Name == ct.Name) {
							found = true;
							break;
						}
					}
					if (!found)
						popCount = 0;
					
					//clear the stack of intermediate unclosed tags
					while (popCount > 1) {
						XElement el = context.Nodes.Pop () as XElement;
						if (el != null)
							context.LogError (string.Format (
								"Unclosed tag '{0}' at line {1}, column {2}.", el.Name.FullName, el.Region.BeginLine, el.Region.BeginColumn),
								ct.Region);
						popCount--;
					}
					
					//close the start tag, if we found it
					if (popCount > 0) {
						if (context.BuildTree)
							((XElement) context.Nodes.Pop ()).Close (ct);
						else
							context.Nodes.Pop ();
					} else {
						context.LogError (
							"Closing tag '" + ct.Name.FullName + "' does not match any currently open tag.",
							ct.Region
						);
					}
				} else {
					context.LogError ("Closing tag ended prematurely.");
				}
				return Parent;
			}
			
			if (c == '<') {
				context.LogError ("Unexpected '<' in tag.", context.LocationMinus (1));
				context.Nodes.Pop ();
				rollback = string.Empty;
				return Parent;
			}

			if (XmlChar.IsWhitespace (c)) {
				return null;
			}
			
			if (!ct.IsNamed && (char.IsLetter (c) || c == '_')) {
				rollback = string.Empty;
				return NameState;
			}
			
			rollback = string.Empty;
			context.LogError ("Unexpected character '" + c + "' in closing tag.", context.LocationMinus (1));
			context.Nodes.Pop ();
			return Parent;
		}