• 四则运算的词法分析


    四则运算的词法分析

             之前我们处理四则运算的方法有两种,第一种是对输入的格式强制限定运算符两边都有空白符,另一种是我们根据输入的字符串,对其中的运算符进行添加空白符预处理。通过添加空白符进行处理里显然不太规范和方便,真正需要做的应该是我们对输入的四则运算表达式进行词法分析,解析出相应的运算符和操作符,然后在进行中缀转后缀、后缀表达式的计算等过程。

             我们的四则运算表达式只包含两种元素:操作符和操作数。

             其中,操作符目前限定为+、-、*、/四种,另外还有括号:左括号和右括号。

             操作数可以是小数也可以是整数。

             操作符和操作数我们将其视为token,其对应的种别码分别为:

    token

    id

    +

    1

    -

    2

    *

    3

    /

    4

    (

    5

    )

    6

    操作符

    7

             操作数的定义如下:操作数 = 数字 数字*

             空白符包括空格符、制表符,我们将其忽略,由于我们处理的四则运算表达式都是单行的输入,所以我们不对换行符 进行考虑。

             程序输出的结果为二元组:<token,id>。

             以下为具体的程序实现

    // 四则运算的词法分析
    #include <iostream>
    #include <string>
    #include <vector>
    #include <map>
    using namespace std;
    
    struct TI
    {
        string token;
        int    id;
    };
    
    bool is_blank(char ch)
    {
        return ch == ' ' || ch == '    ';
    }
    
    void get_exp(string& exp)
    {
        getline(cin, exp);
    }
    
    void init_keys(map<string, int>& keys)
    {
        keys.clear();
        keys["+"] = 1;
        keys["-"] = 2;
        keys["*"] = 3;
        keys["/"] = 4;
        keys["("] = 5;
        keys[")"] = 6;
        keys["__NUM__"] = 7;
    }
    
    void lex(const string& exp, vector<TI>& to_id, const map<string, int>& keys)
    {
        to_id.clear();
        char ch;
        for (string::size_type pos = 0; pos < exp.size(); /* ++pos */)
        {
            TI ti;
            ch = exp[pos];
    
            if (is_blank(ch))
            {
                ++pos;
                continue;
            }
            if (ch >= '0' && ch <= '9' || ch == '.')
            {
                ti.token += ch;
                ++pos;
                if (pos >= exp.size())
                {
                    ti.id = keys.size();
                    to_id.push_back(ti);
                    return;
                }
                ch = exp[pos];
                while (ch >= '0' && ch <= '9' || ch == '.')
                {
                    ti.token += ch;
                    ++pos;
                    if (pos >= exp.size())
                    {
                        ti.id = keys.size();
                        to_id.push_back(ti);
                        return;
                    }
                    ch = exp[pos];
                }
                ti.id = keys.size();
                to_id.push_back(ti);
            }
            else
            {
                map<string, int>::const_iterator cit;
                switch (ch)
                {
                case '+':
                case '-':
                case '*':
                case '/':
                case '(':
                case ')':
                    ti.token += ch;
                    cit = keys.find(ti.token);
                    if (cit == keys.end())
                    {
                        cout << "test" << endl;
                    }
                    ti.id = cit->second;
                    to_id.push_back(ti);
                    ++pos;
                    break;
    
                default:
                    ti.token += string("未知字符:") + ch;
                    ti.id = -1;
                    to_id.push_back(ti);
                    ++pos;
                    break;
                }
            }
        }
    }
    
    int main()
    {
        string exp;
        get_exp(exp);
        map<string, int> keys;
        init_keys(keys);
    
        vector<TI> to_id;
    
        lex(exp, to_id, keys);
    
        for (vector<TI>::size_type i = 0; i != to_id.size(); ++i)
        {
            cout << '<' << to_id[i].token << ',' << to_id[i].id << '>' << endl;
        }
        return 0;
    }

    测试1:

    测试2:

    在我们的程序中,我们没有对操作数的合法性进行检测,关于操作数的合法性会在中缀表达式转换后缀表达式的过程中进行处理。

    下一步工作将集中在:利用四则运算的词法分析进行四则运算表达式的计算;对含有字母未知量的代数表达式进行计算;语法分析;虚拟机等。

  • 相关阅读:
    在react中实现CSS模块化
    react 组件的生命周期
    HTTP缓存机制与原理
    H5新增API和操作DOM
    js操作json方法总结
    gulp详细教程——前端自动化构建工具
    JavaScript你必须掌握的8大知识点
    HTTP请求与服务器响应流程
    max-height实现任意高度元素的展开收缩动画
    移动端轮播图手势分析+源码
  • 原文地址:https://www.cnblogs.com/unixfy/p/3261648.html
Copyright © 2020-2023  润新知