/** * @param 0: string * @param 1: position of a character to be used as starting character for the substring. * @param 2: length of the substring * @return substr */ Token str_substr(TokenStack& args) { args.check(3); int size = args.pop_int(); int from = args.pop_int(); std::string str = args.pop_string(); return Token::create_string(str.substr(from, size)); }
/** * Convert to lowercase * @param 0: string * @return lowercase string */ Token str_lower(TokenStack& args) { args.check(1); std::string str = args.pop_string(); for (size_t i = 0; i < str.length(); ++i) { str[i] = tolower(str[i]); } return Token::create_string(str); }
/** * Returns a sub-stack of elements from the given stack, starting * at the current position of the stack until the end of statement. */ TokenStack* CodeParser::getStackToEndOfStatement( TokenStack* stack ) { Token* t; // gather the arguments up to the end of the statement TokenStack* substack = new TokenStack(); while( ( t = stack->next() ) && ( t->getType() != tok::END_OF_STATEMENT ) ) { substack->pushFront( t ); } return substack; }
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); }
/** * Remove leading and trailing whitespaces * @param 0: string * @return trimmed string */ Token str_trim(TokenStack& args) { args.check(1); std::string str = args.pop_string(); const char* WHITESPACES = " \t\n\r\0xb"; std::string::size_type first = str.find_first_not_of(WHITESPACES); if (first != std::string::npos) { std::string::size_type last = str.find_last_not_of(WHITESPACES); return Token::create_string(str.substr(first, last - first + 1)); } return Token::create_string(str); }
/** * Count occurences in a string * @param 0: string * @param 1: occurrence * @return occurrence count */ Token str_count(TokenStack& args) { args.check(2); std::string look_for = args.pop_string(); std::string str = args.pop_string(); size_t pos = str.find(look_for); int count = 0; while (pos != std::string::npos) { pos = str.find(look_for, pos + 1); ++count; } return Token::create_int(count); }
/** * @param 0: target string * @param 1: sous-chaîne rechercher * @param 2: sous-chaîne à caser * @return chaîne remplacée */ Token str_replace(TokenStack& args) { args.check(3); std::string replace_by = args.pop_string(); std::string look_for = args.pop_string(); std::string target = args.pop_string(); size_t step = replace_by.size(); size_t offset = look_for.size(); size_t pos = target.find(look_for); while (pos != std::string::npos) { target.replace(pos, offset, replace_by); pos = target.find(look_for, pos + step); } return Token::create_string(target); }
void gen_aux (const Grammar &g, const std::string &start, std::vector<std::string> &result) { TokenStack lifo; expand_aux (g, start, lifo); while (!lifo.empty()) { const std::string curr_word = lifo.top(); lifo.pop(); if (!bracketed (curr_word)) { result.push_back (curr_word); } else { expand_aux (g, curr_word, lifo); } } }
/** * Parses method call parameters */ int CodeParser::parseMethodParameters( Scope* scope, TokenStack* stack, list<Parameter*> params ) { Token* t; // the next token must be a parenthesis block (e.g. "( .. )") if( !( t = stack->next() ) || ( t->getType() != tok::PARENTHESIS_BLOCK ) ) { SYNTAX_ERROR( "Symbol '(' expected", stack->last() ); return -1; } // get the sub-stack TokenStack* substack = ((ComplexToken*)t)->getChildren(); // gather the parameters while( ( t = substack->next() ) ) { printf( "CodeParser::parseMethodParameters token: %s\n", t->getText() ); // TODO add method parameter parsing logic here } return 0; }
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]); } } }
/** * Parses the expression from the given token stack */ int CodeParser::parseExpression( Scope* scope, TokenStack* stack ) { int errorCode = 0; Token* t; // gather the arguments up to the end of the statement TokenStack* substack = getStackToEndOfStatement( stack ); // get the argument list while( !errorCode && substack->hasNext() && ( t = substack->next() ) ) { printf( "CodeParser::parseExpression: '%s' [%s]\n", t->getText(), t->getTypeName() ); // handle the token by type switch( t->getType() ) { case tok::ALPHA_NUMERIC: // is the argument a field? if( scope->lookupField( t->getText() ) ) { printf( "CodeParser::parseExpression: Field - [%s]\n", t->getText() ); } // is it a method call? else if( substack->hasNext() && substack->peek()->getType() == tok::PARENTHESIS_BLOCK ) { errorCode = parseExpression_MethodCall( t->getText(), scope, substack ); } break; case tok::DECIMAL: case tok::INTEGER: break; case tok::DQUOTE_TEXT: break; case tok::SQUOTE_TEXT: break; case tok::OPERATOR: break; case tok::PARENTHESIS_BLOCK: break; default: errorCode = -1; SYNTAX_ERROR( "unexpected token", substack->last() ); } } // delete the stack delete substack; // return the error code return errorCode; }
// 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; }
// 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; }
/** * Compute number of characters * @param 0: target string * @return string length */ Token str_len(TokenStack& args) { args.check(1); int length = args.pop_string().size(); return Token::create_int(length); }
// 逆波兰式计算求值 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; } }
void IRCSession::calculate(string privmsg) { sk = TokenStack(); while(!q.empty()) { Token t = q.get(); if(t.tkntype == TKN_NUMBER || t.tkntype == TKN_NAME) sk.put(t); else if(t.tkntype == TKN_OPERATOR) { if(t.str == "+") { Token o1, o2; if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o2 = getValue(sk.get()); if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o1 = getValue(sk.get()); Token e = Token(TKN_NUMBER, o1.number+o2.number, ""); sk.put(e); } else if(t.str == "-") { Token o1, o2; if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o2 = getValue(sk.get()); if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o1 = getValue(sk.get()); Token e = Token(TKN_NUMBER, o1.number-o2.number, ""); sk.put(e); } else if(t.str == "*") { Token o1, o2; if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o2 = getValue(sk.get()); if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o1 = getValue(sk.get()); Token e = Token(TKN_NUMBER, o1.number*o2.number, ""); sk.put(e); } else if(t.str == "/") { Token o1, o2; if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o2 = getValue(sk.get()); if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o1 = getValue(sk.get()); Token e = Token(TKN_NUMBER, o1.number/o2.number, ""); sk.put(e); } else if(t.str == "%") { Token o1, o2; if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o2 = getValue(sk.get()); if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o1 = getValue(sk.get()); Token e = Token(TKN_NUMBER, cast_int(o1.number)%cast_int(o2.number), ""); sk.put(e); } else if(t.str == "^" || t.str == "**") { Token o1, o2; if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o2 = getValue(sk.get()); if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o1 = getValue(sk.get()); Token e = Token(TKN_NUMBER, pow(o1.number, o2.number), ""); sk.put(e); } /*else if(t.str == "sin") { Token o1, o2; if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o2 = getValue(sk.get()); if(!sk.empty() && (sk.seek().tkntype == TKN_NUMBER || sk.seek().tkntype == TKN_NAME)) o1 = getValue(sk.get()); Token e = Token(TKN_NUMBER, sin(12), ""); sk.put(e); }*/ } } double d; if(!sk.empty()) d = getValue(sk.get()).number; else d = 0.0f; if(d-cast_int(d) < 0.00000049) SendChatMessage(PRIVMSG, privmsg.c_str(), "%d", cast_int(d)); else SendChatMessage(PRIVMSG, privmsg.c_str(), "%f", d); varv.clear(); }
void IRCSession::makepolishform(string szam) { string s = szam; q = TokenQueue(); sk = TokenStack(); CalcLexer cl = CalcLexer(s); Token t; do { if(t.tkntype == TKN_NEXT_LINE) cl = CalcLexer(s); t = cl.getNextToken(); if(t.tkntype == TKN_NUMBER || t.tkntype == TKN_NAME) q.put(t); else if(t.tkntype == TKN_OPEN_PAR) sk.put(t); else if(t.tkntype == TKN_CLOSE_PAR) { Token t1; while(!sk.empty() && sk.seek().tkntype != TKN_OPEN_PAR) q.put(sk.get()); sk.get(); } else if(t.tkntype == TKN_OPERATOR) { while(!sk.empty() && getpriority(sk.seek()) <= getpriority(t)) q.put(sk.get()); sk.put(t); } } while(t.tkntype != TKN_TERMINATION); while(!sk.empty()) q.put(sk.get()); }