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

📄 compiler.cpp

📁 一个功能强大的内存数据库源代码,c++编写,有详细的注释
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	break;      case tkn_true:	expr = new dbExprNode(dbvmLoadTrue);	break;      case tkn_null:	expr = new dbExprNode(dbvmLoadNull);	break;      case tkn_iconst:	expr = new dbExprNode(dbvmLoadIntConstant, ivalue);	break;      case tkn_fconst:	expr = new dbExprNode(dbvmLoadRealConstant, fvalue);	break;      case tkn_sconst:	expr = new dbExprNode(dbvmLoadStringConstant, svalue); 	lex = scan();	return field(expr, NULL, NULL);      case tkn_var:	expr = new dbExprNode(dbvmLoadVarBool + varType - 			      dbQueryElement::qVarBool, varPtr);	refTable = varRefTable;	lex = scan();	return field(expr, refTable, NULL);      case tkn_abs:      case tkn_length:      case tkn_lower:      case tkn_upper:      case tkn_integer:      case tkn_real:      case tkn_string:	pos = currPos;	expr = term();	switch (cop) {	  case tkn_abs:	    if (expr->type == tpInteger) { 		cop = dbvmAbsInt;	    } else if (expr->type == tpReal) { 		cop = dbvmAbsReal;	    } else { 		error("ABS function can be applied only "		      "to integer or real expression", pos);	    }	    break;	  case tkn_length:	    if (expr->type == tpArray) { 		cop = dbvmLength;	    } else if (expr->type == tpString) { 		cop = dbvmStringLength;	    } else { 		error("LENGTH function is defined only for arrays and strings",		      pos);	    } 	    break;	  case tkn_integer:	    if (expr->type == tpReal) { 		cop = dbvmRealToInt;	    } else { 		error("INTEGER function can be applied only to "		      "expression of real type", pos);	    }	    break;	  case tkn_real:	    if (expr->type == tpInteger) { 		cop = dbvmIntToReal;	    } else { 		error("REAL function can be applied only to "		      "expression of integer type", pos);	    }	    break;	  case tkn_string:	    if (expr->type == tpInteger) { 		cop = dbvmIntToString;	    } else if (expr->type == tpReal) { 		cop = dbvmRealToString;	    } else { 		error("STRING function can be applied only "		      "to integer or real expression", pos);	    }	    break;	  case tkn_lower:	    if (expr->type != tpString) { 		error("LOWER function can be applied only to string argument",		      pos);	    } else { 		cop = dbvmLowerString;	    }	    break;	  case tkn_upper:	    if (expr->type != tpString) { 		error("UPPER function can be applied only to string argument",		      pos);	    } else { 		cop = dbvmUpperString;	    }	    break;	  default:	    assert(false);	}	return field(new dbExprNode(cop, expr), NULL, NULL);      case tkn_lpar:        {	    expr = disjunction();	    dbExprNode* list = NULL;	    while (lex == tkn_comma) { 		list = new dbExprNode(dbvmList, list, expr);		expr = disjunction();	    }	    if (lex != tkn_rpar) { 		error("')' expected");	    }	    if (list != NULL) { 		expr = new dbExprNode(dbvmList, list, expr);	    }	}	break;      case tkn_not:	pos = currPos;	expr = comparison();	if (expr->type == tpInteger) { 	    if (expr->cop == dbvmLoadIntConstant) { 		expr->ivalue = ~expr->ivalue;	    } else {		expr = new dbExprNode(dbvmNotInt, expr);	    } 	    return expr;	} else if (expr->type == tpBoolean) { 	    return new dbExprNode(dbvmNotBool, expr);	} else { 	    error("NOT operator can be applied only to "		  "integer or boolean expressions", pos);	}	break;      case tkn_add:	error("Using of unary plus operator has no sence");	break;      case tkn_sub:	pos = currPos;	expr = term();	if (expr->type == tpInteger) { 	    if (expr->cop == dbvmLoadIntConstant) { 		expr->ivalue = -expr->ivalue;	    } else { 		expr = new dbExprNode(dbvmNegInt, expr);	    }	    return expr;	} else if (expr->type == tpReal) { 	    if (expr->cop == dbvmLoadRealConstant) { 		expr->fvalue = -expr->fvalue;	    } else { 		expr = new dbExprNode(dbvmNegReal, expr);	    }	    return expr;	} else { 	    error("Unary minus can be applied only to "		  "integer or real expressions", pos);	}      default:	error("operand expected");    }    lex = scan();    return expr;}void dbCompiler::error(const char* msg, int pos) {     if (pos < 0) { 	if ((pos = currPos-1) < 0) { 	    pos = 0;	}    } else if (pos < firstPos) { 	pos = firstPos;    }    if (pos + offsetWithinStatement >= 0) { 	pos += offsetWithinStatement;    }    table->db->handleError(dbDatabase::QueryError, msg, pos);    longjmp(abortCompilation, dbDatabase::QueryError);}void dbCompiler::compileStartFollowPart(dbQuery& query){    if (lex != tkn_start) {		return;    }    int pos = currPos;    if (scan() != tkn_from) { 	error("FROM expected after START", pos);    }    pos = currPos;    switch (scan()) {       case tkn_first:	query.startFrom = dbCompiledQuery::StartFromFirst; 	break;      case tkn_last:	query.startFrom = dbCompiledQuery::StartFromLast; 	break;      case tkn_var:	if (varType == dbQueryElement::qVarReference) { 	    if (varRefTable != table) { 		error("Incompatiable type of reference variable");	    }	    query.startFrom = dbCompiledQuery::StartFromRef; 	} else if (varType == dbQueryElement::qVarArrayOfRef) {	    if (varRefTable != table) { 		error("Incompatiable type of array of reference variable");	    }	    query.startFrom = dbCompiledQuery::StartFromArray; 	} else if (varType == dbQueryElement::qVarArrayOfRefPtr) {	    if (varRefTable != table) { 		error("Incompatiable type of array of reference variable");	    }	    query.startFrom = dbCompiledQuery::StartFromArrayPtr; 	} else { 	    error("Reference or array of reference variable expected");	}	query.root = varPtr;	break;      default:	error("FIRST, LAST or reference varaible expected", pos);     }    if ((lex = scan()) == tkn_follow) { 	pos = currPos;	if (scan() != tkn_by) { 	    error("BY expected after FOLLOW", pos);	}	do { 	    pos = currPos;	    if (scan() != tkn_ident) { 		error("Field name expected", pos);	    }	    dbFieldDescriptor* fd;	    if ((fd = table->findSymbol(name)) == NULL) { 		error("Field not found");	    }	    while (fd->type == dbField::tpStructure) { 		pos = currPos;		if (scan() != tkn_dot) { 		    error("'.' expected", pos);		}		pos = currPos;		if (scan() != tkn_ident) { 		    error("Field name expected", pos);		}		if ((fd = fd->find(name)) == NULL) { 		    error("Field not found");		}	    }	    if (!(fd->type == dbField::tpReference 		  && fd->refTable == table) &&		!(fd->type == dbField::tpArray 		  && fd->components->type == dbField::tpReference		  && fd->components->refTable == table)) 	    { 		error("Follow field should be of compatibale reference "		      "or array of reference type");	    }	    dbFollowByNode* node = new dbFollowByNode;	    node->field = fd;	    node->next = query.follow; // list should be inverted	    query.follow = node;	} while ((lex = scan()) == tkn_comma);     }	}void dbCompiler::compileOrderByPart(dbQuery& query){    dbOrderByNode** opp = &query.order;    if (lex == tkn_order) {		int pos = currPos;	if (scan() != tkn_by) { 	    error("BY expected after ORDER", pos);	}	int parentheses = 0;	bool length = false;	dbFieldDescriptor* fd;	while (true) { 	    pos = currPos;	    switch (scan()) { 	      case tkn_lpar:		parentheses += 1;		continue;	      case tkn_rpar:		if (--parentheses < 0) { 		    error("Unbalanced parentheses ");		}		continue;	      case tkn_length:		length = true;		continue;	      case tkn_ident:				if ((fd = table->findSymbol(name)) == NULL) { 		    error("Field not found", pos);		}		while (fd->type == dbField::tpStructure) { 		    if (scan() != tkn_dot) { 			error("'.' expected");		    }		    if (scan() != tkn_ident) { 			error("field name expected", pos);		    }		    if ((fd = fd->find(name)) == NULL) { 			error("Field not found", pos);		    }		}		if (fd->type > dbField::tpReference) { 		    if (fd->type != dbField::tpRawBinary  			&& (fd->type != dbField::tpArray || !length)) 		    { 		        error("Sort key should be of scalar or string type", pos);		    }		} else if (length && fd->type != dbField::tpString) { 		   error("Length in ORDER BY part can be applied only to arrays or strings", pos);		}		  		dbOrderByNode* node = new dbOrderByNode;		node->field = fd;		node->ascent = true;				node->stringLength = length;		*opp = node;		opp = &node->next;		*opp = NULL;		int tkn = scan();		while (tkn == tkn_rpar) { 		    if (--parentheses < 0) { 			error("Unbalanced parentheses");		    }		    tkn = scan();		}		if (tkn == tkn_desc) { 		    node->ascent = false;		    tkn = scan();		} else if (tkn == tkn_asc) { 		    tkn = scan();		}		while (tkn == tkn_rpar) { 		    if (--parentheses < 0) { 			error("Unbalanced parentheses");		    }		    tkn = scan();		}		if (tkn == tkn_eof) { 		    if (parentheses != 0) {			error("Unbalanced parentheses");		    }		    return;		} else if (tkn != tkn_comma) { 		    error("',' expected");		}	    }	}    } else if (lex != tkn_eof) { 	error("ORDER BY expected");    }}dbExprNode* dbCompiler::compileExpression(dbTableDescriptor* table, char const* expr, int startPos){    TRACE_MSG(("Compile expression %s for table %s\n", table->name));        if (setjmp(abortCompilation) == 0) { 	this->table = table;	bindings = NULL;	nFreeVars = 0;	dbQueryElement elem(dbQueryElement::qExpression, expr, NULL); 	queryElement = &elem;	currPos = firstPos = 0;	offsetWithinStatement = startPos;	return disjunction();     } else {	return NULL;    }}bool dbCompiler::compile(dbTableDescriptor* table, dbQuery& query){    TRACE_MSG(("Compile query for table %s\n", table->name));    query.destroy();     if (setjmp(abortCompilation) == 0) { 	this->table = table;	bindings = NULL;	nFreeVars = 0;	queryElement = query.elements;	currPos = firstPos = 0;	offsetWithinStatement = query.pos;	dbExprNode* expr = disjunction(); 	if (expr->type != tpBoolean && expr->type != tpVoid) { 	    table->db->handleError(dbDatabase::QueryError, "Conditional "				   "expression should have boolean type\n", 0);	    delete expr;	    return false;	}	compileStartFollowPart(query); 	compileOrderByPart(query); 	query.tree  = expr;	query.table = table;	return true;    } else { 	for (dbOrderByNode *op = query.order, *nop; op != NULL; op = nop) {	    nop = op->next;	    delete op;	}	for (dbFollowByNode *fp = query.follow, *nfp; fp != NULL; fp = nfp) {	    nfp = fp->next;	    delete fp;	}	return false;    }}dbCompiler::dbCompiler() {    static struct { 	char* name;	int   tag;    } keywords[] = { 	{"all",     tkn_all},	{"abs",     tkn_abs},	{"and",     tkn_and},	{"asc",     tkn_asc},	{"between", tkn_between},	{"by",      tkn_by},	{"current", tkn_current},	{"desc",    tkn_desc},	{"escape",  tkn_escape},	{"exists",  tkn_exists},	{"first",   tkn_first},	{"false",   tkn_false},	{"follow",  tkn_follow},	{"from",    tkn_from},	{"in",      tkn_in},	{"is",      tkn_is},	{"integer", tkn_integer},	{"insert",  tkn_insert},	{"into",    tkn_into},	{"last",    tkn_last},	{"length",  tkn_length},	{"like",    tkn_like},	{"lower",   tkn_lower},	{"not",     tkn_not},	{"null",    tkn_null},	{"or",      tkn_or},	{"order",   tkn_order},	{"real",    tkn_real},	{"select",  tkn_select},	{"start",   tkn_start},	{"string",  tkn_string},	{"table",   tkn_table},	{"true",    tkn_true},	{"upper",   tkn_upper},	{"where",   tkn_where}    };    if (!initialized) { 	for (unsigned i = 0; i < items(keywords); i++) { 	    dbSymbolTable::add(keywords[i].name, keywords[i].tag, FASTDB_CLONE_ANY_IDENTIFIER);    	}	initialized = true;    }}void dbInheritedAttribute::removeTemporaries(){    for (dbStringValue *next, *s = tempStrings; s != NULL; s = next) { 	next = s->next;	delete s;    }}void dbTrace(char* message, ...) {    va_list args;    va_start (args, message);    vfprintf(stderr, message, args);    va_end(args);}

⌨️ 快捷键说明

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