ACdream 1232 SGU 215 PL/Cool 手写了一个语法分析引擎

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


*/


你可能感兴趣的:(ACdream 1232 SGU 215 PL/Cool 手写了一个语法分析引擎)