void expand_aux (const Grammar &g, const std::string &word, TokenStack &result) { Grammar::const_iterator it = g.find (word); if (g.end() != it) { const RuleCollection &rc = it->second; const Rule &r = rc[nrand(rc.size())]; for (int i = r.size() - 1; i > -1; --i) { result.push(r[i]); } } }
// 逆波兰式计算求值 bool CalcExpr(const TokenVector & input, const TokenVector & expr, Token & result) { TokenStack stack; TokenVector::const_iterator it = expr.begin(); for (; it != expr.end(); ++it) { if (it->type == INT || it->type == FLOAT || it->type == BOOL) { stack.push(*it); } else if (it->type == ARG) { if (it->value.index >= input.size()) return false; const Token & a = input[it->value.index]; if (a.type == INT || a.type == FLOAT || a.type == BOOL) { stack.push(a); } else { return false; } } else if (it->type == RAND) { Token a; a.type = INT; a.value.i = rand(); stack.push(a); } else if (it->type == OP) { if (stack.size() < 2) return false; Token a = stack.top(); stack.pop(); Token b = stack.top(); stack.pop(); Token c; if (GetValue(it->value.op, b, a, c)) { stack.push(c); } else { return false; } } } if (!stack.empty()) { result = stack.top(); return true; } else { return false; } }
// Process declaration statements. void Parser::procDeclaration() { Token declToken; // Actual token of the declared entity TokenStack varNames; // Names of declared variables bool haveFunction; // Have a function declaration bool insideParams; // Inside parameter list of a function int parenCount; // Count of unmatched parentheses int consParenCount; // Count of consecutive open parantheses declToken = _currToken; if (_buffer.lastLookahead().getType() == Token::openparen) { haveFunction = true; insideParams = true; parenCount = 1; // Burn the paranthese, so not confused with argument declarations _buffer.nextToken(); } else { haveFunction = false; insideParams = false; parenCount = 0; } // Process the rest of the declaration. consParenCount = 0; while (_statementType == declaration) { _currToken = _buffer.nextToken(); // Check for defined symbols if (_currToken.getType() == Token::identifier) _symbolTable.checkForSymbol(_currToken); // Process combined types if (_currToken.getType() == Token::compound) procCombType(); switch (_currToken.getType()) { case Token::identifier: // Burn parenthases around the identifier while ((_buffer.nextLookahead().getType() == Token::closeparen) && (consParenCount > 0)) { _buffer.nextToken(); consParenCount--; } if (_buffer.lastLookahead().getType() == Token::openparen) /* Function call. This terminates a function declaration, and marks the start of the initial value for a variable declaration */ _statementType = expression; else { /* Variable name. For functions, this is a parameter name; for variable declarations, assume multiple vars are being declared in one declaration statement. Note: due to K+R style parameter declarations, function parameter declarations do not need to be whithin parentheses */ _currToken.setType(Token::varname); if (haveFunction || (_braceCount > 0)) _currToken.setScope(Token::localscope); else _currToken.setScope(Token::filescope); varNames.push(_currToken); // Add to variable list /* K+R variable declarations have a trailing semicolon, which must be burned also */ if (haveFunction && (!insideParams) && // K+R style declaration (_buffer.lastLookahead().getType() == Token::semicolon)) _buffer.nextToken(); } break; case Token::openparen: parenCount++; break; case Token::closeparen: parenCount--; if (insideParams && (parenCount <= 0)) insideParams = false; break; case Token::typedeftoken: case Token::statictoken: if (!insideParams) // Modifier on the entire declaration _parseStack.push(_currToken); break; case Token::ampersand: case Token::othersymbol: /* Have reached the initializer list for var declarations; this is an error for function declarations */ if (haveFunction) _statementType = undet; else _statementType = expression; break; case Token::typetoken: case Token::declsymbol: // Ignore it break; case Token::fieldaccess: /* If inside params and have a dot, assume this is part of varags symbol (It is not common enough to have a seperate token for it) */ if ((!insideParams) || (_currToken.getLexeme() != ".")) _statementType = undet; // else part of varargs indicator, so ignore it break; default: // token is not allowed in declarations _statementType = undet; } // Update or clear consecutive parenthese count, as needed if (_currToken.getType() == Token::openparen) consParenCount++; else consParenCount = 0; } // Process the just read declaration if (haveFunction) procFunctDeclaration(declToken, _currToken, insideParams); else { // variable or type declaration // Set token type if (_parseStack.hasType(Token::typedeftoken)) declToken.setType(Token::typetoken); else declToken.setType(Token::varname); // Set its scope if (_braceCount > 0) declToken.setScope(Token::localscope); else declToken.setScope(Token::filescope); _symbolTable.updateNameSpace(declToken); } /* add new variables to the namespace. Ignore the vars in a function declaration unless it is followed by an openbrace, as it is actually a prototype, not a declaration */ if ((declToken.getType() == Token::varname) || (declToken.getType() == Token::functdecl)) while (!varNames.empty()) _symbolTable.updateNameSpace(varNames.pop()); _readNextToken = false; // Need to process token that ended declaration }
// 把解析好的表达式转换成逆波兰式 bool ConvertExpr(const TokenVector & input, TokenVector & output) { TokenStack stack; output.clear(); TokenVector::const_iterator it = input.begin(); for (; it != input.end(); ++it) { if (it->type == OP) { // 左括号,直接压进操作符栈 if (it->value.op == LEFT) { stack.push(*it); } // 右括号,从栈里弹出操作符,直到碰到右括号 else if (it->value.op == RIGHT) { bool find_left = false; while (!stack.empty()) { if (stack.top().value.op == LEFT) { find_left = true; stack.pop(); break; } else { output.push_back(stack.top()); stack.pop(); } } if (!find_left) return false; } // 其它操作符,和栈顶操作符比较优先级 else { while (!stack.empty() && stack.top().value.op != LEFT && OPPriority(stack.top().value.op) >= OPPriority(it->value.op)) { output.push_back(stack.top()); stack.pop(); } stack.push(*it); } } // 非操作符直接输出 else { output.push_back(*it); } } while (!stack.empty()) { output.push_back(stack.top()); stack.pop(); } return true; }
// 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; }