Wx::

编译原理 - 表达式计算器

支持

  • 百分数 %
  • 取模 %
  • 次方 ^
  • 加 + 减 - 乘 * 除 /
  • 负数 -
  • 括号 ( )
  • 及其嵌套组合的表达式

演示

500%%3*(24%10-1)^((-14+3*5)*(6/3))-6.5%

计算结果:17.935


前驱知识点

算符优先文法

实现此表达式计算器基于「算符优先文法」,即每两个具有左右序的终结符(算符)都具有确定的优先级,依此进行文法的 规约
规约规则:将输入串从左至右进行扫描,当遇到优先级“下降”时进行规约,此处不再详细展开其概念。


实现

语法基类(Grammar)

即预测分析文法、算符优先文法、LR 文法等均继承此类
具体定义:-brev-

class GrammarElement {
    // 语法元素,即一条语法规则
public:
    Symbol left; // 左端为单个符号(以后可能会改进)
    vector<Symbol> right; // 右端为符号串,特殊符号 $ 表示空

    GrammarElement();
    GrammarElement(Symbol left, vector<Symbol> right);

    // 为便于整条规则的输出,定义此函数
    string toString();
};

class Grammar {
    // 文法基类
public:
    Grammar() {
        srcFilePath = "";
        outFilePath = "";
    }
    ~Grammar(){
        if (fout.is_open()) {
            fout.close();
        }
    }
    
private:
    // 调用词法分析器,解析一行语法规则:
    void parseLine(string t);

protected:
    ifstream fin;
    ofstream fout;
    string srcFilePath;
    string outFilePath;

    string inputStr; // 原始输入代码
    int type; // 1:单字符文法 or 0:多字符符号
    bool executable; // 是否需要执行,如算符优先中输入串是否计算数值

    vector<GrammarElement> gramOldSet; // 原始文法产生集
    set<Symbol> terSymbol; // 终结符;包括空字符 $ 及结束符 #
    set<Symbol> nonTer; // 非终结符
    Symbol startSymbol; // 第一个出现的非终结符判定为开始符号

    bool inputGrammer();
};

over

具体实现:-brev-

void Grammar::parseLine(string t) {
    // 解析一行文法
    int i = 0;
    string token;
    GrammarElement g;

    // 调用词法分析的新的实现:
    LexicalAnalyzer la;
    vector<string> keys = { "->", "$" };
    la.addKeywords(keys);
    pair<vector<Symbol>, bool> processRes = la.process(t);
    vector<Symbol> symbols = processRes.first;
    bool error = !processRes.second;
    if (error) {
        cout << "Lexical analysis error: " << t << endl;
        return;
    }
    bool left = true;
    string sTmp;
    for (int i = 0; i < symbols.size(); i++) {
        sTmp = symbols[i].data;

        // 新增符号:
        if (sTmp[0] >= 'A' && sTmp[0] <= 'Z') {
            nonTer.insert(sTmp);
        }
        else if(sTmp!="->" && sTmp!="|") {
            terSymbol.insert(sTmp);
        }

        // 确定文法开始符号:
        if (startSymbol.data.compare("")==0) {
            startSymbol = sTmp;
        }

        // 记录规则:
        if (sTmp == "->") {
            left = false;
        }
        else if (sTmp == "|") {
            gramOldSet.push_back(g);
            g.right.clear();
        }
        else if (left) {
            g.left = sTmp;
        }
        else {
            g.right.push_back(sTmp);
        }
    }

    // 因之前只碰到 | 才记录,所以最后一条规则需在此记录:
    gramOldSet.push_back(g);
}

bool Grammar::inputGrammer() {
    if (!fin.is_open()) {
        if (srcFilePath != "") {
            fin.open(srcFilePath);
        }
        else {
            cout << "error: src or out file path undefined!" << endl;
            return false;
        }
    }

    // 读取元数据:
    int IgnoreLineNumber; // 文件元数据(不需要读)的行数
    string GrammerStart; // 表示文法开始的符号串
    string InputStringStart; // 表示文法开始的符号串
    stringstream ss;
    string t = "";
    ss.clear();
    fin >> t;
    ss << t;
    ss >> IgnoreLineNumber;
    ss.clear();
    fin >> t;
    ss << t;
    ss >> this->type;
    ss.clear();
    fin >> t;
    GrammerStart = t;
    fin >> t;
    InputStringStart = t;
    fin >> t;
    ss << t;
    executable = (t == "1" ? true : false);
    

    for (int i = 0; i < IgnoreLineNumber; i++) {
        getline(fin, t);
    }

    // fin>>t 和 getline(fin, t) 混用时 getline 可能读错

    // 读取符号定义部分(文法开始之前)声明的符号
    int flag = 0;
    while (flag == 0 && fin >> t) { // 先判断 flag,flag==1时不读入
        if (t.compare(GrammerStart) == 0) {
            flag = 1;
        }
        else if (t[0] >= 'A' && t[0] <= 'Z') {
            definedSymbol.insert(Symbol(t));
        }
        else if(t[0] >= 'a' && t[0] <= 'z') {
            definedSymbol.insert(Symbol(t));
        }
        else {
            //cout << "warning: reading symbol, has invalid head char" << endl;
        }
    }

    // 读取文法:
    while (getline(fin, t)) {
        // 处理空白符:
        for (int i = 0; i < t.size();) {
            if ((t[i] == ' '&& i == t.size() - 1) || (t[i] == ' '&& t[i + 1] == ' ')) {
                t.erase(i, 1);
            }
            else if (t[i] == '\t' || t[i] == '\n') {
                t[i] = ' ';
            }
            else {
                i++;
            }
        }
        
        if (t == " " || t == "") {
            // 此时为空行,跳过
            continue;
        }
        else if (t.compare(InputStringStart) == 0) {
            break;
        }
        
        string tt = "";
        if (this->type == 1) {
            // 将单字符以空格分隔,以便之后以符号格式存取:
            for (int j = 0; j < 3; j++) {
                tt += t[j];
            }
            
            for (int j = 3; j < t.length(); j++) {
                tt += t[j];
                tt += " ";
            }
            t = tt;
        }
        
        parseLine(t);
    }
    
    // 读取待分析串:
    inputStr = "";
    while (getline(fin, t)) {
        // 清除空格:
        for (int i = 0; i < t.size();) {

            if (t[i] == ' '&&t[i + 1] == ' ') {
                t.erase(i, 1);
            }
            else if (t[i] == '\t' || t[i] == '\n') {
                t[i] = ' ';
            }
            else {
                i++;
            }
        }
        if (t == "") {
            // 此时为空行,跳过
            continue;
        }

        inputStr += t;
    }
    // 将结束符添加到终结符:
    terSymbol.insert(Symbol('#'));
    fin.close();

    if (outFilePath.compare("") != 0) {
        if (!fout.is_open()) {
            fout.open(outFilePath);
        }

        fout << "terminal symbol:" << endl;
        for (set<Symbol>::iterator i = terSymbol.begin(); i != terSymbol.end(); i++) {
            fout << i->data << " ";
        }
        fout << endl << endl << "non-ter symbol:" << endl;
        for (set<Symbol>::iterator i = nonTer.begin(); i != nonTer.end(); i++) {
            fout << i->data << " ";
        }
        fout << endl << endl << "grammer:" << endl;
        for (int i = 0; i < gramOldSet.size(); i++) {
            fout << gramOldSet[i].toString() << endl;
        }
    }

    return true;
}

over


扩充符号类(OppSymbol)

为使文法规约过程附带计算的功能,因此将原有符号类扩充为算符优先符号类,即在原有基础上增加成员变量 “值”,当词法分析器获取符号的性质为常整型或常浮点数时,在算符优先分析过程中将其符号重置为 “i”(用符号 i 在文法中代表数值),并为其 “值” 属性赋值,以便参与规约和计算。

具体定义:-brev-

class OppSymbol : public Symbol {
public:
    double value;

    OppSymbol() {
        this->type = -1;
        this->value = 0;
    }
    OppSymbol(char s, double d = 0, int i = -1):Symbol(s) {
        this->type = i;
        this->value = d;
    }
    OppSymbol(string s, double d = 0, int i = -1):Symbol(s) {
        this->type = i;
        this->value = d;
    }
    OppSymbol(const Symbol &s) {
        this->data = s.data;
        this->type = -1;
        this->value = 0;
    }
};

over


优先函数

与 “算符优先表” 功能相同,记录每对非终结符(尤其是算术符号)的优先级关系。

具体定义:-brev-

class PrecedenceFunction {
public:
    int f;
    int g;

    PrecedenceFunction() {
        f = g = 0;
    }

    bool operator >(const PrecedenceFunction &pf) {
        return (this->f > pf.g);
    }
    bool operator <(const PrecedenceFunction &pf) {
        return (this->f < pf.g);
    }
    bool operator ==(const PrecedenceFunction &pf) {
        return (this->f == pf.g);
    }
};

over


算符优先分析

大体过程

  • 调用父类方法 inputGrammar 读入源文法及待分析串,需用到词法分析器(从 srcFilePath 中)

  • 获取 FirstVT 与 LastVT 集

  • 分析获取优先表并推出优先函数

  • 进行优先分析并计算

准备过程实现

展开:-brev-

void OPP::getFirstVt() {
    set<pair<Symbol, Symbol>> fpa;
    vector<Symbol> right;
    for (int i = 0; i < gramOldSet.size(); i++) {
        right = gramOldSet[i].right;
        for (int j = 0; j < right.size(); j++) {
            if (terSymbol.count(right[j])) {
                fpa.insert(make_pair(gramOldSet[i].left, right[j]));
                firstVt[gramOldSet[i].left].insert(right[j]);
                break;
            }
        }
    }
    pair<Symbol, Symbol> pa;
    while (fpa.size()) {
        pa = *(fpa.begin());
        fpa.erase(fpa.begin());
        for (int i = 0; i < gramOldSet.size(); i++) {
            if (gramOldSet[i].right[0] == pa.first && !firstVt[gramOldSet[i].left].count(pa.second)) {
                fpa.insert(make_pair(gramOldSet[i].left, pa.second));
                firstVt[gramOldSet[i].left].insert(pa.second);
            }
        }
    }

    if (outFilePath != "") {
        if (!fout.is_open()) {
            fout.open(outFilePath);
        }
        fout << "\nfirstVt: \n";
        for (map<Symbol, set<Symbol>>::iterator it = firstVt.begin(); it != firstVt.end(); it++) {
            fout << it->first.data << ": ";
            for (set<Symbol>::iterator itt = it->second.begin(); itt != it->second.end(); itt++) {
                fout << itt->data << " ";
            }
            fout << "\n";
        }
    }
}

void OPP::getLastVt() {
    set<pair<Symbol, Symbol>> fpa;
    vector<Symbol> right;
    for (int i = 0; i < gramOldSet.size(); i++) {
        right = gramOldSet[i].right;
        for (int j = right.size()-1; j >=0 ; j--) {
            if (terSymbol.count(right[j])) {
                fpa.insert(make_pair(gramOldSet[i].left, right[j]));
                lastVt[gramOldSet[i].left].insert(right[j]);
                break;
            }
        }
    }
    pair<Symbol, Symbol> pa;
    while (fpa.size()) {
        pa = *(fpa.begin());
        fpa.erase(fpa.begin());
        for (int i = 0; i < gramOldSet.size(); i++) {
            if (*(gramOldSet[i].right.end()-1) == pa.first && !lastVt[gramOldSet[i].left].count(pa.second)) {
                fpa.insert(make_pair(gramOldSet[i].left, pa.second));
                lastVt[gramOldSet[i].left].insert(pa.second);
            }
        }
    }

    if (outFilePath != "") {
        if (!fout.is_open()) {
            fout.open(outFilePath);
        }
        fout << "\nlastVt: \n";
        for (map<Symbol, set<Symbol>>::iterator it = lastVt.begin(); it != lastVt.end(); it++) {
            fout << it->first.data << ": ";
            for (set<Symbol>::iterator itt = it->second.begin(); itt != it->second.end(); itt++) {
                fout << itt->data << " ";
            }
            fout << "\n";
        }
    }
}

void OPP::getPrecedenceTable() {
    for (set<Symbol>::iterator it = terSymbol.begin(); it != terSymbol.end(); it++) {
        for (set<Symbol>::iterator itt = terSymbol.begin(); itt != terSymbol.end(); itt++) {
            T[make_pair(*it, *itt)] = -5;            
        }
    }
    // 添加新开始符号 E'->#E#
    gramOldSet.push_back(GrammarElement(Symbol("E'"), vector<Symbol>{'#', startSymbol, '#'}));

    vector<Symbol>* right;
    for (int i = 0; i < gramOldSet.size(); i++) {
        right = &gramOldSet[i].right;
        for (vector<Symbol>::iterator j = right->begin(); j != right->end(); j++) {
            if (terSymbol.count(*j)) {
                if (right->size()>=3 && j <= right->end() - 3 && terSymbol.count(*(j + 2))) {
                    if (T[make_pair(*j, *(j + 2))] != 0&& T[make_pair(*j, *(j + 2))] != -5) {
                        cout << "不是算符优先!" << endl;
                        //return;
                    }
                    T[make_pair(*j, *(j + 2))] = 0;
                }
                if (j < right->end() - 1 && terSymbol.count(*(j + 1))) {
                    if (T[make_pair(*j, *(j + 1))] != 0&& T[make_pair(*j, *(j + 1))] != -5) {
                        cout << "不是算符优先!" << endl;
                        //return;
                    }
                    T[make_pair(*j, *(j + 1))] = 0;
                }
                if (j < right->end() - 1 && nonTer.count(*(j + 1))) {
                    for (set<Symbol>::iterator it = firstVt[*(j + 1)].begin(); it != firstVt[*(j + 1)].end(); it++) {
                        if (T[make_pair(*j, *it)] != -1&& T[make_pair(*j, *it)] != -5) {
                            cout << "不是算符优先!" << endl;
                            //return;
                        }
                        T[make_pair(*j, *it)] = -1;
                    }
                }
            }
            else if (j < right->end() - 1 && terSymbol.count(*(j + 1))) {
                for (set<Symbol>::iterator it = lastVt[*(j)].begin(); it != lastVt[*(j)].end(); it++) {

                    if (T[make_pair(*it, *(j + 1))] != 1 && T[make_pair(*it, *(j + 1))] != -5) {
                        cout << "不是算符优先!" << endl;
                        //return;
                    }
                    T[make_pair(*it, *(j + 1))] = 1;
                }
            }
        }
    }
    if (outFilePath != "") {
        if (!fout.is_open()) {
            fout.open(outFilePath);
        }
        fout << "\nPrecedence table: \n";
        fout << "\t";
        for (set<Symbol>::iterator it = terSymbol.begin(); it != terSymbol.end(); it++) {
            fout << setw(5) << it->data;
        }
        
        for (set<Symbol>::iterator it = terSymbol.begin(); it != terSymbol.end(); it++) {
            fout<< "\n" << it->data << "\t";
            for (set<Symbol>::iterator itt = terSymbol.begin(); itt != terSymbol.end(); itt++) {
                if (T.count(make_pair(*it, *itt))) {
                    switch (T[make_pair(*it, *itt)]){
                    case -1:
                        fout << setw(5) << "<";
                        break;
                    case 0:
                        fout << setw(5) << "=";
                        break;
                    case 1:
                        fout << setw(5) << ">";
                        break;
                    default:
                        break;
                    }
                }
                else {
                    fout << setw(5) << " ";
                }
            }
            
        }
    }
}

void OPP::getPrecedenceFunction() {
    // 转为优先函数 F、G
    bool converge = true; // 是否达到收敛

    while (converge) {
        converge = false;
        for (set<Symbol>::iterator it = terSymbol.begin(); it != terSymbol.end(); it++) {
            for (set<Symbol>::iterator itt = terSymbol.begin(); itt != terSymbol.end(); itt++) {
                if(T[make_pair(*it, *itt)]==-5){
                    continue;
                }
                if (T[make_pair(*it, *itt)] > 0 && !(pf[*it] > pf[*itt])) {
                    pf[*it].f = pf[*itt].g + 1;
                    converge = true;
                }
                else if (T[make_pair(*it, *itt)] == 0 && !(pf[*it] == pf[*itt])) {
                    pf[*it].f = pf[*itt].g = max(pf[*it].f, pf[*itt].g);
                    converge = true;
                }
                else if (T[make_pair(*it, *itt)] < 0 && !(pf[*it] < pf[*itt])) {
                    pf[*itt].g = pf[*it].f + 1;
                    converge = true;
                }
                
                if (pf[*it].f > 2 * terSymbol.size() || pf[*itt].g > 2 * terSymbol.size()) {
                    cout << "warning: cannot find complete precedence function!";
                    fout << "\n\n无法得出优先函数:\n";
                    pfIsOk = false;
                    return;
                }
            }
        }

    }
    pfIsOk = true;

    // 销毁表 T
    T.clear();

    if (outFilePath != "") {
        if (!fout.is_open()) {
            fout.open(outFilePath);
        }
        fout << "\n\nPrecedence function (f & g): \n";
        fout << setw(5) << " ";
        for (set<Symbol>::iterator it = terSymbol.begin(); it != terSymbol.end(); it++) {
            fout << setiosflags(ios::left) << setw(5) << it->data;
        }
        fout << "\n";
        fout << setiosflags(ios::left) << setw(5) << "f";
        for (set<Symbol>::iterator it = terSymbol.begin(); it != terSymbol.end(); it++) {
            fout << setiosflags(ios::left) << setw(5) << pf[*it].f;
        }
        fout << "\n";
        fout << setiosflags(ios::left) << setw(5) << "g";
        for (set<Symbol>::iterator it = terSymbol.begin(); it != terSymbol.end(); it++) {
            fout << setiosflags(ios::left) << setw(5) << pf[*it].g;
        }
        fout << "\n";
    }
}

int OPP::compare(const Symbol &s1, const Symbol &s2) {
    // 比较优先级
    if (pfIsOk) {
        // 通过优先函数:
        return pf[s1].f - pf[s2].g;
    }
    else {
        // 通过优先关系表:
        return T[make_pair(s1, s2)];
    }
}

over

主分析过程实现

pair<int, int> OPP::process(string newInputStr) {
    // 开始输入串分析:
    if (newInputStr != "") {
        // 若存在参数,则以参数中待分析串为准(以便向以后提供接口)
        inputStr = newInputStr;
    }
    if (inputStr.compare("") == 0) {
        cout << "error: inputed string is null!" << endl;
        return make_pair(1, 2);
    }

    if (outFilePath.compare("") == 0) {
        cout << "warning: out file path undefined!" << endl;
    }
    else if (!fout.is_open()) {
        fout.open(outFilePath);
    }

    if (fout.is_open()) {
        fout << "\n\n算符优先分析过程(" << inputStr << "):" << endl;
    }

    stringstream ss;
    double dTmp;
    LexicalAnalyzer la;
    pair<vector<Symbol>, bool> processRes = la.process(inputStr + "#");
    vector<Symbol> oldSymbols = processRes.first;
    vector<OppSymbol> symbols;
    bool error = !processRes.second;    
    if (error) {
        cout << "OPP processing error: lexical analysis error: " << endl;
        return make_pair(1, 0);
    }
    else {
        // 处理 Symbol 为 OppSymbol
        for (int i = 0; i < oldSymbols.size(); i++) {
            if (oldSymbols[i].type == LexicalAnalyzer::DoubleTypeNum) {
                ss.clear();
                ss << oldSymbols[i].data;
                ss >> dTmp;
                symbols.push_back(OppSymbol('i', dTmp, LexicalAnalyzer::DoubleTypeNum));
            }
            else {
                symbols.push_back(oldSymbols[i]);
            }
        }
    }

    vector<OppSymbol> sta; // 模拟栈
    sta.push_back('#');
    vector<OppSymbol> rig; // 暂存待规约串(最左素短语)

    int pos = 0; // 指示当前栈顶终结符
    int posTmp = 0;
    int cnt = 0;
    OppSymbol s1, s2; // 暂存符号以便输出
    int lenTmp;

    if (fout.is_open()) {
        fout << setiosflags(ios::left) << setw(5) << cnt;
        fout << symbolsToString(sta, 20);
        fout << symbolsToString(symbols, inputStr.size() + 3, 2);
        fout << "\t";
        fout << setw(10) << "# 移进";
        fout << "预备\n";
    }
    while (true) {
        cnt++;
        pos = sta.size() - 1;
        if (nonTer.count(Symbol(sta[pos].data))) {
            pos--;
        }
        if (!symbols.size()) {
            return make_pair(1, 0);
        }
        if (sta[pos] == '#' && symbols[0] == '#') {
            if (fout.is_open()) {
                fout << "接受,计算结果:" << sta[1].value;
            }
            cout << "= " << sta[1].value << endl;
            break;
        }
        s1 = sta[pos];
        s2 = *symbols.begin();
        if (compare(s1, s2)<=0) {
            sta.push_back(s2);
            symbols.erase(symbols.begin());

            if (fout.is_open()) {
                fout << setiosflags(ios::left) << setw(5) << cnt;
                fout << symbolsToString(sta, 20);
                fout << symbolsToString(symbols, inputStr.size() + 3, 2);
                fout << "\t";
                fout << setw(10) << (s1.data + "<" + s2.data);
                fout << setw(15) << (s2.data + " 移进") << "\n";
            }
            continue;
        }

        // 向前找第一个优先级为“小于”的终结符关系
        posTmp = pos - 1;
        while (nonTer.count(Symbol( sta[posTmp].data)) || compare(sta[posTmp], s1) >= 0) {
            if (!nonTer.count(Symbol( sta[posTmp].data))) { // 用非终结符集判断
                s1 = sta[posTmp];
            }
            posTmp--;
        }

        // 将要规约的串从尾部依次弹出并前插入 rig
        lenTmp = sta.size();
        rig.clear();
        for (int i = posTmp+1; i < lenTmp; i++) {
            rig.insert(rig.begin(), *(sta.end() - 1));
            sta.pop_back();
        }

        bool match;
        for (vector<GrammarElement>::iterator it = gramOldSet.begin(); it != gramOldSet.end(); it++) {
            // 依据右端及文法规则进行模式化匹配,而非完全相同匹配
            // 模式:对应位置符号性质相同且终结符处符号相等,不考虑非终结符具体符号字符

            match = false;
            for (int i = 0; i < it->right.size() && i < rig.size(); i++) {
                if (terSymbol.count(it->right[i]) && terSymbol.count(Symbol(rig[i].data))) {
                    if (it->right[i].data == rig[i].data) {
                        match = true;
                    }
                    else {
                        match = false;
                    }
                }
            }
            if (match) {
                if (executable) {
                    dTmp = eval(rig);
                }
                else {
                    dTmp = 0;
                }
                sta.push_back(OppSymbol(it->left.data, dTmp, LexicalAnalyzer::DoubleTypeNum));

                if (fout.is_open()) {
                    fout << setiosflags(ios::left) << setw(5) << cnt;
                    fout << symbolsToString(sta, 20);
                    fout << symbolsToString(symbols, inputStr.size() + 3, 2);
                    fout << "\t";
                    fout << setw(10) << (s1.data + ">" + s2.data);
                    fout << setw(15) << (it->toString() + " 规约");

                    // 输出此步运算的过程:

                    if (executable) {
                        for (int i = 0; i < rig.size(); i++) {
                            if (rig[i].type == LexicalAnalyzer::DoubleTypeNum) {
                                fout << rig[i].value << " ";
                            }
                            else {
                                fout << rig[i].data << " ";
                            }
                        }
                        fout << "= ";
                        fout << dTmp;
                        fout << "\n";
                    }
                }
                break;
            }
        }
    }
}

double OPP::eval(const vector<OppSymbol> &v) {
    // 算值函数

    stringstream ss;
    double d, d1, d2;
    if (v.size() == 1 && v[0].type == LexicalAnalyzer::DoubleTypeNum) {
        // 原数值直接返回
        d = v[0].value;
        return d;
    }
    else if (v.size() == 2 && v[1].type == LexicalAnalyzer::DoubleTypeNum) {
        // -3
        d = v[1].value;
        if (v[0].data.compare("-") == 0) {
            return -1 * d;
        }
        else if (v[0].data.compare("+") == 0) {
            return d;
        }
        else {
            cout << "eval error: " + symbolsToString(v) << endl;
            return 0;
        }
    }
    else if (v.size() == 3 && v[1].type == LexicalAnalyzer::DoubleTypeNum) {
        // (3)
        d = v[1].value;
        return d;
    }
    else if (v.size() == 2 && v[0].type == LexicalAnalyzer::DoubleTypeNum) {
        // 3%
        // 实际上百分数(如30%)是依据模运算(如3%5)的规则进行规约,
        // 而 eval 函数会判断符号串长度,因此可以正确得出结果
        d = v[0].value;
        return d / 100.0;
    }
    else if (v.size() == 3 && v[0].type == LexicalAnalyzer::DoubleTypeNum 
                                     && v[2].type == LexicalAnalyzer::DoubleTypeNum) {
        d1 = v[0].value;
        d2 = v[2].value;
        if (v[1].data == "+") {
            return  d1 + d2;
        }
        else if (v[1].data == "-") {
            return d1 - d2;
        }
        else if (v[1].data == "*") {
            return d1*d2;
        }
        else if (v[1].data == "/") {
            return d1 / d2;
        }
        else if (v[1].data == "%") {
            // 百分号% 同时为取模运算符
            return int(d1) % int(d2);
        }
        else if (v[1].data == "^") {
            return pow(d1, d2);
        }
        else {
            cout << "error: cannot identify operator" << endl;
        }
    }
    else {
        cout << "eval error: cannot judge type (=26?)\nstring: " + symbolsToString(v) << endl;
        return 0;
    }
    return 0;
}

7

评论(0

评论 取消
验证码:
搜索