简化版本 SQL-Minus 解释器
update:
诶我去,怎么这么多人看
哦,原来是我抄了一遍标题,哈哈
就当你被骗了吧
先扔一下我们伟大的助教提供的题面。
注:以下做法仅供娱乐,大多数都十分复杂且低效,请尽量不要尝试。
CREATE TABLE
考虑实现一个 array<ValEx>
。
初始化时由于字段数未知,需要实现一个 list<ValEx>
来支持插入,最后将其转为 array<ValEx>
。
INSERT
考虑实现一个 vector<array<Val>>
。
需要实现一个 list<Val>
来支持插入,最后将其转为 array<Val>
。
另一种实现方式可以使用 array<vector<Val>>
,即在字段列表后逐一 append 数据,这样可以省去 list<Val>
。
WHERE (<condition_clause>)
考虑对给出的条件子句构造一棵表达式树,每次递归求值。
建树后,进行一次类型推导判断是否 ERROR。
Parsing
为了保证 SYNTAX ERROR 返回及时,且内存利用充分,考虑动态构造上述的 list<>
,并且随时准备报错并手动析构现有数据。
实现细节
尽量使用指针来做到动态构造、析构。
为了保持代码朴素,尽量减少不必要的封装,多使用裸露的 malloc 和 free。(指针类型自行推导)
目前的进度
neix@MetallicBrick:/cplcode$ cd projekt-01
neix@MetallicBrick:/cplcode/projekt-01$ ls
__main_discarded_0.c __main_discarded_1.c
不想写了于是把代码扔到这里
还剩几个操作没写,但是看申必解析标准不爽,遂弃
db bnf 啥的都写好了,比较现成。bnf 求值那里可能需要加一个 syntax error 的状态,然后解析再搞搞。懒了。
// START SEGMENT BNF
enum triBool{
triTrue=1847,
triFalse,
triUnknown,
triError=-1847
};
enum triBool triAnd(enum triBool a,enum triBool b){
if(a==triTrue&&b==triTrue){return triTrue;}
if(a==triFalse||b==triFalse){return triFalse;}
return triUnknown;
}
enum triBool triOr(enum triBool a,enum triBool b){
if(a==triFalse&&b==triFalse){return triFalse;}
if(a==triTrue||b==triTrue){return triTrue;}
return triUnknown;
}
enum triBool triNot(enum triBool a){
if(a==triFalse){return triTrue;}
if(a==triTrue){return triFalse;}
return triUnknown;
}
enum BNFObjectTypeEnum{
BNFFuncAnd=114, // (bool,bool) -> bool
BNFFuncOr, // (bool,bool) -> bool
BNFFuncNot, // (bool) -> bool
// cmp
BNFFuncEq, // (ordered<T>,ordered<T>) -> bool
BNFFuncNeq, // (ordered<T>,ordered<T>) -> bool
BNFFuncLess, // (ordered<T>,ordered<T>) -> bool
BNFFuncGreater, // (ordered<T>,ordered<T>) -> bool
BNFFuncLeq, // (ordered<T>,ordered<T>) -> bool
BNFFuncGeq, // (ordered<T>,ordered<T>) -> bool
// range
BNFFuncBetween, // (ordered<T>,range<T>) -> bool
BNFFuncRange, // (ordered<T>,ordered<T>) -> range<T>
BNFFuncIsNull, // (ordered<T>) -> bool
BNFFuncIsNotNull, // (ordered<T>) -> bool
BNFOrdered, // ordered<T>
BNFRange, // range<T>
BNFBool, // bool
BNFDelay, // '('
BNFContinue // ')'
};
struct _BNFObject{
enum BNFObjectTypeEnum type;
// <T>
enum valTypeEnum valType;
// ordered
int dataNull;
int requireEval,requireIndex;
int dataInt;
char *dataChar; // always shallow copy
// range
int dataNullRange;
int dataIntRange[2];
char *dataCharRange[2];
// value bool
enum triBool dataBool;
};
void evalVal_BNFObject(struct _BNFObject *dest,struct _ValArray *src){
if(dest->requireEval){dest->requireEval=0;}else{return;}
// DEBUG_DO{printf("req_index=%d\n",dest->requireIndex);}
if(dest->valType==intType){
dest->dataNull=src->data[dest->requireIndex].dataNull;
dest->dataInt=src->data[dest->requireIndex].dataInt;
}else{
dest->dataNull=src->data[dest->requireIndex].dataNull;
dest->dataChar=src->data[dest->requireIndex].dataChar;
}
// DEBUG_DO{printf("req_complete.\n");}
}
void clear_BNFObject(struct _BNFObject *dest){
memset(dest,0,sizeof(struct _BNFObject));
}
struct _BNFStack{
int top;
struct _BNFObject stack[512];
};
void init_BNFStack(struct _BNFStack *p){p->top=0;}
void push_BNFStack(struct _BNFStack *p,struct _BNFObject src){p->stack[++p->top]=src;}
void pop_BNFStack(struct _BNFStack *p){if(p->top){p->top--;}else{fprintf(stderr,"[?] pop on empty stack\n");}}
int isEmpty_BNFStack(struct _BNFStack *p){if(p->top){return 0;}else{return 1;}}
struct _BNFObject getTop_BNFStack(struct _BNFStack *p){if(p->top){return p->stack[p->top];}else{fprintf(stderr,"[?] getTop on empty stack\n");return p->stack[p->top];}}
int getPriority(enum BNFObjectTypeEnum type){
if(type==BNFFuncRange )return 7;
if(type==BNFFuncBetween )return 6;
if(type==BNFFuncEq )return 5;
if(type==BNFFuncNeq )return 5;
if(type==BNFFuncLess )return 5;
if(type==BNFFuncGreater )return 5;
if(type==BNFFuncLeq )return 5;
if(type==BNFFuncGeq )return 5;
if(type==BNFFuncIsNull )return 4;
if(type==BNFFuncIsNotNull )return 4;
if(type==BNFFuncNot )return 3;
if(type==BNFFuncAnd )return 2;
if(type==BNFFuncOr )return 1;
if(type==BNFOrdered ){fprintf(stderr,"[?] get priority on value\n");return -1;}
if(type==BNFRange ){fprintf(stderr,"[?] get priority on value\n");return -1;}
if(type==BNFBool ){fprintf(stderr,"[?] get priority on value\n");return -1;}
return 0;
}
/* DEBUG START */
void printVal(struct _BNFObject dest){
if(dest.type==BNFOrdered){
if(dest.valType==intType ){fprintf(stderr," [int: ");}
if(dest.valType==charType ){fprintf(stderr," [char: ");}
if(dest.dataNull==1 ){fprintf(stderr,"NULL]");return;}
if(dest.valType==intType ){fprintf(stderr,"%d]",dest.dataInt);}
if(dest.valType==charType ){fprintf(stderr,"%s]",dest.dataChar);}
}
if(dest.type==BNFRange){
if(dest.valType==intType ){fprintf(stderr," [int: ");}
if(dest.valType==charType ){fprintf(stderr," [char: ");}
if(dest.dataNullRange==1 ){fprintf(stderr,"NULL]");return;}
if(dest.valType==intType ){fprintf(stderr,"%d %d]",dest.dataIntRange[0],dest.dataIntRange[1]);}
if(dest.valType==charType ){fprintf(stderr,"%s %s]",dest.dataCharRange[0],dest.dataCharRange[1]);}
}
if(dest.type==BNFBool){
if(dest.dataBool==triTrue ){fprintf(stderr," [triTrue]");}
if(dest.dataBool==triFalse ){fprintf(stderr," [triFalse]");}
if(dest.dataBool==triUnknown){fprintf(stderr," [triUnknown]");}
if(dest.dataBool==triError ){fprintf(stderr," [triError]");}
}
}
void printTypeVal(struct _BNFObject dest){
if(dest.type==BNFDelay ){fprintf(stderr,"BNFDelay");}
if(dest.type==BNFContinue ){fprintf(stderr,"BNFContinue");}
if(dest.type==BNFFuncRange ){fprintf(stderr,"BNFFuncRange");}
if(dest.type==BNFFuncBetween ){fprintf(stderr,"BNFFuncBetween");}
if(dest.type==BNFFuncEq ){fprintf(stderr,"BNFFuncEq");}
if(dest.type==BNFFuncNeq ){fprintf(stderr,"BNFFuncNeq");}
if(dest.type==BNFFuncLess ){fprintf(stderr,"BNFFuncLess");}
if(dest.type==BNFFuncGreater ){fprintf(stderr,"BNFFuncGreater");}
if(dest.type==BNFFuncLeq ){fprintf(stderr,"BNFFuncLeq");}
if(dest.type==BNFFuncGeq ){fprintf(stderr,"BNFFuncGeq");}
if(dest.type==BNFFuncIsNull ){fprintf(stderr,"BNFFuncIsNull");}
if(dest.type==BNFFuncIsNotNull ){fprintf(stderr,"BNFFuncIsNotNull");}
if(dest.type==BNFFuncNot ){fprintf(stderr,"BNFFuncNot");}
if(dest.type==BNFFuncAnd ){fprintf(stderr,"BNFFuncAnd");}
if(dest.type==BNFFuncOr ){fprintf(stderr,"BNFFuncOr");}
if(dest.type==BNFOrdered ){fprintf(stderr,"BNFOrdered");printVal(dest);}
if(dest.type==BNFRange ){fprintf(stderr,"BNFRange");printVal(dest);}
if(dest.type==BNFBool ){fprintf(stderr,"BNFBool");printVal(dest);}
}
void printStk(struct _BNFStack *psv,struct _BNFStack *psf){
printf("printStk():{\n\tsv[siz=%d]:{\n",psv->top);
for(int i=1;i<=psv->top;i++){printf("\t\t");printTypeVal(psv->stack[i]);puts("");}
printf("\t},\n\tsf[siz=%d]:{\n",psf->top);
for(int i=1;i<=psf->top;i++){printf("\t\t");printTypeVal(psf->stack[i]);puts("");}
printf("\t}\n}\n");
}
/* DEBUG END */
enum triBool less_BNFOrdered(struct _BNFObject aa,struct _BNFObject bb){
if(aa.dataNull||bb.dataNull)return triUnknown;
if(aa.valType==intType){
return aa.dataInt<bb.dataInt?triTrue:triFalse;
}else{
return strcmp(aa.dataChar,bb.dataChar)<0?triTrue:triFalse;
}
}
enum triBool inRange_BNFRange(struct _BNFObject aa,struct _BNFObject bb){
if(aa.dataNull||bb.dataNullRange)return triUnknown;
if(aa.valType==intType){
return (bb.dataIntRange[0]<=aa.dataInt&&aa.dataInt<=bb.dataIntRange[1])?triTrue:triFalse;
}else{
return (strcmp(bb.dataCharRange[0],aa.dataChar)<0&&strcmp(aa.dataChar,bb.dataCharRange[1])<0)?triTrue:triFalse;
}
}
int evalF(struct _BNFStack *psv,struct _BNFStack *psf,struct _ValArray *srcVal){
if(isEmpty_BNFStack(psf))return triError;
if(getPriority(getTop_BNFStack(psf).type)==-1)return triError;
enum BNFObjectTypeEnum tempFunc=getTop_BNFStack(psf).type;
/* DEBUG_DO{
printf("Eval Type: ");printTypeVal(getTop_BNFStack(psf));puts("");
printStk(psv,psf);
}*/
if( tempFunc==BNFFuncEq||
tempFunc==BNFFuncNeq||
tempFunc==BNFFuncLess||
tempFunc==BNFFuncGreater||
tempFunc==BNFFuncLeq||
tempFunc==BNFFuncGeq){
if( psv->top<3||
psv->stack[psv->top].type!=BNFOrdered||
psv->stack[psv->top-1].type!=tempFunc||
psv->stack[psv->top-2].type!=BNFOrdered||
psv->stack[psv->top].valType!=psv->stack[psv->top-2].valType){
return triError;
}
struct _BNFObject valL,valR,ret;
valR=psv->stack[psv->top];
valL=psv->stack[psv->top-2];
evalVal_BNFObject(&valR,srcVal);
evalVal_BNFObject(&valL,srcVal);
pop_BNFStack(psv);
pop_BNFStack(psv);
pop_BNFStack(psv);
pop_BNFStack(psf);
ret.type=BNFBool;
if(tempFunc==BNFFuncEq )ret.dataBool=triNot(triOr(less_BNFOrdered(valL,valR),less_BNFOrdered(valR,valL)));
else if(tempFunc==BNFFuncNeq )ret.dataBool=triOr(less_BNFOrdered(valL,valR),less_BNFOrdered(valR,valL));
else if(tempFunc==BNFFuncLess )ret.dataBool=less_BNFOrdered(valL,valR);
else if(tempFunc==BNFFuncGreater)ret.dataBool=less_BNFOrdered(valR,valL);
else if(tempFunc==BNFFuncLeq )ret.dataBool=triNot(less_BNFOrdered(valR,valL));
else if(tempFunc==BNFFuncGeq )ret.dataBool=triNot(less_BNFOrdered(valL,valR));
push_BNFStack(psv,ret);
return 0;
}else if(tempFunc==BNFFuncRange){
if( psv->top<3||
psv->stack[psv->top].type!=BNFOrdered||
psv->stack[psv->top-1].type!=tempFunc||
psv->stack[psv->top-2].type!=BNFOrdered||
psv->stack[psv->top].valType!=psv->stack[psv->top-2].valType){
return triError;
}
struct _BNFObject valL,valR,ret;
valR=psv->stack[psv->top];
valL=psv->stack[psv->top-2];
evalVal_BNFObject(&valR,srcVal);
evalVal_BNFObject(&valL,srcVal);
pop_BNFStack(psv);
pop_BNFStack(psv);
pop_BNFStack(psv);
pop_BNFStack(psf);
ret.type=BNFRange;
if(valL.dataNull||valR.dataNull)ret.dataNullRange=1;
else if(valL.valType==intType){ret.valType=intType;ret.dataIntRange[0]=valL.dataInt;ret.dataIntRange[1]=valR.dataInt;}
else if(valL.valType==charType){ret.valType=charType;ret.dataCharRange[0]=valL.dataChar;ret.dataCharRange[1]=valR.dataChar;}
push_BNFStack(psv,ret);
}else if(tempFunc==BNFFuncBetween){
if( psv->top<3||
psv->stack[psv->top].type!=BNFRange||
psv->stack[psv->top-1].type!=tempFunc||
psv->stack[psv->top-2].type!=BNFOrdered||
psv->stack[psv->top].valType!=psv->stack[psv->top-2].valType){
return triError;
}
struct _BNFObject valL,valR,ret;
valR=psv->stack[psv->top];
valL=psv->stack[psv->top-2];
evalVal_BNFObject(&valL,srcVal);
pop_BNFStack(psv);
pop_BNFStack(psv);
pop_BNFStack(psv);
pop_BNFStack(psf);
ret.type=BNFBool;
ret.dataBool=inRange_BNFRange(valL,valR);
push_BNFStack(psv,ret);
}else if( tempFunc==BNFFuncIsNull||
tempFunc==BNFFuncIsNotNull){
if( psv->top<2||
psv->stack[psv->top].type!=tempFunc||
psv->stack[psv->top-1].type!=BNFOrdered){
return triError;
}
struct _BNFObject valL,ret;
valL=psv->stack[psv->top-1];
evalVal_BNFObject(&valL,srcVal);
pop_BNFStack(psv);
pop_BNFStack(psv);
pop_BNFStack(psf);
ret.type=BNFBool;
if(tempFunc==BNFFuncIsNull )ret.dataBool=(valL.dataNull==1)?triTrue:triFalse;
else if(tempFunc==BNFFuncIsNotNull )ret.dataBool=(valL.dataNull==0)?triTrue:triFalse;
push_BNFStack(psv,ret);
}else if( tempFunc==BNFFuncAnd||
tempFunc==BNFFuncOr){
if( psv->top<3||
psv->stack[psv->top].type!=BNFBool||
psv->stack[psv->top-1].type!=tempFunc||
psv->stack[psv->top-2].type!=BNFBool){
return triError;
}
struct _BNFObject valL,valR,ret;
valR=psv->stack[psv->top];
valL=psv->stack[psv->top-2];
pop_BNFStack(psv);
pop_BNFStack(psv);
pop_BNFStack(psv);
pop_BNFStack(psf);
ret.type=BNFBool;
if(tempFunc==BNFFuncAnd)ret.dataBool=triAnd(valL.dataBool,valR.dataBool);
else if(tempFunc==BNFFuncOr )ret.dataBool=triOr(valL.dataBool,valR.dataBool);
push_BNFStack(psv,ret);
}else if( tempFunc==BNFFuncNot){
if( psv->top<2||
psv->stack[psv->top].type!=BNFBool||
psv->stack[psv->top-1].type!=tempFunc){
return triError;
}
struct _BNFObject valR,ret;
valR=psv->stack[psv->top];
pop_BNFStack(psv);
pop_BNFStack(psv);
pop_BNFStack(psf);
ret.type=BNFBool;
ret.dataBool=triNot(valR.dataBool);
push_BNFStack(psv,ret);
}else{
return triError;
}
/*DEBUG_DO{
printf("After Eval:\n");
printStk(psv,psf);
}*/
return triTrue;
}
enum triBool tryEval(struct _BNFObject *src,int cnt,struct _ValArray *srcVal){
struct _BNFStack sv,sf;
init_BNFStack(&sv);
init_BNFStack(&sf);
for(int idx=0;idx<cnt;idx++){
struct _BNFObject *nw=src+idx;
switch(nw->type){
case BNFDelay:{
push_BNFStack(&sv,*nw);
push_BNFStack(&sf,*nw);
break;
}
case BNFOrdered:{
push_BNFStack(&sv,*nw);
break;
}
case BNFContinue:{
while(!isEmpty_BNFStack(&sf)&&getTop_BNFStack(&sf).type!=BNFDelay){
if(evalF(&sv,&sf,srcVal)==triError)return triError;
}
if(isEmpty_BNFStack(&sf))return triError;
if(sv.top<2||sv.stack[sv.top].type!=BNFBool||sv.stack[sv.top-1].type!=BNFDelay)return triError;
struct _BNFObject res=sv.stack[sv.top];
pop_BNFStack(&sv);
pop_BNFStack(&sv);
pop_BNFStack(&sf);
push_BNFStack(&sv,res);
break;
}
case BNFFuncAnd:
case BNFFuncOr:
case BNFFuncNot:
case BNFFuncEq:
case BNFFuncNeq:
case BNFFuncLess:
case BNFFuncGreater:
case BNFFuncLeq:
case BNFFuncGeq:
case BNFFuncBetween:
case BNFFuncRange:
case BNFFuncIsNull:
case BNFFuncIsNotNull:{
// pop until [priority[top_v] <priority[nw]]
while(!isEmpty_BNFStack(&sf)&&getPriority(getTop_BNFStack(&sf).type)>=getPriority(nw->type)){
if(evalF(&sv,&sf,srcVal)==triError)return triError;
}
push_BNFStack(&sv,*nw);
push_BNFStack(&sf,*nw);
break;
}
default:{
return triError;
break;
}
}
}
while(!isEmpty_BNFStack(&sf)){if(evalF(&sv,&sf,srcVal)==triError)return triError;}
if(sv.top!=1){fprintf(stderr,"[!] sv contains more than / no elements\n");return triError;}
if(getTop_BNFStack(&sv).type!=BNFBool){fprintf(stderr,"[!] sv contains non-bool value\n");return triError;}
return getTop_BNFStack(&sv).dataBool;
}
// END SEGMENT BNF