예제 #1
0
void ParserThread::HandleForWhile()
{
    SymbolKind id;
    Token * tok = ConsumeToken(); //eat for or while key word
    id = (tok->type_id()==TKN_FOR)? tkFor:tkWhile;
    Symbol * sym = DoAddToken(id,*tok);
    ConsumeToken(); //eat the left parenthesis
    PushContext();  //save the old context
    m_Context.parentToken=sym;
    DoParse();      // do a parse, and should returned on an unbalanced right parenthesis
    PopContext();   // restore the old context

    tok = PeekToken();
    if(tok->type_id()==TKN_L_BRACE)
    {
        ConsumeToken(); //eat {
        PushContext();  //save the old context
        m_Context.parentToken=sym;
        DoParse();      // do a parse, and should returned on an unbalanced right brace
        PopContext();   // restore the old context
    }
    else
        SkipStatementBlock();

}
예제 #2
0
void ParserThread::HandleEnum()
{
    // enums have the following rough definition:
    // enum [xxx] { type1 name1 [= 1][, [type2 name2 [= 2]]] };

    ConsumeToken();
    Token * tk = ConsumeToken();    // the token after "enum"
    //Token * newToken = 0;
    if (tk->type_id() == TKN_IDENTIFIER)           // enum XXX
    {
        Token *pk = PeekToken();
        if(pk->type_id() == TKN_L_BRACE )  //enum XXX {
        {
            // Do Add Token of enum
            TRACE("find enum %s at line(%d)",tk->get_text().c_str(),tk->line_number());
            DoAddToken(tkEnum, *tk);
            //newToken->m_ImplLineStart = pk->line_number();
            ConsumeToken();                     //consume {
            PushContext();
            ReadEnumList();
            PopContext();
        }
        else
        {
            SkipStatementBlock();          //something wrong
            return;
        }
    }
    else if (tk->type_id()== TKN_L_BRACE) //  enum {
    {
        // // Do Add Token of enum
        TRACE("find unnamed enum at line(%d)",tk->line_number());
        DoAddToken(tkEnum, *tk);
        ConsumeToken();                    //consume {
        PushContext();
        ReadEnumList();
        PopContext();
    }

    // Token's implement End line information added
    tk = ConsumeToken();
    //we are now after the }

    // if we find a ;, good, end of definition of enum
    // if we find an id, then this is something like enum XXX{...} A,B;
    // A,B were the instant of the enum

    tk = ConsumeToken();
    if(tk->type_id() == TKN_IDENTIFIER)
    {
        //Add variables list
        return;
    }
    else if(tk->type_id() == TKN_SEMICOLON)
    {
        //OK, end of enum definition
        return;
    }

}
nsXFormsXPathNode*
nsXFormsXPathParser::Parse(const nsAString& aExpression)
{
#ifdef DEBUG_XF_PARSER
  printf("=====================================\n");
  printf("Parsing: %s\n", NS_ConvertUTF16toUTF8(aExpression).get());
  printf("=====================================\n");
#endif

  mScanner.Init(aExpression);
  mAnalyzeStackPointer = 0;
  mPredicateLevel = 0;
  mHead = nsnull;
  PopToken();
  PushContext();
  
  nsXFormsXPathNode* root = mHead;
  Expr();
  PopContext();

#ifdef DEBUG_XF_PARSER
  Dump(root);
  printf("-------------------------------------\n");
#endif

  return root;
}
예제 #4
0
void ParserThread::HandleNamespace()
{
    ConsumeToken();
    Token *pk = PeekToken();
    Token name;
    if(pk->type_id()==TKN_IDENTIFIER)
    {
        name = *pk;
        ConsumeToken();
    }
    else
    {
        //un-named namespace
    }

    pk = PeekToken();
    if(pk->type_id()==TKN_L_BRACE)
    {
        ConsumeToken();
        Symbol * sym = DoAddToken(tkNamespace,name);
        PushContext();
        m_Context.parentToken = sym;
        DoParse();
        PopContext();
        TRACE("end of namespace\n");
    }

}
예제 #5
0
//--------------------------------------------------------------------------------------------------
static void PopContext
(
    Parser_t* parserPtr
)
//--------------------------------------------------------------------------------------------------
{
    // Don't do anything if a client handler has already stopped parsing.
    if (NotStopped(parserPtr))
    {
        // Pop the top one and release it.
        le_sls_Link_t* linkPtr = le_sls_Pop(&parserPtr->contextStack);
        le_mem_Release(CONTAINER_OF(linkPtr, Context_t, link));

        // Check the new context
        le_json_ContextType_t context = GetContext(parserPtr)->type;

        switch (context)
        {
            case LE_JSON_CONTEXT_DOC:

                // We've finished parsing the whole document.
                // Automatically stop parsing and report the document end to the client.
                StopParsing(parserPtr);
                Report(parserPtr, LE_JSON_DOC_END);
                break;

            case LE_JSON_CONTEXT_OBJECT:

                // We've finished parsing an object member.
                // Expect a comma separator or the end of the object next.
                parserPtr->next = EXPECT_COMMA_OR_OBJECT_END;
                break;

            case LE_JSON_CONTEXT_MEMBER:

                // We've finished parsing the value of an object member.
                // This is also the end of the member, so pop that context too.
                PopContext(parserPtr);
                break;

            case LE_JSON_CONTEXT_ARRAY:

                // We've finished parsing an array element value.
                // Expect a comma separator or the end of the array next.
                parserPtr->next = EXPECT_COMMA_OR_ARRAY_END;
                break;

            // These are all leaf contexts.  That is, we should never find one of these
            // contexts after popping another one off the stack.
            case LE_JSON_CONTEXT_STRING:
            case LE_JSON_CONTEXT_NUMBER:
            case LE_JSON_CONTEXT_TRUE:
            case LE_JSON_CONTEXT_FALSE:
            case LE_JSON_CONTEXT_NULL:

                LE_FATAL("Unexpected context after pop: %s", le_json_GetContextName(context));
        }
    }
}
예제 #6
0
void ParserThread::HandleFunction()
{
    //TRACE("HandleFunction() : %s %s()",m_Context.type.back().name.get_text().c_str(),name.c_str());

    // should always at the ( , so we firstly read the parentheses
    if(m_Context.nameQueue.size()==0)
    {
        m_Context.nameQueue = m_Context.typeQueue;
        m_Context.typeQueue.clear();
    }
    Symbol * sym = DoAddToken(tkFunction, m_Context.nameQueue.back().name);

    ArgumentList args;
    ReadFunctionArguments(args);

    Token * peek = PeekToken();

    if(peek->type_id() == TKN_CONST)
        ConsumeToken();

    // skip the member initialization list
    if(PeekToken()->type_id() == TKN_COLON)
    {
        ConsumeToken();
        while(true)
        {
            if(PeekToken()->type_id()!=TKN_L_BRACE)
                ConsumeToken();
            else
                break;
        }
    }



    peek = PeekToken();
    if (peek->type_id() == TKN_L_BRACE)   // function definition
    {
        TRACE("Function definition");

        //SkipBrace();
        ConsumeToken();
        //Symbol * sym = DoAddToken(tkFunction, m_Context.nameQueue.back().name);
        PushContext();
        m_Context.parentToken = sym;
        DoParse();
        PopContext();

    }
    else if (peek->type_id() == TKN_SEMICOLON)
    {
        TRACE("Function declaration");
        //DoAddToken(tkFunction, m_Context.nameQueue.back().name);
        //newToken->m_Args = args;
        ConsumeToken();
    }
    m_Context.EndStatement();
}
예제 #7
0
RDFContentSinkImpl::~RDFContentSinkImpl()
{
#ifdef DEBUG_REFS
    --gInstanceCount;
    fprintf(stdout, "%d - RDF: RDFContentSinkImpl\n", gInstanceCount);
#endif

    NS_IF_RELEASE(mDocumentURL);

    if (mContextStack) {
        PR_LOG(gLog, PR_LOG_WARNING,
               ("rdfxml: warning! unclosed tag"));

        // XXX we should never need to do this, but, we'll write the
        // code all the same. If someone left the content stack dirty,
        // pop all the elements off the stack and release them.
        PRInt32 i = mContextStack->Length();
        while (0 < i--) {
            nsIRDFResource* resource;
            RDFContentSinkState state;
            RDFContentSinkParseMode parseMode;
            PopContext(resource, state, parseMode);

#ifdef PR_LOGGING
            // print some fairly useless debugging info
            // XXX we should save line numbers on the context stack: this'd
            // be about 1000x more helpful.
            if (resource) {
                nsXPIDLCString uri;
                resource->GetValue(getter_Copies(uri));
                PR_LOG(gLog, PR_LOG_NOTICE,
                       ("rdfxml:   uri=%s", (const char*) uri));
            }
#endif

            NS_IF_RELEASE(resource);
        }

        delete mContextStack;
    }
    PR_FREEIF(mText);


    if (--gRefCnt == 0) {
        NS_IF_RELEASE(gRDFService);
        NS_IF_RELEASE(gRDFContainerUtils);
        NS_IF_RELEASE(kRDF_type);
        NS_IF_RELEASE(kRDF_instanceOf);
        NS_IF_RELEASE(kRDF_Alt);
        NS_IF_RELEASE(kRDF_Bag);
        NS_IF_RELEASE(kRDF_Seq);
        NS_IF_RELEASE(kRDF_nextVal);
    }
}
예제 #8
0
void ParserThread::ReadFunctionArguments(ArgumentList &args)
{
    //TKN_L_PAREN
    args.clear();
    ConsumeToken();//remove the first TKN_L_PAREN

    PushContext();
    m_Context.parseType = FunctionParameter;
    DoParse();
    PopContext();

}
void
nsXFormsXPathParser::LocationPath()
{
  if (DoRelative()) {
    PushContext();
    RelativeLocationPath();
    PopContext();
  } else {
    nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
    switch (t) {
    case nsXFormsXPathScanner::SLASH:
    case nsXFormsXPathScanner::SLASHSLASH:
      PushContext();
      AbsoluteLocationPath();
      PopContext();
      break;

    default:
      XPathCompilerException("Not a location path", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
    }
  }
}
void
nsXFormsXPathParser::PathExpr()
{
  nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
  switch (t) {
  case nsXFormsXPathScanner::ANCESTOR:
  case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
  case nsXFormsXPathScanner::ATTRIBUTE:
  case nsXFormsXPathScanner::CHILD:
  case nsXFormsXPathScanner::DESCENDANT:
  case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
  case nsXFormsXPathScanner::FOLLOWING:
  case nsXFormsXPathScanner::FOLLOWING_SIBLING:
  case nsXFormsXPathScanner::NAMESPACE:
  case nsXFormsXPathScanner::PARENT:
  case nsXFormsXPathScanner::PRECEDING:
  case nsXFormsXPathScanner::PRECEDING_SIBLING:
  case nsXFormsXPathScanner::SELF:
  case nsXFormsXPathScanner::AT:
  case nsXFormsXPathScanner::STAR:
  case nsXFormsXPathScanner::NCNAME:
  case nsXFormsXPathScanner::QNAME:
  case nsXFormsXPathScanner::COMMENT:
  case nsXFormsXPathScanner::TEXT:
  case nsXFormsXPathScanner::PI:
  case nsXFormsXPathScanner::NODE:
  case nsXFormsXPathScanner::DOT:
  case nsXFormsXPathScanner::DOTDOT:
  case nsXFormsXPathScanner::SLASH:
  case nsXFormsXPathScanner::SLASHSLASH:
    LocationPath();
    break;
    
  default:
    PushContext();
    FilterExpr();
    t = PeekToken();
    if (t == nsXFormsXPathScanner::SLASH || t == nsXFormsXPathScanner::SLASHSLASH) {
      PopToken();

      if (DoRelative()) {
        RelativeLocationPath();
      } else {
        XPathCompilerException("After / in a filter expression it is required to have a relative path expression",
                               EmptyString());
      }

    }
    PopContext();
  }
}
예제 #11
0
/*
 * Parse the command string contained in the current context.
 */
void CmdStringParse( OPT_STORAGE *cmdOpts, int *itemsParsed )
/***********************************************************/
{
    int                 ch;
    char *              filename;

    for( ;; ) {
        /*** Find the start of the next item ***/
        CmdScanWhitespace();
        ch = GetCharContext();
        if( ch == '\0' )  break;
        MarkPosContext();               /* mark start of switch */

        /*** Handle switches, command files, and input files ***/
        if( ch == '-'  ||  ch == '/' ) {        /* switch */
            if( OPT_PROCESS( cmdOpts ) != 0 ) {
                cmd_line_error();
            }
        } else if( ch == '@' ) {                /* command file */
            filename = CmdScanFileNameWithoutQuotes();
            PushContext();
            if( OpenFileContext( filename ) ) {
                FatalError( "Cannot open '%s'.", filename );
            }
            FreeMem( filename );
            CmdStringParse( cmdOpts, itemsParsed );
            PopContext();
        } else if( ch == '"' ) {                /* quoted option or file name */
            ch = GetCharContext();
            if( ch == '-' ) {
                Quoted = 1;
                if( OPT_PROCESS( cmdOpts ) != 0 ) {
                    cmd_line_error();
                }
            } else {
                UngetCharContext();
                UngetCharContext();
                filename = CmdScanFileName();
                AddFile( TYPE_DEFAULT_FILE, filename );
                FreeMem( filename );
            }                
        } else {                                /* input file */
            UngetCharContext();
            filename = CmdScanFileName();
            AddFile( TYPE_DEFAULT_FILE, filename );
            FreeMem( filename );
        }
        (*itemsParsed)++;
    }
    CloseContext();
}
예제 #12
0
NS_IMETHODIMP 
RDFContentSinkImpl::HandleEndElement(const PRUnichar *aName)
{
  FlushText();

  nsIRDFResource* resource;
  if (NS_FAILED(PopContext(resource, mState, mParseMode))) {
      // XXX parser didn't catch unmatched tags?
#ifdef PR_LOGGING
      if (PR_LOG_TEST(gLog, PR_LOG_WARNING)) {
          nsAutoString tagStr(aName);
          char* tagCStr = ToNewCString(tagStr);

          PR_LogPrint
                 ("rdfxml: extra close tag '%s' at line %d",
                  tagCStr, 0/*XXX fix me */);

          NS_Free(tagCStr);
      }
#endif

      return NS_ERROR_UNEXPECTED; // XXX
  }

  // If we've just popped a member or property element, _now_ is the
  // time to add that element to the graph.
  switch (mState) {
    case eRDFContentSinkState_InMemberElement: 
      {
        nsCOMPtr<nsIRDFContainer> container;
        NS_NewRDFContainer(getter_AddRefs(container));
        container->Init(mDataSource, GetContextElement(1));
        container->AppendElement(resource);
      } 
      break;

    case eRDFContentSinkState_InPropertyElement: 
      {
        mDataSource->Assert(GetContextElement(1), GetContextElement(0), resource, PR_TRUE);                                          
      } break;
    default:
      break;
  }
  
  if (mContextStack->IsEmpty())
      mState = eRDFContentSinkState_InEpilog;

  NS_IF_RELEASE(resource);
  return NS_OK;
}
예제 #13
0
//--------------------------------------------------------------------------------------------------
static void ParseString
(
    Parser_t* parserPtr,
    char c
)
//--------------------------------------------------------------------------------------------------
{
    // See if this is a string terminating '"' character.
    if (c == '"')
    {
        if ((parserPtr->numBytes != 0) && (parserPtr->buffer[parserPtr->numBytes - 1] == '\\'))
        {
            // Escaped ", replace with ".
            parserPtr->buffer[parserPtr->numBytes - 1] = '"';
        }
        else
        {
            // Make we have a valid UTF-8 string.
            if (!le_utf8_IsFormatCorrect(parserPtr->buffer))
            {
                Error(parserPtr, LE_JSON_SYNTAX_ERROR, "String is not valid UTF-8.");
            }
            else
            {
                // Handling of the end of the string depends on the context.
                le_json_ContextType_t contextType = GetContext(parserPtr)->type;

                if (contextType == LE_JSON_CONTEXT_STRING)
                {
                    Report(parserPtr, LE_JSON_STRING);
                    PopContext(parserPtr);
                }
                else if (contextType == LE_JSON_CONTEXT_MEMBER)
                {
                    Report(parserPtr, LE_JSON_OBJECT_MEMBER);
                    parserPtr->next = EXPECT_COLON;
                }
                else
                {
                    LE_FATAL("Unexpected context '%s' for string termination.",
                             le_json_GetContextName(contextType));
                }
            }
        }
    }
    else
    {
        AddToBuffer(parserPtr, c);
    }
}
void UtilCaptureImpl::DeviceImpl::ThreadFunc(void) {
    EnterCriticalSection(&cs);
    queues.resize(streams.size());
    LeaveCriticalSection(&cs);
    while (!stop) {
        std::deque<pxcU32> updates;
        UpdateSample(updates);
        
        for (std::deque<pxcU32>::iterator update=updates.begin();update!=updates.end();update++) {
            SampleContext context;
			PopContext(*update,context);
			SignalContext(context,ProcessSample(*update,context.storage));
        }
    }
}
예제 #15
0
/*
 * Parse the command string contained in the current context.
 */
void CmdStringParse( OPT_STORAGE *cmdOpts, int *itemsParsed )
/***********************************************************/
{
    char                ch;
    char *              filename;
    char *              str;

    for( ;; ) {
        /*** Find the start of the next item ***/
        CmdScanWhitespace();
        ch = GetCharContext();
        if( ch == '\0' )  break;
        MarkPosContext();               /* mark start of switch */

        /*** Handle switches, command files, and input files ***/
        if( ch == '-'  ||  ch == '/' ) {        /* switch */
            if( OPT_PROCESS( cmdOpts ) ) {
                /*
                 * Switch didn't match, if user entered empty switch,
                 * just be silent like MS's nmake does.
                 */

                ch = GetCharContext();
                if( ch != '\0' && !isspace( ch ) ) {
                    cmd_line_error();
                }
            }
        } else if( ch == '@' ) {                /* command file */
            filename = CmdScanFileNameWithoutQuotes();
            PushContext();
            if( OpenFileContext( filename ) ) {
                FatalError( "Cannot open '%s'.", filename );
            }
            FreeMem( filename );
            CmdStringParse( cmdOpts, itemsParsed );
            PopContext();
        } else {                                /* targets and macros */
            UngetCharContext();
            str = CmdScanString();
            add_string( &(cmdOpts->t010101010101_value), str, '\0' );
            cmdOpts->t010101010101 = 1;
        }
        (*itemsParsed)++;
    }
    CloseContext();
}
예제 #16
0
//--------------------------------------------------------------------------------------------------
static void ProcessNumber
(
    Parser_t* parserPtr
)
//--------------------------------------------------------------------------------------------------
{
    char* endPtr;

    errno = 0;

    // Attempt conversion.
    parserPtr->number = strtod(parserPtr->buffer, &endPtr);

    // If it stopped before the end, then there are bad characters in the number.
    if (endPtr[0] != '\0')
    {
        Error(parserPtr, LE_JSON_SYNTAX_ERROR, "Invalid characters in number.");
    }
    // If errno has been set, then there was an underflow or overflow in the conversion.
    else if (errno == ERANGE)
    {
        if (parserPtr->number == 0)
        {
            Error(parserPtr, LE_JSON_READ_ERROR, "Numerical underflow occurred.");
        }
        else
        {
            Error(parserPtr, LE_JSON_READ_ERROR, "Numerical overflow occurred.");
        }
    }
    // If all's good, report the value match to the client and pop the context.
    else
    {
        Report(parserPtr, LE_JSON_NUMBER);
        PopContext(parserPtr);
    }
}
예제 #17
0
void ParserThread::HandleClass(EClassType ct)
{

    // class xxx {   or class {
    // the keyworkd "class" is already comsumed

    //assert(CurrentToken()->type_id()==TKN_CLASS);
    ConsumeToken();


    Token * current =  ConsumeToken();      // class name
    Token * next    =  PeekToken();

    TRACE("HandleClass() : Found class '%s'", current->get_text().c_str() );


    // Check current firstly
    if (current->type_id() == TKN_L_BRACE)   // unnamed class/struct/union
    {
//                cc_string unnamedTmp;
//                unnamedTmp.Printf(_T("%s%s%d"),
//                                  ParserConsts::unnamed.wx_str(),
//                                  ct == ctClass ? _T("Class") :
//                                  ct == ctUnion ? _T("Union") :
//                                                  _T("Struct"), ++m_pTokensTree->m_StructUnionUnnamedCount);
//
//                Token* newToken = DoAddToken(tkClass, unnamedTmp, lineNr);
//
//                PushContext();
//                m_Context.Clear();
//                m_Context.parentToken = newToken;
//                m_Context.accessScope  = ct == ctClass ? tsPrivate : tsPublic; // struct has default public scope
//
//				newToken->m_ImplLine = lineNr;
//				newToken->m_ImplLineStart = m_Tokenizer.GetLineNumber();
//
//                DoParse();
//
//                PopContext();
    }
    else if (current->type_id() == TKN_IDENTIFIER)     //OK, we need to check the next
    {
        //parser base clause
        if ( next->type_id() == TKN_COLON )
        {
            //ReadType
            //ConsumeToken(); //remove :id
            ConsumeToken(); //remove  :
            ConsumeToken(); //remove protect/public/private
            //ConsumeToken(); //need to read the id
            ParseFullIdentifer();
        }
        next = PeekToken();
        if ( next->type_id() == TKN_L_BRACE)   // class AAA {, we find the "{" here
        {

            //ParserThreadContext savedContext = m_Context;
            //m_Context.EndStatement();
            //m_Context.parentToken = newToken;
            ConsumeToken();// consume {
            Symbol * sym = DoAddToken(tkClass, *current);
            PushContext();
            m_Context.parentToken = sym;
            DoParse();  // when meet a }, we should return from DoParse()
            PopContext();
            current = ConsumeToken();
            if(current->type_id()==TKN_SEMICOLON)  // class A {.....};
                return;
            else
                SkipStatementBlock(); //struct A {....} a b;

        }
    }
    else
    {
        // something wrong, should be skip to a semicolon
        SkipStatementBlock();
    }

}
예제 #18
0
//--------------------------------------------------------------------------------------------------
static void ProcessChar
(
    Parser_t* parserPtr,
    char c
)
//--------------------------------------------------------------------------------------------------
{
    switch (parserPtr->next)
    {
        case EXPECT_OBJECT_OR_ARRAY:

            // Throw away whitespace characters until '{' or '[' is found.
            if (c == '{')
            {
                PushContext(parserPtr, LE_JSON_CONTEXT_OBJECT, GetEventHandler(parserPtr));
                parserPtr->next = EXPECT_MEMBER_OR_OBJECT_END;
                Report(parserPtr, LE_JSON_OBJECT_START);
            }
            else if (c == '[')
            {
                PushContext(parserPtr, LE_JSON_CONTEXT_ARRAY, GetEventHandler(parserPtr));
                parserPtr->next = EXPECT_VALUE_OR_ARRAY_END;
                Report(parserPtr, LE_JSON_ARRAY_START);
            }
            else if (!isspace(c))
            {
                Error(parserPtr, LE_JSON_SYNTAX_ERROR, "Document must start with '{' or '['.");
            }
            return;

        case EXPECT_MEMBER_OR_OBJECT_END:

            // Throw away whitespace until a '"' or '}' is found.
            if (c == '}')   // Object end found.
            {
                Report(parserPtr, LE_JSON_OBJECT_END);
                PopContext(parserPtr);
            }
            else if (c == '"')  // Start of member name (string) found.
            {
                PushContext(parserPtr, LE_JSON_CONTEXT_MEMBER, GetEventHandler(parserPtr));
                parserPtr->next = EXPECT_STRING;
            }
            else if (!isspace(c))
            {
                Error(parserPtr,
                      LE_JSON_SYNTAX_ERROR,
                      "Expected end of object (}) or beginning of object member name (\").");
            }
            return;

        case EXPECT_COLON:

            // Throw away whitespace until a ':' is found.
            if (c == ':')
            {
                parserPtr->next = EXPECT_VALUE;
            }
            else if (!isspace(c))
            {
                Error(parserPtr,
                      LE_JSON_SYNTAX_ERROR,
                      "Expected ':' after object member name.");
            }
            return;

        case EXPECT_VALUE:

            ParseValue(parserPtr, c);
            return;

        case EXPECT_COMMA_OR_OBJECT_END:

            // Throw away whitespace until a ',' or '}' is found.
            if (c == '}')   // Object end found.
            {
                Report(parserPtr, LE_JSON_OBJECT_END);
                PopContext(parserPtr);
            }
            else if (c == ',')  // Comma separator found.
            {
                parserPtr->next = EXPECT_MEMBER;
            }
            else if (!isspace(c))
            {
                Error(parserPtr,
                      LE_JSON_SYNTAX_ERROR,
                      "Expected end of object (}) or beginning of object member name (\").");
            }
            return;

        case EXPECT_MEMBER:

            // Throw away whitespace until a '"' is found.
            if (c == '"')  // Start of member name (string) found.
            {
                PushContext(parserPtr, LE_JSON_CONTEXT_MEMBER, GetEventHandler(parserPtr));
                parserPtr->next = EXPECT_STRING;
            }
            else if (!isspace(c))
            {
                Error(parserPtr,
                      LE_JSON_SYNTAX_ERROR,
                      "Expected beginning of object member name (\").");
            }
            return;

        case EXPECT_VALUE_OR_ARRAY_END:

            if (c == ']')
            {
                Report(parserPtr, LE_JSON_ARRAY_END);
                PopContext(parserPtr);
            }
            else
            {
                ParseValue(parserPtr, c);
            }
            return;

        case EXPECT_COMMA_OR_ARRAY_END:

            // Throw away whitespace until a ',' or ']' is found.
            if (c == ']')   // Array end found.
            {
                Report(parserPtr, LE_JSON_ARRAY_END);
                PopContext(parserPtr);
            }
            else if (c == ',')  // Comma separator found.
            {
                parserPtr->next = EXPECT_VALUE;
            }
            else if (!isspace(c))
            {
                Error(parserPtr,
                      LE_JSON_SYNTAX_ERROR,
                      "Expected end of array (]) or a comma separator (,).");
            }
            return;

        case EXPECT_STRING:

            ParseString(parserPtr, c);
            return;

        case EXPECT_NUMBER:

            if ((c == '.') || isdigit(c))
            {
                AddToBuffer(parserPtr, c);
            }
            else
            {
                ProcessNumber(parserPtr);
                ProcessChar(parserPtr, c);
            }
            return;

        case EXPECT_TRUE:

            ParseConstant(parserPtr, c, "true");
            if (strcmp(parserPtr->buffer, "true") == 0)
            {
                Report(parserPtr, LE_JSON_TRUE);
                PopContext(parserPtr);
            }
            return;

        case EXPECT_FALSE:

            ParseConstant(parserPtr, c, "false");
            if (strcmp(parserPtr->buffer, "false") == 0)
            {
                Report(parserPtr, LE_JSON_FALSE);
                PopContext(parserPtr);
            }
            return;

        case EXPECT_NULL:

            ParseConstant(parserPtr, c, "null");
            if (strcmp(parserPtr->buffer, "null") == 0)
            {
                Report(parserPtr, LE_JSON_NULL);
                PopContext(parserPtr);
            }
            return;

        case EXPECT_NOTHING:    ///< Parsing stopped.
            return;
    }

    LE_FATAL("Internal error: Invalid JSON parser expectation %d.", parserPtr->next);
}