哈尔滨理工大学

软件与微电子学院

《面型对象程序设计(vc++)》

项目实践报告

题 目:词法分析器
班 级:软件18-1班
专 业:软件工程
姓名:张立辉
学号:1814010130
指导教师:尹莉莉
日期:2020年3月16日

哈尔滨理工大学软件与微电子学院


目录

一、需求分析(三号,宋体,粗体)-----------------------------------------------------------------------1
二、系统设计(三号,宋体,粗体)-----------------------------------------------------------------------1
(一)系统中的数据定义(四号,黑体,粗体)--------------------------------------------------------------1
(二)系统的概要设计----------------------------------------------------------------------------------1
(三)系统的详细设计----------------------------------------------------------------------------------1
(四)系统的核心算法----------------------------------------------------------------------------------1
三、系统编码及运行(三号,宋体,粗体)-----------------------------------------------------------------2
(一)系统开发涉及的软件------------------------------------------------------------------------------2
(二)系统运行界面及结果------------------------------------------------------------------------------2
四、系统测试(三号,宋体,粗体)----------------------------------------------------------------------2
五、总结--------------------------------------------------------------------------------------------2
附录(源代码)---------------------------------------------------------------------------------------3
(注:这部分可以点击右键更新生成,重新设置字体为四号)


一、需求分析(三号,宋体,粗体)

通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
编制一个读单词的程序,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符和分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示)

二、系统设计(三号,宋体,粗体)

(一)系统中的数据定义(四号,黑体,粗体)

string Guanjianzi [62] //关键字
char Fengefu [14] //分隔符
char Yunsuanfu [11] //运算符
char Guolvfu [4] //过滤符
string glf[4]//过滤符
int Biaoshifu //标识符值
int Changshu //常数值
int Zhushi //注释值

(二)系统的概要设计

可以通过画框图或流程图阐述系统模块之间的关系以及运行的先后顺序。
图1

(三)系统的详细设计

各个功能模块内部结构执行的过程,可以画流程图。
过滤符:
图2
关键字:
图3
标识符:
图4
数字:
图5
运算符:
图6
分隔符:
图7

(四)系统的核心算法

可以使用伪代码或者流程图表示系统各模块设计中用到的核心算法。
图8

三、系统编码及运行(三号,宋体,粗体)

(一)系统开发涉及的软件

Microsoft Visual Studio Community 2019;
图(1)
Office2016;(包括Word2016与visio2016)
图(2)

(二)系统运行界面及结果

要求有运行结果截图展示,可以分模块说明。如图1所示为系统登录界面。
图1 系统登录界面

图2程序运行界面

图3程序运行界面

四、系统测试(三号,宋体,粗体)

测试数据:

int main()
{
    /*a1
    d2
    c31*2*3*/
    //  123abc
    int  a, b;
    a=10.10;
    b<=a+20;
}

图1

结果:

图2

发现系统的bug

vs2019,fopen函数报错

解决方法

图3
图4

结果:

图5

发现问题:

输出没对齐

解决办法:

添加输出控件

cout.width(10); cout.setf(ios::left);

运行结果:

图6

发现问题:

运算符未显示
图7

解决办法:

添加fseek函数

fseek(fpin,-1L,SEEK_CUR);

运行结果:

图8

发现问题:

浮点数不显示
图9

解决办法:

char p = fgetc(fpin);
fseek(fpin, -1L, SEEK_CUR);
while (shuzi(ch) || (ch == '.' && shuzi(p)))

运行结果:

图10
五、总结
通过设计编制调试一个具体的词法分析程序,加深了对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。遇到各种bug也加深了对程序的理解,所有bug均已解决。
附录(源代码,注意代码格式)
C++实现词法分析器.h

#pragma once
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
class cffxq
{
public:
  
    string Guanjianzi[62] = { "asm","auto","bool","break","case","catch","char","class","const",
        "const_cast","continue","default","delete","do","double","dynamic_cast","else","enum",
        "explicit","export","extern","false","float","for","friend","goto","if","inline","int",
        "long","mutable","namespace","new","operator","private","protected","public","register",
        "reinterpret_cast","return","short","signed","sizeof","static","static_cast","struct",
        "switch","template","this","throw","true","try","typedef","typeid","typename","union",
        "unsigned","using","virtual","void","volatile","wchar_t"};//关键字1-62
    char Fengefu[14] = { ';',',','{','}','[',']','(',')' ,':','\'','\"','.','#','\\'};//分隔符63-76
    char Yunsuanfu[11] = { '+','-','*','/','>','<','=','!','%','&','|'};//运算符77-87
    char Guolvfu[4] = { ' ','\t','\r' ,'\n' };//过滤符88-91
    string glf[4] = { "空格","水平制表","回车","换行" };
    const int Biaoshifu = 92;//标识符值
    const int Changshu = 93;//常数值
    const int Zhushi = 94;//注释值
    bool daxiezimu(char ch);//判断是否为大写字母
    bool xiaoxiezimu(char ch);//判断是否为小写字母
    bool guolvfu(char ch);//判断是否为过滤符
    bool zhushi(char ch, FILE* f); //判断是否为注释
    bool guanjianzi(string str);//判断是否为关键字
    bool fengefu(char ch); //判断是否为分隔符
    bool shuzi(char ch);//判断是否为数字
    bool yunsuanfu(char ch);//判断是否为运算符
    template <class T>
    int zhi(T* a, int n, T str);//返回每个字的值
    void sifafenxi(FILE* f);//词法分析
    void show();
    void show2();
    int show3();
    void xmxh();
    void show4();
};

C++实现词法分析器.cpp

#include"C++实现词法分析器.h"
cffxq cf;

bool cffxq::daxiezimu(char ch)//判断是否为大写字母
{
    if (ch >= 'A' && ch <= 'Z')
    {
        return true;
    }
    return false;
}

bool cffxq::xiaoxiezimu(char ch)//判断是否为小写字母
{
    if (ch >= 'a' && ch <= 'z')
    {
        return true;
    }
    return false;
}

bool cffxq::guolvfu(char ch)//判断是否为过滤符
{
    for (int i = 0; i < 4; i++)
    {
        if (cf.Guolvfu[i] == ch)
        {
            return true;
        }
    }
    return false;
}

bool cffxq::zhushi(char ch, FILE* f)//判断是否为注释
{
    if (ch == '/')
    {
        char p = fgetc(f);
        fseek(f, -1L, SEEK_CUR);
        if (p == '/')
        {
            return true;
        }
        else if (p == '*')
        {
            return true;
        }
    }
    return false;
}

bool cffxq::guanjianzi(string str) //判断是否为关键字
{
    for (int i = 0; i < 62; i++) 
    {
        if (cf.Guanjianzi[i] == str)
        {
            return true;
        }
    }
    return false;
}

bool cffxq::fengefu(char ch)//判断是否为分隔符
{
    for (int i = 0; i < 14; i++) 
    {
        if (cf.Fengefu[i] == ch)
        {
            return true;
        }
    }
    return false;
}

bool cffxq::shuzi(char ch)//判断是否为数字
{
    if (ch >= '0' && ch <= '9')
    {
        return true;
    }
    return false;
}

bool cffxq::yunsuanfu(char ch)//判断是否为运算符
{
    for (int i = 0; i < 11; i++)
    {
        if (cf.Yunsuanfu[i] == ch)
        {
            return true;
        }
    }
    return false;
}

template <class T>
int cffxq::zhi(T* a, int n, T str)//返回每个字的值
{
    for (int i = 0; i < n; i++) 
    {
        if (a[i] == str)
        {
            return i + 1;
        }
    }
    return -1;
}

void cffxq::sifafenxi(FILE* f) //词法分析
{
    char ch;
    string arr = "";
    while ((ch = fgetc(f)) != EOF) 
    {
        arr = "";
        if (guolvfu(ch))//判断是否为过滤符
        {
            /*while (IsFilter(ch))
            {
                arr += ch;
                ch = fgetc(f);
            }
            fseek(f, -1L, SEEK_CUR);*/
            arr += ch;
            if (guolvfu(*arr.data()))
            {
                printf("%3d    ", 87+zhi(cf.Guolvfu, 4, *arr.data()));
                //printf("%d", arr);
                //cout << "'" << arr;
                cout.width(15);
                cout.setf(ios::left);
                cout<< glf[zhi(cf.Guolvfu, 15, *arr.data())-1] << "过滤符" << endl;
            }
          
        }
        else if (zhushi(ch, f))//注释
        {
            char p = fgetc(f);
            fseek(f, -1L, SEEK_CUR);
            if (p == '/')
            {
                //p = fgetc(f);
                //fseek(f, -1L, SEEK_CUR);
                while (ch != '\n')
                {
                    arr += ch;
                    ch = fgetc(f);
                }
                fseek(f, -1L, SEEK_CUR);
                printf("%3d    ", Zhushi);
                cout.width(15);
                cout.setf(ios::left);
                cout << arr << "注释啊" << endl;
            }
            else if (p == '*')
            {
                arr += ch;
                ch = fgetc(f);
                arr += ch;
                ch = fgetc(f);
                while (ch != '*' || p != '/')
                {
                    arr += ch;
                    ch = fgetc(f);
                    p = fgetc(f);
                    fseek(f, -1L, SEEK_CUR);
                }
                //fseek(f, -1L, SEEK_CUR);
                arr += ch;
                ch = fgetc(f);
                arr += ch;
                ch = fgetc(f);
                printf("%3d    ", Zhushi);
                cout.width(15);
                cout.setf(ios::left);
                cout << arr << "注释啊" << endl;
            }
            else
            {

            }
        }
        else if (xiaoxiezimu(ch)) //关键字
        { 
            while (xiaoxiezimu(ch) || ch == '_' || shuzi(ch))
            {
                arr += ch;
                ch = fgetc(f);
            }
            fseek(f,-1L,SEEK_CUR);
            if (guanjianzi(arr))
            {
                printf("%3d    ", zhi(cf.Guanjianzi, 62, arr));
                cout.width(15);
                cout.setf(ios::left);
                cout << arr << "关键字" << endl;
            }
            else
            {
                printf("%3d    ", cf.Biaoshifu);
                cout.width(15);
                cout.setf(ios::left);
                cout << arr << "标识符" << endl;
            }
        }
        else if (daxiezimu(ch) || xiaoxiezimu(ch) || ch == '_') //标识符
        {
            while (daxiezimu(ch) || xiaoxiezimu(ch) || ch == '_' || shuzi(ch))
            {
                arr += ch;
                ch = fgetc(f);
            }
            fseek(f, -1L, SEEK_CUR);
            printf("%3d    ", cf.Biaoshifu);
            cout.width(15);
            cout.setf(ios::left);
            cout << arr << "标识符" << endl;
        }
        else if (shuzi(ch)) //数字
        {
            char p = fgetc(f);
            fseek(f, -1L, SEEK_CUR);
            while (shuzi(ch) || (ch == '.' && shuzi(p)))
            {
                arr += ch;
                ch = fgetc(f);
            }
            fseek(f, -1L, SEEK_CUR);
            printf("%3d    ", cf.Changshu);
            cout.width(15);
            cout.setf(ios::left);
            cout << arr << "整形数" << endl;
        }
       else if(yunsuanfu(ch))//运算符
        {
            while (yunsuanfu(ch))
            {
                arr += ch;
                ch = fgetc(f);
            }
            fseek(f, -1L, SEEK_CUR);
            //arr += ch;
            printf("%3d    ", 76 + zhi(cf.Yunsuanfu, 11, *arr.data()));
            cout.width(15);
            cout.setf(ios::left);
            cout << arr << "运算符" << endl;
        }
        else if (fengefu(ch))//分隔符
        {
            /*while (IsSeparater(ch))
            {
                arr += ch;
                ch = fgetc(f);
            }
            fseek(f, -1L, SEEK_CUR);*/
            arr += ch;
            printf("%3d    ", 62 + zhi(cf.Fengefu, 14, *arr.data()));
            cout.width(15);
            cout.setf(ios::left);
            cout << arr << "分隔符" << endl;
        }
        else
        {
            cout << "\"" << ch << "\":无法识别的字符!" << endl;
        }
    }
}

main.cpp

#include"C++实现词法分析器.h"
cffxq cff;
void cffxq::xmxh()
{
    cout << "*   1    888888    1        4   0000000    1    0000000    1    3333333 0000000 *" << endl;
    cout << "*  11    8    8   11      4 4   0     0   11    0     0   11          3 0     0 *" << endl;
    cout << "* 1 1    8    8  1 1     4  4   0     0  1 1    0     0  1 1          3 0     0 *" << endl;
    cout << "*   1    888888    1    4   4   0     0    1    0     0    1    3333333 0     0 *" << endl;
    cout << "*   1    8    8    1   4444444  0     0    1    0     0    1          3 0     0 *" << endl;
    cout << "*   1    8    8    1        4   0     0    1    0     0    1          3 0     0 *" << endl;
    cout << "*1111111 888888 1111111     4   0000000 1111111 0000000 1111111 3333333 0000000 *" << endl;
    cout << "*                                                                               *" << endl;
    cout << "*      张张张张 张    张          立                 辉     辉辉辉辉辉          *" << endl;
    cout << "*            张 张   张             立            辉 辉 辉  辉  辉  辉          *" << endl;
    cout << "*            张 张  张    立立立立立立立立立立     辉辉辉      辉               *" << endl;
    cout << "*      张张张张 张 张                            辉辉辉辉辉  辉辉辉辉           *" << endl;
    cout << "*      张       张张         立          立        辉 辉     辉                 *" << endl;
    cout << "*      张     张张张张张      立        立         辉 辉    辉  辉              *" << endl;
    cout << "*      张张张张 张张           立      立          辉 辉    辉辉辉辉辉          *" << endl;
    cout << "*            张 张 张           立    立           辉 辉        辉              *" << endl;
    cout << "*            张 张  张           立  立            辉 辉    辉辉辉辉辉          *" << endl;
    cout << "*         张 张 张   张                           辉  辉 辉     辉              *" << endl;
    cout << "*          张张 张    张     立立立立立立立      辉   辉        辉              *" << endl;
}
void cffxq::show()//欢迎界面
{
    cout << "*********************************************************************************" << endl;
    cout << "*                             欢迎使用词法分析器                                *" << endl;
    cout << "*-------------------------------------------------------------------------------*" << endl;
    cout << "*                                 设计制做:                                    *" << endl;
    xmxh();
    cout << "*********************************************************************************" << endl;
    system("pause");
    system("cls");
}
void cffxq::show2()//输入词法分析文档界面
{
    char inFile[40];
    //char inFile[40] = { 'b','.','t','x','t' };
    FILE* fpin;
    cout << "请输入源文件名(包括路径和后缀):";
    cout << endl;
    while (true) {
        cin >> inFile;
        //cout << inFile << endl;
        if ((fpin = fopen(inFile, "r")) != NULL)
        {
            break;
        }
        else
        {
            cout << "文件名错误!" << endl;
            cout << "请重新输入源文件名(包括路径和后缀):";
            cout << endl;
        }
    }
    cout << "--------词法分析如下--------" << endl;
    cff.sifafenxi(fpin);
    cout << "--------词法分析结束--------" << endl;
    system("pause");
    system("cls");
}
int cffxq::show3()
{
    cout << "***************************************************" << endl;
    cout << "*               是否继续进行词法分析              *" << endl;
    cout << "*-------------------------------------------------*" << endl;
    cout << "*               1:继续        2:退出              *" << endl;
    cout << "*                                                 *" << endl;
    cout << "*                 请从键盘输入选择                *" << endl;
    cout << "***************************************************" << endl;
    int a;
    cin >> a;
    if (a == 1)
    {
        //system("pause");
        system("cls");
        show2();
    }
    else
    {
        return 2;
    }
}
void cffxq::show4()
{
    system("pause");
    system("cls");
    cout << "*********************************************************************************" << endl;
    cout << "*                             感谢使用词法分析器                                *" << endl;
    cout << "*-------------------------------------------------------------------------------*" << endl;
    cout << "*                                 设计制做:                                    *" << endl;
    xmxh();
    cout << "*********************************************************************************" << endl;
}
int main()
{
    int a = 0;
    cff.show();
    cff.show2();
    while (a != 2)
    {
        a = cff.show3();
    }
    cff.show4();
    return 0;
}
最后修改:2021 年 05 月 11 日
如果觉得我的文章对你有用,请随意赞赏