Пример #1
0
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);
}
Пример #2
0
    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);
                 });
    }
Пример #3
0
    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 );
            }
        }
    }
Пример #4
0
    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);
                 });
    }
Пример #5
0
// 词法分析,解析表达式
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;
}
Пример #6
0
// 把解析好的表达式转换成逆波兰式
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;
}
Пример #7
0
/**
  * 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;
}