从头开始搭建算式表达式解析器,第四部分

这一部分,是解析器的具体实现了。

GetLequ将字符串转化为Atom链表

TryLequ是分析运算符、函数、括号、逗号、数字和变量的排布和数量,排除错误算式

AsmLequ则是对Atom链表进行组装,从开始每个链表的节点只包含一个Atom,变成每个节点包含一个算式树,最后可能会有多个节点,也就是返回多个值,如果你使用逗号分隔多个算式的话。构树是采用的后缀表达式法,也就是在翻译为后缀表达式的过程中,直接就构树了,规则十分简单:

两个栈(算式树栈:E、运算符栈:O),一个队列(上面的Atom链表:A)

从A依次获得Atom:

1)如果是变量或者数值,直接入E
2)函数、算符,要入O,在入之前,坚持O中的算符,根据优先级(函数最高,一元算符和函数一样高,二元算符依次是('*' , '/') > ('+' , '-') > ('>' , '>=' , '<' , '<=' , '==' , '!=') > ('&&' , '||'),赋值运算符优先级都相同且低于二元算符,左括号和逗号最小)
        1>函数和运算符是左结合,因此要把优先级不低于要入栈函数/算符的O中元素依次出栈入E。
        2>赋值运算符是右结合,,因此要把优先级要入栈函数/算符的O中元素依次出栈入E。
3)如果是逗号,则从O中出栈到E一直到左括号,但左括号不出栈,逗号不入栈
4)如果是右括号,则从O中出栈到E一直到左括号,左括号出栈,右括号不入栈
5)A中Atom读取结束后,将O中元素依次出栈入E
6)如果要获得后缀表达式,那么在入E时就不需要操作,如果要获得算式树,那么在O中元素入E时,要作:
        1>一元函数、一元算符,以E栈顶Atom为算符左子,然后E栈顶出栈,算符入栈
        2>二元函数、二元算符、赋值算符,以E栈顶Atom为算符右子,E出栈,新栈顶为算符左子,E再出栈,算符入栈

至于检验算式就很好说了,规则很多,但是很简单,大家看看算式就可以理解了,我的函数也是看着复杂,一堆switch-casr,但其实表达的东西就是那些,只是单纯的堆积代码而已。我事先检验,主要是为了避免搭建时发现错误不太好删除错误算式,但其实也可以在搭建算式时进行验证的。

好了,下面是代码:


Lequ *GetLequ(char *str)
{
	Lequ *sp,rt;
	int j;
	sp=&rt;
	while(1)
	{
		while(*str==' ' || *str=='	')str++;
		if(*str)
		{
			sp->nxt=new Lequ;
			sp->nxt->lst=sp;
			sp=sp->nxt;
			sp->equ=new Atom;
			j=GetAtom(str,sp->equ);
			if(j==0)
			{
				RemoveLequ(rt.nxt);
				return 0;
			}
			str+=j;
		}
		else break;
	}
	rt.nxt->lst=NULL;
	return rt.nxt;
}
bool TryLequ(Lequ *ary)
{
	Lequ *sp,*sq;
	int i,j;
	switch(ary->equ->type)
	{
		case Is_Rquot:
		case Is_Comma:
		case Is_Opr2p:
		case Is_Setvr:
			return false;
		break;
		default:break;
	}
	sp=ary,ary=sp->nxt;
	while(ary)
	{
		switch(ary->equ->type)
		{
			case Is_Lquot:
				switch(sp->equ->type)
				{
					case Is_Rquot:
					case Is_Value:
					case Is_Param:
						return false;
					break;
					default:break;
				}
				sq=ary->nxt;
				i=1,j=0;
				while(i && sq)
				{
					switch(sq->equ->type)
					{
						case Is_Lquot:i++;
						break;
						case Is_Comma:j++;
						break;
						case Is_Rquot:i--;
						break;
						default:break;
					}
					sq=sq->nxt;
				}
				if(i)
				{
					return false;
				}
				else
				{
					if(ary->lst && ary->lst->equ->type==Is_Fun2p)
					{
						if(j!=1)return false;
					}
					else
					{
						if(j!=0)return false;
					}
				}
			break;
			case Is_Comma:
				switch(sp->equ->type)
				{
					case Is_Comma:
					case Is_Fun1p:
					case Is_Fun2p:
					case Is_Opr1p:
					case Is_Opr2p:
					case Is_Setvr:
						return false;
					break;
					default:break;
				}
			break;
			case Is_Rquot:
				switch(sp->equ->type)
				{
					case Is_Comma:
					case Is_Fun1p:
					case Is_Fun2p:
					case Is_Opr1p:
					case Is_Opr2p:
					case Is_Setvr:
						return false;
					break;
					default:break;
				}
				i=1,sq=sp;
				while(i && sq)
				{
					switch(sq->equ->type)
					{
						case Is_Lquot:i--;
						break;
						case Is_Rquot:i++;
						break;
						default:break;
					}
					sq=sq->lst;
				}
				if(i)return false;
			break;
			case Is_Value:
			case Is_Param:
			case Is_Opr1p:
				switch(sp->equ->type)
				{
					case Is_Rquot:
					case Is_Value:
					case Is_Param:
					case Is_Fun1p:
					case Is_Fun2p:
						return false;
					break;
					default:break;
				}
			break;
			case Is_Fun1p:
			case Is_Fun2p:
				switch(sp->equ->type)
				{
					case Is_Rquot:
					case Is_Value:
					case Is_Param:
					case Is_Fun1p:
					case Is_Fun2p:
						return false;
					break;
					default:break;
				}
				if(ary->nxt==NULL || ary->nxt->equ->type!=Is_Lquot)return false;
			break;
			case Is_Opr2p:
				switch(sp->equ->type)
				{
					case Is_Lquot:
					case Is_Comma:
					case Is_Fun1p:
					case Is_Fun2p:
					case Is_Opr1p:
					case Is_Opr2p:
					case Is_Setvr:
						return false;
					break;
					default:break;
				}
			break;
			case Is_Setvr:
				switch(sp->equ->type)
				{
					case Is_Lquot:
					case Is_Comma:
					case Is_Fun1p:
					case Is_Fun2p:
					case Is_Opr1p:
					case Is_Opr2p:
					case Is_Setvr:
						return false;
					break;
					default:break;
				}
				sq=ary->lst;
				if(sq==NULL || sq->equ->type!=Is_Param)return false;
				while(sq && sq->equ->type!=Is_Lquot && sq->equ->type!=Is_Comma)
				{
					switch(sq->equ->type)
					{
						case Is_Rquot:
						case Is_Value:
						case Is_Fun1p:
						case Is_Fun2p:
						case Is_Opr1p:
						case Is_Opr2p:
							return false;
						break;
						default:break;
					}
				}
			break;
			default:break;
		}
		sp=ary,ary=ary->nxt;
	}
	switch(sp->equ->type)
	{
		case Is_Lquot:
		case Is_Comma:
		case Is_Opr2p:
		case Is_Setvr:
		case Is_Fun1p:
		case Is_Fun2p:
			return false;
		break;
		default:break;
	}
	return true;
}
Lequ *AsmLequ(Lequ *ori)
{
	Lequ rt,op,*pe,*po,*sp;
	int i;
	
	if(sp=ori)
	{
		pe=&rt;
		po=&op; 
		while(sp)
		{
			switch(sp->equ->type)
			{
				case Is_Lquot:
					po->nxt=sp;
					sp->lst=po;
					po=sp;
					sp=sp->nxt;
					sp->lst=NULL;
					po->nxt=NULL;
				break;
				case Is_Comma:
					while(po!=&op && po->equ->type!=Is_Lquot)
					{
						switch(po->equ->type)
						{
							case Is_Fun1p:
							case Is_Opr1p:
								po->equ->Lsun=pe->equ;
								pe->equ=po->equ;
								po=po->lst;
								delete po->nxt;
								po->nxt=NULL;
							break;
							case Is_Fun2p:
							case Is_Opr2p:
							case Is_Setvr:
								po->equ->Lsun=pe->lst->equ;
								po->equ->Rsun=pe->equ;
								pe->lst->equ=po->equ;
								po=po->lst;
								pe=pe->lst;
								delete po->nxt;
								delete pe->nxt;
								po->nxt=NULL;
								pe->nxt=NULL;
							break;
							default:break;
						}
					}
					sp=sp->nxt;
					delete sp->lst;
					sp->lst=NULL;
				break;
				case Is_Rquot:
					while(po!=&op && po->equ->type!=Is_Lquot)
					{
						switch(po->equ->type)
						{
							case Is_Fun1p:
							case Is_Opr1p:
								po->equ->Lsun=pe->equ;
								pe->equ=po->equ;
								po=po->lst;
								delete po->nxt;
								po->nxt=NULL;
							break;
							case Is_Fun2p:
							case Is_Opr2p:
							case Is_Setvr:
								po->equ->Lsun=pe->lst->equ;
								po->equ->Rsun=pe->equ;
								pe->lst->equ=po->equ;
								po=po->lst;
								pe=pe->lst;
								delete po->nxt;
								delete pe->nxt;
								po->nxt=NULL;
								pe->nxt=NULL;
							break;
							default:break;
						}
					}
					if(sp->nxt)
					{
						sp=sp->nxt;
						delete sp->lst;
						sp->lst=NULL;
					}
					else
					{
						delete sp;
						sp=NULL;
					}
					po=po->lst;
					delete po->nxt;
					po->nxt=NULL;
				break;
				case Is_Value:
				case Is_Param:
					pe->nxt=sp;
					sp->lst=pe;
					pe=sp;
					if(sp->nxt)
					{
						sp=sp->nxt;
						sp->lst=NULL;
					}
					else
					{
						sp=NULL;
					}
					pe->nxt=NULL;
				break;
				case Is_Fun1p:
				case Is_Opr1p:
				case Is_Fun2p:
				case Is_Opr2p:
					i=GetRight(sp->equ);
					while(po!=&op && GetRight(po->equ)>=i)
					{
						switch(po->equ->type)
						{
							case Is_Fun1p:
							case Is_Opr1p:
								po->equ->Lsun=pe->equ;
								pe->equ=po->equ;
								po=po->lst;
								delete po->nxt;
								po->nxt=NULL;
							break;
							case Is_Fun2p:
							case Is_Opr2p:
							case Is_Setvr:
								po->equ->Lsun=pe->lst->equ;
								po->equ->Rsun=pe->equ;
								pe->lst->equ=po->equ;
								po=po->lst;
								pe=pe->lst;
								delete po->nxt;
								delete pe->nxt;
								po->nxt=NULL;
								pe->nxt=NULL;
							break;
							default:break;
						}
					}
					po->nxt=sp;
					sp->lst=po;
					po=sp;
					sp=sp->nxt;
					po->nxt=NULL;
					sp->lst=NULL;
				break;
				case Is_Setvr:
					i=GetRight(sp->equ);
					while(po!=&op && GetRight(po->equ)>i)
					{
						switch(po->equ->type)
						{
							case Is_Fun1p:
							case Is_Opr1p:
								po->equ->Lsun=pe->equ;
								pe->equ=po->equ;
								po=po->lst;
								delete po->nxt;
								po->nxt=NULL;
							break;
							case Is_Fun2p:
							case Is_Opr2p:
							case Is_Setvr:
								po->equ->Lsun=pe->lst->equ;
								po->equ->Rsun=pe->equ;
								pe->lst->equ=po->equ;
								po=po->lst;
								pe=pe->lst;
								delete po->nxt;
								delete pe->nxt;
								po->nxt=NULL;
								pe->nxt=NULL;
							break;
							default:break;
						}
					}
					po->nxt=sp;
					sp->lst=po;
					po=sp;
					sp=sp->nxt;
					po->nxt=NULL;
					sp->lst=NULL;
				break;
				default:break;
			}
		}
		while(po!=&op)
		{
			switch(po->equ->type)
			{
				case Is_Fun1p:
				case Is_Opr1p:
					po->equ->Lsun=pe->equ;
					pe->equ=po->equ;
					po=po->lst;
					delete po->nxt;
					po->nxt=NULL;
				break;
				case Is_Fun2p:
				case Is_Opr2p:
				case Is_Setvr:
					po->equ->Lsun=pe->lst->equ;
					po->equ->Rsun=pe->equ;
					pe->lst->equ=po->equ;
					po=po->lst;
					pe=pe->lst;
					delete po->nxt;
					delete pe->nxt;
					po->nxt=NULL;
					pe->nxt=NULL;
				break;
				default:break;
			}
		}
		rt.nxt->lst=NULL;
		return rt.nxt;
	}
	return NULL;
}


你可能感兴趣的:(从头开始搭建算式表达式解析器,第四部分)