Some skeletal work for non-blocking parsing
diff --git a/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParser.java
index 6c67e26..d53bdd9 100644
--- a/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParser.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParser.java
@@ -7,6 +7,7 @@
 import com.fasterxml.jackson.core.async.ByteArrayFeeder;
 import com.fasterxml.jackson.core.async.NonBlockingInputFeeder;
 import com.fasterxml.jackson.core.io.IOContext;
+import com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper;
 import com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer;
 import com.fasterxml.jackson.core.util.VersionUtil;
 
@@ -39,6 +40,29 @@
 
     /*
     /**********************************************************************
+    /* Location tracking, additional
+    /**********************************************************************
+     */
+
+    /**
+     * Alternate row tracker, used to keep track of position by `\r` marker
+     * (whereas <code>_currInputRow</code> tracks `\n`). Used to simplify
+     * tracking of linefeeds, assuming that input typically uses various
+     * linefeed combinations (`\r`, `\n` or `\r\n`) consistently, in which
+     * case we can simply choose max of two row candidates.
+     */
+    protected int _currInputRowAlt = 1;
+
+    /*
+    /**********************************************************************
+    /* Other state
+    /**********************************************************************
+     */
+
+    protected int _currentQuote;
+
+    /*
+    /**********************************************************************
     /* Life-cycle
     /**********************************************************************
      */
@@ -148,14 +172,14 @@
 
         // No: fresh new token; may or may not have existing one
         _numTypesValid = NR_UNKNOWN;
-//            _tokenInputTotal = _currInputProcessed + _inputPtr;
+        _tokenInputTotal = _currInputProcessed + _inputPtr;
         // also: clear any data retained so far
         _binaryValue = null;
         int ch = _inputBuffer[_inputPtr++];
 
         switch (_majorState) {
         case MAJOR_INITIAL:
-            // TODO: Bootstrapping? BOM?
+            return _startDocument(ch);
 
         case MAJOR_ROOT:
             return _startValue(ch);
@@ -193,6 +217,50 @@
     /**********************************************************************
      */
 
+    private final JsonToken _startDocument(int ch) throws IOException
+    {
+        ch &= 0xFF;
+
+        // Very first byte: could be BOM
+        if (ch == ByteSourceJsonBootstrapper.UTF8_BOM_1) {
+            // !!! TODO
+        }
+
+        // If not BOM (or we got past it), could be whitespace or comment to skip
+        while (ch <= 0x020) {
+            if (ch != INT_SPACE) {
+                if (ch == INT_LF) {
+                    ++_currInputRow;
+                    _currInputRowStart = _inputPtr;
+                } else if (ch == INT_CR) {
+                    ++_currInputRowAlt;
+                    _currInputRowStart = _inputPtr;
+                } else if (ch != INT_TAB) {
+                    _throwInvalidSpace(ch);
+                }
+            }
+            if (_inputPtr >= _inputEnd) {
+                _minorState = MINOR_FIELD_ROOT_GOT_SEPARATOR;
+                if (_closed) {
+                    return null;
+                }
+                // note: if so, do not even bother changing state
+                if (_endOfInput) { // except for this special case
+                    return _eofAsNextToken();
+                }
+                return JsonToken.NOT_AVAILABLE;
+            }
+            ch = _inputBuffer[_inputPtr++] & 0xFF;
+        }
+        return _startValue(ch);
+    }
+
+    /*
+    /**********************************************************************
+    /* Second-level decoding, value parsing
+    /**********************************************************************
+     */
+    
     /**
      * Helper method called to detect type of a value token (at any level), and possibly
      * decode it if contained in input buffer.
@@ -200,6 +268,121 @@
      */
     private final JsonToken _startValue(int ch) throws IOException
     {
+        if (ch == INT_QUOTE) {
+            return _startString(ch);
+        }
+        switch (ch) {
+        case '-':
+            return _startNegativeNumber();
+
+        // Should we have separate handling for plus? Although
+        // it is not allowed per se, it may be erroneously used,
+        // and could be indicate by a more specific error message.
+        case '0':
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9':
+            return _startPositiveNumber(ch);
+        case 'f':
+            return _startFalseToken();
+        case 'n':
+            return _startNullToken();
+        case 't':
+            return _startTrueToken();
+        case '[':
+            return _startArrayScope();
+        case ']':
+            return _closeArrayScope();
+        case '{':
+            return _startObjectScope();
+        case '}':
+            return _closeObjectScope();
+        default:
+        }
+        return _startUnexpectedValue(ch);
+    }
+
+    protected JsonToken _startUnexpectedValue(int ch) throws IOException
+    {
+        // TODO: Maybe support non-standard tokens that streaming parser does:
+        //
+        // * NaN
+        // * Infinity
+        // * Plus-prefix for numbers
+        // * Apostrophe for Strings
+
+        switch (ch) {
+        case '\'':
+            return _startString(ch);
+            
+        case ',':
+            // If Feature.ALLOW_MISSING_VALUES is enabled we may allow "missing values",
+            // that is, encountering a trailing comma or closing marker where value would be expected
+            if (!_parsingContext.inObject() && isEnabled(Feature.ALLOW_MISSING_VALUES)) {
+                // Important to "push back" separator, to be consumed before next value;
+                // does not lead to infinite loop
+               --_inputPtr;
+               return _valueComplete(JsonToken.VALUE_NULL);
+            }
+            break;
+        }
+        // !!! TODO: maybe try to collect more information for better diagnostics
+        _reportUnexpectedChar(ch, "expected a valid value (number, String, array, object, 'true', 'false' or 'null')");
+        return null;
+    }
+
+    /*
+    /**********************************************************************
+    /* Second-level decoding, simple tokens
+    /**********************************************************************
+     */
+
+    protected JsonToken _startFalseToken() throws IOException
+    {
+        return null;
+    }
+
+    protected JsonToken _startTrueToken() throws IOException
+    {
+        return null;
+    }
+
+    protected JsonToken _startNullToken() throws IOException
+    {
+        return null;
+    }
+
+    /*
+    /**********************************************************************
+    /* Second-level decoding, String decoding
+    /**********************************************************************
+     */
+
+    protected JsonToken _startString(int q) throws IOException
+    {
+        _currentQuote = q;
+        return null;
+    }
+
+    /*
+    /**********************************************************************
+    /* Second-level decoding, String decoding
+    /**********************************************************************
+     */
+
+    protected JsonToken _startPositiveNumber(int ch) throws IOException
+    {
+        return null;
+    }
+    
+    protected JsonToken _startNegativeNumber() throws IOException
+    {
         return null;
     }