#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试试。