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

📄 compiler.cpp

📁 一个功能强大的内存数据库源代码,c++编写,有详细的注释
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//-< COMPILE.CPP >---------------------------------------------------*--------*// FastDB                    Version 1.0         (c) 1999  GARRET    *     ?  *// (Main Memory Database Management System)                          *   /\|  *//                                                                   *  /  \  *//                          Created:     20-Nov-98    K.A. Knizhnik  * / [] \ *//                          Last update: 15-Jan-99    K.A. Knizhnik  * GARRET *//-------------------------------------------------------------------*--------*// Conditional expresion compiler//-------------------------------------------------------------------*--------*#define INSIDE_FASTDB#include <ctype.h>#include "database.h"#include "array.h"#include "query.h"#include "cursor.h"#include "compiler.h"#include "symtab.h"nat1 const dbExprNode::nodeTypes[] = { #define DBVM(cop, type, n_opernads, commutative) type,#include "compiler.d"0};nat1 const dbExprNode::nodeOperands[] = { #define DBVM(cop, type, n_operands, commutative) n_operands,#include "compiler.d"0};nat1 const dbExprNode::commutativeOperator[] = { #define DBVM(cop, type, n_operands, commutative) commutative,#include "compiler.d"0};dbExprNode* dbExprNode::freeNodeList;dbMutex&    dbExprNode::mutex = *new dbMutex;bool        dbCompiler::initialized;dbExprNodeSegment* dbExprNode::segmentList;dbExprNode::dbExprNode(dbExprNode* node){    memcpy(this, node, sizeof(*this));        for (int i = nodeOperands[cop]; --i >= 0;) { 	operand[i] = new dbExprNode(operand[i]);    }    if (cop == dbvmLoadStringConstant) { 	char* s = new char[strlen(svalue.str)+1];	strcpy(s, svalue.str);	svalue.str = s;    } }void* dbExprNode::operator new(size_t) {     dbCriticalSection cs(mutex);    dbExprNode* node = freeNodeList;    if (node == NULL) {	dbExprNodeSegment* seg = new dbExprNodeSegment;	seg->next = segmentList;	segmentList = seg;	node = (dbExprNode*)seg->buf;	dbExprNode* freeNode = NULL;	for (int i = dbExprNodeSegment::allocationQuantum; --i != 0;) { 	    node->next = freeNode;	    freeNode = node++;	} 	freeNodeList = freeNode;    } else { 	freeNodeList = node->next;    }    return node;}void dbExprNode::cleanup(){    dbExprNode* freeNode = NULL;    for (dbExprNodeSegment* seg = segmentList; seg != NULL; seg = seg->next)     { 	dbExprNode* node = (dbExprNode*)seg->buf;	for (int i = dbExprNodeSegment::allocationQuantum; --i >= 0;) { 	    node->next = freeNode;	    freeNode = node++;	 }    }    freeNodeList = freeNode;}dbExprNode::~dbExprNode(){    if (cop == dbvmLoadStringConstant) { 	delete[] svalue.str;    } else { 	for (int i = nodeOperands[cop]; --i >= 0; ) { 	    delete operand[i];	}    }}int dbCompiler::scan() {    char ch;    char *p, *q;    int  i, n, value;    char buf[maxStrLen+1];   nextElement:    if (queryElement == NULL) { 	return tkn_eof;    }    if (queryElement->type != dbQueryElement::qExpression) {	varType = queryElement->type;	varPtr = queryElement->ptr;	varRefTable = queryElement->ref;	queryElement = queryElement->next;	return tkn_var;    }     p = q = (char*)queryElement->ptr + currPos;        do { 	ch = *p++;	if (ch == '\n') { 	    offsetWithinStatement = (char*)queryElement->ptr - p;	    firstPos = 0;	}    } while (isspace(byte(ch)));    currPos += p - q;    switch (ch) {       case '\0':	if ((queryElement = queryElement->next) == NULL) { 	    return tkn_eof;	}	currPos = 0;	goto nextElement;      case '+':	return tkn_add;      case '-':	if (*p == '-') { 	    // ANSI comments	    q = p;	    do { 		p += 1;	    } while (*p != '\n' && *p != '\0');	    currPos += p - q;	    goto nextElement;	}	return tkn_sub;      case '*':	return tkn_mul;      case '/':	return tkn_div;      case '.':	return tkn_dot;      case ',':	return tkn_comma;      case '(':	return tkn_lpar;      case ')':	return tkn_rpar;      case '[':	return tkn_lbr;      case ']':	return tkn_rbr;      case ':':	return tkn_col;      case '^':	return tkn_power;      case '<':	if (*p == '=') { 	    currPos += 1;	    return tkn_le;	} else if (*p == '>') { 	    currPos += 1;	    return tkn_ne;	}	return tkn_lt;      case '>':	if (*p == '=') { 	    currPos += 1;	    return tkn_ge;	}	return tkn_gt;      case '=':	return tkn_eq;      case '!':	if (*p != '=') { 	    error("Invalid token '!'");	} 	currPos += 1;	return tkn_ne;      case '|':	if (*p != '|') { 	    error("Invalid token '|'");	} 	currPos += 1;	return tkn_add;      case '\'':	q = p;	i = 0; 	while (true) { 	    if (*p == '\'') { 		if (*++p != '\'') { 		    break;		}	    } else if (*p == '\0') { 		error("Unterminated character constant");	    }	    if (i == maxStrLen) { 		error("String constant too long");	    }	    buf[i++] = *p++;	}	buf[i++] = '\0';	currPos += p - q;	svalue.str = new char[i];	strcpy(svalue.str, buf);	svalue.len = i;	return tkn_sconst;      case '0': case '1': case '2': case '3': case '4':       case '5': case '6': case '7': case '8': case '9':	value = ch - '0';	for (q = p; isdigit(*(byte*)p); p++) { 	    value = value*10 + *p - '0';	}	if (*p == '.' || *p == 'e' || *p == 'E') { 	    if (sscanf(q-1, "%lf%n", &fvalue, &n) != 1) { 		error("Bad floating point constant");	    }	    currPos += n - 1;	    return tkn_fconst;	} else if (p - q >= 9) { 	    if (sscanf(q-1, INT8_FORMAT "%n", &ivalue, &n) != 1) { 		error("Bad integer constant");	    }	    currPos += n - 1;	    return tkn_iconst;	} else { 	    currPos += p - q; 	    ivalue = value;	    return tkn_iconst;	}      default:	if (isalpha(ch) || ch == '$' || ch == '_') { 	    i = 0;	    do { 		if (i == maxStrLen) { 		    error("Name too long");		}		buf[i++] = ch;		ch = *p++;	    } while (isalnum(ch) || ch == '$' || ch == '_');	    buf[i] = '\0';	    name = buf;	    currPos += i - 1;	} else { 	    error("Invalid symbol");	} 	return dbSymbolTable::add(name, tkn_ident);   }}dbExprNode* dbCompiler::disjunction(){    dbExprNode* left = conjunction();    if (lex == tkn_or) { 	int pos = currPos;	dbExprNode* right = disjunction();	if (left->type == tpInteger && right->type == tpInteger) { 	    left = new dbExprNode(dbvmOrInt, left, right);	} else if (left->type == tpBoolean && right->type == tpBoolean) { 	    left = new dbExprNode(dbvmOrBool, left, right);	} else { 	    error("Bad operands for OR operator", pos);	}    }    return left;}dbExprNode* dbCompiler::conjunction(){    dbExprNode* left = comparison();    if (lex == tkn_and) { 	int pos = currPos;	dbExprNode* right = conjunction();	if (left->type == tpInteger && right->type == tpInteger) { 	    left = new dbExprNode(dbvmAndInt, left, right);	} else if (left->type == tpBoolean && right->type == tpBoolean) { 	    left = new dbExprNode(dbvmAndBool, left, right);	} else { 	    error("Bad operands for AND operator", pos);	}    }    return left;}inline dbExprNode* int2real(dbExprNode* expr) {    if (expr->cop == dbvmLoadIntConstant) { 	expr->fvalue = (real8)expr->ivalue;	expr->cop = dbvmLoadRealConstant;	expr->type = tpReal;    } else { 	expr = new dbExprNode(dbvmIntToReal, expr);    }    return expr;}int dbCompiler::compare(dbExprNode* expr, dbExprNode* list){    int n = 1;    if (list->operand[0] != NULL) { 	n = compare(expr, list->operand[0]);	expr = new dbExprNode(expr);    }    dbExprNode* elem = list->operand[1];    int cop = dbvmVoid;    int rawBinarySize = 0;    void* rawBinaryComparator = NULL;    if (expr->type == tpInteger) { 	if (elem->type == tpReal) { 	    expr = int2real(expr);	    cop = dbvmEqReal;	} else if (elem->type == tpInteger) { 	    cop = dbvmEqInt;	}    } else if (expr->type == tpReal) {	if (elem->type == tpReal) { 	    cop = dbvmEqReal;	} else if (elem->type == tpInteger) { 	    cop = dbvmEqReal;	    elem = int2real(elem);	}    } else if (expr->type == tpString && elem->type == tpString) {	cop = dbvmEqString;    } else if (expr->type == tpReference && elem->type == tpReference) {	cop = dbvmEqReference;    } else if (expr->type == tpBoolean && elem->type == tpBoolean) {	cop = dbvmEqBool;    } else if (expr->type == tpRawBinary && elem->type == tpRawBinary) {	cop = dbvmEqBinary;	if ((expr->cop == dbvmLoadSelfRawBinary || expr->cop == dbvmLoadRawBinary) 	    && expr->ref.field != NULL)	{	    rawBinarySize = expr->ref.field->dbsSize;	    rawBinaryComparator = (void*)expr->ref.field->comparator;	} else if ((elem->cop == dbvmLoadSelfRawBinary || elem->cop == dbvmLoadRawBinary) 	    && elem->ref.field != NULL)	{	    rawBinarySize = elem->ref.field->dbsSize;	    rawBinaryComparator = (void*)elem->ref.field->comparator;	} else { 	    error("Operations with raw binary types should include at least one record field");	}    }    if (cop == dbvmVoid) { 	char buf[256];	sprintf(buf, "Expression %d in right part of IN operator have "		"incompatible type", n);	error(buf);    } else { 	list->type = tpBoolean;	if (list->operand[0] != NULL) { 	    expr = new dbExprNode(cop, expr, elem, rawBinarySize);	    expr->func.fptr = rawBinaryComparator;	    list->operand[1] = expr;	    list->cop = dbvmOrBool;	} else { 	    list->operand[0] = expr;	    list->cop = cop;	    list->offs = rawBinarySize;	    list->func.fptr = rawBinaryComparator;	}    }    return ++n;}dbExprNode* dbCompiler::comparison(){    int leftPos = currPos;    dbExprNode *left, *right;    left = addition();    int cop = lex;    if (cop == tkn_eq || cop == tkn_ne || cop == tkn_gt || cop == tkn_ge	|| cop == tkn_le || cop == tkn_lt || cop == tkn_between 	|| cop == tkn_like || cop == tkn_not || cop == tkn_is || cop == tkn_in)    {	int rightPos = currPos;	bool notOp = false;	if (cop == tkn_not) { 	    notOp = true;	    cop = scan();	    if (cop != tkn_like && cop != tkn_between && cop != tkn_in) { 		error("LIKE, BETWEEN or IN expected", rightPos);	    } 	    rightPos = currPos;	} else if (cop == tkn_is) {	    if (left->type != tpReference) { 		error("IS [NOT] NULL predicate can be applied only to "		      "references", rightPos);	    } 	    rightPos = currPos;	    if ((cop = scan()) == tkn_null) { 		left = new dbExprNode(dbvmIsNull, left);	    } else if (cop == tkn_not) { 		rightPos = currPos;		if (scan() == tkn_null) { 		    left = new dbExprNode(dbvmNotBool, 					  new dbExprNode(dbvmIsNull, left));		} else { 		    error("NULL expected", rightPos);		}	    } else { 		error("[NOT] NULL expected", rightPos);	    } 	    lex = scan();	    return left;	}		right = addition();	if (cop == tkn_in) { 	    int type;	    switch (right->type) {	      case tpArray:		type = (right->cop == dbvmLoadVarArray || right->cop == dbvmLoadVarArrayPtr)		     ? dbField::tpReference 		     : right->ref.field->components->type;		if ((left->type == tpBoolean && type == dbField::tpBool) 		    || (left->type == tpInteger 			&& (type == dbField::tpInt1 			    || type == dbField::tpInt2			    || type == dbField::tpInt4 			    || type == dbField::tpInt8))		    || (left->type == tpReal 			&& (type == dbField::tpReal4			    || type == dbField::tpReal8))		    || (left->type == tpString && type == dbField::tpString)		    || (left->type == tpReference 			&& type == dbField::tpReference))		{		    left = new dbExprNode(dbvmInArrayBool + type, left, right);		} else {		    error("Type of selective expression of IN operator doesn't"			  " match type of the array");		}		break;	      case tpString:		if (left->type == tpString) { 		    left = new dbExprNode(dbvmInString, left, right);		} else { 		    error("Left operand of IN expression hasn't string type");		}		break;	      case tpList:		compare(left, right);		left = right;		break;	      default:		error("List of expressions or array expected", rightPos);	    }	} else if (cop == tkn_between) { 	    int andPos = currPos;	    if (lex != tkn_and) { 		error("AND expected");	    }	    dbExprNode* right2 = addition();	    if (left->type == tpReal 		|| right->type == tpReal || right2->type == tpReal)	    {		if (left->type == tpInteger) { 		    left = int2real(left);		} else if (left->type != tpReal) { 		    error("operand of BETWEEN operator should be of "			  "integer, real or string type", leftPos);		}

⌨️ 快捷键说明

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