public void Push(char c) { try { //track line, column if (c == '\n') { location.Line++; location.Column = 1; } else { location.Column++; } position++; for (int loopLimit = 0; loopLimit < 10; loopLimit++) { currentStateLength++; string rollback = null; State 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; } //"complex" rollbacks require actually skipping backwards. //Note the previous state is invalid for this operation. else if (rollback.Length > 0) { position -= (rollback.Length + 1); foreach (char rollChar in rollback) { Push(rollChar); } 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 void Push(char c) { try { //FIXME: position/location should be at current char, not after it position++; if (c == '\n') { previousLineEnd = new TextLocation(location.Line, location.Column + 1); location = new TextLocation(location.Line + 1, 1); } else { location = new TextLocation(location.Line, location.Column + 1); } for (int loopLimit = 0; loopLimit < 10; loopLimit++) { currentStateLength++; string rollback = null; if (currentState == null) { return; } State 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 TextLocation(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 TextLocation(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); } }