📄 parser.cpp
字号:
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 + -