bool CalcExpr(const string & expr, int a1, int a2, Token & result) { map<string,TokenVector>::iterator its=cache.find(expr); if(its==cache.end()) { TokenVector a; bool r = ParseExpr(expr, a); if (!r) return false; TokenVector b; r = ConvertExpr(a, b); if (!r) return false; cache.insert(std::map<string,TokenVector> :: value_type(expr,b)); } map<string,TokenVector>::iterator it=cache.find(expr); TokenVector input; Token x; x.type = INT; x.value.i = a1; input.push_back(x); x.value.i = a2; input.push_back(x); return CalcExpr(input, it->second, result); }
void VerifyEscapedOctalDigits(unsigned int expectedToken, wstring octalDigitStringPrefix, wstring octalDigitStringSuffix) { vector<wstring> escapedOctalItems; //Test we recognize the basic set of Octal digits (0-7) (we use '8' below in make_pair as the range is the standard STL style range where it is //up to, but not including, the 'end' position). PopulateASCIICharacterCodes(escapedOctalItems, make_pair(static_cast<int>(L'0'), static_cast<int>(L'8')), wstring(L"\\")); //Test we recognize 1, 2 and 3 digit octal strings (obvioulsy exhustive tests for all possible octal numbers from 0-777 would take forever to run escapedOctalItems.push_back(wstring(L"\\1")); escapedOctalItems.push_back(wstring(L"\\11")); escapedOctalItems.push_back(wstring(L"\\111")); for_each(escapedOctalItems.begin(), escapedOctalItems.end(), [expectedToken, &octalDigitStringPrefix, &octalDigitStringSuffix] (const wstring& refStringLit) -> void { wstring toLex = octalDigitStringPrefix + refStringLit + octalDigitStringSuffix; TokenVector expectedTokens; expectedTokens.push_back(make_pair(expectedToken, toLex)); VerifyLex(toLex, expectedTokens); }); }
void PrintTokenVector(const TokenVector & tokens) { TokenVector::const_iterator it = tokens.begin(); for (; it != tokens.end(); ++it) { PrintToken(*it); } }
float similarity(const TokenVector& lv, const TokenVector& rv) { if (lv.size() != rv.size()) { return -1; } float sim = 0.0; float lsum = 0.0; float rsum = 0.0; for (std::size_t i = 0; i < lv.size(); ++i) { sim += lv[i] * rv[i]; lsum += lv[i]; rsum += rv[i]; } return sim / lsum/ rsum; }
void VerifyEscapedControlCodes(unsigned int expectedToken, wstring codeStringPrefix, wstring codeStringSuffix) { vector<wstring> controlEscapeStringLiteralItems; PopulateASCIICharacterCodes(controlEscapeStringLiteralItems, make_pair(64, 96), wstring(L"\\^")); for_each(controlEscapeStringLiteralItems.begin(), controlEscapeStringLiteralItems.end(), [expectedToken, &codeStringPrefix, &codeStringSuffix] (const wstring& refStringLit) -> void { wstring toLex = codeStringPrefix + refStringLit + codeStringSuffix; TokenVector expectedTokens; expectedTokens.push_back(make_pair(expectedToken, toLex)); VerifyLex(toLex, expectedTokens); }); }
void VerifyLex(const wstring& refToLex, const TokenVector& expectedTokens, bool shouldSucceed /*= true*/) { wchar_t const* first = refToLex.c_str(); wchar_t const* last = first + refToLex.size(); TokenVector actualTokens; auto cur = g_lexer.begin(first, last); auto end = g_lexer.end(); for(; cur != end && cur->is_valid() ; ++cur) { try { actualTokens.push_back(make_pair(cur->id(), wstring(cur->value().begin(), cur->value().end()))); } catch(const std::bad_alloc&) { break; } } const bool lexingSucceeded = (cur == end); const bool lexResultAsExpected = lexingSucceeded == shouldSucceed; //Kind of goofy to have to do it this way but the unit test stuff is not set up to output wstrings :( if(!lexResultAsExpected) { wcout << endl << L"Lexing was expected to " << (shouldSucceed ? L"pass" : L"fail") << L"but it " << (shouldSucceed ? L"failed" : L"passed") << L" with input '" << refToLex << L"'" << endl; } BOOST_CHECK( lexResultAsExpected ); if(shouldSucceed) { const bool sizeMatches = actualTokens.size() == expectedTokens.size(); if(!sizeMatches) { wcout << endl << L"Expected lexing to result in " << expectedTokens.size() << L" but it actually resulted in " << actualTokens.size() << L" tokens." << endl; } BOOST_CHECK( sizeMatches ); //avoid annoying signed/unsigned mismatch or relying on the fact that ::size_type is == size_t typedef decltype(actualTokens.size()) IndexType; for(IndexType i = 0 ; i < actualTokens.size() ; ++i) { auto actual = actualTokens[i]; auto expected = expectedTokens[i]; const bool areEqual = (actual == expected); if(!areEqual) { wcout << endl << L"Expected token '" << expected.second + L"' (" << expected.first << "), but got '" << actual.second << L"' (" << actual.first << L") at token index " << i << endl; } BOOST_CHECK( areEqual ); } } }
void PSU1Rules::Detect(const TokenVector& tv) { for(unsigned int i=0; i<tv.size(); ++i) { gKey.Process(tv[i]); t1Key.Process(tv[i]); t2Key.Process(tv[i]); } const double bauda = any_cast<double>(param::FindParameter(t1Key.GetTupleRef(), "bauda").value); for(unsigned int i=0; i<tv.size(); ++i) { trKey.Process(tv[i],bauda); txaKey.Process(tv[i],bauda); codeKey.Process(tv[i]); saKey.Process(tv[i]); } }
AssemblerResult Assembler::tokenize(const char* infile) { std::ifstream asmfile(infile); if (asmfile.is_open()) { int lineNo = 1; std::string line; while (std::getline(asmfile, line)) { // check if the line contains an include statement char* writeable = strdup(line.c_str()); char* token = strtok(writeable, " \t"); std::string tok; if (token != NULL) { for (int i = 0; i < strlen(token) ; i ++) tok.push_back(std::toupper(token[i])); if (tok == std::string("#INCLUDE")) { char *fname = strtok(NULL, "\"\'"); //std::cout << fname << std::endl; // Recurse AssemblerResult res = tokenize(fname); free(writeable); if (res != ASSEMBLER_OK) return res; continue; } } free(writeable); // Else, tokenise the line TokenVector* tv = new TokenVector(); AssemblerResult res = tv->tokenize(std::string(infile), lineNo, line); if (res != ASSEMBLER_OK) { return ASSEMBLER_ERROR; } m_lineTokens.push_back(tv); lineNo ++; } } else { std::cout << "Error opening file: " << infile << std::endl; return ASSEMBLER_ERROR_FILENOTFOUND; } return ASSEMBLER_OK; }
// 逆波兰式计算求值 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; } }
// 词法分析,解析表达式 bool ParseExpr(const string & expr, TokenVector & tokens) { // 表达式的解析较简单,就不用状态机了,直接一个一个解析。。。 int i = 0; Token token; string buffer; tokens.clear(); while (i < expr.length()) { // 空白跳过 if (isblank(expr[i])) { ++i; continue; } // 单个字符的操作符和括号 if (expr[i] == '+' || expr[i] == '-' || expr[i] == '*' || expr[i] == '/' || expr[i] == '%' || expr[i] == '^' || expr[i] == '(' || expr[i] == ')') { token.type = OP; if (expr[i] == '+') token.value.op = ADD; else if (expr[i] == '-') token.value.op = SUB; else if (expr[i] == '*') token.value.op = MUL; else if (expr[i] == '/') token.value.op = DIV; else if (expr[i] == '%') token.value.op = MOD; else if (expr[i] == '^') token.value.op = POW; else if (expr[i] == '(') token.value.op = LEFT; else if (expr[i] == ')') token.value.op = RIGHT; tokens.push_back(token); ++i; continue; } // 整数或浮点数 else if (isdigit(expr[i])) { buffer.clear(); buffer += expr[i++]; bool point = false; while (i < expr.length()) { if (isdigit(expr[i])) { buffer += expr[i++]; } else if (expr[i] == '.' && !point) { buffer += expr[i++]; point = true; } else { break; } } if (point) { token.type = FLOAT; token.value.f = strtof(buffer.c_str(), NULL); } else { token.type = INT; token.value.i = strtoul(buffer.c_str(), NULL, 0); } tokens.push_back(token); } // 随机数 else if (expr[i] == 'r') { token.type = RAND; token.value.i = 0; tokens.push_back(token); ++i; } // 参数 else if (expr[i] == 'x') { ++i; buffer.clear(); while (i < expr.length() && isdigit(expr[i])) { buffer += expr[i]; ++i; } if (buffer.empty()) { return false; } token.type = ARG; token.value.index = strtoul(buffer.c_str(), NULL, 0); tokens.push_back(token); continue; } // > 或 >= else if (expr[i] == '>') { token.type = OP; ++i; if (i < expr.length() && expr[i] == '=') { token.value.op = GE; ++i; } else { token.value.op = GT; } tokens.push_back(token); } // < 或 <= else if (expr[i] == '<') { token.type = OP; ++i; if (i < expr.length() && expr[i] == '=') { token.value.op = LE; ++i; } else { token.value.op = LT; } tokens.push_back(token); } // == else if (i + 1 < expr.length() && expr[i] == '=' && expr[i + 1] == '=') { token.type = OP; token.value.op = EQ; tokens.push_back(token); i += 2; } // != else if (i + 1 < expr.length() && expr[i] == '!' && expr[i + 1] == '=') { token.type = OP; token.value.op = NE; tokens.push_back(token); i += 2; } // && else if (i + 1 < expr.length() && expr[i] == '&' && expr[i + 1] == '&') { token.type = OP; token.value.op = AND; tokens.push_back(token); i += 2; } // || else if (i + 1 < expr.length() && expr[i] == '|' && expr[i + 1] == '|') { token.type = OP; token.value.op = OR; tokens.push_back(token); i += 2; } else { return false; } } return true; }
// 把解析好的表达式转换成逆波兰式 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; }
/** * Nastavi svuj stav podle vstupniho XML, ktere parsuje. * * @param xml vstupni XML se stavem simulace * * @return true pokud se podarilo nastavit stav, jinak false */ bool SimState::setState(QString xml) { //inicializuji hodnoty places.clear(); transits.clear(); places_id.clear(); transits_id.clear(); QString errorStr; int errorLine; int errorColumn; QDomDocument document; if (!document.setContent(xml,&errorStr,&errorLine,&errorColumn)) { //proparsuju XML qCritical() << "Error during parsing xml on line: " << errorLine << ", column: " << errorColumn; return false; } QDomElement root = document.documentElement(); if (root.tagName() != "petrinet") { //nejedna se petriho sit qCritical() << "Error during parsing xml, not valid"; return false; } //nactu informace o siti author = root.attribute("author"); name = root.attribute("name"); version = root.attribute("version").toInt(); info = root.attribute("info"); //iteruji nad misty QDomElement xml_places = root.firstChildElement("places"); QDomElement one_place = xml_places.firstChildElement("place"); while (!one_place.isNull()) { TokenVector tokens; //projdu vsechny tokeny QDomElement one_token = one_place.firstChildElement("token"); while (!one_token.isNull()) { pntype token = one_token.text().toInt(); tokens.push_back(token); one_token = one_token.nextSiblingElement("token"); } //vytvorim nove misto, naplnim ho PNPlace *place = new PNPlace(one_place.attribute("posx"),one_place.attribute("posy") ,one_place.attribute("id"),tokens); places.push_back(place); //a zapisu do vektoru mist places_id[one_place.attribute("id")] = place; //zapisu jeho ID one_place = one_place.nextSiblingElement("place"); } //iteruji nad prechody QDomElement xml_trans = root.firstChildElement("transitions"); QDomElement one_trans = xml_trans.firstChildElement("transition"); while (!one_trans.isNull()) { StringToPnplaceMap in_names; StringToPnplaceMap out_names; ConstraintVector constraints; //nejdriv inicializuji vstupni mista QDomElement one_element = one_trans.firstChildElement("inplace"); while (!one_element.isNull()) { bool isNum = false; one_element.attribute("name").toInt(&isNum); //vstupni misto je konstanta if (isNum) { //pridam omezeni prechod == konstanta in_names[one_element.attribute("name")] = places_id[one_element.text()]; constraints.push_back(new Constraint(one_element.attribute("name"),OP_EQ,one_element.attribute("name").toInt())); } else { in_names[one_element.attribute("name")] = places_id[one_element.text()]; //uchovam ukazatel na vstupni misto } one_element = one_element.nextSiblingElement("inplace"); } //pote udelam to stejne s vystupnimi misty one_element = one_trans.firstChildElement("outplace"); while (!one_element.isNull()) { out_names[one_element.attribute("name")] = places_id[one_element.text()]; one_element = one_element.nextSiblingElement("outplace"); } //pak iteruji nad omezenimi QDomElement one_cond = one_trans.firstChildElement("constraint"); while (!one_cond.isNull()) { Constraint *cond; if (one_cond.attribute("type") == "const") { //druha hodnota je konstanta cond = new Constraint(one_cond.attribute("var1"),one_cond.attribute("op").toInt(),one_cond.attribute("const").toInt()); } else { //druha hodnota je promenna cond = new Constraint(one_cond.attribute("var1"),one_cond.attribute("op").toInt(),one_cond.attribute("var2")); } constraints.push_back(cond); //ulozim omezeni one_cond = one_cond.nextSiblingElement("constraint"); } //nakonec iteruji nad operacemi OutputOperations operations; QDomElement one_op = one_trans.firstChildElement("operation"); while (!one_op.isNull()){ OneOut oneout; oneout.output = one_op.attribute("output"); QDomElement one_operation = one_op.firstChildElement(); //iteruji nad jednou vstupni operaci while(!one_operation.isNull()) { Operation op; if (one_operation.tagName() == "plus") { op.op = ADD; } else { op.op = SUB; } op.var = one_operation.attribute("id"); oneout.operations.push_back(op); one_operation = one_operation.nextSiblingElement(); } operations.push_back(oneout); one_op = one_op.nextSiblingElement("operation"); } //vytvorim novy prechod a naplnim hodnotami PNTrans *trans = new PNTrans(one_trans.attribute("posx"), one_trans.attribute("posy"), one_trans.attribute("id"), constraints, in_names, out_names, operations); transits_id[one_trans.attribute("id")] = trans; transits.push_back(trans); //ulozim do vektoru mist one_trans = one_trans.nextSiblingElement("transition"); } return true; }
/** * Vrati XML se stavem simulace. * * @return XML se stavem simulace */ QString SimState::getState() { QString result; //vysledne XML QXmlStreamWriter doc(&result); doc.setAutoFormatting(true); doc.writeStartDocument(); doc.writeStartElement("petrinet"); //zapisi informace o siti doc.writeAttribute("author",author); doc.writeAttribute("name",name); doc.writeAttribute("version",QString::number(version)); doc.writeAttribute("info",info); //nejprve zapisi mista doc.writeStartElement("places"); PlaceVector::iterator pit; for (pit = places.begin(); pit != places.end(); pit++) { //zapisi misto a informace o nem doc.writeStartElement("place"); PNPlace *place = (*pit); doc.writeAttribute("id",place->id); doc.writeAttribute("posx",place->x); doc.writeAttribute("posy",place->y); TokenVector::iterator tit; TokenVector tokens = place->getTokens(); //zapisi tokeny for (tit = tokens.begin(); tit < tokens.end(); tit++) { doc.writeTextElement("token",QString::number(*tit)); } doc.writeEndElement(); } doc.writeEndElement(); //pote zapisi prechody doc.writeStartElement("transitions"); TransVector::iterator trit; for (trit = transits.begin(); trit != transits.end(); trit++) { doc.writeStartElement("transition"); //zapisi informace o prechodu PNTrans *transit = (*trit); doc.writeAttribute("id",transit->id); doc.writeAttribute("posx",transit->x); doc.writeAttribute("posy",transit->y); ConstraintVector::iterator cvit; for (cvit = transit->constraints.begin(); cvit != transit->constraints.end(); cvit++) { //zapisi podminku Constraint *constraint = (*cvit); bool isNum = false; constraint->first.toInt(&isNum); if (isNum) continue; doc.writeEmptyElement("constraint"); if (constraint -> type == TYPENONE) { doc.writeAttribute("type","none"); } else if (constraint -> type == TYPEANYTHING) { doc.writeAttribute("type","anything"); } else { doc.writeAttribute("var1",constraint->first); doc.writeAttribute("op",QString::number(int(constraint->op))); if (constraint -> type == TYPEVAR) { doc.writeAttribute("type","var"); doc.writeAttribute("var2",constraint->second_var); } else if (constraint -> type == TYPECONST) { doc.writeAttribute("type","const"); doc.writeAttribute("const",QString::number(constraint->second_const)); } } } //zapisi vstupni a vystupni mista prechodu StringToPnplaceMap::iterator placeit; for (placeit = transit->in_names.begin(); placeit != transit->in_names.end(); placeit++) { doc.writeStartElement("inplace"); PNPlace *place = (*placeit).second; doc.writeAttribute("name",(*placeit).first); doc.writeCharacters(place->id); doc.writeEndElement(); } for (placeit = transit->out_names.begin(); placeit != transit->out_names.end(); placeit++) { doc.writeStartElement("outplace"); doc.writeAttribute("name",(*placeit).first); PNPlace *place = (*placeit).second; doc.writeCharacters(place->id); doc.writeEndElement(); } OutputOperations::iterator oit; //nakonec zapisi operace for (oit = transit->operations.begin(); oit != transit->operations.end(); oit++) { doc.writeStartElement("operation"); doc.writeAttribute("output",(*oit).output); OperationVector::iterator opit; //a jednotlive kroky dane operace for (opit = (*oit).operations.begin(); opit != (*oit).operations.end(); opit++) { Operation operation = (*opit); if (operation.op == ADD) doc.writeEmptyElement("plus"); else if (operation.op == SUB) doc.writeEmptyElement("minus"); else { qCritical() << "Error: unknown operation during saving XML"; } doc.writeAttribute("id",operation.var); } doc.writeEndElement(); } doc.writeEndElement(); } doc.writeEndElement(); doc.writeEndElement(); doc.writeEndDocument(); return result; }