示例#1
0
int Parser::parse() try {
    push__(0); // initial state
    clearin(); // clear the tokens.

    while (true) {
        try {
            if (s_state[d_state__]->d_type & REQ_TOKEN)
                nextToken(); // obtain next token

            int action = lookup(false); // lookup d_token__ in d_state__

            if (action > 0) // SHIFT: push a new state
            {
                push__(action);
                popToken__();      // token processed
            } else if (action < 0) // REDUCE: execute and pop.
            {
                executeAction(-action);
                // next token is the rule's LHS
                reduce__(s_productionInfo[-action]);
            } else
                ACCEPT();
        } catch (ErrorRecovery__) {
            errorRecovery();
        }
    }
} catch (Return__ retValue) {
    return retValue;
}
示例#2
0
// If d_token__ is _UNDETERMINED_ then if d_nextToken__ is _UNDETERMINED_
// another
// token is obtained from lex(). Then d_nextToken__ is assigned to d_token__.
void Parser::nextToken()
{
    if (d_token__ != _UNDETERMINED_) // no need for a token: got one
        return;                      // already

    if (d_nextToken__ != _UNDETERMINED_) {
        popToken__(); // consume pending token
    } else {
        ++d_acceptedTokens__; // accept another token (see
                              // errorRecover())
        d_token__ = lex();
        if (d_token__ <= 0)
            d_token__ = _EOF_;
    }
    print();
}
    // When an error has occurred, pop elements off the stack until the top
    // state has an error-item. If none is found, the default recovery
    // mode (which is to abort) is activated. 
    //
    // If EOF is encountered without being appropriate for the current state,
    // then the error recovery will fall back to the default recovery mode.
    // (i.e., parsing terminates)
void JSONTokenizer::errorRecovery()
try
{
    if (d_acceptedTokens__ >= d_requiredTokens__)// only generate an error-
    {                                           // message if enough tokens 
        ++d_nErrors__;                          // were accepted. Otherwise
        std::string _str("Syntax error at line ");
        muzzley::tostr(_str, d_scanner.lineNr());
        error(_str.data());                  // simply skip input
    }


    // get the error state
    while (not (s_state[top__()][0].d_type & ERR_ITEM))
    {
        pop__();
    }

    // In the error state, lookup a token allowing us to proceed.
    // Continuation may be possible following multiple reductions,
    // but eventuall a shift will be used, requiring the retrieval of
    // a terminal token. If a retrieved token doesn't match, the catch below 
    // will ensure the next token is requested in the while(true) block
    // implemented below:

    int lastToken = d_token__;                  // give the unexpected token a
                                                // chance to be processed
                                                // again.

    pushToken__(_error_);                       // specify _error_ as next token
    push__(lookup(true));                       // push the error state

    d_token__ = lastToken;                      // reactivate the unexpected
                                                // token (we're now in an
                                                // ERROR state).

    bool gotToken = true;                       // the next token is a terminal

    while (true)
    {
        try
        {
            if (s_state[d_state__]->d_type & REQ_TOKEN)
            {
                gotToken = d_token__ == _UNDETERMINED_;
                nextToken();                    // obtain next token
            }
            
            int action = lookup(true);

            if (action > 0)                 // push a new state
            {
                push__(action);
                popToken__();

                if (gotToken)
                {

                    d_acceptedTokens__ = 0;
                    return;
                }
            }
            else if (action < 0)
            {
                // no actions executed on recovery but save an already 
                // available token:
                if (d_token__ != _UNDETERMINED_)
                    pushToken__(d_token__);
 
                                            // next token is the rule's LHS
                reduce__(s_productionInfo[-action]); 
            }
            else
                ABORT();                    // abort when accepting during
                                            // error recovery
        }
        catch (...)
        {
            if (d_token__ == _EOF_)
                ABORT();                    // saw inappropriate _EOF_
                      
            popToken__();                   // failing token now skipped
        }
    }
}
catch (ErrorRecovery__)       // This is: DEFAULT_RECOVERY_MODE
{
    ABORT();
}