std::string TreeBuilder::getExpectedTokensGrammar() const { std::vector<std::string> tokens = getExpectedTokens(); if (tokens.empty()) return "No productions expected"; std::string result(tokens.at(0)); if (tokens.size() > 1) { result += ": [\n"; for (std::size_t i = 1; i < tokens.size(); ++i) { result += "\t" + tokens[i] + ",\n"; } result.erase(result.end() - 1); return result + "\n]"; } return result; }
void PlSqlParser::correctError(int *token, ParsingTableRow *row, ParsingTableAction **actionOnCurrentToken) { //qDebug("--------started error recovery--------------"); bool reservedWord = parsingTable->isReservedWord(scanner->getTokenLexeme()); if(*token!=PLS_SEMI){ *actionOnCurrentToken=row->actions->value(PLS_NOT_SEMI, 0); if(!reservedWord){ replaceKeywordWithIdentifier(*token, row, actionOnCurrentToken); } } if(*actionOnCurrentToken == 0 && !this->strict){ //try to recognize major constructs //read input until we encounter one of (first of) PLS_SEMI, END opt_identifier PLS_SEMI //while reading add all read tokens to token stack QList<TokenInfo*> reduceTokens; bool hasNonUsedReduceTokens = false; do{ if(!reservedWord || countOnLastPosition>maxStayCountOnSamePosition){ reduceTokens.prepend(createTokenInfo(*token)); hasNonUsedReduceTokens = true; } if(*token == PLS_SEMI || reservedWord){ int reducedConstruct = 0; QList<int> expectedTerminals = getExpectedTokens(row).first; //bool waitingForSemicolon = (expectedTerminals.size()==1 && expectedTerminals[0]==PLS_SEMI); bool waitingForSemicolon = expectedTerminals.contains(PLS_SEMI); if(reservedWord && countOnLastPosition<=maxStayCountOnSamePosition && !waitingForSemicolon){ //if current token is reserved word, try to reduce expression first int constuctsToCheck[] = {R_EXPRESSION, R_DECLARATION, R_STATEMENT}; reducedConstruct = reduceMajorConstruct(reduceTokens, constuctsToCheck, 3); }else{ //on semicolon try to reduce declaration or statement int constuctsToCheck[] = {R_DECLARATION, R_STATEMENT}; reducedConstruct = reduceMajorConstruct(reduceTokens, constuctsToCheck, 2); } if(reducedConstruct){ //read next token for parser to operate if(!reservedWord || countOnLastPosition>maxStayCountOnSamePosition){ *token = scanner->getNextToken(); if(*token == PLS_SEMI){ correctError(token, row, actionOnCurrentToken); } } ParsingTableRow *newRow=parsingTable->rows.at(stack.top()); //reduceMajorConstruct pushed new gotoState into stack *actionOnCurrentToken=(*newRow->actions).value(*token, 0); replaceKeywordWithIdentifier(*token, newRow, actionOnCurrentToken); }else{ qDeleteAll(reduceTokens); } hasNonUsedReduceTokens = false; break; } *token = scanner->getNextToken(); reservedWord = parsingTable->isReservedWord(scanner->getTokenLexeme()); }while(*token != PLS_E_O_F); if(hasNonUsedReduceTokens){ qDeleteAll(reduceTokens); } } if(scanner->getTokenStartPos() == lastErrorPosition){ ++countOnLastPosition; }else if(countOnLastPosition > 0){ countOnLastPosition = 0; } lastErrorPosition = scanner->getTokenStartPos(); //qDebug("--------completed error recovery--------------"); }