public override State PushChar(char c, IParseContext context, ref string rollback) { XElement element = context.Nodes.Peek() as XElement; if (element == null || element.IsComplete) { element = new XElement(context.LocationMinus(2)); // 2 == < + current char context.Nodes.Push(element); } if (c == '<') { if (element.IsNamed) { context.LogError("Unexpected '<' in tag '" + element.Name.FullName + "'."); Close(element, context, context.LocationMinus(1)); } else { context.LogError("Unexpected '<' in unnamed tag."); } rollback = string.Empty; return(Parent); } Debug.Assert(!element.IsComplete); if (element.IsClosed && c != '>') { if (char.IsWhiteSpace(c)) { context.LogWarning("Unexpected whitespace after '/' in self-closing tag."); return(null); } context.LogError("Unexpected character '" + c + "' after '/' in self-closing tag."); context.Nodes.Pop(); return(Parent); } //if tag closed if (c == '>') { if (context.StateTag == MAYBE_SELF_CLOSING) { element.Close(element); } if (!element.IsNamed) { context.LogError("Tag closed prematurely."); } else { Close(element, context, context.Location); } return(Parent); } if (c == '/') { context.StateTag = MAYBE_SELF_CLOSING; return(null); } if (context.StateTag == ATTEMPT_RECOVERY) { if (XmlChar.IsWhitespace(c)) { context.StateTag = RECOVERY_FOUND_WHITESPACE; } return(null); } if (context.StateTag == RECOVERY_FOUND_WHITESPACE) { if (!XmlChar.IsFirstNameChar(c)) { return(null); } } context.StateTag = OK; if (!element.IsNamed && XmlChar.IsFirstNameChar(c)) { rollback = string.Empty; return(NameState); } if (context.CurrentStateLength > 1 && XmlChar.IsFirstNameChar(c)) { rollback = string.Empty; return(AttributeState); } if (XmlChar.IsWhitespace(c)) { return(null); } context.LogError("Unexpected character '" + c + "' in tag.", context.LocationMinus(1)); context.StateTag = ATTEMPT_RECOVERY; return(null); }
public override State PushChar(char c, IParseContext context, ref string rollback) { XDocType doc = context.Nodes.Peek() as XDocType; if (doc == null) { doc = new XDocType(context.LocationMinus("<!DOCTYPE".Length + 1)); context.Nodes.Push(doc); } if (!doc.RootElement.IsValid) { if (XmlChar.IsWhitespace(c)) { return(null); } else if (XmlChar.IsFirstNameChar(c)) { rollback = ""; return(nameState); } } else if (doc.PublicFpi == null) { if (context.StateTag == 0) { if (c == 's' || c == 'S') { context.StateTag = 1; return(null); } else if (c == 'p' || c == 'P') { context.StateTag = -1; return(null); } if (XmlChar.IsWhitespace(c)) { return(null); } } else if (Math.Abs(context.StateTag) < 6) { if (context.StateTag > 0) { if ("YSTEM"[context.StateTag - 1] == c || "ystem"[context.StateTag - 1] == c) { context.StateTag++; if (context.StateTag == 6) { context.StateTag = 0; doc.PublicFpi = ""; } return(null); } } else { int absState = Math.Abs(context.StateTag) - 1; if ("UBLIC"[absState] == c || "ublic"[absState] == c) { context.StateTag--; return(null); } } } else { if (context.KeywordBuilder.Length == 0) { if (XmlChar.IsWhitespace(c)) { return(null); } else if (c == '"') { context.KeywordBuilder.Append(c); return(null); } } else { if (c == '"') { context.KeywordBuilder.Remove(0, 1); doc.PublicFpi = context.KeywordBuilder.ToString(); context.KeywordBuilder.Length = 0; context.StateTag = 0; } else { context.KeywordBuilder.Append(c); } return(null); } } } else if (doc.Uri == null) { if (context.KeywordBuilder.Length == 0) { if (XmlChar.IsWhitespace(c)) { return(null); } else if (c == '"') { context.KeywordBuilder.Append(c); return(null); } } else { if (c == '"') { context.KeywordBuilder.Remove(0, 1); doc.Uri = context.KeywordBuilder.ToString(); context.KeywordBuilder.Length = 0; } else { context.KeywordBuilder.Append(c); } return(null); } } else if (doc.InternalDeclarationRegion.EndLine <= 0) { if (XmlChar.IsWhitespace(c)) { return(null); } switch (context.StateTag) { case 0: if (c == '[') { doc.InternalDeclarationRegion = new DomRegion(context.Location, TextLocation.Empty); context.StateTag = 1; return(null); } break; case 1: if (c == '<') { context.StateTag = 2; return(null); } else if (c == ']') { context.StateTag = 0; doc.InternalDeclarationRegion = new DomRegion(doc.InternalDeclarationRegion.Begin, context.Location); return(null); } break; case 2: if (c == '>') { context.StateTag = 1; } return(null); default: throw new InvalidOperationException(); } } doc = (XDocType)context.Nodes.Pop(); if (c == '<') { rollback = string.Empty; context.LogError("Doctype ended prematurely."); } else if (c != '>') { context.LogError("Unexpected character '" + c + "' in doctype."); } if (context.BuildTree) { doc.End(context.Location); ((XContainer)context.Nodes.Peek()).AddChildNode(doc); } return(Parent); }