简化版本 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
posted @ 2023-12-23 16:48  Xi'En  阅读(238)  评论(4编辑  收藏  举报