예제 #1
0
        /// <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;
        }
예제 #2
0
 public XmlParser(XmlRootState rootState, bool buildTree)
 {
     this.rootState     = rootState;
     this.currentState  = rootState;
     this.previousState = rootState;
     this.buildTree     = buildTree;
     Reset();
 }
예제 #3
0
 public XmlParser(XmlRootState rootState, bool buildTree)
 {
     RootState     = rootState;
     CurrentState  = rootState;
     previousState = rootState;
     BuildTree     = buildTree;
     Reset();
 }
예제 #4
0
        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());
        }
예제 #5
0
 public void Reset()
 {
     CurrentState       = RootState;
     previousState      = RootState;
     Position           = 0;
     stateTag           = 0;
     keywordBuilder     = new StringBuilder();
     CurrentStateLength = 0;
     Nodes = new NodeStack();
     Nodes.Push(RootState.CreateDocument());
 }
예제 #6
0
        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());
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
        }
예제 #9
0
        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;
            }
        }
예제 #10
0
        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);
            }
        }
예제 #11
0
		protected void Adopt (XmlParserState child)
		{
			Debug.Assert (child.parent == null);
			child.parent = this;
		}
예제 #12
0
 protected void Adopt(XmlParserState child)
 {
     Debug.Assert(child.parent == null);
     child.parent = this;
 }
예제 #13
0
        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);
            }
        }
예제 #14
0
        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);
        }