/// <summary> /// Parse a document by pushing characters one at a time. /// </summary> /// <param name="c">The character</param> public void Push(char c) { for (int loopLimit = 0; loopLimit < 10; loopLimit++) { string rollback = null; if (Context.CurrentState == null) { goto done; } XmlParserState nextState = Context.CurrentState.PushChar(c, Context, ref rollback); // no state change if (nextState == Context.CurrentState || nextState == null) { Context.CurrentStateLength++; goto done; } // state changed; reset stuff Context.PreviousState = Context.CurrentState; Context.CurrentState = nextState; Context.StateTag = 0; Context.CurrentStateLength = 0; if (Context.KeywordBuilder.Length < 50) { Context.KeywordBuilder.Length = 0; } else { Context.KeywordBuilder = new StringBuilder(); } // only loop if the same char should be run through the new state if (rollback == null) { goto done; } //simple rollback, just run same char through again if (rollback.Length == 0) { continue; } //"complex" rollbacks require actually skipping backwards. //Note the previous state is invalid for this operation. foreach (char rollChar in rollback) { Push(rollChar); } } throw new InvalidOperationException($"Too many state changes for char '{c}'. Current state is {Context.CurrentState.ToString ()}."); done: Context.Position++; return; }
public XmlParser(XmlRootState rootState, bool buildTree) { this.rootState = rootState; this.currentState = rootState; this.previousState = rootState; this.buildTree = buildTree; Reset(); }
public XmlParser(XmlRootState rootState, bool buildTree) { RootState = rootState; CurrentState = rootState; previousState = rootState; BuildTree = buildTree; Reset(); }
public override string ToString() { StringBuilder builder = new StringBuilder(); builder.AppendFormat("[Parser Location={0} CurrentStateLength={1}", position, currentStateLength); builder.AppendLine(); builder.Append(' ', 2); builder.AppendLine("Stack="); XObject rootOb = null; foreach (XObject ob in nodes) { rootOb = ob; builder.Append(' ', 4); builder.Append(ob.ToString()); builder.AppendLine(); } builder.Append(' ', 2); builder.AppendLine("States="); XmlParserState s = currentState; while (s != null) { builder.Append(' ', 4); builder.Append(s.ToString()); builder.AppendLine(); s = s.Parent; } if (buildTree && rootOb != null) { builder.Append(' ', 2); builder.AppendLine("Tree="); rootOb.BuildTreeString(builder, 3); } if (buildTree && errors.Count > 0) { builder.Append(' ', 2); builder.AppendLine("Errors="); foreach (Error err in errors) { builder.Append(' ', 4); builder.AppendFormat("[{0}@{1}:{2}, {3}]\n", err.ErrorType, err.Region.Begin.Line, err.Region.Begin.Column, err.Message); } } builder.AppendLine("]"); return(builder.ToString()); }
public void Reset() { CurrentState = RootState; previousState = RootState; Position = 0; stateTag = 0; keywordBuilder = new StringBuilder(); CurrentStateLength = 0; Nodes = new NodeStack(); Nodes.Push(RootState.CreateDocument()); }
public override string ToString() { StringBuilder builder = new StringBuilder(); builder.AppendFormat("[Parser Location={0} CurrentStateLength={1}", Position, CurrentStateLength); builder.AppendLine(); builder.Append(' ', 2); builder.AppendLine("Stack="); XObject rootOb = null; foreach (XObject ob in Nodes) { rootOb = ob; builder.Append(' ', 4); builder.Append(ob.ToString()); builder.AppendLine(); } builder.Append(' ', 2); builder.AppendLine("States="); XmlParserState s = CurrentState; while (s != null) { builder.Append(' ', 4); builder.Append(s.ToString()); builder.AppendLine(); s = s.Parent; } if (BuildTree && rootOb != null) { builder.Append(' ', 2); builder.AppendLine("Tree="); rootOb.BuildTreeString(builder, 3); } if (BuildTree && Diagnostics.Count > 0) { builder.Append(' ', 2); builder.AppendLine("Errors="); foreach (XmlDiagnosticInfo err in Diagnostics) { builder.Append(' ', 4); builder.AppendLine($"[{err.Severity}@{err.Span}: {err.Message}]"); } } builder.AppendLine("]"); return(builder.ToString()); }
XmlParser(XmlParser copyFrom) { BuildTree = false; RootState = copyFrom.RootState; CurrentState = copyFrom.CurrentState; previousState = copyFrom.previousState; Position = copyFrom.Position; stateTag = copyFrom.stateTag; keywordBuilder = new StringBuilder(copyFrom.keywordBuilder.ToString()); CurrentStateLength = copyFrom.CurrentStateLength; //clone the node stack var l = new List <XObject> (CopyXObjects(copyFrom.Nodes)); l.Reverse(); Nodes = new NodeStack(l); }
XmlParser(XmlParser copyFrom) { buildTree = false; rootState = copyFrom.rootState; currentState = copyFrom.currentState; previousState = copyFrom.previousState; position = copyFrom.position; previousLineEnd = copyFrom.location; location = copyFrom.location; stateTag = copyFrom.stateTag; keywordBuilder = new StringBuilder(copyFrom.keywordBuilder.ToString()); currentStateLength = copyFrom.currentStateLength; //clone the node stack var l = new List <XObject> (CopyXObjects(copyFrom.nodes)); l.Reverse(); nodes = new NodeStack(l); }
public void Reset() { currentState = rootState; previousState = rootState; position = 0; stateTag = 0; location = new DocumentLocation(1, 1); previousLineEnd = DocumentLocation.Empty; keywordBuilder = new StringBuilder(); currentStateLength = 0; nodes = new NodeStack(); nodes.Push(rootState.CreateDocument()); if (buildTree) { errors = new List <Error> (); } else { errors = null; } }
public void Push(char c) { try { //FIXME: position/location should be at current char, not after it position++; if (c == '\n') { previousLineEnd = new DocumentLocation(location.Line, location.Column + 1); location = new DocumentLocation(location.Line + 1, 1); } else { location = new DocumentLocation(location.Line, location.Column + 1); } for (int loopLimit = 0; loopLimit < 10; loopLimit++) { currentStateLength++; string rollback = null; if (currentState == null) { return; } XmlParserState nextState = currentState.PushChar(c, this, ref rollback); // no state change if (nextState == currentState || nextState == null) { return; } // state changed; reset stuff previousState = currentState; currentState = nextState; stateTag = 0; currentStateLength = 0; if (keywordBuilder.Length < 50) { keywordBuilder.Length = 0; } else { keywordBuilder = new StringBuilder(); } // only loop if the same char should be run through the new state if (rollback == null) { return; } //simple rollback, just run same char through again if (rollback.Length == 0) { continue; } //"complex" rollbacks require actually skipping backwards. //Note the previous state is invalid for this operation. //rollback position and location so they're valid position -= (rollback.Length + 1); location = new DocumentLocation(location.Line, location.Column - (rollback.Length + 1)); if (location.Column < 0) { throw new InvalidOperationException("Can't roll back across line boundary"); } foreach (char rollChar in rollback) { Push(rollChar); } //restore position and location position++; location = new DocumentLocation(location.Line, location.Column + 1); } throw new InvalidOperationException("Too many state changes for char '" + c + "'. Current state is " + currentState.ToString() + "."); } catch (Exception ex) { //attach parser state to exceptions throw new Exception(ToString(), ex); } }
protected void Adopt (XmlParserState child) { Debug.Assert (child.parent == null); child.parent = this; }
protected void Adopt(XmlParserState child) { Debug.Assert(child.parent == null); child.parent = this; }
public void Push(char c) { try { //FIXME: position/location should be at current char, not after it Position++; for (int loopLimit = 0; loopLimit < 10; loopLimit++) { CurrentStateLength++; string rollback = null; if (CurrentState == null) { return; } XmlParserState nextState = CurrentState.PushChar(c, this, ref rollback); // no state change if (nextState == CurrentState || nextState == null) { return; } // state changed; reset stuff previousState = CurrentState; CurrentState = nextState; stateTag = 0; CurrentStateLength = 0; if (keywordBuilder.Length < 50) { keywordBuilder.Length = 0; } else { keywordBuilder = new StringBuilder(); } // only loop if the same char should be run through the new state if (rollback == null) { return; } //simple rollback, just run same char through again if (rollback.Length == 0) { continue; } //"complex" rollbacks require actually skipping backwards. //Note the previous state is invalid for this operation. //rollback position so it's valid Position -= (rollback.Length + 1); foreach (char rollChar in rollback) { Push(rollChar); } //restore position Position++; } throw new InvalidOperationException("Too many state changes for char '" + c + "'. Current state is " + CurrentState.ToString() + "."); } catch (Exception ex) { //attach parser state to exceptions throw new Exception(ToString(), ex); } }
public override XmlParserContext TryRecreateState(XObject xobject, int position) { var fromAtt = AttributeState.TryRecreateState(xobject, position); if (fromAtt != null) { return(fromAtt); } // we can also recreate state for attributes within the tag, if the attribute state didn't var el = xobject as XElement; if (el == null && xobject is XAttribute a) { el = (XElement)a.Parent; } if (el != null && position >= el.Span.Start && position < el.Span.End) { // recreating name builder and value builder state is a pain to get right // for now, let parent recreate state at start of tag if (position <= el.NameSpan.End) { return(null); } // if there are attributes, then at the start of an attribute is also a pretty safe place to recreate state // but if not, let parent recreate state at start of tag if (el.Attributes.First == null) { return(null); } var newEl = new XElement(el.Span.Start, el.Name); int prevStateEnd = el.NameSpan.End; XmlParserState prevState = NameState; foreach (var att in el.Attributes) { if (att.Span.End < position) { prevStateEnd = att.Span.End; prevState = AttributeState; //spine parser is currently expected to have attributes newEl.Attributes.AddAttribute((XAttribute)att.ShallowCopy()); continue; } if (att.Span.End > position) { position = att.Span.Start; break; } } var parents = NodeStack.FromParents(el); parents.Push(newEl); return(new XmlParserContext { CurrentState = this, Position = position, PreviousState = prevState, CurrentStateLength = position - prevStateEnd, KeywordBuilder = new StringBuilder(), Nodes = parents, StateTag = FREE }); } return(null); }