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

📄 parser.cpp

📁 一个经典的词法分析器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
bool CESql::E()
{
	CString tk;
	T();
	EPRIME();
	GetToken();
	if (tokenString == "AND" || tokenString == "OR") {
		tk = tokenString;
		Accept();
		E();
		stack->Push(tk);
	}
	return TRUE;
}

//
// E' production. Finds lowest prececence operators
bool CESql::EPRIME()
{
	CString tk = "";

	if (!GetToken()) return false;
	switch (TokenToType(tokenString)) {
	case EQUALS:
		tk = "=";
		Accept();
		break;
	case LESS_THAN:
		Accept();
		if (!GetToken()) return false;
		if (tokenString == ">") {
			tk = "<>";
			Accept();
		}
		else { 
			if (tokenString == "<") {
				tk ="<=";
				Accept();
			}
			else {
				tk ="<";
			}
		}
		break;
	case GREATER_THAN:
		Accept();
		if (!GetToken()) return false;
		if (tokenString == "=") {
			tk = ">=";
			Accept();
		}
		else
			tk = ">"; 
		break;
	case NOT:
		Accept();
		if (!GetToken()) return false;
		if (tokenString != "LIKE") 
			return false;
		tk = "NOT LIKE";
		Accept();
		break;
	case LIKE:
		tk = "LIKE";
		Accept();
		break;
	default:
		tk = "";
	}
	if (tk != "") {
		T();
		EPRIME();
		stack->Push(tk);
	}
	return true;
}

//
// T production
bool CESql::T()
{
	Z();
	TPRIME();
	return TRUE;
}

//
// T' production. Finds the + and - operators, the next to lowest precedence operators
bool CESql::TPRIME()
{
	CString tk = "";
	if (!GetToken()) return false;
	tk = tokenString;
	if (tokenString == "+" || tokenString == "-") {
		Accept();
		Z();
		TPRIME();
		stack->Push(tk);
		return true;
	}
	return true;
}

bool CESql::Z()
{
	F();
	ZPRIME();
	return true;
}

//
// Finds the next to the strongest precedence operators, * and /
bool CESql::ZPRIME()
{
	CString tk = "";
	if (!GetToken()) return false;
	tk = tokenString;
	if (tokenString == "*" || tokenString == "/") {
		Accept();
		F();
		ZPRIME();
		stack->Push(tk);
	}
	return true;
}

//
// Factor (terminal or precedence overload operator '(')
bool CESql::F()
{
	CString tuple1 = "", tuple2 = "", table = "";

	if (!GetToken()) return false;

	if (IsIdentifier(tokenString) ||
		IsNumber(tokenString) ||
		IsStringLiteral(tokenString)) {
		Accept();
		if (IsIdentifier(tokenString) && !AttributeExists(tokenString,table)) {
			errorString = "No such element " + tokenString + " in " + table;
			return false;
		}
	}
	tuple1 = tokenString;

	if (tokenString == "(") {
		Accept();
		E();
		if (!GetToken()) return false;
		if (tokenString == ")")
			Accept();
		else {
			errorString = "Expected right parenthesis at:" + inputString;
			return false;
		}
		return true;
	}
	stack->Push(tuple1);

	return true;
}

//
// Execute the stack.
void CESql::Execute(SCCollection *stk)
{
	CString *v;
	SCCollection* copy = stk->Copy();// make a copy of the stack
	eStack->Load(copy);

	if (printStack)
		stk->Print();

	result = eStack->Execute();		// interpret the copy stack
	v = copy->Pop();
	if (*v == "ERROR")
		errorString = *copy->Pop();
	copy->Clear();						// clear left overs on the copy stack

	delete copy;						// release resources
}

//
// From the token, return it's conditional type
int CESql::TokenToType(CString s)
{
	if (s == "=") return EQUALS;
	if (s == "<") return LESS_THAN;
	if (s == ">") return  GREATER_THAN;
	if (s.CompareNoCase ("NOT")==0) return NOT;
	if (s.CompareNoCase("LIKE")==0) return LIKE;
	return UNDEFINED;
}

/////////////////////////////////////////////////////////////

//
// Does the named attribute exist in the specified table?
bool CESql::AttributeExists(CString attr, CString table)
{
	return true;
}

//
// Get a list of identifiers  fron the input string and place it onto the execution stack
bool CESql::GetListIds()
{
	bool rc = true;
	if (GetToken("*")) {						// wildcard indicated
		stack->Push("EOLIST");
		stack->Push("*");
		stack->Push("LIST");
		return true;
	}
	if (!GetIdentifier()) {						// must have at least one attribute
		errorString = "Expected attribute not found";
		return false;
	}
	stack->Push("EOLIST");						// mark end of list
	stack->Push(tokenString);					// push first attribute
	while(rc) {									// find comma separated list
		rc = GetToken(",");
		if (rc) {
			if (GetIdentifier())
				stack->Push(tokenString);		// and push each attribute onto the list
			else {
				errorString = "Unexpected chars at '" + inputString + "'";
				return false;
			}
		}
	}
	stack->Push("LIST");							// mark beginning of list
	return true;
}

//
// Get a list of expressions and put them onto the execution stack
bool CESql::GetListExps()
{
	SCCollection* list = NULL;
	bool rc = true;
	stack->Push("EOLIST");						// mark end of list
	if (!E()) return false;						// find first expression
	while(rc) {				
		rc = GetToken(",");						// find comma separated list
		if (rc) {
			if (E()) ;							// push them onto the stack
			else {
				errorString = "Unexpected chars at '" + inputString + "'";
				return false;
			}
		}
	}
	stack->Push("LIST");						// mark beginning of list
	return true;
}

//
// Get an assignment in the form of <atrtribute = <expression>>
bool CESql::GetAssignment()
{
	bool rc = true;
	if (!LHS()) return false;				// one assignment is required
	while(rc) {
		rc = GetToken(",");					// find comma separated list
		if (rc && !LHS()) return true;		// and push onto the stack
	}	
	return true;
}

//
// Accept the token input, thus chop the input string up to where we
// have successfully parsed
void CESql::Accept()
{
	int chop = inputString.Find(tokenString) + tokenString.GetLength();		// how much of input to trip off beginning based on the size of the last token
	inputString = inputString.Right(inputString.GetLength() - chop);	// chop it off
	inputString.TrimLeft();												// and any white space too
}

//
// Retrives a number from the input string
bool CESql::GetNumber()
{
	if (!GetToken("",",\n\t ")) return false;		// Get the token
	if (!IsNumber(tokenString)) return false;		// is it recognized as a number
	Accept();										// accept if true
	return true;
}

//
// Is the string 'test' a number?
bool CESql::IsNumber(CString test)
{
	int dotCount = 0, dashCount = 0;
	for (int i=0;i<test.GetLength();i++) {
		if (!isdigit(test[i])) {
			if (test[i] == '.') {
				if (dotCount == 0) 
					dotCount++;
				else
					return false;
			}
			else {
				if (test[i] == '-') {
					if (dashCount == 0) 
						dashCount++;
					else
						return false;
				}
				else
					return false;
			}
		}
	}
	return true;
}

//
// Get the next lexical token. Return any token bracketed by the span
// if hunt not supplied. If hint is supplied, it is mandatory to get
// only that token. Returns false if criteria not met, or no more tokens.
//
// Sets the attribute "tokenString" to what was read, or "" if end-of-string
bool CESql::GetToken(CString hunt, CString span)
{
	CString opSpan = "=<>()+-*/,";
	CString testForOps = "";
	tokenString = inputString.SpanExcluding(span);				// get bracketed token
	testForOps = tokenString.SpanExcluding(opSpan);				// additional check to see if we have an operator
	if (testForOps != "") {										// if found something...
		if (testForOps != tokenString)							// then if ne then use testForOps
			tokenString = testForOps;							
	}
	else {
		testForOps=tokenString.SpanIncluding(opSpan);			// look for an operator
		if (testForOps != "") tokenString = testForOps[0];		// if found, then use the 1st character
	}	

	if (hunt != "") {											// look for specific?
			tokenString = tokenString.Left(hunt.GetLength());	// trim off what we don't need
		if (tokenString.CompareNoCase(hunt) != 0) {				// case not important
			return false;										// so return false
		}
		Accept();												// eat up the input
	}
	if (tokenString.GetLength() == 0) return false;				// if 0 length, no token matches
//
// Watch for quoted string literals
//
	if (tokenString[0] == '\'')	 {								// watch for the quote character
		for (int i=1;i<inputString.GetLength();i++) {				// if you find it, gobble up to and including the next '
			if (inputString[i] == '\'') {							//    but keep eating if escape char found
				if (inputString[i-1] != '\\') {
					tokenString = inputString.Left(i) + "'";
					return true;
				}
			}
		}
		errorString = "Unterminated literal string";
		return false;											// dangling string
	}
	return true;												// otherwise ok
}

//
// Return an identifier, alphanumeric, any length
bool CESql::GetIdentifier()
{
	if (!GetToken("") || !IsIdentifier(tokenString)) return false;
	Accept();
	return true;
}

//
// Determine if the test string is an identifier, that is, any 
// alphanumeric string, of any length
bool CESql::IsIdentifier(CString test)
{
	for (int i=0;i<test.GetLength();i++) {
		if (!isalpha(test[i])) 
			if (!(i > 0 && (isdigit(test[i]) || test[1] == '_'))) return false;
	}
	return true;
}

//
// Gets a string literal of the form 'blah-blah-blah' or ''?.
bool CESql::GetStringLiteral()
{
	if (!GetToken() || !IsStringLiteral(tokenString)) return false;
	Accept();
	return true;
}

//
// Is the test string a string literal of the form 'blah-blah-blah'. '' works too
bool CESql::IsStringLiteral(CString test)
{
	if (test[0] == '\'') return true;
	return false;
}

//
// Set the error message
void CESql::SetError(CString s)
{
	errorString =s;
}
//
// Return the error string
const CString CESql::ReturnError()
{
	return errorString;
}

//
// Return the last token processed
const CString CESql::ReturnToken()
{
	return tokenString;
}

//
// Set the column info. Called by the Sql() method to setup the information
// about the table involved in the last transaction
void CESql::SetColumnInfo(CString table)
{
	SCTable* tbl = FindTable(table);
	if (tbl == NULL) {
		nCols = -1;
		columnInfo = NULL;
		return;
	}
	nCols = tbl->Columns();
	columnInfo = tbl->GetColumnInfo();
}

//
// Return the column array from the table involved in the last transaction
SCColumn** CESql::GetColumnInfo()
{
	return columnInfo;
}

//
// Return the number of columns in the table involved in the last transaction
int CESql::GetColumnCount()
{
	return nCols;
}

//
// Set the stack print flag
void CESql::PrintStack(BOOL t)
{
	printStack = t;
}

⌨️ 快捷键说明

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