Exemple #1
0
void TXFMXPath::evaluateEnvelope(DOMNode *t) {

	// A special case where the XPath expression is already known

	if (document == NULL) {

		throw XSECException(XSECException::XPathError, 
		   "Attempt to define XPath Name Space before setInput called");

	}

	DOMElement * e = document->getDocumentElement();

	if (e == NULL) {

		throw XSECException(XSECException::XPathError, 
              "Element node not found in Document");

	}

	// Set the xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"

	e->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS, MAKE_UNICODE_STRING("xmlns:dsig"), DSIGConstants::s_unicodeStrURIDSIG);
	
	
	// Evaluate

	evaluateExpr(t, XPATH_EXPR_ENVELOPE);

	// Now we are done, remove the namespace
	
	e->removeAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS, MAKE_UNICODE_STRING("dsig"));

}
bool PromelaDataModel::evalAsBool(const Arabica::DOM::Element<std::string>& node, const std::string& expr) {
	PromelaParser parser(expr, 1, PromelaParser::PROMELA_EXPR);
//	parser.dump();
	Data tmp = evaluateExpr(parser.ast);

	if (tmp.atom.compare("false") == 0)
		return false;
	if (tmp.atom.compare("0") == 0)
		return false;
	return true;
}
void PromelaDataModel::setVariable(void* ast, Data value) {
	PromelaParserNode* node = (PromelaParserNode*)ast;

	std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
	switch (node->type) {
	case PML_VAR_ARRAY: {
		PromelaParserNode* name = *opIter++;
		PromelaParserNode* expr = *opIter++;

		if (INVALID_ASSIGNMENT(name->value)) {
			ERROR_EXECUTION_THROW("Cannot assign to " + name->value);
		}

		int index = dataToInt(evaluateExpr(expr));

		if (_variables.compound.find(name->value) == _variables.compound.end()) {
			ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
		}

		if (!_variables[name->value].hasKey("size")) {
			ERROR_EXECUTION_THROW("Variable " + name->value + " is no array");
		}

		if (strTo<int>(_variables[name->value]["size"].atom) <= index) {
			ERROR_EXECUTION_THROW("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
		}

		_variables.compound[name->value].compound["value"][index] = value;

		break;
	}
	case PML_NAME:
		if (INVALID_ASSIGNMENT(node->value)) {
			ERROR_EXECUTION_THROW("Cannot assign to " + node->value);
		}
		_variables.compound[node->value].compound["value"] = value;
		break;
	default:
		break;
	}

//	std::cout << Data::toJSON(_variables) << std::endl;
}
void PromelaDataModel::evaluateStmnt(void* ast) {
	PromelaParserNode* node = (PromelaParserNode*)ast;
	std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
	switch (node->type) {
	case PML_ASGN: {
		PromelaParserNode* name = *opIter++;
		PromelaParserNode* expr = *opIter++;
		setVariable(name, evaluateExpr(expr));
		break;
	}
	case PML_STMNT: {
		while(opIter != node->operands.end()) {
			evaluateStmnt(*opIter++);
		}
		break;
	}
	default:
		ERROR_EXECUTION_THROW("No support for " + PromelaParserNode::typeToDesc(node->type) + " statement implemented");
	}
}
Data PromelaDataModel::getVariable(void* ast) {
	PromelaParserNode* node = (PromelaParserNode*)ast;
//	node->dump();

	std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
	switch(node->type) {
	case PML_NAME:
		if (_variables.compound.find(node->value) == _variables.compound.end()) {
			ERROR_EXECUTION_THROW("No variable " + node->value + " was declared");
		}
//		if (_variables[node->value].compound.find("size") != _variables[node->value].compound.end()) {
//			ERROR_EXECUTION_THROW("Type error: Variable " + node->value + " is an array");
//		}
		return _variables[node->value]["value"];
	case PML_VAR_ARRAY: {
		PromelaParserNode* name = *opIter++;
		PromelaParserNode* expr = *opIter++;
		int index = dataToInt(evaluateExpr(expr));

		if (_variables.compound.find(name->value) == _variables.compound.end()) {
			ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
		}

		if (!_variables[name->value].hasKey("size")) {
			ERROR_EXECUTION_THROW("Variable " + name->value + " is no array");
		}

		if (strTo<int>(_variables[name->value]["size"].atom) <= index) {
			ERROR_EXECUTION_THROW("Index " + toStr(index) + " in array " + name->value + "[" + _variables[name->value]["size"].atom + "] is out of bounds");
		}
		return _variables.compound[name->value].compound["value"][index];
	}
	case PML_CMPND: {
//		node->dump();
//		std::cout << Data::toJSON(_variables["_event"]);

		std::stringstream idPath;
		PromelaParserNode* name = *opIter++;

		// special case for _x variables
		if (name->value.compare("_x") == 0) {
			PromelaParserNode* what = *opIter++;

			if (what->type == PML_VAR_ARRAY) {
				if (what->operands.size() == 2) {
					std::string arrName = what->operands.front()->value;
					std::string index = what->operands.back()->value;

					if (what->operands.back()->type == PML_STRING) {
						index = index.substr(1, index.size() - 2); // remove quotes
					}

					if (arrName.compare("states") == 0) {
						return Data(_interpreter->isInState(index));
					}
				}
			}
			ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
		}

		if (_variables.compound.find(name->value) == _variables.compound.end()) {
			ERROR_EXECUTION_THROW("No variable " + name->value + " was declared");
		}

		Data currData = _variables.compound[name->value]["value"];
		idPath << name->value;
		while(opIter != node->operands.end()) {
			std::string key = (*opIter)->value;
			idPath << "." << key;
			if (currData.compound.find(key) == currData.compound.end()) {
				ERROR_EXECUTION_THROW("No variable " + idPath.str() + " was declared");
			}
			Data tmp = currData.compound[key];
			currData = tmp;

			opIter++;
		}
		return currData;
	}
	default:
		ERROR_EXECUTION_THROW("Retrieving value of " + PromelaParserNode::typeToDesc(node->type) + " variable not implemented");
	}
	return 0;
}
Data PromelaDataModel::evaluateExpr(void* ast) {
	PromelaParserNode* node = (PromelaParserNode*)ast;
	std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
	switch (node->type) {
	case PML_CONST:
		if (iequals(node->value, "false"))
			return Data(false);
		if (iequals(node->value, "true"))
			return Data(true);
		return strTo<int>(node->value);
	case PML_NAME:
	case PML_VAR_ARRAY:
	case PML_CMPND:
		return getVariable(node);
	case PML_STRING: {
		std::string stripped = node->value.substr(1, node->value.size() - 2);
		return Data(stripped, Data::VERBATIM);
	}
	case PML_PLUS:
		return dataToInt(evaluateExpr(*opIter++)) + dataToInt(evaluateExpr(*opIter++));
	case PML_MINUS:
		return dataToInt(evaluateExpr(*opIter++)) - dataToInt(evaluateExpr(*opIter++));
	case PML_DIVIDE:
		return dataToInt(evaluateExpr(*opIter++)) / dataToInt(evaluateExpr(*opIter++));
	case PML_MODULO:
		return dataToInt(evaluateExpr(*opIter++)) % dataToInt(evaluateExpr(*opIter++));
	case PML_EQ: {
		PromelaParserNode* lhs = *opIter++;
		PromelaParserNode* rhs = *opIter++;

		Data left = evaluateExpr(lhs);
		Data right = evaluateExpr(rhs);

		if (left == right) // overloaded operator==
			return Data(true);

		// literal strings or strings in variables
		if ((lhs->type == PML_STRING || rhs->type == PML_STRING)
		        || (left.type == Data::VERBATIM && right.type == Data::VERBATIM)) {
			return (left.atom.compare(right.atom) == 0 ? Data(true) : Data(false));
		}
		return dataToInt(left) == dataToInt(right);
	}
	case PML_NEG:
		return !dataToBool(evaluateExpr(*opIter++));
	case PML_LT:
		return dataToInt(evaluateExpr(*opIter++)) < dataToInt(evaluateExpr(*opIter++));
	case PML_LE:
		return dataToInt(evaluateExpr(*opIter++)) <= dataToInt(evaluateExpr(*opIter++));
	case PML_GT:
		return dataToInt(evaluateExpr(*opIter++)) > dataToInt(evaluateExpr(*opIter++));
	case PML_GE:
		return dataToInt(evaluateExpr(*opIter++)) >= dataToInt(evaluateExpr(*opIter++));
	case PML_TIMES:
		return dataToInt(evaluateExpr(*opIter++)) * dataToInt(evaluateExpr(*opIter++));
	case PML_LSHIFT:
		return dataToInt(evaluateExpr(*opIter++)) << dataToInt(evaluateExpr(*opIter++));
	case PML_RSHIFT:
		return dataToInt(evaluateExpr(*opIter++)) >> dataToInt(evaluateExpr(*opIter++));
	case PML_AND:
	case PML_OR: {
		PromelaParserNode* lhs = *opIter++;
		PromelaParserNode* rhs = *opIter++;

		std::cout << "-----" << std::endl;
		lhs->dump();
		rhs->dump();

		Data left = evaluateExpr(lhs);
		Data right = evaluateExpr(rhs);

		bool truthLeft = dataToBool(left);
		bool truthRight = dataToBool(right);

		if (node->type == PML_AND) {
			return truthLeft && truthRight;
		} else {
			return truthLeft || truthRight;
		}
	}
	default:
		ERROR_EXECUTION_THROW("Support for " + PromelaParserNode::typeToDesc(node->type) + " expressions not implemented");
	}
	return 0;
}
void PromelaDataModel::evaluateDecl(void* ast) {
	PromelaParserNode* node = (PromelaParserNode*)ast;
	if (false) {
	} else if (node->type == PML_DECL) {
		std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
		PromelaParserNode* vis = *opIter++;
		PromelaParserNode* type = *opIter++;
		PromelaParserNode* varlist = *opIter++;

		for (std::list<PromelaParserNode*>::iterator nameIter = varlist->operands.begin();
		        nameIter != varlist->operands.end();
		        nameIter++) {
			Data variable;
			variable.compound["vis"] = Data(vis->value, Data::VERBATIM);
			variable.compound["type"] = Data(type->value, Data::VERBATIM);

			if (false) {
			} else if ((*nameIter)->type == PML_NAME) {
				// plain variables without initial assignment

				if (type->value == "mtype") {
					variable.compound["value"] = Data(_lastMType++, Data::INTERPRETED);
				} else {
					variable.compound["value"] = Data(0, Data::INTERPRETED);
				}
				_variables.compound[(*nameIter)->value] = variable;

			} else if ((*nameIter)->type == PML_ASGN) {
				// initially assigned variables

				std::list<PromelaParserNode*>::iterator opIterAsgn = (*nameIter)->operands.begin();
				PromelaParserNode* name = *opIterAsgn++;
				PromelaParserNode* expr = *opIterAsgn++;

				variable.compound["value"] = evaluateExpr(expr);

				assert(opIterAsgn == (*nameIter)->operands.end());
				_variables.compound[name->value] = variable;
			} else if ((*nameIter)->type == PML_VAR_ARRAY) {
				// variable arrays

				std::list<PromelaParserNode*>::iterator opIterAsgn = (*nameIter)->operands.begin();
				PromelaParserNode* name = *opIterAsgn++;
				int size = dataToInt(evaluateExpr(*opIterAsgn++));

				variable.compound["size"] = size;
				for (int i = 0; i < size; i++) {
					variable.compound["value"].array.push_back(Data(0, Data::INTERPRETED));
				}

				assert(opIterAsgn == (*nameIter)->operands.end());
				_variables.compound[name->value] = variable;

			} else {
				ERROR_EXECUTION_THROW("Declaring variables via " + PromelaParserNode::typeToDesc((*nameIter)->type) + " not implemented");
			}
		}
		assert(opIter == node->operands.end());
	} else if (node->type == PML_DECLLIST) {
		for (std::list<PromelaParserNode*>::iterator declIter = node->operands.begin();
		        declIter != node->operands.end();
		        declIter++) {
			evaluateDecl(*declIter);
		}
	} else {
		ERROR_EXECUTION_THROW("Declaring variables via " + PromelaParserNode::typeToDesc(node->type) + " not implemented");
	}
}
Data PromelaDataModel::evaluateExpr(const std::string& expr) {
	PromelaParser parser(expr, 1, PromelaParser::PROMELA_EXPR);
	return evaluateExpr(parser.ast);
}
std::string PromelaDataModel::evalAsString(const std::string& expr) {
	PromelaParser parser(expr);
	return evaluateExpr(parser.ast);
}
Data PromelaDataModel::getStringAsData(const std::string& content) {
	return evaluateExpr(content);
}