自制编译型表达式计算器

起因是这个问题

http://zhidao.baidu.com/question/1110099820559411499.html

因为当时我编译原理课根本没有好好听,所以就决定尝试一下自己写这样的东西能写成什么样。

虽然写出来了,不过貌似没有满足,然后就进行魔改。

下面的代码是魔改的结果,能蛋疼成这样,我实在无话可说了……(死鱼眼

输入一个表达式,然后这个程序能计算它的值。支持加减乘除和括号,只支持整数,表达式中不能含有空格

注意:不能在“数据执行保护(DEP)”环境下执行。VC链接的时候不能带/NXCOMPAT选项,系统设置里也不能用“为所有程序启用数据执行保护”。

#define _SCL_SECURE_NO_WARNINGS
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;

typedef unsigned char uchar;
typedef vector<uchar> Buf;
typedef const Buf CBuf;

void App(Buf& b, CBuf& c) {
    b.insert(b.end(), c.begin(), c.end());
}
Buf Eax(int n, CBuf& c = CBuf()) {
    Buf r(5);
    r[0] = 0xb8;
    copy(reinterpret_cast<uchar*>(&n), reinterpret_cast<uchar*>(&n+1), &r[1]);
    App(r, c);
    return r;
}
Buf Eax2Edx(CBuf& c = CBuf()) {
    Buf r(2);
    r[0] = 0x8b;
    r[1] = 0xd0;
    App(r, c);
    return r;
}
Buf Edx2Eax(CBuf& c = CBuf()) {
    Buf r(2);
    r[0] = 0x8b;
    r[1] = 0xc2;
    App(r, c);
    return r;
}
Buf Eax2Ecx(CBuf& c = CBuf()) {
    Buf r(2);
    r[0] = 0x8b;
    r[1] = 0xc8;
    App(r, c);
    return r;
}
Buf Ecx2Eax(CBuf& c = CBuf()) {
    Buf r(2);
    r[0] = 0x8b;
    r[1] = 0xc1;
    App(r, c);
    return r;
}
Buf Push(CBuf& c = CBuf()) {
    Buf r(2);
    r[0] = 0xff;
    r[1] = 0xf0;
    App(r, c);
    return r;
}
Buf Pop(CBuf& c = CBuf()) {
    Buf r(2);
    r[0] = 0x8f;
    r[1] = 0xc0;
    App(r, c);
    return r;
}
Buf Add(CBuf& c = CBuf()) {
    Buf r(2);
    r[0] = 0x03;
    r[1] = 0xc2;
    App(r, Push());
    App(r, c);
    return Pop(Eax2Edx(Pop(r)));
}
Buf Sub(CBuf& c = CBuf()) {
    Buf r(2);
    r[0] = 0x2b;
    r[1] = 0xc2;
    App(r, Push());
    App(r, c);
    return Pop(Eax2Edx(Pop(r)));
}
Buf Mul(CBuf& c = CBuf()) {
    Buf r(2);
    r[0] = 0xf7;
    r[1] = 0xe2;
    App(r, Push());
    return Pop(Eax2Edx(Pop(r)));
}
Buf Div(CBuf& c = CBuf()) {
    Buf r(2);
    r[0] = 0xf7;
    r[1] = 0xf1;
    App(r, Push());
    App(r, c);
    return Eax(0, Eax2Edx(Pop(Eax2Ecx(Pop(r)))));
}
Buf Ret() {
    Buf r(1);
    r[0] = 0xc3;
    return r;
}
Buf Neg(CBuf& c = CBuf()) {
    Buf r(2);
    r[0] = 0xf7;
    r[1] = 0xd8;
    App(r, Push());
    App(r, c);
    return Pop(r);
}

bool parseKakko(const char* &p, Buf& x);

bool parseNumber(const char* &p, Buf& x) {
    if (parseKakko(p, x)) return true;
    
    const char* lp = p;
    if (*lp == '-') {
        ++lp;
        if (parseNumber(lp, x)) {
            App(x, Neg());
            p = lp;
            return true;
        }
    }
    
    if (*lp >= '0' && *lp <= '9') {
        int val = 0;
        while(*lp >= '0' && *lp <= '9') {
            val = val * 10 + (*lp - '0');
            ++lp;
        }
        p = lp;
        App(x, Eax(val, Push()));
        return true;
    } else {
        return false;
    }
}

bool parseOP1(const char* &p, char &x) {
    if (*p == '*' || *p == '/') {
        x = *p;
        ++p;
        return true;
    } else
        return false;
}

bool parseOP2(const char* &p, char &x) {
    if (*p == '+' || *p == '-') {
        x = *p;
        ++p;
        return true;
    } else
        return false;
}

bool parseFactor(const char* &p, Buf &x) {
    Buf lhs, rhs;
    char op;
    const char* lp = p;
    if ( parseNumber(lp, lhs) ) {
        const char* lp2 = lp;
        while (parseOP1(lp2, op) ) {
            if (parseNumber(lp2, rhs)) {
                App(x, lhs);
                App(x, rhs);
                if (op == '*') App(x, Mul());
                if (op == '/') App(x, Div());
                lp = lp2;
                lhs.clear();
                rhs.clear();
            } else break;
        }
        App(x, lhs);
        p = lp;
        return true;
    } else return false;
}

bool parseExpr(const char* &p, Buf &x) {
    Buf lhs, rhs;
    char op;
    const char* lp = p;
    
    if (parseFactor(lp, lhs)) {
        const char* lp2 = lp;
        while (parseOP2(lp2, op)) {
            if (parseFactor(lp2, rhs)) {
                App(x, lhs);
                App(x, rhs);
                if (op == '+') App(x, Add());
                if (op == '-') App(x, Sub());
                lp = lp2;
                lhs.clear();
                rhs.clear();
            } else break;
        }
        App(x, lhs);
        p = lp;
        return true;
    } else return false;
}

bool parseKakko(const char* &p, Buf &x) {
    const char* lp = p;
    Buf t;
    if (*lp == '(') {
        ++lp;
        if (parseExpr(lp, t)) {
            if (*lp == ')') {
                ++lp;
                p = lp;
                App(x, t);
                return true;
            } else return false;
        } else return false;
    } else return false;
}

#include <stdio.h>

int main()
{
    Buf code;
    char str[256];
    gets(str);
    const char* pstr = str;
    if (parseExpr(pstr, code)) {
        int i, l = pstr - str;
        for(i = 0; i < l; ++i)
            putchar(' ');
        puts("^ parsed until here");
        App(code, Pop(Ret()));
        int (*run)() = (int (*)()) &code[0];
        printf("%d\n", run());
    }
    return 0;
}


 

发表评论