http://acdream.info/problem?pid=1232
手写了一个词法分析引擎。肯定是写麻烦了。
词法分析器Lexer将字符串解析为词法单元。
词法单元Token,储存词法单元的属性和值。
语法分析器Parser,读取词法单元,构建语法树。
表达式结点Expr。
define操作用并查集搞。
print操作用Parser读取一个Expr,然后执行Expr求值。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <string> #include <vector> #include <cmath> using namespace std; const int maxn=411111; int _Cnt; map<string,int>idmap; map<int,int>conmap; int _Pa[maxn]; int _Val[maxn]; void makeset(int i){ _Pa[i]=i; _Val[i]=0; } int findset(int x){ if (x!=_Pa[x]) _Pa[x]=findset(_Pa[x]); return _Pa[x]; } void Define(int x,int y){ if (x!=_Pa[x]) return; x=findset(x); y=findset(y); if (x!=y) _Pa[x]=y; //printf("Pa[%d]=%d\n",x,y); } void SetValue(int x,int v){ _Val[x]=v; } int GetValue(int x){ //printf("GetValue(%d) ",x); //printf("Pa[%d]=%d ",x,_Pa[x]); x=findset(x); //printf("findSet=%d Value=%d\n",x,_Val[x]); return _Val[x]; } int RegistInt(int v){ //printf("Regist Int %d\n",v); map<int,int>::iterator it; it=conmap.find(v); if (it!=conmap.end()){ return it->second; } else{ conmap[v]=++_Cnt; makeset(_Cnt); SetValue(_Cnt,v); return _Cnt; } } int RegistStr(string str){ //printf("Regist Str %s\n",str.c_str()); map<string,int>::iterator it; it=idmap.find(str); if (it!=idmap.end()){ //printf("Find %d\n",it->second); return it->second; } else{ idmap[str]=++_Cnt; makeset(_Cnt); SetValue(_Cnt,0); //printf("Not Fine %d\n",_Cnt); return _Cnt; } } int power(int a,int b){ int ans=1; while(b){ if(b&1) ans=ans*a; a=a*a; b>>=1; } return ans; } class Token { public: enum Tag { Int,Id,Add,Sub,Mul,Div,Mod,Pow,Lp,Rp,Eof }; Token() { type=Eof; } Token(int v) { type=Int; num=v; } Token(char c) { switch (c) { case '+': type=Add; break; case '-': type=Sub; break; case '*': type=Mul; break; case '/': type=Div; break; case '%': type=Mod; break; case '^': type=Pow; break; case '(': type=Lp; break; case ')': type=Rp; break; default: type=Eof; break; } op=c; } Token(char *p) { type=Id; id=p; } Tag type; char op; int num; char *id; }; class Expr { public: Expr() {} virtual int Eval() { return 0; } virtual ~Expr() {} }; class Constant : public Expr { public: Constant(int v) { value=v; } virtual ~Constant() {} virtual int Eval() { int s=RegistInt(value); int v=GetValue(s); //printf("const %d = %d inset num=%d\n",value,v,s); return v; } int value; }; class Id : public Expr { public: Id(string i) : id(i) {} virtual ~Id() {} virtual int Eval() { int s=RegistStr(id); int v=GetValue(s); //printf("Id %s = %d\n",id.c_str(),v); return v;// TODO } string id; }; class Arith : public Expr { public: Arith(char o,Expr* x1,Expr* x2) { op=o; expr1=x1; expr2=x2; } virtual ~Arith() { delete expr1; delete expr2; } virtual int Eval() { int v1=expr1->Eval(); int v2=expr2->Eval(); //printf("Eval %d %c %d\n",v1,op,v2); int ans=0; int ng=0; switch (op) { case '+': return v1+v2; case '-': return v1-v2; case '*': return v1*v2; case '/': ng=0; if (v1<0) { ng^=1; v1=-v1; } if (v2<0){ ng^=1; v2=-v2; } if (ng) return -(v1/v2); else return v1/v2; case '%': ng=0; if (v1<0) { ng^=1; v1=-v1; } if (v2<0){ ng^=1; v2=-v2; } if (ng) return -(v1%v2); else return v1%v2; case '^': //ans=1; //for (int i=0;i<v2;i++) ans*=v1; //ans=(int)pow(v1,v2); ans=power(v1,v2); return ans; default: return 0; } } char op; Expr* expr1; Expr* expr2; }; class Unary : public Expr { public: Unary(char o,Expr* x) { op=o; expr=x; } virtual ~Unary() { delete expr; } virtual int Eval() { int v=expr->Eval(); //printf("Eval %c %d\n",op,v); switch (op) { case '-': return -v; default: return 0; } } char op; Expr* expr; }; class Lexer { public: void init(char *s) { buf=s; pos=0; len=strlen(buf); peek=' '; //printf("len = %d\n",len); } void Readch() { if (pos<len) { peek=buf[pos++]; } else { peek=0; } } Token Scan() { for (;; Readch()) { if (peek==' '||peek=='\t') continue; else if (peek==0) return Token(); else break; } //printf("peek = %c\n",peek); if (isdigit(peek)) { int v=0; do { v=10*v+peek-'0'; Readch(); } while (isdigit(peek)); return Token(v); } if (isalpha(peek)) { int cnt=0; do { if (peek>='A'&&peek<='Z') peek=peek-'A'+'a'; idt[cnt++]=peek; Readch(); } while (isalnum(peek)); idt[cnt]=0; return Token(idt); } char tp=peek; peek=' '; return Token(tp); } private: char idt[20]; char *buf; int pos; int len; char peek; } lexer; class Parser { public: void init(Lexer *l) { lex=l; Read(); } void Read() { look=lex->Scan(); //printf("Get Token type=%d value=",look.type); //if (look.type==Token::Int) printf("%d\n",look.num); //else if (look.type==Token::Id) printf("%s\n",look.id); //else printf("%c\n",look.op); } Expr* expr() { Expr* x=term(); while (look.type==Token::Add||look.type==Token::Sub) { char op=look.op; Read(); x=new Arith(op,x,term()); } return x; } Expr* term() { Expr* x=powpow(); while (look.type==Token::Mul||look.type==Token::Div||look.type==Token::Mod) { char op=look.op; Read(); x=new Arith(op,x,powpow()); } return x; } Expr* powpow() { Expr* x=unary(); if (look.type!=look.Pow) return x; char op=look.op; vector<Expr*>v; v.push_back(x); while (look.type==look.Pow) { Read(); Expr* ex=unary(); v.push_back(ex); } x=v.back(); v.pop_back(); for (vector<Expr*>::reverse_iterator it=v.rbegin(); it!=v.rend(); it++) { Expr* ex=(*it); x=new Arith(op,ex,x); } return x; } Expr* unary() { if (look.type==Token::Sub) { Read(); return new Unary('-',unary()); } else return factor(); } Expr* factor() { if (look.type==Token::Lp) { Read(); Expr* x=expr(); if (look.type==Token::Rp) { Read(); } return x; } else if (look.type==Token::Int) { int v=look.num; Read(); return new Constant(v); } else if (look.type==Token::Id) { string str(look.id); Read(); return new Id(str); } else { return new Expr(); } } private: Lexer* lex; Token look; } parser; char cmd[20]; char expr[2222]; int main() { _Cnt=0; idmap.clear(); conmap.clear(); while (~scanf("%s",cmd)) { if (cmd[0]=='p') { gets(expr); lexer.init(expr); /* for (;;){ Token tok=lexer.Scan(); if (tok.type==Token::Eof) break; printf("%d ",tok.type); if (tok.type==Token::Int) printf("%d\n",tok.num); else if (tok.type==Token::Id) printf("%s\n",tok.id); else printf("%c\n",tok.op); } */ parser.init(&lexer); Expr* p=parser.expr(); int res=p->Eval(); printf("%d\n",res); delete p; } else if (cmd[0]=='d') { gets(expr); lexer.init(expr); Token tok1=lexer.Scan(); int s1,s2; if (tok1.type==Token::Int){ s1=RegistInt(tok1.num); } else if (tok1.type==Token::Id){ s1=RegistStr(tok1.id); } Token tok2=lexer.Scan(); if (tok2.type==Token::Int){ s2=RegistInt(tok2.num); } else if (tok2.type==Token::Id){ s2=RegistStr(tok2.id); } Define(s1,s2); } } return 0; } /* define x y print x+x define y 2 print x+x print y print x */