`

递归下降分析的计算算术表达式的解释器

阅读更多
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <functional>
#include <string>
#include <map>
#include <iostream>
using namespace std;
#define ID 1
#define ERROR 255

enum TYPE{
	INT=1,
	FLOAT,
	CHAR,
};
struct Value{
	TYPE type;
	union {
		int v1;
		double v2;
		char *v3;
	};
	template<typename T>

	void setValue(T v){
		if(type == FLOAT){
			v2 =v;
		}
		else if(type==INT){
			v1=v;
		}
	}
	template<typename T>
	T getValue(T x){
		if(type == FLOAT){
			return v2;
		}
		else if(type==INT){
			return v1;
		}
	}
};
struct Expression{
	enum{

		NUM_INT =2,
		NUM_FLOAT
		, PLUS 
		, MINUS // ‘-‘
		, TIMERS // ‘*’
		, OVER // ‘/’
		, LPAREN // ‘(‘
		, RPAREN // ‘)’
		, MOD,
		NOT,
		LOGIC_NOT,
		LOGIC_AND,
		LOGIC_OR,
		LOGIC_XOR,
		ASSIGN,
		LT,
		GT,
		//占2个字符
		AND,
		OR,
		LE,
		GE,
		EQ,
		NE,

	}

	;

	char *nextchar;
	string token;
	void settoken( char* expr){
		token=expr;
		nextchar=expr;
	}

	int gettoken()
	{

		while(isspace(*nextchar)){
			nextchar++;
		}
		switch(*nextchar)
		{
		case '+': nextchar++; return PLUS;
		case '-': nextchar++; return MINUS;
		case '*': nextchar++; return TIMERS;
		case '/': nextchar++; return OVER;
		case '%': nextchar++; return MOD;
		case '(': nextchar++; return LPAREN;
		case ')': nextchar++; return RPAREN;

		case '&':nextchar++;
			if(*nextchar=='&'){nextchar++;return AND;}
			else {
				return LOGIC_AND;
			}

		case '!':nextchar++; 
			if(*nextchar=='='){
				nextchar++;return NE;}
			else {
				return NOT;
			}

		case '|':nextchar++; 
			if(*nextchar=='|'){
				nextchar++;return OR;}
			else {
				return LOGIC_OR;
			}
		case '<':nextchar++; 
			if(*nextchar=='='){
				nextchar++;return LE;}
			else {
				return LT;
			}

		case '>':nextchar++; 
			if(*nextchar=='='){
				nextchar++;return GE;}
			else {
				return GT;
			}
		case '=':nextchar++; 
			if(*nextchar=='='){
				nextchar++;return EQ;}
			else {
				return ASSIGN;
			}


		default: break;
		}
		if(isalpha(*nextchar))
		{
			char *beg = nextchar;
			char *end= nextchar;
			while(isalpha(*nextchar) || isdigit(*nextchar))
			{
				nextchar++;
			}
			PRINT_TOKEN(beg,end);
			token=(beg,end);
			return ID;
		}
		// NUM 的词法识别分析
		// NUM := 0(X|x)[digit|A-F|a-f]+
		// NUM := [digit]+
		// NUM := [digit]* \.[digit]+
		char *last = nextchar;
		if(isdigit(*nextchar))
		{
			char *beg = nextchar;
			char *end= nextchar;
			int digitType=0;

			//是16进制么
			if(*nextchar=='0'&& (*(1+nextchar)=='x'||*(1+nextchar)=='X'))
			{
				nextchar +=2;
				//beg=nextchar;
				while(isdigit(*nextchar) ||(*nextchar>='a'&& *nextchar<='f')||(*nextchar>='A'&& *nextchar<='F')){
					nextchar++;
					end++;
				}
			}

			else{
				if(*nextchar=='0' && *(nextchar+1)!=NULL && (*(1+nextchar)!='x'||*(1+nextchar)!='X')){
					fprintf(stderr,"not support 8 decimal,%s ",nextchar);
				}
				int dotOccur=0;
				while(isdigit(*nextchar) ||(*nextchar=='.'&&dotOccur==0))
				{
					if(*nextchar=='.')
					{
						dotOccur=1;
					}
					nextchar++;
					end++;
				}
				if(dotOccur==0){
					digitType= INT;
				}
				else{
					digitType=FLOAT;
				}
			}
			PRINT_TOKEN(beg,end);
			if(beg==end){
				fprintf(stderr,"parse error: %s",beg);
			}
			token= string(beg,end);
			if(digitType==INT){
				return NUM_INT;
			}
			else{
				return NUM_FLOAT;
			}
		}
		return ERROR;
	}
	//E := T+E |T
	//T := F*T | F
	//F := (E)|(!E)|ID

	void Statements(){
		//Statements = [statement]+
	}
	void Statement(){
		//S :=;|{}
		//IF_STATEMENT='if'S;
		//ELSE_STATEMENT='else'S;
		//EXPR_STATEMENT=E;
		//BLOCK_STATEMENT ={S}

	}
	Value Assign(){
		// id=E();
		char *last = nextchar;
		int leftType = gettoken();
		bool flag=false;

		string id;
		if(leftType==ID){
			id = token;
			int opType = gettoken();
			if(opType == ASSIGN){
				flag=true;
			}
		}
		if(flag){
			Value val = Assign();
			symTable[id]=val;
			return val;
		}
		else{
			nextchar = last;
			return E();
		}
		
	}
	Value E()
	{
		//bug:二元运算符的字符个数 ^=,^,赋值运算符=和==
		Value left = T(); // 对应文法中的第一个Term
		Value r;
		int tokentype;
		while(*nextchar == '+' || *nextchar == '-' ||
			*nextchar == '|' || *nextchar == '^'
			|| *nextchar=='<' || *nextchar=='>' ||
			*nextchar == '='||
			(*nextchar == '!'&&*(nextchar+1)=='=')
			)
		{
			tokentype = gettoken();
			switch(tokentype)
			{
			case PLUS:
				//printf("PLUS");
				r = T();
				{
					Value result;
					result.type = (r.type ==FLOAT||left.type == FLOAT)?FLOAT:INT;
					result.setValue(left.getValue(left.type==INT?1:0.1) + r.getValue(r.type==INT?1:0.1));
					left = result;
				}
				break;
			case MINUS:
				//printf("MINUS");
				r = T();
				{
					Value result;
					result.type = (r.type ==FLOAT||left.type == FLOAT)?FLOAT:INT;
					result.setValue(left.getValue(left.type==INT?1:0.1) - r.getValue(r.type==INT?1:0.1));
					left = result;
				}
				break;
			case LOGIC_OR:
				//printf("LOGIC_OR");
				r = T();
				if(r.type ==FLOAT||left.type == FLOAT){
					fprintf(stderr,"error, not support float LOGIC_OR");
				}
				{
					Value result;
					result.type = INT;
					result.setValue((int)left.getValue(left.type==INT?1:0.1) | (int)r.getValue(r.type==INT?1:0.1));
					left = result;
				}
				break;
			case LOGIC_XOR:
				r = T();
				if(r.type ==FLOAT||left.type == FLOAT){
					fprintf(stderr,"error, not support Float XOR");
				}
				{
					Value result;
					result.type = INT;
					result.setValue((int)left.getValue(left.type==INT?1:0.1) ^(int) r.getValue(r.type==INT?1:0.1));
					left = result;
				}
				break;
			case OR:
				r = T();
				if(r.type ==FLOAT||left.type == FLOAT){
					fprintf(stderr,"error, not support Float OR");
				}
				{
					Value result;
					result.type = INT;
					result.setValue((int)left.getValue(left.type==INT?1:0.1) || (int)r.getValue(r.type==INT?1:0.1));
					left = result;
				}				
				break;
			case LT:
				//printf("LT");

				r = T();
				{
					Value result;
					result.type = INT;
					result.setValue(left.getValue(left.type==INT?1:0.1) < r.getValue(r.type==INT?1:0.1));
					left = result;
				}
				break;
			case LE:
				r = T();
				//printf("LE");
				{
					Value result;
					result.type = INT;
					result.setValue(left.getValue(left.type==INT?1:0.1) <= r.getValue(r.type==INT?1:0.1));
					left = result;
				}
				break;
			case GT:
				r = T();
				//printf("GT");
				{
					Value result;
					result.type = INT;
					result.setValue(left.getValue(left.type==INT?1:0.1) > r.getValue(r.type==INT?1:0.1));
					left = result;
				}
				break;
			case GE:
				r= T();
				{
					Value result;
					result.type = INT;
					result.setValue(left.getValue(left.type==INT?1:0.1) >= r.getValue(r.type==INT?1:0.1));
					left = result;
				}
				break;
			case NE:
				r = T();
				{
					Value result;
					result.type = INT;
					result.setValue(left.getValue(left.type==INT?1:0.1) != r.getValue(r.type==INT?1:0.1));
					left = result;
				}
				break;
			default:
				break;
			}
		}
		return left;
	}
	Value T()
	{
		Value left;
		int tokentype;
		left = F(); 
		Value r;
		while(*nextchar == '*' || *nextchar == '/' ||  *nextchar == '%' || *nextchar == '&' ) 
		{
			tokentype =gettoken();

			switch(tokentype)
			{
			case TIMERS:
				//printf("TIMERS");
				r = T();
				{
					Value result;
					result.type = (r.type ==FLOAT||left.type == FLOAT)?FLOAT:INT;
					result.setValue(left.getValue(left.type==INT?1:0.1) * r.getValue(r.type==INT?1:0.1));
					left = result;
				}

				break;
			case OVER:
				r = T();
				{								
					Value result;
					result.type = (r.type ==FLOAT||left.type == FLOAT)?FLOAT:INT;
					result.setValue(left.getValue(left.type==INT?1:0.1) / r.getValue(r.type==INT?1:0.1));
					left = result;
				}

				break;
			case MOD:
				r = T();
				if(r.type ==FLOAT||left.type == FLOAT){
					fprintf(stderr,"not support float % operator");
					//left.type == FLOAT;
					//left.setValue(left.getValue() %r.getValue());
				}
				{
					Value result;
					result.type = INT;
					result.setValue((int)left.getValue(left.type==INT?1:0.1) %(int) r.getValue(r.type==INT?1:0.1));
					left = result;
				}

				break;
			case LOGIC_AND:
				r = T();
				if(r.type ==FLOAT||left.type == FLOAT){
					fprintf(stderr,"not support float & operator");
					//left.type == FLOAT;
					//left.setValue(left.getValue() %r.getValue());
				}
				{
					Value result;
					result.type = INT;
					result.setValue((int)left.getValue(left.type==INT?1:0.1) &(int) r.getValue(r.type==INT?1:0.1));
					left = result;
				}
				break;
			case AND:
				//printf("AND");
				r = T();
				{
					Value result;
					result.type = INT;
					result.setValue((int)left.getValue(left.type==INT?1:0.1) &&(int) r.getValue(r.type==INT?1:0.1));
					left = result;
				}

				break;
			default:
				break;
			}
		}
		return left;
	}

	Value F()
	{
		Value number;
		switch(gettoken())
		{
		case ID: 
			//printf("ID");
			//number《-- 赋值id
			number = symTable[token];
			break;
		case NUM_INT:
			//printf("NUM");
			if(token[0]=='0' && token.size()>3 && (token[1]=='X'||token[1]=='x'))
			{
				number.type = INT;
				int v;
				sscanf(token.c_str(),"%x",&v);
				number.setValue(v);

			}else
			{
				number.type=INT;
				number.setValue(atoi(token.c_str()));
			}

			break;
		case NUM_FLOAT:
			number.type=FLOAT;
			number.setValue(atof(token.c_str()));
			break;
		case LPAREN:
			//printf("LPAREN");
			number = E();
			if(gettoken()
				!= RPAREN){
					printf("lost ')' in the expression \n");
			}
			break;
		case NOT:
			//printf("NOT");
			number = F();			
			
			number.setValue(!(int)number.getValue(1));
			number.type = INT;
			break;
		case LOGIC_NOT:
			//printf("LOGIC_NOT");
			number =E();
			if(number.type!=INT){
				fprintf(stderr,"not suport FLOAT !");
			}
			number.setValue(~(int)number.getValue(1));
			number.type = INT;
			break;
		case MINUS:
			number =E();
			if(number.type==INT)
			{
				number.setValue(-number.getValue(1));
			}
			else{
				number.setValue(-number.getValue(0.1));
			}
		default:
			break;
		}
		return number;
	}
	void PRINT_TOKEN(const char *beg,const char*end){
		for(const char* p=beg;p!=end;p++){
			//printf("%c",*p);
		}


	}
	map<string,Value> symTable;
};
using namespace std;

int main(int argc,char*argv[])
{

	Expression e;
	e.settoken("3+5*(7+2)");

	Value v ;

	v= e.E();
	if(v.type==INT){
		cout<<"TYPE=INT"<<endl;
	}
	else{
		cout<<"TYPE=FLOAT"<<endl;
	}
	cout<< ((v.type==INT)?v.getValue(1):v.getValue(0.1))<<endl;

	e.settoken("3+5<(7+1.0)");
	v=e.E();
	cout<< ((v.type==INT)?v.getValue(1):v.getValue(0.1))<<endl;
	e.settoken("3+(5.0<(7+1.0))||0");
	v=e.E();
	cout<<"expect:"<<(3+(5.0<(7+1.0))||0)<<"--real:"<< ((v.type==INT)?v.getValue(1):v.getValue(0.1))<<endl;


	e.settoken("3+5.0<=(7+1.0))&&(-7/6.0)<0");
	v=e.E();
	cout<<"expect:"<<(3+5.0<=(7+1.0)&&(-7/6.0)<0)<<"--real:"<<((v.type==INT)?v.getValue(1):v.getValue(0.1))<<endl;
	//printf("\n%d",e.E());

	//单元运算符出错,因为是右结合的,递归下降分析比较复杂
	e.settoken("(-7/6.0)");
	v=e.E();
	cout<<"expect:"<<(-7/6.0)<<"--real:"<<((v.type==INT)?v.getValue(1):v.getValue(0.1))<<endl;

	e.settoken("-(7/6.0)");
	v=e.E();
	cout<<"expect:"<<-(7/6.0)<<"--real:"<<((v.type==INT)?v.getValue(1):v.getValue(0.1))<<endl;


	e.settoken("-3+5");
	v=e.E();
	cout<<"expect:"<<-3+5<<"--real:"<<((v.type==INT)?v.getValue(1):v.getValue(0.1))<<endl;


	e.settoken("!3+9");
	v=e.E();
	cout<<"expect:"<<!3+9<<"--real:"<<((v.type==INT)?v.getValue(1):v.getValue(0.1))<<endl;


	e.settoken("!(3+9)");
	v=e.E();
	cout<<"expect:"<<!(3+9)<<"--real:"<<((v.type==INT)?v.getValue(1):v.getValue(0.1))<<endl;

	//e.settoken("3+6==(7+2)");
	//printf("\n%d",e.E());

	getchar();
	return 0;
}

 

上周五闲着无事,重新写了算术表达式,采用C/C++表达,目前支持 +,-,* 、%,()括号,运算符优先级

,同时支持整形和浮点型。

 

思路:

(1)递归下降分析,属性制导翻译(没有完全实现,但实现了部分,继承属性,综合属性)

E=T|T+E

T=T*F

F=id|(E)|-E|!E

(2)其实也支持其他很多运算符,如:比较运算符,(但没有特别处理运算符优先级,因此会出错,比如3<5+7,会翻译成(3<5)+7;逻辑运算符

(3)调用E()函数得到的是算术表达式的值,有机会的话,改造成,支持多个语句,以及语句块,嗯,用YacC和Lex试试。

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics