Example #1
0
Token *Parser::parse(bool *ok, QString *err, Token *token) const
{
    if (mtokens.isEmpty())
        return bRet(ok, true, err, QString(), token, Token(), new Token(Token::Program_Token));
    TokenStack stack;
    int i = 0;
    while (true) {
        if (mtokens.size() == i) {
            stack.freeAll();
            return bRet(ok, false, err, tr("Unexpected end of token list", "error"), token, Token(), (Token *) 0);
        }
        const Token &t = mtokens.at(i);
        int x = 0;
        ShiftReduceChoice choice = chooseShiftReduce(stack.state(), t.type(), &x);
        switch (choice) {
        case StateChangeChoice: {
            stack.append(new Token(t), x);
            ++i;
            break;
        }
        case ReduceChoice: {
            bool b = false;
            Token *nt = reduce(stack, x, &b, err);
            if (!b) {
                delete nt;
                stack.freeAll();
                return bRet(ok, b, token, t, (Token *) 0);
            }
            if (nt->type() == Token::Program_Token && stack.isEmpty()) {
                if (i < mtokens.size() - 1)
                    return bRet(ok, false, err, tr("Unexpected error", "error"), token, t, (Token *) 0);
                return bRet(ok, true, err, QString(), token, Token(), nt);
            }
            choice = chooseShiftReduce(stack.state(), nt->type(), &x);
            if (ShiftChoice != choice)
                return bRet(ok, false, err, tr("Failed to find shift rule", "error"), token, t, (Token *) 0);
            stack.append(nt, x);
            break;
        }
        case ShiftChoice: {
            stack.freeAll();
            return bRet(ok, false, err, tr("Unexpected shift rule", "error"), token, t, (Token *) 0);
        }
        case ErrorChoice:
        default: {
            stack.freeAll();
            return bRet(ok, false, err, tr("Failed to find shift or reduce rule", "error"), token, t, (Token *) 0);
        }
        }
    }
    return bRet(ok, false, err, tr("Failed to finish parsing", "error"), token, Token(), (Token *) 0);
}
Example #2
0
// LET command translate function
TokenStatus letTranslate(Translator &translator, Token *commandToken,
	Token *&token)
{
	TokenStatus status;
	int column;
	bool hidden;
	DataType dataType;
	bool done;
	TokenStack letStack;
	bool haveSubStr = false;

	if (commandToken == NULL)
	{
		column = token->column();
		hidden = true;
	}
	else  // delete unneeded command token and get another token
	{
		column = commandToken->column();
		delete commandToken;
		hidden = false;
	}
	dataType = Any_DataType;
	do
	{
		if ((status = translator.getOperand(token, dataType,
			Translator::All_Reference)) != Good_TokenStatus)
		{
			if (token->column() > column)
			{
				return status;
			}
			// next token determines error
			Token *nextToken;
			if ((status = translator.getToken(nextToken)) != Good_TokenStatus)
			{
				status = ExpCmd_TokenStatus;
			}
			if (nextToken->isCode(Comma_Code) || nextToken->isCode(Eq_Code))
			{
				status = ExpAssignItem_TokenStatus;
			}
			else
			{
				status = ExpCmd_TokenStatus;
			}
			delete nextToken;
			return status;
		}

		// get and check next token for comma or equal
		status = translator.getToken(token);
		if (token->isCode(Comma_Code))
		{
			done = false;
		}
		else if (token->isCode(Eq_Code))
		{
			done = true;
		}
		else  // invalid token or parser error
		{
			if (translator.table().hasFlag(translator.doneStackTopToken(),
				SubStr_Flag))
			{
				delete translator.doneStackPop();
			}
			return ExpEqualOrComma_TokenStatus;
		}

		// check if this is a sub-string assignment
		if (translator.table().hasFlag(translator.doneStackTopToken(),
			SubStr_Flag))
		{
			// delete comma/equal token, use sub-string function token
			delete token;

			// get sub-string function token from rpn item on top of stack
			// (delete rpn item since it was not appended to output)
			RpnItem *rpnItem = translator.doneStackPop();
			token = rpnItem->token();
			rpnItem->setToken(NULL);  // prevent delete of token
			delete rpnItem;

			// change to assign sub-string code (first associated code)
			translator.table().setToken(token,
				translator.table().associatedCode(token->code()));

			haveSubStr = true;
		}
		else  // use comma/equal token
		{
			// change token to appropriate assign code
			translator.table().setToken(token, Assign_Code);
			status = translator.processDoneStackTop(token);
			if (status != Good_TokenStatus)
			{
				return status;
			}
		}
		letStack.push(token);  // save token

		// get data type for assignment
		if (dataType == Any_DataType)
		{
			dataType = token->dataType();
		}

		token = NULL;
	}
	while (!done);

	// get expression for value to assign
	if ((status = translator.getExpression(token,
		translator.equivalentDataType(dataType))) != Done_TokenStatus)
	{
		if (status == Parser_TokenStatus && token->isDataType(None_DataType))
		{
			status = ExpOpOrEnd_TokenStatus;
		}
		return status;
	}

	Token *letToken = letStack.pop();
	if (!letStack.isEmpty())
	{
		if (haveSubStr)
		{
			// add each token saved in let stack except the last
			do
			{
				// change to keep code (second associated code)
				translator.table().setToken(letToken,
					translator.table().associatedCode(letToken->code()));

				// append to output and pop next token from let stack
				translator.outputAppend(letToken);
				letToken = letStack.pop();
			}
			while (!letStack.isEmpty());  // continue until last token
		}
		else  // have a multiple assignment, change to list code
		{
			translator.table().setToken(letToken,
				translator.table().secondAssociatedCode(letToken->code()));
		}
	}

	// drop expresion result from done stack, append last assignment token
	translator.doneStackDrop();
	translator.outputAppend(letToken);

	// set hidden LET flag if needed
	if (!hidden)
	{
		letToken->addSubCode(Option_SubCode);
	}

	// check terminating token for end-of-statement
	if (!translator.table().hasFlag(token, EndStmt_Flag))
	{
		return ExpOpOrEnd_TokenStatus;
	}

	return Done_TokenStatus;
}