⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 executestack.cpp

📁 一个经典的词法分析器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	if (*value == "LIST") {					// values list		
		while(*value != "EOLIST") {
			value = stack->Pop();
			if (*value != "EOLIST") 
				valueStack->Add((CObject*)value);
		}
	}
	value = stack->Pop();
	if (*value == "LIST") {					// attribute list
		while(*value != "EOLIST") {
			value = stack->Pop();
			if (*value != "EOLIST") 
				attrStack->Add((CObject*)value);
		}
	}
	if (attrStack->GetSize() != valueStack->GetSize()) {
		errorString = "Number of values don't match number of attributes";
		goto cleanup;
	}
//
// For each attribute, find the column in the table and assign a value to it
// until all the columns are initialized with their values. Note, if you don't
// set the attribute, the last setting will be used
//
	for (i=0;i<attrStack->GetSize();i++) {
		attr = (CString*)attrStack->GetAt(i);
		value = (CString*)valueStack->GetAt(i);
		col = tableInQuestion->Column(*attr);
		if (col == NULL) {
			errorString = "Undefined column " + *attr + " in table " + *table;
			goto cleanup;
		}
		col->SetValueByType(*value);	// set the attribute's value
	}
	tableInQuestion->AddRow();						// add the new row
cleanup:	;
	attrStack->Clear();
	valueStack->Clear();
	delete attrStack;
	delete valueStack;
	return true;
}

//
// The DELETE execution method.
bool CEStack::ExecuteDelete()
{
	CString *value = NULL;
	CString *table = NULL;
	SCCollection *saveStack = NULL, *copyStack = NULL;
	SCCollection deletes;
	int *row = NULL;

	errorString = "";					// no error, yet
	DeleteResult();						// prepare for new result
	result = new SCCollection();
	table = stack->Pop();				// get the table to use
	tableInQuestion = CESql::FindTable(*table);
	if (!tableInQuestion) {
		errorString = "No such table " + *table;
		return true;
	}
	value = stack->Pop();				// where
	if (value == NULL) {				// DELETE all records if null
		tableInQuestion->DeleteAllRows();
		return true;
	}
//
// Iterate through each of the records in the table. 
// At each record, execute the stack.
// If the result is true, then delete this record, else leave alone
//
	saveStack = stack;						// save stack at this point
	copyStack = stack->Copy();

	for (int i=0;i<tableInQuestion->NRows();i++) {
		rowInQuestion = tableInQuestion->GetRow(i);
		stack = copyStack->Copy();	// restore the stack for each record test
		value = stack->Pop();
		ExecuteOperator(*value);
		value = stack->Pop();
		if (Numberize(*value) > 0.0) {
			row = new int;
			*row = i;
			deletes.Add((CObject*)row);
		}
		stack->Clear();
		delete stack;
	}
	copyStack->Clear();
	delete copyStack;
	saveStack = stack;
	for (i=deletes.GetSize()-1;i>=0;i--) {
		row = (int *)deletes.GetAt(i);
		tableInQuestion->DeleteRow(*row);
		delete row;
	}
	return true;
}

//
// Execute an  operation. Pops 2 productions off the stack and then
// applies the operator. The PopProduction method will call this method 
// recursively until the stack is exhausted per the operations
bool CEStack::ExecuteOperator(CString op)
{
	char buf[64] = {""};
	double c = 0;
	int a = 0, b = 0;
	errorString = "";					// no error, yet
	CString* object1 = PopProduction();
	CString* object2 = PopProduction();

	if (op == "AND") {
		a = (int)Numberize(*object1);
		b = (int)Numberize(*object2);
		c = a & b;
	}
	else
	if (op == "OR")  {
		a = (int)Numberize(*object1);
		b = (int)Numberize(*object2);
		c = a | b;
	}
	else
		c = DoOperation(*object2,*object1,op);
	sprintf(buf,"%f",c);
	stack->Push(buf);
	return true;
}

//
// Evaluate a and b if they need to be looked up in the database, and
// then do the indicated operation. Does the operation based on the type of
// 'a'. If the operation is not defined an error is returned
double CEStack::DoOperation(CString a, CString b, CString op)
{
	double ret = 0;
	int type = tableInQuestion->Type(a);
	CString *valueA = GetValue(a), *valueB = GetValue(b);

	if (valueA == NULL) {
		errorString = "Can't find symbol: " + a;
		return 0;
	}
	if (valueB == NULL) {
		errorString = "Can't find symbol: " + b;
		return 0;
	}
	switch(type) {
	case CSTRING:
	case CTIME:
		if (op == "<") { ret = (*valueA < *valueB); goto end; }
		if (op == ">") { ret = (*valueA > *valueB); goto end; }
		if (op == "<=") { ret = (*valueA <= *valueB); goto end; }
		if (op == ">=") { ret = (*valueA >= *valueB); goto end; }
		if (op == "=") { ret = (*valueA == *valueB); goto end; }
		if (op == "<>") { ret = (*valueA != *valueB); goto end; }
		if (op == "LIKE") { ret = Compare(*valueB, *valueA); goto end; }	// reverse order, so wild cards appear on left
		errorString = "Error: Operation " + op + " not defined for " + b;
		break;
	default:
		if (op == "<") { ret = (Numberize(*valueA) < Numberize(*valueB)); goto end; }
		if (op == ">") { ret = (Numberize(*valueA) > Numberize(*valueB)); goto end; }
		if (op == "<=") {ret = (Numberize(*valueA) <= Numberize(*valueB)); goto end; }
		if (op == ">=") {ret = (Numberize(*valueA) >= Numberize(*valueB)); goto end; }
		if (op == "=") { ret = (Numberize(*valueA) == Numberize(*valueB)); goto end; }
		if (op == "<>") { ret = (Numberize(*valueA) != Numberize(*valueB)); goto end; }
		if (op == "+") { ret = Numberize(*valueA) + Numberize(*valueB); goto end; }
		if (op == "-") { ret = Numberize(*valueA) - Numberize(*valueB); goto end; }
		if (op == "/") { ret = Numberize(*valueA) / Numberize(*valueB); goto end; }
		if (op == "*") { ret = Numberize(*valueA) * Numberize(*valueB); goto end; }
		errorString = "Error: Operation " + op + " not defined for " + b;
		break;
	}
end:	;
	delete valueA;
	delete valueB;
	return ret;
}

//
// Do LIKE comparison, with wildcards
double CEStack::Compare(CString a, CString b)
{
	CString test = "";
	int rc = 0;
	if ((rc=a.Find("*"))<0) {
		if (a == b) return 1.0;
		return 0.0;
	}
	if (rc == 0) {					// *blahblah*
		test = a.Mid(1,a.GetLength()-1);
		rc = test.Find("*");		// look for trailing *
		if (rc > 0) {
			test = test.Mid(0,a.GetLength()-2);
			rc = b.Find(test);
			if (rc >= 0) return 1.0;
		}
		rc = b.Find(test);			// test for absolute match on right side
		if (rc >= 0 && (rc + test.GetLength() == b.GetLength()) ) return 1.0;
		return 0.0;
	}

	test = a.Mid(0,rc);				// test for blah*
	rc = b.Find(test);
	if (rc == 0) return 1.0;
	return 0.0;
}

//
// Look in the table record for this attribute, unless it is a quoted string, then just return it
CString* CEStack::GetValue(CString attr)
{
	CString* a = NULL;
	int index = 0, type = CUNDEFINED;
	if (CESql::IsStringLiteral(attr)) {
		attr = attr.Mid(1,attr.GetLength()-2);
		a = new CString(attr);
		return a;
	}
	if (CESql::IsNumber(attr)) return new CString(attr);
	index = tableInQuestion->Index(attr);
	if (index < 0) return NULL;
	type = tableInQuestion->Type(index);
	a = SCTable::InterpretAsString(type,rowInQuestion[index]);
	return a;
}

//
// Assign an expression to an attribute. Pop 2 things off the stack,
// First item is the attribute, second is a production to evaluate and
// assign to the attribute.
// The attributes are an array of void ptrs stored in column order. So,
// by finding the column index of the attribute name, we have the index into
// the array of pointers to use to make the assignment.
bool CEStack::ExecuteAssign()
{
	CString *attr = NULL, *value = NULL;
	SCColumn *col = NULL;
	int index = 0;
	errorString = "";
	attr = stack->Pop();	
	if (attr == NULL) {
		errorString = "No attribute to assign!";
		return false;
	}
	if (tableInQuestion == NULL) {
		errorString = "Table does not exist, can't assign";
		return false;
	}
	index = tableInQuestion->Index(*attr);			// find column index
	if (index < 0) {
		errorString = "No such attribute " + *attr;
		return false;
	}
	value = PopProduction();						// evaluate right hand side
	if (value == NULL) {
		errorString = "No production to assign to attribute " + *attr;
		return false;
	}
	col = tableInQuestion->Column(index);			// get the column object
	col->SetValueByType(*value);					// assign based on type
	shared_free((char*)rowInQuestion[index]);		// delete the old value of the attr
	rowInQuestion[index] = col->Value();			// assign the new value
	return true;
}

//
// Is the string an operator we recognize?
bool CEStack::IsOperator(CString s)
{
	char c = s[0];
	if (s == "+" || s == "-" || s == '*' || s == '=' || s == '<' || s == '>' ||
		s == "<=" || s == ">=" || s == "<>" ||
	    s == "AND" || s == "OR" || s == "LIKE" || s == "NOT LIKE") return true;
	return false;
}

//
// Turn S into a number. If it is an attribute, then look up it's value
double CEStack::Numberize(CString s)
{
	double res;
	if (CESql::IsNumber(s))
		res = atof(s);
	else {
		errorString = "Error: " + s + " is not a number";
		res = -1.0;
	}
	return res;
}

CString CEStack::TableInQuestion()
{
	return tableName;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -