📄 compiler.cpp
字号:
//-< 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};bool dbCompiler::initialized;dbExprNodeAllocator dbExprNodeAllocator::instance; dbExprNodeAllocator::~dbExprNodeAllocator() { dbExprNodeSegment* segm = segmentList; while (segm != NULL) { dbExprNodeSegment* next = segm->next; delete segm; segm = next; }}inline dbExprNode* dbExprNodeAllocator::allocate(){ dbCriticalSection cs(mutex); dbExprNode* node = freeNodeList; if (node == NULL) { dbExprNodeSegment* seg = new dbExprNodeSegment; seg->next = segmentList; segmentList = seg; node = (dbExprNode*)seg->buf; dbExprNode* free = NULL; for (int i = dbExprNodeSegment::allocationQuantum; --i != 0;) { node->next = free; free = node++; } freeNodeList = free; } else { freeNodeList = node->next; } return node;}void dbExprNodeAllocator::deallocate(dbExprNode* node){ if (node != NULL) { node->next = freeNodeList; freeNodeList = node; }}void dbExprNodeAllocator::reset(){ dbExprNode* free = NULL; for (dbExprNodeSegment* seg = segmentList; seg != NULL; seg = seg->next) { dbExprNode* node = (dbExprNode*)seg->buf; for (int i = dbExprNodeSegment::allocationQuantum; --i >= 0;) { node->next = free; free = node++; } } freeNodeList = free;}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; } }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]; if (hasToken) { hasToken = false; return lex; } 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 == tpReference) { expr = new dbExprNode(dbvmIntToReference, expr); cop = dbvmEqReference; } 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 || elem->type == tpInteger)) { if (elem->type == tpInteger) { elem = new dbExprNode(dbvmIntToReference, elem); } cop = dbvmEqReference; } else if (expr->type == tpBoolean && elem->type == tpBoolean) { cop = dbvmEqBool; } else if (expr->type == tpRawBinary && elem->type == tpRawBinary) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -