- namespace Ink
- {
- public class StringParserState
- {
- public int lineIndex {
- get { return currentElement.lineIndex; }
- set { currentElement.lineIndex = value; }
- }
- public int characterIndex {
- get { return currentElement.characterIndex; }
- set { currentElement.characterIndex = value; }
- }
- public int characterInLineIndex {
- get { return currentElement.characterInLineIndex; }
- set { currentElement.characterInLineIndex = value; }
- }
- public uint customFlags {
- get { return currentElement.customFlags; }
- set { currentElement.customFlags = value; }
- }
- public bool errorReportedAlreadyInScope {
- get {
- return currentElement.reportedErrorInScope;
- }
- }
- public int stackHeight {
- get {
- return _numElements;
- }
- }
- public class Element {
- public int characterIndex;
- public int characterInLineIndex;
- public int lineIndex;
- public bool reportedErrorInScope;
- public int uniqueId;
- public uint customFlags;
- public Element() {
- }
- public void CopyFrom(Element fromElement)
- {
- _uniqueIdCounter++;
- this.uniqueId = _uniqueIdCounter;
- this.characterIndex = fromElement.characterIndex;
- this.characterInLineIndex = fromElement.characterInLineIndex;
- this.lineIndex = fromElement.lineIndex;
- this.customFlags = fromElement.customFlags;
- this.reportedErrorInScope = false;
- }
- // Squash is used when succeeding from a rule,
- // so only the state information we wanted to carry forward is
- // retained. e.g. characterIndex and lineIndex are global,
- // however uniqueId is specific to the individual rule,
- // and likewise, custom flags are designed for the temporary
- // state of the individual rule too.
- public void SquashFrom(Element fromElement)
- {
- this.characterIndex = fromElement.characterIndex;
- this.characterInLineIndex = fromElement.characterInLineIndex;
- this.lineIndex = fromElement.lineIndex;
- this.reportedErrorInScope = fromElement.reportedErrorInScope;
- this.customFlags = fromElement.customFlags;
- }
- static int _uniqueIdCounter;
- }
- public StringParserState ()
- {
- const int kExpectedMaxStackDepth = 200;
- _stack = new Element[kExpectedMaxStackDepth];
- for (int i = 0; i < kExpectedMaxStackDepth; ++i) {
- _stack [i] = new Element ();
- }
- _numElements = 1;
- }
- public int Push()
- {
- if (_numElements >= _stack.Length)
- throw new System.Exception ("Stack overflow in parser state");
- var prevElement = _stack [_numElements - 1];
- var newElement = _stack[_numElements];
- _numElements++;
- newElement.CopyFrom (prevElement);
- return newElement.uniqueId;
- }
- public void Pop(int expectedRuleId)
- {
- if (_numElements == 1) {
- throw new System.Exception ("Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?");
- }
- if ( currentElement.uniqueId != expectedRuleId)
- throw new System.Exception ("Mismatched rule IDs - do you have mismatched Begin/Succeed/Fail?");
- // Restore state
- _numElements--;
- }
- public Element Peek(int expectedRuleId)
- {
- if (currentElement.uniqueId != expectedRuleId)
- throw new System.Exception ("Mismatched rule IDs - do you have mismatched Begin/Succeed/Fail?");
- return _stack[_numElements-1];
- }
- public Element PeekPenultimate()
- {
- if (_numElements >= 2) {
- return _stack [_numElements - 2];
- } else {
- return null;
- }
- }
- // Reduce stack height while maintaining currentElement
- // Remove second last element: i.e. "squash last two elements together"
- // Used when succeeding from a rule (and ONLY when succeeding, since
- // the state of the top element is retained).
- public void Squash()
- {
- if (_numElements < 2) {
- throw new System.Exception ("Attempting to remove final stack element is illegal! Mismatched Begin/Succceed/Fail?");
- }
- var penultimateEl = _stack [_numElements - 2];
- var lastEl = _stack [_numElements - 1];
- penultimateEl.SquashFrom (lastEl);
- _numElements--;
- }
- public void NoteErrorReported()
- {
- foreach (var el in _stack) {
- el.reportedErrorInScope = true;
- }
- }
- protected Element currentElement
- {
- get {
- return _stack [_numElements - 1];
- }
- }
- private Element[] _stack;
- private int _numElements;
- }
- }