Example #1
0
        private void ParseNext()
        {
            var trailingWhitespace = false;

            var token = _scanner.NextToken();

            while (true)
            {
                int action = TransitionActions[_state, token];
                switch (action)
                {
                default:
                    throw new InvalidTokenException(token);

                case ActionNotDefined:
                    throw new IonException("Invalid state");

                case ActionEof:
                    _state = StateEof;
                    _eof   = true;
                    return;

                case ActionLoadFieldName:
                    if (!IsInStruct)
                    {
                        throw new IonException("Field names have to be inside struct");
                    }

                    LoadTokenContents(token);
                    var symtok = ParseSymbolToken(_valueBuffer, token);
                    SetFieldName(symtok);
                    ClearValueBuffer();
                    token = _scanner.NextToken();
                    if (token != TextConstants.TokenColon)
                    {
                        throw new InvalidTokenException("Field name has to be followed by a colon");
                    }
                    _scanner.MarkTokenFinished();
                    _state = StateBeforeAnnotationContained;
                    token  = _scanner.NextToken();
                    break;

                case ActionLoadAnnotation:
                    LoadTokenContents(token);
                    trailingWhitespace = _scanner.SkipWhiteSpace();
                    if (!_scanner.TrySkipDoubleColon())
                    {
                        _state = GetStateAfterAnnotation(_state, _containerStack.Peek());
                        break;
                    }

                    var sym = ParseSymbolToken(_valueBuffer, token);
                    _annotations.Add(sym);
                    ClearValueBuffer();
                    _scanner.MarkTokenFinished();
                    // Consumed the annotation, move on.
                    // note: that peekDoubleColon() consumed the two colons
                    // so nextToken won't see them
                    token = _scanner.NextToken();
                    switch (token)
                    {
                    case TextConstants.TokenSymbolIdentifier:
                    case TextConstants.TokenSymbolQuoted:
                        // This may be another annotation, so stay in this state
                        // and come around the horn again to check it out.
                        break;

                    default:
                        // we leave the error handling to the transition
                        _state = GetStateAfterAnnotation(_state, _containerStack.Peek());
                        break;
                    }

                    break;

                case ActionStartStruct:
                    _valueType = IonType.Struct;
                    _expectedContainerClosingSymbol.Push(TextConstants.TokenCloseBrace);
                    _state = StateBeforeFieldName;
                    return;

                case ActionStartList:
                    _valueType = IonType.List;
                    _expectedContainerClosingSymbol.Push(TextConstants.TokenCloseSquare);
                    _state = StateBeforeAnnotationContained;
                    return;

                case ActionStartSexp:
                    _valueType = IonType.Sexp;
                    _expectedContainerClosingSymbol.Push(TextConstants.TokenCloseParen);
                    _state = StateBeforeAnnotationSexp;
                    return;

                case ActionStartLob:
                    switch (_scanner.PeekLobStartPunctuation())
                    {
                    case TextConstants.TokenStringDoubleQuote:
                        _lobToken  = TextConstants.TokenStringDoubleQuote;
                        _valueType = IonType.Clob;
                        break;

                    case TextConstants.TokenStringTripleQuote:
                        _lobToken  = TextConstants.TokenStringTripleQuote;
                        _valueType = IonType.Clob;
                        break;

                    default:
                        _state     = StateInBlobContent;
                        _lobToken  = TextConstants.TokenOpenDoubleBrace;
                        _valueType = IonType.Blob;
                        break;
                    }

                    return;

                case ActionLoadScalar:
                    if (token == TextConstants.TokenSymbolIdentifier)
                    {
                        LoadTokenContents(token);
                        //token has been wholy loaded
                        _scanner.MarkTokenFinished();

                        _valueKeyword = TextConstants.GetKeyword(_valueBuffer, 0, _valueBuffer.Length);
                        switch (_valueKeyword)
                        {
                        default:
                            _valueType = IonType.Symbol;
                            break;

                        case TextConstants.KeywordNull:
                            ReadNullType(trailingWhitespace);
                            break;

                        case TextConstants.KeywordTrue:
                            _valueType   = IonType.Bool;
                            _v.BoolValue = true;
                            break;

                        case TextConstants.KeywordFalse:
                            _valueType   = IonType.Bool;
                            _v.BoolValue = false;
                            break;

                        case TextConstants.KeywordNan:
                            _valueType = IonType.Float;
                            ClearValueBuffer();
                            _v.DoubleValue = double.NaN;
                            break;

                        case TextConstants.KeywordSid:
                            var sid = TextConstants.DecodeSid(_valueBuffer);
                            _v.IntValue = sid;
                            _valueType  = IonType.Symbol;
                            break;
                        }

                        //do not clear the buffer yet because LoadTokenContents() might be called again
                    }
                    else if (token == TextConstants.TokenDot)
                    {
                        _valueType = IonType.Symbol;
                        ClearValueBuffer();
                        _v.StringValue = ".";
                    }
                    else
                    {
                        // if it's not a symbol we just look at the token type
                        _valueType = TextConstants.GetIonTypeOfToken(token);
                    }

                    _state = GetStateAfterValue(_containerStack.Peek());
                    return;

                case ActionEatComma:
                    if (_containerProhibitsCommas)
                    {
                        throw new InvalidTokenException(',');
                    }

                    _state = _containerIsStruct ? StateBeforeFieldName : StateBeforeAnnotationContained;
                    _scanner.MarkTokenFinished();
                    token = _scanner.NextToken();
                    break;

                case ActionFinishDatagram:
                    Debug.Assert(CurrentDepth == 0);
                    _eof   = true;
                    _state = StateEof;
                    return;

                case ActionFinishContainer:
                    ValidateClosingSymbol(token);
                    _state = GetStateAfterContainer(_containerStack.Peek());
                    _eof   = true;
                    return;

                case ActionFinishLob:
                    _state = GetStateAfterValue(_containerStack.Peek());
                    return;

                case ActionPlusInf:
                    _valueType = IonType.Float;
                    ClearValueBuffer();
                    _v.DoubleValue = double.PositiveInfinity;
                    _state         = GetStateAfterValue(_containerStack.Peek());
                    return;

                case ActionMinusInf:
                    _valueType = IonType.Float;
                    ClearValueBuffer();
                    _v.DoubleValue = double.NegativeInfinity;
                    _state         = GetStateAfterValue(_containerStack.Peek());
                    return;
                }
            }
        }